# Create an interface that fits the XKCD Types

colors.rgb("blue") yields "#0000FF". colors.rgb("yellowish blue") yields NaN. colors.sort() yields "rainbow"

Using the rules set out in the image and its title text (quoted here), create a program that accepts all the given input and displays the appropriate output.

• Input can be taken with stdin or nearest equivalent. There should be a line like [n]> on which to type it, and n increases by 1 each command. It should start at 1.

• The result should be displayed using stdout or nearest equivalent. There should be a => on each line of output.

All 13 conditions, plus the 3 in the title (quoted) must work.

This is code golf, so shortest answer wins.

• How general should the interface be? For instance, does the floor function have to work for any provided float or can we assume it will only ever be passed 10.5? Jul 10, 2015 at 22:52
• Are the > for the output aligned with the > for the input, as n grows and the input > moves farther to the right? Jul 10, 2015 at 22:54
• This comic can potentially be interpreted in several ways. Could you provide a list of what specific types and operations we need to implement? Jul 11, 2015 at 2:09
• Why should n increase by 1? That's not what the comic does... ;-) Jul 11, 2015 at 23:46
• @WolframH It is - but he made 2 = 4 in command 11 so it displays 14 not 12.
– Tim
Jul 12, 2015 at 9:48

# Python 3, 700 698 697 689 683 639 611

Tabs as indentation.

from ast import*
E=literal_eval
O='=>%s\n'
P=print
I=int
def Q(a):P(O%a)
def W(a):Q('"%s"'%str(a))
def gb(a):W(_ if'y'in a else'#0000FF')
def t():W('rainbow')
def FLOOR(n):P(O%'|'*3+(O%'|{:_^10}').format(n))
def RANGE(*a):Q([('"','!',' ','!','"'),(1,4,3,4,5)][len(a)])
c=0
while 1:
try:
c+=1;A,*B=input('[%d]>'%c).split('+')
if not A:W(c+I(B[0]))
elif A=='""':Q("'\"+\"'")
elif B:
A=E(A);B=E(B[0])
if A==B:Q('DONE')
elif type(A)==list:Q(A[-1]==B-1)
elif type(B)==list:W([I(A)])
else:W(A+I(B))
else:eval(A.lstrip('colrs.'))
except:Q('Na'+['N','P','N.%s13'%('0'*13)][('-'in A)+len(B)])


Since this uses a bare Except you can't Ctrl-C it. Ctrl-Z and kill %% work though

Some of the conditions are generalized and others will only work with exact input.

1. A+"B" will work with any A and B not just when A == B
2. "A"+[] will work for any A that can be converted to an int (Includes hex and binary strings e.g 0xff and 0b01010)
3. (A/0) will work for any A, Eval Causes DivideByZeroError which is handled in the except
4. (A/0)+B will work with any A or B. literal_eval (E) raises an error.
5. ""+"" only works for the + sign. Anything else will print NaN, NaP or NaN.00...
6. [A, B, C]+D works by checking that D == C+1 so will work for any length of list and any numbers.
7. ^^
8. 2/(2-(3/2+1/2)), Anything that fails to parse that has - with a + somewhere after it will output NaN.000...13
9. RANGE(" ") Hardcoded
10. +A will work for any A. Ouputs "current_line_number+A"
11. A+A works for any A as long as they are the same and are bulitin python types
12. RANGE(1,5) Hardcoded.
13. FLOOR(A) works for any A.
14. colors.rgb("blue") The lstrip in eval turns this in gb("blue") which has a hardcoded response.
15. colors.rgb("yellowish blue") The lstrip in eval turns this in gb("yellowish blue") which attempts to use a non existent variable if y is present in the arguement causing an error which the except turns into NaN
16. colors.sort() The lstrip turns this into t() which has a hardcoded response.

Brainsteel pointed out an error in my assumption for rule 10.

• Very neat. I think, on #10, it seems that the "+A" is intended to output the line number + A, rather than just prepending 1. Jul 11, 2015 at 2:06
• Ahh yes, obvious now that its pointed out. Well that means that int will be better as a single letter function. Might save a byte or two. Jul 11, 2015 at 2:12
• re #9: RANGE(" ") is a range of characters from the double quote character \x22 to the space character \x20 and back. Jul 11, 2015 at 5:11
• re the jump: because Randall set 2 to 4 in line 11, 2 is now 4 and 12 is now 14. This also applies to line numbers. Jul 11, 2015 at 5:15
• You could save some bytes by using space, tab and tab + space for your indentation. Jul 11, 2015 at 20:34

# Python, 1110 bytes

from re import*
class V(str):
class S(str):
def __str__(s):return "'"+s+"'"if '"'in s else'"'+s+'"'
def __repr__(s):return str(s)
def __add__(s,r):s=str(s)[1:-1];return S('['+s+']'if type(r)==L else '"+"' if(s,r)==('','')else s+r)
class I(int):
def __add__(s,r):return type(r)(int(s)+int(r))if s!=r else V('DONE')
def __div__(s,r):return N if r==0 else int(s)/int(r)
def __pos__(s):return s+c*10
def __mul__(s,r):return V('NaN.'+'0'*13+'13')if r==1 else int(s)*int(r)
class L(list):
def RANGE(a,b=0):return 2*(a,S(chr(ord(a)+1)))if b==0 else tuple([a]+[b-1,a+2]*((b-a)/4)+[b-1,b])
def FLOOR(n):return V('|\n|\n|\n|___%s___'%n)
def colorsrgb(c):
m={'blue':V('#0000FF')}
return m.get(c,N)
N=V('NaN')
c=1
while True:
try:l=raw_input('[%d] >'%c)
except:break
l=sub(r'(?<!"|\.)(\d+)(?!\.|\d)',r'I(\1)',l)
l=sub(r'"(.*?)"',r'S("\1")',l)
l=sub(r'$(.*?)$',r'L([\1])',l)
l=sub(r'/\(','*(',l)
l=sub('s\.','s',l)
for x in str(eval(l)).split('\n'):print ' =',x
c+=1


My goal wasn't as much winning (obviously) as it is making it as generic as possible. Very little is hardcoded. Try stuff like RANGE(10), 9*1, and RANGE("A"), (2/0)+14, and "123" for fun results!

Here's a sample session:

ryan@DevPC-LX:~/golf/xktp$python xktp.py [1] >ryan@DevPC-LX:~/golf/xktp$ python xktp.py
[1] >1+1
= DONE
[2] >2+"2"
= "4"
[3] >"2"+2
Traceback (most recent call last):
File "xktp.py", line 31, in <module>
for x in str(eval(l)).split('\n'):print ' =',x
File "<string>", line 1, in <module>
File "xktp.py", line 7, in __add__
def __add__(s,r):s=str(s)[1:-1];return S('['+s+']'if type(r)==L else '"+"' if(s,r)==('','')else s+r)
TypeError: cannot concatenate 'str' and 'I' objects
ryan@DevPC-LX:~/golf/xktp$python xktp.py [1] >ryan@DevPC-LX:~/golf/xktp$
ryan@DevPC-LX:~/golf/xktp$ryan@DevPC-LX:~/golf/xktp$
ryan@DevPC-LX:~/golf/xktp$python xktp.py [1] >2+"2" = "4" [2] >"2"+[] = "[2]" [3] >"2"+[1, 2, 3] = "[2]" [4] >(2/0) = NaN [5] >(2/0)+2 = NaP [6] >(2/0)+14 = Na\ [7] >""+"" = '"+"' [8] >[1,2,3]+2 = FALSE [9] >[1,2,3]+4 = TRUE [10] >[1,2,3,4,5,6,7]+9 = FALSE [11] >[1,2,3,4,5,6,7]+8 = TRUE [12] >2/(2-(3/2+1/2)) = NaN.000000000000013 [13] >9*1 = NaN.000000000000013 [14] >RANGE(" ") = (" ", "!", " ", "!") [15] >RANGE("2") = ("2", "3", "2", "3") [16] >RANGE(2) Traceback (most recent call last): File "xktp.py", line 31, in <module> for x in str(eval(l)).split('\n'):print ' =',x File "<string>", line 1, in <module> File "xktp.py", line 15, in RANGE def RANGE(a,b=0):return 2*(a,S(chr(ord(a)+1)))if b==0 else tuple([a]+[b-1,a+2]*((b-a)/4)+[b-1,b]) TypeError: ord() expected string of length 1, but I found ryan@DevPC-LX:~/golf/xktp$ python xktp.py
[1] >ryan@DevPC-LX:~/golf/xktp$# oops ryan@DevPC-LX:~/golf/xktp$ python xktp.py
[1] >RANGE("2")
= ("2", "3", "2", "3")
[2] >RANGE(2*1)
Traceback (most recent call last):
File "xktp.py", line 31, in <module>
for x in str(eval(l)).split('\n'):print ' =',x
File "<string>", line 1, in <module>
File "xktp.py", line 15, in RANGE
def RANGE(a,b=0):return 2*(a,S(chr(ord(a)+1)))if b==0 else tuple([a]+[b-1,a+2]*((b-a)/4)+[b-1,b])
TypeError: ord() expected a character, but string of length 19 found
ryan@DevPC-LX:~/golf/xktp$python xktp.py # oops again [1] >RANGE(1,20) = (1, 19, 3, 19, 3, 19, 3, 19, 3, 19, 20) [2] >RANGE(1,5) = (1, 4, 3, 4, 5) [3] >RANGE(10,20) = (10, 19, 12, 19, 12, 19, 20) [4] >RANGE(10,200) = (10, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 12, 199, 200) [5] >+2 = 52 [6] >+"99" Traceback (most recent call last): File "xktp.py", line 31, in <module> for x in str(eval(l)).split('\n'):print ' =',x File "<string>", line 1, in <module> TypeError: bad operand type for unary +: 'S' ryan@DevPC-LX:~/golf/xktp$ python xktp.py # oops again and again!
[1] >FLOOR(200)
= |
= |
= |
= |___200___
[2] >2+2
= DONE
[3] >3+#
Traceback (most recent call last):
File "xktp.py", line 31, in <module>
for x in str(eval(l)).split('\n'):print ' =',x
File "<string>", line 1
I(3)+#
^
SyntaxError: unexpected EOF while parsing
ryan@DevPC-LX:~/golf/xktp$python xktp.py [1] >3+3 = DONE [2] >ryan@DevPC-LX:~/golf/xktp$


# C, 412 bytes

This is basically hardcoded, but all the other answers so far were missing something...

i;char b[99];main(){for(;;){printf("[%d]>",abs(++i));gets(b);i-=b[2]==50?26:0;printf("=>");puts(*b==82?b[6]==34?"('\"',\"!\",\" \",\"!\",'\"')":"(1,4,3,4,5)":*b==70?"|\n=>|\n=>|\n=>|___10.5___":*b==43?"12":*b==91?b[8]==50?"FALSE":"TRUE":*b==34?b[1]==34?"'\"+\"'":"\"[2]\"":*b==40?b[5]==43?"NaP":"NaN":*b==99?b[7]=='s'?"rainbow":b[12]==98?"#0000FF":"NaN":b[1]==43?b[2]==34?"\"4\"":"DONE":"NaN.000000000000013");}}


Output:

[1]>2+"2"
=>"4"
[2]>"2"+[]
=>"[2]"
[3]>(2/0)
=>NaN
[4]>(2/0)+2
=>NaP
[5]>""+""
=>'"+"'
[6]>[1,2,3]+2
=>FALSE
[7]>[1,2,3]+4
=>TRUE
[8]>2/(2-(3/2+1/2))
=>NaN.000000000000013
[9]>RANGE(" ")
=>('"',"!"," ","!",'"')
[10]>+2
=>12
[11]>2+2
=>DONE
[14]>RANGE(1,5)
=>(1,4,3,4,5)
[13]>FLOOR(10.5)
=>|
=>|
=>|
=>|___10.5___


## Python 3, 298

Everything is hardcoded, but the input is turned into a number that is then converted to a string and looked up in a large string that contains all these numbers followed by their answers.

B="""53"#0000FF"~62DONE~43NaN.000000000000013~25(1,4,3,4,5)~26"rainbow"~49"4"~21"[2]"~29FALSE~15|*|*|*|___10.5___~17'"+"'~1212~60('"',"!"," ","!",'"')~24NaN~31TRUE~64NaN~76NaP"""
i=0
while 1:i+=1;s=input("[%s]>"%i);print("=>"+B[B.find(str(sum(map(ord,s))%81))+2:].split("~")[0].replace("*","\n=>"))


# Python 3, 542 484 bytes

Since there was no mention of absolute hardcoding here's my solution.

a={'2+"2"':'"4"','"2"+[]':'"[2]"',"(2/0)":"NaN","(2/0)+2":"NaP",'""+""':"'\"+\"'","[1,2,3]+2":"FALSE","[1,2,3]+4":"TRUE","2/(2-(3/2+1/2))":"NaN.000000000000013",'RANGE(" ")':'(\'"\',"!"," ","!",\'"\')',"+2":"12","2+2":"DONE","RANGE(1,5)":"(1,4,3,4,5)","FLOOR(10.5)":"|\n|\n|\n|___10.5___",'colors.rgb("blue")':'"#0000FF"','colors.rgb("yellowish blue")':"NaN","colors.sort()":'"rainbow"'}
i=1
while 1:b=a[input("[%i]>"%i).replace("\t","")].split("\n");print("=> "+"\n=> ".join(b));i+=1

• Hardcoding is fine, but I think the loopholes that are forbidden by default are forbidden by default. :P Jul 11, 2015 at 4:05
• @ThomasKwa I don't see anything here that is a forbidden loophole. Is there? Jul 11, 2015 at 4:08
• Everything looks compliant to me. I earlier assumed you were exploiting a loophole because you said there was "no mention of [...] standard loopholes". Jul 11, 2015 at 4:54
• I think it's creative, but not an answer. The question clearly talks about input and output: "create a program that accepts all the given input and displays the appropriate output" Jul 11, 2015 at 6:02
• You can save a good amount by using both quotes. "2+\"2\"" becomes '2+"2"'. Importing count could also be removed if you add a counter variable. Jul 11, 2015 at 9:32