# Introduction

Mathematicians often work with number sets. These are groups of numbers that share common properties. These are number sets are, in order from most specific to most broad:

Natural numbers   (symbol N): These are the counting numbers: 1, 2, 3, ...
Integers          (symbol Z): These are all the numbers without a fractional part: ..., -3, -2, -1, 0, 1, 2, 3, ...
Rational numbers  (symbol Q): These numbers are the quotients of two integers, such as: 1.1 (11/10), 5.67 (567/100), or 0.333333333... (1/3)
-----The following two numbers sets are equally specific in describing numbers-----
Real numbers      (symbol R): These are positive, zero, and negative numbers, such as: π (3.1415926...), e (2.7182818...), or √2 (1.4142135...)
Imaginary numbers (symbol I): Numbers that give negative values when squared; for this reason they aren't very useful in everyday life.
These numbers contain the letter i in them, with i representing the √-1.
Examples: 2i, -1.5i 78i, 9i, -3.1415i, i
-----------------------------------------------------------------------------------
Complex numbers   (symbol C): The sum of a real and an imaginary number in the form a + bi, examples: 2 + 7i, 3 + 3i, 1 - i, -8 + i


Note that when there is only a single i, it is not written 1i.

# Challenge

Given a number from one of these number sets, print the symbol for the most specific number set that could describe it.

# Test cases

Input              Output
73.0            -> N
4/2             -> N
-73             -> Z
-1/3            -> Q
0.56            -> Q
0.555...        -> Q
0.123123123...  -> Q
3.1415926535... -> R
-1.37i          -> I
7892/5 + 23/4i  -> C


# Other info

• Natural numbers and integers may be given with a decimal point followed by a string of zeros
• To add on to the previous point, any input that can be converted into a simpler form shall have its output corresponding to the simplified input
• Rational numbers may be given with a / to represent a fraction, or a sequence of numbers occurring 3 or more times followed by ...
• Numbers ending with ... represent repeated decimals or un-terminated decimal real numbers
• Any number sets less specific than Q can also have inputs be given as a fraction
• You do not need to handle repeated decimals or un-terminated decimals for number sets other than Q and R
• Any error caused by lack of precision in floating point numbers will not invalidate a submission

This is code golf, so shortest code wins. If there is something unclear, let me know in the comments' section or edit the question.

• I don't see how one could distinguish Q and R given the limited precision of machine numbers. – xnor Nov 29 '17 at 23:34
• More fundamentally, it's not clear to me whether the inputs are number types in our languages, or strings of them. How much control do we have for how an input is given, in a language where, say, 0 can be represented as one of multiple number types? For example, when you say that inputs can be given as a fraction, do you mean that we have to handle inputs that might possibly be fractions, or this is a choice you can opt for? I think there's a lot of subtlety in specifying this challenge and suggest taking it the Sandbox. – xnor Nov 29 '17 at 23:37
• @LuisMendo Very good point but I think you could have expanded. Indeed there are many machines employing only floating point that would say -3/3 = -0.999.. or possibly even 1.000...1. That's why many languages have different operators for integer and noninteger division, so the programmer gets to decide. – Level River St Nov 29 '17 at 23:44
• @ericw31415 What I think xnor meant is: can we write the program and state "rationals are input with a /"? Or must the program be able to handle both 1/2 and 0.5 as input? – Luis Mendo Nov 29 '17 at 23:57
• @xnor 3 repeats of a sequence of digits before the ... seems to be the distinguishing factor between them – PrincePolka Nov 30 '17 at 0:09

# JavaScript (ES6), 121 110 bytes

s=>[...'QRCI'].find((_,i)=>[/(.+)\1\1\.\./,/\.\./,/.+[+-].*i/,/i/][i].test(s))||'QNZ'[k=eval(s),k%1?0:k>0?1:2]


### Test cases

let f =

s=>[...'QRCI'].find((_,i)=>[/(.+)\1\1\.\./,/\.\./,/.+[+-].*i/,/i/][i].test(s))||'QNZ'[k=eval(s),k%1?0:k>0?1:2]

console.log(f('73.0'           )) // -> N
console.log(f('4/2'            )) // -> N
console.log(f('-73'            )) // -> Z
console.log(f('-1/3'           )) // -> Q
console.log(f('0.56'           )) // -> Q
console.log(f('0.555...'       )) // -> Q
console.log(f('0.123123123...' )) // -> Q
console.log(f('3.1415926535...')) // -> R
console.log(f('-1.37i'         )) // -> I
console.log(f('7892/5 + 23/4i' )) // -> C

### Formatted and commented

s =>                  // given the input string s
[...'QRCI'].find(   // we first apply some regular expressions:
(_, i) => [       //   i = index
/(.+)\1\1\.\./, //     i = 0 (Q): 3x the same pattern, followed by '..' -> rational
/\.\./,         //     i = 1 (R): '..' without the repeated pattern -> real
/.+[+-].*i/,    //     i = 2 (C): a real part +/- an imaginary part -> complex
/i/             //     i = 3 (I): just an imaginary part -> imaginary
][i].test(s)      //   this is a find(), so we exit as soon as something matches
) || 'QNZ'[         // if all regular expressions failed:
k = eval(s),      //   assume the expression can now be safely evaluated as JS code
k % 1 ?           //   if there's a decimal part:
0               //     -> rational
:                 //   else:
k > 0 ?         //     if strictly positive:
1             //       -> natural
:               //     else:
2             //       -> integer
]                   //

• Very nice! I probably would not have been able to come up with a regex that fast. – ericw31415 Nov 29 '17 at 23:54
• Save 1 B using (.+){3} vs. (.+)\1\1 – Ephellon Dantzler Nov 30 '17 at 3:14
• @EphellonDantzler This would match any string of at least 3 characters instead of 3 times the same string. – Arnauld Nov 30 '17 at 7:49