fork download
  1. ######################################################################
  2. # gibberish.py - python gibberish interpreter
  3. #
  4. # possible inconsistencies:
  5. # - q(3) stops the entire program, not just the currently running
  6. # piece of code, even when called from an exec'ed string
  7. # (I took "currently-running program" to mean the entire program)
  8. #
  9. # - not in specification, but unfinished official interpreter seems to
  10. # do it this way and/or given examples seem to rely on this:
  11. # - trying to copy/move/pop past the stack results in a run-time error
  12. # - numbers are floating point
  13. # - numbers used for stack indexes are rounded down
  14. # - type mismatches are run-time errors
  15. # - the stack and selected instruction set are global across "subroutines"
  16. # - pushing a string constant [like this] counts as one instruction
  17. # - using x(0) to set the instruction set to one that doesn't exist
  18. # is a run-time error
  19. #
  20. # - neither in specification or in unfinished official interpreter
  21. # - but seems logical:
  22. # - exec'ing a string of malformed code is a run-time error
  23. #
  24. # - numbers used for string indexes are rounded down
  25. # (like the stack)
  26. #
  27. # - reading past EOF returns -1 (char) or "" ([]?) (str)
  28. # (most other esolangs return -1 on EOF)
  29. #
  30. # - a line read from stdin still has its newline attached
  31. # (to distinguish [\n] (=empty line) from [] (=EOF),
  32. # also this is how almost everyone else does it)
  33. #
  34. # - logical operators consider 0.0000... to be false and everything
  35. # else to be true
  36. #
  37. # - and I have no idea how else to do it:
  38. # - lshift and rshift convert their arguments to ints first
  39. # (can't shift something, say, 2.3 bits to the left,
  40. # and bitshifting IEEE-754 floating point values seems monumentally
  41. # useless in comparison with bitshifting ints)
  42. #
  43. # - arguments to binary and/or are converted to ints first
  44. # (fits with lshift/rshift)
  45. #
  46. ##########################################
  47.  
  48.  
  49. from operator import *
  50. import sys
  51.  
  52. # types used for strings and numbers
  53. STRT = str
  54. NUMT = float
  55.  
  56. ### helper functions ###
  57. def typedesc(type):
  58. if type==STRT: return "string"
  59. if type==NUMT: return "number"
  60. return "invalid (%s)"%str(type)
  61.  
  62. # make error string
  63. def errstr(code, error, position):
  64. amt = max(0, position - 5)
  65. prev = code[amt : position]
  66. if amt!=0: prev = "..." + prev
  67.  
  68. amt = min(position + 6, len(code))
  69. next = code[position+1 : amt]
  70. if amt!=len(code): next += "..."
  71.  
  72. return "%s at position %d (%s ->%s<- %s)" % \
  73. (error, position, prev, code[position], next)
  74.  
  75. # make error string with list of items
  76. def items_errstr(code, error, position):
  77. prev = ",".join([str(c) for c in code[max(0, position - 5) : position]])
  78. next = ",".join([str(c) for c in code[position+1:position+6]])
  79.  
  80. return "%s at ip %s (%s ->%s<- %s)" % \
  81. (error, position, prev, str(code[position]), next)
  82.  
  83.  
  84. # return ordinal suffix (i.e. 1 => st and 4 => th)
  85. def ordsuffix(num):
  86. if (int(num) % 100 in (11,12,13)): return "th"
  87. if (int(num) % 10 == 1): return "st"
  88. if (int(num) % 10 == 2): return "nd"
  89. if (int(num) % 10 == 3): return "rd"
  90. return "th"
  91.  
  92. #####
  93.  
  94. # stack class
  95. class Stack:
  96.  
  97. stack = None
  98.  
  99. def __init__(self, copystack=None):
  100. if copystack:
  101. self.stack = copystack[:]
  102. else:
  103. self.stack = []
  104.  
  105.  
  106. def push(self, value):
  107. # make sure all numbers use the same type
  108. if type(value) in [bool, int]: value = NUMT(value)
  109. self.stack.append(value)
  110.  
  111. def pop(self):
  112. return self.stack.pop()
  113.  
  114. def swapn(self, n):
  115. n=int(n)
  116. foo = self.stack[-1-n]
  117. self.stack[-1-n] = self.stack[-1]
  118. self.stack[-1] = foo
  119.  
  120. swap = lambda s: s.swapn(1)
  121. swap2 = lambda s: s.swapn(2)
  122. swap3 = lambda s: s.swapn(3)
  123.  
  124. def copy(self, n):
  125. n=int(n)
  126. self.stack.append(self.stack[-1-n])
  127.  
  128. dup = lambda s: s.copy(0)
  129.  
  130. def move(self, n):
  131. n=int(n)
  132. self.stack.append(self.stack[-1-n])
  133. del self.stack[-1-n]
  134.  
  135. def insert(self, n, value):
  136. n=int(n)
  137. self.stack.insert(-n-1, value)
  138.  
  139. # 'inverted' copy/move = copy/move counting from the bottom of the stack
  140. def invcopy(self, n):
  141. n=int(n)
  142. self.stack.append(self.stack[n])
  143.  
  144. def invmove(self, n):
  145. n=int(n)
  146. self.stack.append(self.stack[n])
  147. del self.stack[n]
  148.  
  149. # getitem/setitem/len
  150. def __getitem__(self, n):
  151. return self.stack[-1-n]
  152. def __setitem__(self, n, val):
  153. self.insert(n, val)
  154. def __len__(self):
  155. return len(self.stack)
  156.  
  157.  
  158. # parser
  159. class Parser:
  160. CONSTANT, COMMAND = range(2)
  161.  
  162. # program will be made up of a list of these
  163. class Item:
  164. def __init__(self, type, value):
  165. if type in (Parser.CONSTANT, Parser.COMMAND):
  166. self.type=type
  167. self.value=value
  168. else: raise TypeError, "item type invalid: %d" % type
  169.  
  170. def __str__(self):
  171. if self.type==Parser.COMMAND: return self.value
  172. elif self.type==Parser.CONSTANT:
  173. if isinstance(self.value, str): return "[%s]" % self.value
  174. else: return str(self.value)
  175.  
  176. # takes string, returns list of items
  177. @staticmethod
  178. def parse(string):
  179. items = []
  180. i = 0
  181. while i<len(string):
  182. # numbers
  183. if string[i] in "0123456789":
  184. items.append(Parser.Item(Parser.CONSTANT, NUMT(string[i])))
  185. # strings
  186. elif string[i] == '[':
  187. curstr = ''
  188. lvl = 1
  189. while lvl>0:
  190. i += 1
  191. if (i>=len(string) and lvl>0):
  192. raise ValueError(errstr(string, "unterminated [", i-1))
  193. if string[i] == ']': lvl -= 1
  194. elif string[i] == '[': lvl += 1
  195. if (lvl!=0): curstr += string[i]
  196. items.append(Parser.Item(Parser.CONSTANT, curstr))
  197. # whitespace is ignored
  198. elif string[i] in ' \n\t': pass
  199. # ] without [ == error
  200. elif string[i] == ']':
  201. raise ValueError(errstr(string, "] without [", i))
  202. # not one of these == command
  203. else:
  204. items.append(Parser.Item(Parser.COMMAND, string[i]))
  205. i += 1
  206.  
  207. return items
  208.  
  209. class Interpreter:
  210.  
  211. # exception to be caught if something goes wrong with the code
  212. class CodeError(Exception): pass;
  213.  
  214. world = None
  215. code = None
  216. stack = None
  217. ip = 0
  218. activeset = 0
  219. sets = None # command sets, see init
  220. parent = None
  221.  
  222. def __init__(self,world,code,stack=None,ip=0,activeset=0,parent = None):
  223. self.world = world
  224. self.code = code
  225. if stack==None:
  226. self.stack = Stack()
  227. else:
  228. self.stack = stack
  229. self.ip = ip
  230. self.activeset = activeset
  231. self.parent = None
  232.  
  233. s=self # makes the huge list less long
  234. s.sets = [
  235. # instruction set 0 #
  236. { 'e' : s.activateSet1,
  237. 'f' : s.activateSet2,
  238. 'g' : s.activateSet3,
  239. 'x' : s.cActivateSet,
  240. 'j' : s.cGetSet,
  241. 'z' : s.cNop
  242. },
  243. # instruction set 1 #
  244. { 'u' : s.cDuplicate,
  245. 'a' : s.cAdd,
  246. 's' : s.cSub,
  247. 'm' : s.cMul,
  248. 'd' : s.cDiv,
  249. 't' : s.cToStr,
  250. 'i' : s.cToNum,
  251. 'c' : s.cConcatenate,
  252. 'o' : s.cOutput,
  253. 'q' : s.cInlineOutput,
  254. 'n' : s.cReadChar,
  255. 'l' : s.cReadLine,
  256. 'h' : s.cSubstring,
  257. 'y' : s.cStrLen,
  258. 'v' : s.cDiscard,
  259. 'p' : s.cCopy,
  260. 'k' : s.cMove,
  261. 'r' : s.cStackSize
  262. },
  263. # instruction set 2 #
  264. { 'u' : s.cGT,
  265. 'd' : s.cLT,
  266. 's' : s.cSkip,
  267. 't' : s.cSkipTwo,
  268. 'p' : s.cInsert,
  269. 'a' : s.cAnd,
  270. 'o' : s.cOr,
  271. 'n' : s.cNot,
  272. 'c' : s.cExec,
  273. 'w' : s.cWhile,
  274. 'q' : s.cEqual,
  275. 'l' : s.cLshift,
  276. 'r' : s.cRshift
  277. },
  278. # instruction set 3 #
  279. { 'q' : s.cQuit,
  280. 'w' : s.cRecallWhile,
  281. 'n' : s.cIsNumber,
  282. 's' : s.cIsString,
  283. 'a' : s.cBinAnd,
  284. 'o' : s.cBinOr,
  285. 'i' : s.cInteger,
  286. 'm' : s.cMod,
  287. 't' : s.cToChar,
  288. 'c' : s.cCharAt,
  289. 'r' : s.cReplaceChar,
  290. 'p' : s.cInvertedCopy,
  291. 'k' : s.cInvertedMove,
  292. 'b' : s.cSwap,
  293. 'd' : s.cSwap2,
  294. 'h' : s.cSwap3,
  295. }
  296. ]
  297.  
  298. # step function
  299. # returns True if there are more steps, False if not.
  300. def step(self):
  301. if self.ip >= len(self.code):
  302. return False # at the end of the code
  303.  
  304. curitem = self.code[self.ip]
  305.  
  306. # if there's a trace variable defined and true, give a trace
  307. try:
  308. global trace
  309. if trace:
  310. print "\x1b[7m",
  311. print "trace: cur=", self.ip, str(curitem), "set=", self.activeset, "stack=", self.stack.stack,
  312. print "\x1b[0m"
  313. except: pass
  314.  
  315. if curitem.type == Parser.CONSTANT:
  316. # this is a constant value, push it
  317. self.sf(self.stack.push, [curitem.value])
  318. else:
  319. # it's a command
  320. if curitem.value in self.sets[0]:
  321. # command set 0 has priority above everything
  322. self.sets[0][curitem.value]()
  323. else:
  324. # get it from selected set
  325. if self.activeset<0 or self.activeset>=len(self.sets):
  326. # selected set is invalid
  327. raise Interpreter.CodeError(self.err("no such set: %d",
  328. self.activeset))
  329. else:
  330. if not curitem.value in self.sets[self.activeset]:
  331. #invalid command for selected set
  332. raise Interpreter.CodeError(self.err(
  333. "set %d has no command '%s'"%( self.activeset, \
  334. curitem.value)))
  335. else:
  336. #yay it's good, run it
  337. try:
  338. self.sets[self.activeset][curitem.value]()
  339. except ZeroDivisionError, complaint:
  340. raise Interpreter.CodeError(self.err(
  341. "division by zero (%s)"%complaint))
  342. self.ip += 1
  343. return True
  344.  
  345. # make an error string with error & current state
  346. def err(self, error):
  347. return items_errstr(self.code, error, self.ip)
  348.  
  349.  
  350. # call stack function and catch its errors
  351. def sf(self, func, args):
  352. rv=None
  353. try: rv = func(*args)
  354. except IndexError, complaint:
  355. raise Interpreter.CodeError(self.err("stack error (%s)"%complaint))
  356. return rv
  357.  
  358. # raise a type error
  359. def raiseTypeErr(self, expected, got):
  360. raise Interpreter.CodeError(
  361. self.err("wrong type: expected %s instead of %s" % \
  362. (typedesc(expected), typedesc(got))))
  363.  
  364. ### commands ###
  365.  
  366. # convert a function f(a) into push(f(pop())) + type checking
  367. def unarystackf(self, f, ntype=None, pushresult=True):
  368. def stackfunc():
  369. a=self.sf(self.stack.pop,[])
  370. if ntype and not isinstance(a,ntype):
  371. self.raiseTypeErr(ntype, type(a))
  372.  
  373. res = f(a)
  374. if pushresult: self.sf(self.stack.push,[res])
  375. return stackfunc
  376.  
  377. # convert a function f(a,b) into b=pop(),a=pop(),push(f(a,b)) + type checking
  378. def binstackf(self, f, atype=None, btype=None, pushresult=True):
  379. def stackfunc():
  380. b = self.sf(self.stack.pop,[])
  381. a = self.sf(self.stack.pop,[])
  382. if btype and not isinstance(b, btype):
  383. self.raiseTypeErr(btype, type(b))
  384. if atype and not isinstance(a, atype):
  385. self.raiseTypeErr(atype, type(a))
  386. res=f(a,b)
  387. if pushresult: self.sf(self.stack.push,[res])
  388. return stackfunc
  389.  
  390. # and now one with three arguments f(a,b,c)
  391. def tristackf(self, f, atype=None, btype=None, ctype=None, pushresult=True):
  392. x = self.sf
  393. y = self.stack.pop
  394. def stackfunc():
  395. c = x(y,[])
  396. b = x(y,[])
  397. a = x(y,[])
  398. if ctype and not isinstance(c,ctype):
  399. self.raiseTypeErr(ctype, type(c))
  400. if btype and not isinstance(b,btype):
  401. self.raiseTypeErr(btype, type(b))
  402. if atype and not isinstance(a,atype):
  403. self.raiseTypeErr(atype, type(a))
  404. res = f(a,b,c)
  405. if pushresult: self.sf(self.stack.push,[res])
  406. return stackfunc
  407.  
  408. ## set 0 ##
  409. def cActivateSet(self):
  410. set = self.sf(self.stack.pop,[])
  411. if not isinstance(set, NUMT):
  412. raise Interpreter.CodeError(
  413. self.err("wrong type: expected number"))
  414. if len(self.sets)<=int(set) or int(set)<0:
  415. raise Interpreter.CodeError(
  416. self.err("no instruction set %d exists" % set))
  417. self.activeset = int(set)
  418.  
  419. def activateSet1(self): self.activeset = 1
  420. def activateSet2(self): self.activeset = 2
  421. def activateSet3(self): self.activeset = 3
  422.  
  423. def cGetSet(self):
  424. self.sf(self.stack.push,[self.activeset])
  425.  
  426. def cNop(self): pass
  427.  
  428. ## set 1 ##
  429. def cDuplicate(self): self.sf(self.stack.dup,[])
  430. def cAdd(self): self.binstackf(add, NUMT, NUMT)()
  431. def cSub(self): self.binstackf(sub, NUMT, NUMT)()
  432. def cMul(self): self.binstackf(mul, NUMT, NUMT)()
  433. def cDiv(self): self.binstackf(div, NUMT, NUMT)()
  434.  
  435. # shortest representation of value in string
  436. def v2str(self, n):
  437. if n=="": return n
  438. if isinstance(n,str) and (n[0]==' ' or n[-1]==' '): return n
  439. try: v=str(int(n))
  440. except:
  441. try: v=str(float(n))
  442. except: v=str(n)
  443. return v
  444.  
  445. def cToStr(self): self.unarystackf(self.v2str, NUMT)()
  446. def cToNum(self):
  447. def tonum(s):
  448. # return a number from the string if possible,
  449. # if not a valid number then push the string back
  450. try: n = NUMT(s)
  451. except ValueError: n = s
  452. return n
  453. self.unarystackf(tonum, STRT)()
  454. def cConcatenate(self): self.binstackf(add, STRT, STRT)()
  455. def cOutput(self):
  456. self.unarystackf(
  457. (lambda s:self.world.out(self.v2str(s)+"\n")),pushresult=False)()
  458. def cInlineOutput(self):
  459. self.unarystackf(
  460. (lambda s:self.world.out(self.v2str(s))),pushresult=False)()
  461. def cReadChar(self):
  462. self.sf(self.stack.push, [NUMT(self.world.readchar())])
  463. def cReadLine(self):
  464. self.sf(self.stack.push, [self.world.readline()])
  465.  
  466. def cSubstring(self):
  467. self.tristackf((lambda strn,start,end:strn[int(start):int(end)]),
  468. STRT,NUMT,NUMT)()
  469. def cStrLen(self): self.unarystackf(len, STRT)()
  470. def cDiscard(self): self.sf(self.stack.pop, [])
  471. def cCopy(self): self.unarystackf(self.stack.copy, NUMT, False)()
  472. def cMove(self): self.unarystackf(self.stack.move, NUMT, False)()
  473. def cStackSize(self):
  474. self.sf(self.stack.push, NUMT(len(self.stack)))
  475.  
  476. ## set 2 ##
  477. def cGT(self): self.binstackf(gt)()
  478. def cLT(self): self.binstackf(lt)()
  479. def cSkip(self):
  480. def skip(n): self.ip += int(n)
  481. self.unarystackf(skip,NUMT,False)()
  482. def cSkipTwo(self):
  483. def skip2(n): self.ip += int(n*2)
  484. self.unarystackf(skip2,NUMT,False)()
  485. def cInsert(self):
  486. def insert(thing, where): self.stack.insert(where, thing)
  487. self.binstackf(insert, btype=NUMT, pushresult=False)()
  488. def cAnd(self): self.binstackf(lambda a,b:NUMT(a and b and 1 or 0))()
  489. def cOr(self): self.binstackf(lambda a,b:NUMT((a or b) and 1 or 0))()
  490. def cNot(self): self.unarystackf(lambda a:NUMT(not a and 1 or 0))()
  491.  
  492.  
  493. def execstr(self, codestr):
  494. self.world.recurse(self, codestr)
  495.  
  496. def cExec(self): self.unarystackf(self.execstr,STRT,False)()
  497. def cWhile(self):
  498. while True:
  499. # pop a value
  500. val = self.sf(self.stack.pop,[])
  501. if val:
  502. # pop code, run it
  503. code = self.sf(self.stack.pop,[])
  504. if not isinstance(code, STRT):
  505. self.raiseTypeErr(STRT, type(code))
  506. else:
  507. self.execstr(code)
  508. else:
  509. break
  510. def cEqual(self): self.binstackf(eq)()
  511. def cLshift(self): self.binstackf((lambda a,b:int(a)<<int(b)),NUMT,NUMT)()
  512. def cRshift(self): self.binstackf((lambda a,b:int(a)>>int(b)),NUMT,NUMT)()
  513.  
  514. ## set 3 ##
  515.  
  516. def cQuit(self): self.world.quit()
  517. def cRecallWhile(self):
  518. # pop code
  519. code = self.sf(self.stack.pop,[])
  520. if not isinstance(code, STRT): self.raiseTypeErr(STRT, type(code))
  521. # while
  522. while self.sf(self.stack.pop,[]):
  523. self.execstr(code)
  524.  
  525. def cIsNumber(self):
  526. self.unarystackf(lambda v: isinstance(v,NUMT) and 1 or 0)()
  527. def cIsString(self):
  528. self.unarystackf(lambda v: isinstance(v,STRT) and 1 or 0)()
  529. # binary and/or use integers again
  530. def binop(self,op): return lambda a,b: op(int(a), int(b))
  531. def cBinAnd(self): self.binstackf(self.binop(and_), NUMT, NUMT)()
  532. def cBinOr(self): self.binstackf(self.binop(or_), NUMT, NUMT)()
  533. def cInteger(self): self.unarystackf(int, NUMT)()
  534. def cMod(self): self.binstackf(mod, NUMT, NUMT)()
  535. def cToChar(self): self.unarystackf((lambda k:chr(int(k)%256)), NUMT)()
  536. def cCharAt(self):
  537. def charat(strn, idx):
  538. idx=int(idx)
  539. if (idx<0 or idx>=len(strn)):
  540. # nowhere in the spec it says python-style negative indexes
  541. # are allowed...
  542. raise Interpreter.CodeError(self.err(
  543. ("index out of bounds: tried to get %d-char string's " +\
  544. "%d%s character") % (len(strn), idx, ordsuffix(idx)) ))
  545. return NUMT(ord(strn[idx]))
  546. self.binstackf(charat, STRT, NUMT)()
  547. def cReplaceChar(self):
  548. def replacechar(strn, idx, repl):
  549. idx=int(idx)
  550. if (idx<0 or idx>=len(strn)):
  551. raise Interpreter.CodeError(self.err(
  552. ("index out of bounds: tried to change %d-char string's "+\
  553. "%d%s character") % (len(strn), idx, ordsuffix(idx)) ))
  554. return strn[:idx] + repl[0] + strn[idx+1:]
  555. self.tristackf(replacechar, STRT, NUMT, STRT)()
  556. def cInvertedCopy(self):
  557. self.unarystackf(self.stack.invcopy, NUMT, False)()
  558. def cInvertedMove(self):
  559. self.unarystackf(self.stack.invmove, NUMT, False)()
  560. def cSwap(self): self.sf(self.stack.swap, [])
  561. def cSwap2(self): self.sf(self.stack.swap2, [])
  562. def cSwap3(self): self.sf(self.stack.swap3, [])
  563.  
  564.  
  565.  
  566. # class World
  567. # handles stepping of interpreter and input and output
  568. # World().quit() -> ends program
  569. # World().out("blah") -> stdout.write("blah")
  570. # World().readchar() -> read 1 char from stdin
  571. # World().readline() -> read 1 line from stdin
  572.  
  573. class World:
  574. interpreter = None
  575.  
  576. def __init__(self, codestr, prevint=None):
  577. # parse the code
  578.  
  579. self.code = Parser.parse(codestr)
  580.  
  581.  
  582. if prevint:
  583. self.interpreter = Interpreter( self, self.code,
  584. parent=prevint,
  585. stack=prevint.stack,
  586. activeset=prevint.activeset )
  587. else:
  588. self.interpreter = Interpreter( self, self.code )
  589.  
  590. # run the interpreter until it fails or quits
  591. def run(self):
  592.  
  593. while self.interpreter.step(): pass
  594.  
  595.  
  596. # the interpreter calls these for program control
  597. def quit(self):
  598. sys.exit(0)
  599.  
  600. def out(self, string):
  601. sys.stdout.write(string)
  602.  
  603. def readchar(self):
  604. v = sys.stdin.read(1)
  605. if not v: return -1
  606. else: return ord(v)
  607.  
  608. def readline(self):
  609. return sys.stdin.readline()
  610.  
  611. def recurse(self, prevint, codestr):
  612. try:
  613. # run the sub-interpreter in its own world
  614. w = World(codestr, prevint=prevint)
  615. w.run()
  616. except ValueError, complaint:
  617. # parsing failed
  618. raise Interpreter.CodeError(prevint.err(
  619. "exec: parsing of string failed: \n\t%s\n" % complaint))
  620. except Interpreter.CodeError, complaint:
  621. # run-time error in code
  622. raise Interpreter.CodeError(prevint.err(
  623. "exec: sub-interpreter runtime error: \n\t%s\n" % complaint))
  624. except Exception, complaint:
  625. # something else went wrong
  626. raise Interpreter.CodeError(prevint.err(
  627. "exec: sub-interpreter failed: %s" % str(complaint)))
  628.  
  629.  
  630. ###############################################################
  631.  
  632. # start the program
  633. def main(argv):
  634. global trace
  635. if False:
  636. print "usage: %s [-trace] filename | -" % argv[0]
  637. sys.exit(2)
  638. else:
  639. try:
  640. fname="-"
  641. trace=False
  642. if fname=='-': f = sys.stdin
  643. else: f = file(fname, 'r')
  644. except:
  645. print "Can't open file %s" % argv[1]
  646. sys.exit(3)
  647. code = f.read()
  648. f.close()
  649.  
  650. try:
  651. w = World(code)
  652. w.run()
  653. except Interpreter.CodeError, complaint:
  654. print "Run-time error: %s" % complaint
  655. except ValueError, complaint:
  656. print "Parse error: %s" % complaint
  657. except Exception, complaint:
  658. print "An exception occured: %s" % complaint
  659.  
  660. if __name__=="__main__": main(sys.argv)
Success #stdin #stdout 0.08s 65708KB
stdin
2z7em2z4zmumagt[ABC]
1gc3eua1ua5mm4aesum5uu2ammm[BCD]
1gce6z2aumsg2z1oem5m[2z7em[K]0gc[A]0c1ess]
fc1xm3sm2smgbeqq[ E]q[$GC34CV9]6gc1x2d
[9z1fl[5ez1fl1ea]fc[5ez1fl1ea]2xcemm]fcze1x1am1fl7ezmo
stdout
N4755100 E1311758