Utwórz interfejs pasujący do typów XKCD


34

colors.rgb („niebieski”) zwraca „# 0000FF”. colors.rgb („żółtawy niebieski”) daje NaN. colors.sort () daje „tęczę”

Korzystając z reguł określonych w obrazie i jego tekście tytułowym (cytowanym tutaj), stwórz program, który akceptuje wszystkie podane dane wejściowe i wyświetla odpowiednie dane wyjściowe.

  • Dane wejściowe można pobierać za pomocą stdin lub najbliższego odpowiednika. Powinien być wiersz podobny [n]>do wpisania go, i nzwiększa się o 1 każde polecenie. Powinien zacząć od 1.

  • Wynik powinien zostać wyświetlony przy użyciu standardowego lub najbliższego odpowiednika. W =>każdym wierszu wyniku powinien znajdować się znak .

Wszystkie 13 warunków plus 3 w tytule (cytowane) muszą działać.

To jest golf golfowy, więc wygrywa najkrótsza odpowiedź.


16
Jak ogólny powinien być interfejs? Na przykład, czy funkcja podłogi musi działać dla dowolnego dostarczonego pływaka, czy możemy założyć, że zostanie on kiedykolwiek przekazany 10.5?
ankh-morpork,

1
Czy> dla danych wyjściowych jest wyrównane z> dla danych wejściowych, gdy n rośnie, a dane wejściowe> przesuwają się bardziej w prawo?
Sparr,

1
Ten komiks można potencjalnie interpretować na kilka sposobów. Czy możesz podać listę konkretnych rodzajów i operacji, które musimy wdrożyć?
BrainSteel

5
Dlaczego warto nzwiększyć o 1? Nie to robi komiks ... ;-)
Przywróć Monikę

3
@WolframH Jest - ale wykonał 2 = 4 w poleceniu 11, więc wyświetla 14, a nie 12.
Tim

Odpowiedzi:


21

Python 3, 700 698 697 689 683 639 611

Tabs jako wcięcie.

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)])

Ponieważ używa tego samego, z wyjątkiem tego, że nie możesz Ctrl + C. Ctrl-Z i zabij %% działają jednak

Niektóre warunki są uogólnione, a inne będą działać tylko przy dokładnym wprowadzeniu danych.

  1. A+"B" będzie działać z każdym A i B nie tylko wtedy A == B
  2. "A"+[] będzie działać dla dowolnego A, który można przekonwertować na liczbę całkowitą (zawiera ciąg szesnastkowy i ciąg binarny, np. 0xff i 0b01010)
  3. (A/0) będzie działać dla dowolnej przyczyny ewidentnej A. DivideByZeroError która jest obsługiwana w wyjątku
  4. (A/0)+B będzie działać z dowolnym A lub B. literal_eval (E) podnosi błąd.
  5. ""+""działa tylko dla znaku +. Cokolwiek innego wydrukuje NaN, NaP lub NaN.00 ...
  6. [A, B, C]+D działa poprzez sprawdzenie tego D == C+1 tak będzie działać dla dowolnej długości listy i dowolnych liczb.
  7. ^^
  8. 2/(2-(3/2+1/2))Wszystko, co nie do analizowania, który ma -literę A+ gdzieś po wyświetli NaN.000 ... 13
  9. RANGE(" ") Mocno zakodowane
  10. +A będzie działać dla każdego A. Ouputs "current_line_number+A"
  11. A+A działa dla każdego A, o ile są one takie same i są typami pythonów typu bulitin
  12. RANGE(1,5) Mocno zakodowane.
  13. FLOOR(A) działa dla każdego A.
  14. colors.rgb("blue")Lstrip w eval zmienia to, w gb("blue")co ma zakodowaną odpowiedź.
  15. colors.rgb("yellowish blue")Lstrip w eval zamienia to, w gb("yellowish blue")którym próbuje użyć nieistniejącej zmiennej, jeśli yjest obecna w argumentacji, powodując błąd, który wyjątek zamienia się w NaN
  16. colors.sort()Lstrip zamienia to w twardą t()odpowiedź.

Brainsteel wskazał na błąd w moim założeniu dotyczącym reguły 10.


Bardzo schludny. Wydaje mi się, że na nr 10 wydaje się, że „+ A” ma na celu wyprowadzenie numeru linii + A, a nie tylko wstępne 1.
BrainSteel

Ach tak, teraz oczywiste, że to wskazano. To oznacza, że ​​int będzie lepszy jako funkcja pojedynczej litery. Może zapisać bajt lub dwa.
Daniel Wakefield

do # 9: RANGE(" ")to zakres znaków od znaku podwójnego cudzysłowu \ x22 do znaku spacji \ x20 i odwrotnie.
John Dvorak,

3
re the jump: bo Randall ustawiony 2na4 linię 11, 2 ma teraz 4, a 12 ma teraz 14. Dotyczy to również numerów linii.
John Dvorak,

2
Możesz zaoszczędzić niektóre bajty, używając spacji, tab i tab + spacja dla wcięcia.
Tyilo

16

Python, 1110 bajtów

Przeciążenie operatora nie jest złe, prawda?

from re import*
class V(str):
 def __add__(s,r):return s[:-1]+chr(ord(s[-1])+r)
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 __add__(s,r):return V(str(r==s[-1]+1).upper())
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)
def colorssort():return V('rainbow')
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

Moim celem nie było tyle wygranej (oczywiście), co uczynienie go tak ogólnym, jak to możliwe. Bardzo mało jest zakodowanych na stałe. Próbować takich rzeczy RANGE(10), 9*1i RANGE("A"), (2/0)+14i"123" dla wyników zabawy!

Oto przykładowa sesja:

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$

7

C, 412 bajtów

Jest to zasadniczo zakodowane, ale we wszystkich dotychczasowych odpowiedziach czegoś brakowało ...

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");}}

Wydajność:

[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___

5

Python 3, 298

Wszystko jest zakodowane na stałe, ale dane wejściowe są przekształcane w liczbę, która jest następnie konwertowana na ciąg znaków i przeglądana w dużym ciągu, który zawiera wszystkie te liczby, a następnie ich odpowiedzi.

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=>"))

1

Python 3, 542 484 bajtów

Ponieważ nie było wzmianki o absolutnym kodowaniu na stałe, oto moje rozwiązanie.

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

Kodowanie jest w porządku, ale myślę, że luki, które są domyślnie zabronione, są domyślnie zabronione. : P
lirtosiast

@ThomasKwa Nie widzę tu niczego, co byłoby zabronioną luką. Jest tu?
Ethan Bierlein,

1
Wszystko wydaje mi się zgodne. Wcześniej zakładałem, że wykorzystujesz lukę, ponieważ powiedziałeś, że „nie ma wzmianki o [...] standardowych lukach”.
lirtosiast

1
Myślę, że to kreatywne, ale nie odpowiedź. Pytanie wyraźnie mówi o wejściu i wyjściu: „stwórz program, który akceptuje wszystkie podane dane wejściowe i wyświetla odpowiednie dane wyjściowe”
agtoever

2
Możesz zaoszczędzić sporo, używając obu cytatów. "2+\"2\""staje się '2+"2"'. Licznik importu można również usunąć, jeśli dodasz zmienną licznika.
Daniel Wakefield
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.