fork(1) download
  1. ############################################################################
  2. # Pyth version 1.1.0 #
  3. # Posted before 7-18-2014 #
  4. # #
  5. # Added #, Utf-32 -> ascii, to win all of the "character count" challenges.#
  6. # I agree it's dumb, but them's the rules. #
  7. # #
  8. # This python program is an interpreter for the pyth programming language. #
  9. # It is still in development - expect new versions often. #
  10. # #
  11. # To use, provide pyth code on one line of stdin. #
  12. # Further input on further lines. #
  13. # Prints out resultant python code for debugging purposes, then runs the #
  14. # pyth program. #
  15. # #
  16. # More information: #
  17. # The parse function takes a string of pyth code, and returns a single #
  18. # python expression ready to be executed. #
  19. # general_parse is the same but for multiple expressions. #
  20. # This program also defines the built-ins that the resultant expression #
  21. # uses, once expanded. #
  22. ############################################################################
  23.  
  24. def parse(code,spacing="\n "):
  25. assert type(code)==type('')
  26. # If we've reached the end of the string, give up.
  27. if len(code)==0:
  28. return '',''
  29. # Separate active character from the rest of the code.
  30. active_char=code[0]
  31. rest_code=code[1:]
  32. # Deal with numbers
  33. if active_char in ".0123456789":
  34. output=active_char
  35. while (len(rest_code)>0
  36. and rest_code[0] in ".0123456789"
  37. and (output+rest_code[0]).count(".")<=1):
  38. output+=rest_code[0]
  39. rest_code=rest_code[1:]
  40. return output,rest_code
  41. # String literals
  42. if active_char=='"':
  43. output=active_char
  44. while (len(rest_code)>0
  45. and output.count('"')<2):
  46. output+=rest_code[0]
  47. rest_code=rest_code[1:]
  48. if output[-1]!='"':
  49. output+='"'
  50. return output,rest_code
  51. # Python code literals
  52. if active_char=='$':
  53. output=''
  54. while (len(rest_code)>0
  55. and rest_code[0]!='$'):
  56. output+=rest_code[0]
  57. rest_code=rest_code[1:]
  58. return output,rest_code[1:]
  59. # End paren is magic.
  60. if active_char==')':
  61. return '',rest_code
  62. # Backslash is more magic.
  63. if active_char=='\\':
  64. if rest_code=='':
  65. return '',''
  66. else:
  67. return '','\\'+rest_code
  68. # Designated variables
  69. if active_char in variables:
  70. return active_char,rest_code
  71. # And for general functions
  72. global c_to_f
  73. global next_c_to_f
  74. if active_char in c_to_f:
  75. func_name,arity=c_to_f[active_char]
  76. init_paren = (active_char not in no_init_paren)
  77. # Swap what variables are used in the map, filter or reduce.
  78. if active_char in next_c_to_f:
  79. temp=c_to_f[active_char]
  80. c_to_f[active_char]=next_c_to_f[active_char][0]
  81. next_c_to_f[active_char]=next_c_to_f[active_char][1:]+[temp]
  82. # Recurse until terminated by end paren or EOF
  83. # or received enough arguments
  84. args_list=[]
  85. parsed='Not empty'
  86. while len(args_list) != arity and parsed != '':
  87. parsed,rest_code=parse(rest_code)
  88. args_list.append(parsed)
  89. # Build the output string.
  90. py_code=func_name
  91. if init_paren:
  92. py_code+='('
  93. if len(args_list)>0 and args_list[-1]=='':
  94. args_list=args_list[:-1]
  95. py_code+=','.join(args_list)
  96. py_code+=')'
  97. return py_code,rest_code
  98. # General format functions/operators
  99. global c_to_i
  100. if active_char in c_to_i:
  101. infixes,arity=c_to_i[active_char]
  102. # Make J and K into normal variables, if necessary.
  103. if active_char in next_c_to_i:
  104. c_to_i[active_char]=next_c_to_i[active_char]
  105. args_list=[]
  106. parsed='Not empty'
  107. while len(args_list) != arity and parsed != '':
  108. parsed,rest_code=parse(rest_code)
  109. args_list.append(parsed)
  110. # Statements that cannot have anything after them
  111. if active_char in end_statement:
  112. rest_code=")"+rest_code
  113. py_code=infixes[0]
  114. for i in range(len(args_list)):
  115. py_code+=args_list[i]
  116. py_code+=infixes[i+1]
  117. return py_code, rest_code
  118. # Statements:
  119. if active_char in c_to_s:
  120. # Handle the initial portion (head)
  121. infixes,arity=c_to_s[active_char]
  122. args_list=[]
  123. parsed='Not empty'
  124. while len(args_list) != arity and parsed != '':
  125. parsed,rest_code=parse(rest_code)
  126. args_list.append(parsed)
  127. part_py_code=infixes[0]
  128. for i in range(len(args_list)):
  129. part_py_code+=args_list[i]
  130. part_py_code+=infixes[i+1]
  131. # Handle the body - ends object as well.
  132. assert rest_code != ''
  133. args_list=[]
  134. parsed='Not empty'
  135. while parsed != '':
  136. # Prepend print to any line starting with a function, var or safe infix.
  137. if len(rest_code)>0:
  138. if ((rest_code[0] not in 'p ' and rest_code[0] in c_to_f) or
  139. rest_code[0] in variables or
  140. (rest_code[0] in 'JK' and c_to_i[rest_code[0]]==next_c_to_i[rest_code[0]]) or
  141. rest_code[0] in "@&|]'?;\".0123456789#,"):
  142. rest_code='p"\\n"'+rest_code
  143. parsed,rest_code=parse(rest_code,spacing+' ')
  144. args_list.append(parsed)
  145. # Trim the '' away and combine.
  146. if args_list[-1]=='':
  147. args_list=args_list[:-1]
  148. all_pieces=[part_py_code]+args_list
  149. return spacing.join(all_pieces),rest_code
  150. print("Something's wrong.")
  151. print("Current char is ",active_char)
  152. print("The rest of the code is ",rest_code)
  153. raise NotImplementedError
  154.  
  155. import random
  156. import copy
  157. import string
  158. # Function library, descriptions of everything.
  159. # += # ~ Y - Sets
  160. # repr # ` Y - General
  161. def _not(a):return not a # ! Y - General
  162. # _[_] # @ Y - Ints
  163. def utf32_ascii(a): # #
  164. if type(a)==type(''):
  165. utf_str=a
  166. text_num=0
  167. for char in utf_str:
  168. text_num*=(2**20+2**16)
  169. text_num+=ord(char)
  170. out_str=''
  171. while text_num>0:
  172. next_num=text_num%96
  173. next_chr=chr(next_num+31) if next_num else '\n'
  174. out_str=next_chr+out_str
  175. text_num//=96
  176. return out_str
  177. else:
  178. ascii_str=a[0]
  179. text_num=0
  180. for char in ascii_str:
  181. num=ord(char)
  182. text_num*=96
  183. if 32<=num<=126:
  184. text_num+=num-31
  185. out_str=''
  186. while text_num>0:
  187. next_chr=chr(text_num%(2**20+2**16))
  188. out_str=next_chr+out_str
  189. text_num//=(2**20+2**16)
  190. return out_str
  191.  
  192. # $ is special - python literal Y - General
  193. def mod(a,b):return a%b # % Y - Lists, Sets
  194. # pow # ^ Y - non num
  195. # and # & Y - General
  196. def times(a,b):return a*b # * Y - sets
  197. def _tuple(*a):return a # ( Y - general
  198. # ) is special - end extensible Y - general
  199. def minus(a,b):
  200. if type(a)==type(set()):
  201. return a.difference(b)
  202. return a-b # - Y
  203. def neg(a): # _ Y
  204. return -a
  205. def plus(a,b):
  206. if type(a)==type(set()):
  207. return a.union(b)
  208. if type(b)==type(set()):
  209. return b.union(a)
  210. return a+b # + Y
  211. # = deepcopy # = Y
  212. copy = copy.deepcopy
  213. def _list(*a):return list(a) # [ Y
  214. # set # { Y
  215. # [_] # ] Y
  216. # in # } Y
  217. # or # | Y
  218. # break out of all containing # ) Y
  219. def at_slice(a,b,c=None): # : Y
  220. if c:
  221. return a[slice(b,c)]
  222. else:
  223. return a[slice(b)]
  224. # _.pop() # ; Y
  225. def head(a): # ' Y
  226. if type(a)==type(0):
  227. return a+1
  228. return a[0]
  229. # " is special - string literal Y
  230. # Pairing # , Y
  231. def lt(a,b): # < Y
  232. if type(a)==type(set()):
  233. return a.issubset(b) and a!=b
  234. return a<b
  235. # . is special - numbers # . Y
  236. def gt(a,b): # > Y
  237. if type(a)==type(set()):
  238. return a.issuperset(b) and a!=b
  239. return a>b
  240. def div(a,b):return a//b # / Y
  241. # if else # ? Y
  242. # 0-9 are special - numbers # 0-9 Y
  243. # (x) #| | Y
  244. # all # A Y
  245. # .append() # a Y
  246. # break # B Y
  247. b="\n" # b Y
  248. # chr # C Y
  249. def _chr(a):
  250. if type(a)==type(0):
  251. return chr(a)
  252. if type(a)==type(''):
  253. return ord(a[0])
  254. def count(a,b):return a.count(b) # c Y
  255. # def # D Y
  256. # variable - associated with map # d Y
  257. d=' '
  258. # else # E Y
  259. def lower(a):return a.lower() # e Y
  260. # for # F Y
  261. def _filter(a,b): # f Y
  262. return list(filter(a,b))
  263. # variable - associated with reduce # G Y
  264. G=string.ascii_lowercase
  265. def gte(a,b): # g Y
  266. if type(a)==type(set()):
  267. return a.issuperset(b)
  268. return a>=b
  269. # variable - associated with reduce # H Y
  270. H={}
  271. def read_file(): # h Y
  272. a="\n".join(open(input()))
  273. return a
  274. # h assigns the text of the user
  275. # inputted file to the variable given.
  276. # if # I Y
  277. def _round(a,b=None): # i Y
  278. if b is None:
  279. return float(a)
  280. if b is 0:
  281. return int(a)
  282. return round(a,b)
  283. # Autoinitializing variable # J Y
  284. def join(a,b): # j Y
  285. return a.join(list(map(lambda N:str(N),b)))
  286. # Autoinitializing variable # K Y
  287. k='' # k Y
  288. def lrange(a): # L Y
  289. if type(a)==type(0):
  290. return list(range(a))
  291. return list(range(len(a)))
  292. # len # l Y
  293. # max # M Y
  294. def _map(a,b):return list(map(a,b)) # m Y
  295. N=None # N Y
  296. # min # n Y
  297. def rchoice(a): # O Y
  298. if type(a)==type(0):
  299. return random.choice(_range(a))
  300. return random.choice(list(a))
  301. # order (sorted with key) # o Y
  302. def order(a,b):
  303. if type(b)==type(''):
  304. return ''.join(sorted(b, key=a))
  305. return sorted(b, key=a)
  306. def split(a,b=None): # P Y
  307. if b:
  308. return a.split(b)
  309. else:
  310. return a.split()
  311. def _print(a,b=""): # p Y
  312. print(b,end=a)
  313. def quotient(a,b):return a/b # Q Y
  314. def equal(a,b):return a==b # q Y
  315. # return # R Y
  316. def _range(a,b=None): # r Y
  317. if b:
  318. return list(range(a,b))
  319. else:
  320. return list(range(a))
  321. # sorted # S Y
  322. def _sum(a):
  323. return reduce(lambda b,c:b+c,a) # s Y
  324. # T is associated with filter # T Y
  325. T=10
  326. def tail(a): # t Y
  327. if type(a)==type(0):
  328. return a-1
  329. return a[1:]
  330. def upper(a):return a.upper() # U Y
  331. def reduce(a,b): # u Y
  332. acc=b[0]
  333. seq=b[1:]
  334. while len(seq)>0:
  335. h=seq[0]
  336. acc=a(acc,h)
  337. seq=seq[1:]
  338. return acc
  339. def rev(a): return a[::-1] # V Y
  340. # eval # v Y
  341. # while # W Y
  342. # input # w Y
  343. def index(a,b): # X Y
  344. if b in a:
  345. return a.index(b)
  346. # replicate functionality from str.find
  347. else:
  348. return -1
  349. # exec(general_parse # x Y
  350. Y=[] # Y Y
  351. # any # y Y
  352. Z=0 # Z Y
  353. def _zip(a,b):return list(zip(a,b)) # z Y
  354.  
  355. no_init_paren='fmou'
  356. end_statement='BR'
  357. variables='bdGHkNTYZ'
  358.  
  359. # To do: even preassociated variables deserve to be initialized.
  360. # Variables cheat sheet:
  361. # b = "\n"
  362. # d is for map, d=' '
  363. # G is for reduce, G=string.ascii_lowercase (abc..xyz)
  364. # H is for reduce, H = {}
  365. # k = ''
  366. # J - Autoinitializer - copies, no stringing.
  367. # K - Autoinitializer - can be strung (KJw), no copy.
  368. # N = None, second option variable for map,filter,reduce
  369. # T is for filter, second variable option for reduce, T=10
  370. # Y = []
  371. # Z = 0
  372.  
  373. c_to_s={
  374. 'D':(('def ',':'),1),
  375. 'E':(('else:'),0),
  376. 'F':(('for ',' in ',':'),2),
  377. 'I':(('if ',':'),1),
  378. 'W':(('while ',':'),1),
  379. }
  380. # Arbitrary format operators - use for assignment, infix, etc.
  381. # All surrounding strings, arity
  382. c_to_i={
  383. '~':(('','+=',''),2),
  384. '@':(('','[',']'),2),
  385. '&':(('(',' and ',')'),2),
  386. '|':(('(',' or ',')'),2),
  387. '=':(('','=copy(',')'),2),
  388. ']':(('[',']'),1),
  389. '}':(('(',' in ',')'),2),
  390. '?':(('(',' if ',' else ',')'),3),
  391. ',':(('(',',',')'),2),
  392. ';':(('','.pop()',),1),
  393. 'a':(('','.append(',')'),2),
  394. 'B':(('break',),0),
  395. 'J':(('J=copy(',')'),1),
  396. 'K':(('K=',''),1),
  397. 'R':(('return ',''),1),
  398. 'x':(('exec(general_parse(','))'),1),
  399. }
  400.  
  401. # Simple functions only.
  402. # Extensible is allowed, nothing else complicated is.
  403. # -1 means extensible
  404. # name,arity
  405. c_to_f={
  406. '`':('repr',1),
  407. '!':('_not',1),
  408. '#':('utf32_ascii',1),
  409. '%':('mod',2),
  410. '^':('pow',2),
  411. '*':('times',2),
  412. '(':('_tuple',-1),
  413. '-':('minus',2),
  414. '_':('neg_1r',1),
  415. '+':('plus',2),
  416. '[':('_list',-1),
  417. '{':('set',1),
  418. "'":('head',1),
  419. ':':('at_slice',3),
  420. '<':('lt',2),
  421. '>':('gt',2),
  422. '/':('div',2),
  423. ' ':('',1),
  424. '\t':('',1),
  425. 'A':('all',1),
  426. 'C':('_chr',1),
  427. 'c':('count',2),
  428. 'e':('lower',1),
  429. 'f':('_filter(lambda T:',2),
  430. 'g':('gte',2),
  431. 'h':('read_file',0),
  432. 'i':('_round',2),
  433. 'j':('join',2),
  434. 'L':('lrange',1),
  435. 'l':('len',1),
  436. 'M':('max',1),
  437. 'm':('_map(lambda d:',2),
  438. 'O':('rchoice',1),
  439. 'o':('order(lambda N:',2),
  440. 'P':('split',2),
  441. 'p':('_print',2),
  442. 'Q':('quotient',2),
  443. 'q':('equal',2),
  444. 'r':('_range',2),
  445. 'S':('sorted',1),
  446. 's':('_sum',1),
  447. 't':('tail',1),
  448. 'U':('upper',1),
  449. 'u':('reduce(lambda G,H:',2),
  450. 'V':('rev',1),
  451. 'v':('eval',1),
  452. 'w':('input',0),
  453. 'X':('index',2),
  454. 'z':('_zip',2),
  455. }
  456.  
  457. # Gives next function header to use - for filter, map, reduce.
  458. # map: d, k, b
  459. # filter: T, Y, Z
  460. # order: N, Z,
  461. # reduce: (G,H), (N,T)
  462.  
  463. next_c_to_f={
  464. 'f':[('_filter(lambda Y:',2), ('_filter(lambda Z:',2),],
  465. 'm':[('_map(lambda k:',2), ('_map(lambda b:',2),],
  466. 'o':[('order(lambda Z:',2),],
  467. 'u':[('reduce(lambda N,T:',2),],
  468. }
  469.  
  470. # For autoinitializers. One shot, not rotating.
  471. next_c_to_i={
  472. 'J':(('J'),0),
  473. 'K':(('K'),0),
  474. }
  475.  
  476. assert set(c_to_f.keys())&set(c_to_i.keys())==set()
  477. # Run it!
  478. def general_parse(code):
  479. args_list=[]
  480. parsed='Not empty'
  481. while parsed != '':
  482. # Prepend print to any line starting with a function, var or safe infix.
  483. if len(code)>0:
  484. if ((code[0] not in 'p ' and code[0] in c_to_f) or
  485. code[0] in variables or
  486. (code[0] in 'JK' and c_to_i[code[0]]==next_c_to_i[code[0]]) or
  487. code[0] in "@&|]'?;\".0123456789#,"):
  488. code='p"\\n"'+code
  489. parsed,code=parse(code)
  490. # Necessary for backslash not to infinite loop
  491. if code and code[0]=='\\':
  492. code=code[1:]
  493. args_list.append(parsed)
  494. # Build the output string.
  495. py_code='\n'.join(args_list[:-1])
  496. return py_code
  497. code=input()
  498. print(code)
  499. py_code=general_parse(code)
  500. print(py_code)
  501. print('='*50)
  502. exec(py_code)
Success #stdin #stdout 0.14s 12248KB
stdin
tTFk"*+,-7;=?GHIKVWXYhiklnvwx"C-Ck7
stdout
tTFk"*+,-7;=?GHIKVWXYhiklnvwx"C-Ck7
_print("\n",tail(T))
for k in "*+,-7;=?GHIKVWXYhiklnvwx":
 _print("\n",_chr(minus(_chr(k),7)))
==================================================
9
#
$
%
&
0
4
6
8
@
A
B
D
O
P
Q
R
a
b
d
e
g
o
p
q