Enable Javascript in your browser and then refresh this page, for a much enhanced experience.
Sometimes Python is not enough solution in Uncategorized category for Funny Addition by HonzaKral
# inspired by http://norvig.com/lispy.html Thanks!
import re
from operator import add
def atom(s):
try:
return int(s)
except ValueError:
return s
def tokenize(program):
" Tokenize the input lisp program. "
return list(filter(lambda s: s.strip(), re.split(r'(\W)', program)))
def tokens_to_lists(tokens):
" Convert token list into properly nested python lists. Assume no syntax errors. "
t = tokens.pop(0)
if t == '(':
out = []
while tokens[0] != ')':
out.append(tokens_to_lists(tokens))
tokens.pop(0)
return out
else:
return atom(t)
def parse(program):
" Parse Lisp code from text to python lists. "
return tokens_to_lists(tokenize(program))
class ArgsMapping(object):
" Mapping to be used within user-defined functions to map arguments to values from global state. "
def __init__(self, signature, params, state):
self.local_state = dict(zip(signature, params))
self.global_state = state
def __contains__(self, name):
return name in self.local_state or name in self.global_state
def __getitem__(self, name):
if name in self.local_state:
return self.local_state[name]
return self.global_state[name]
def eval_lisp(program, state):
" Evaluate a single lisp expression. "
if isinstance(program, list):
cmd, *args = program
if cmd == 'define':
state[args[0]] = eval_lisp(args[1], state)
return
elif cmd == 'lambda':
signature, definition = args
return lambda *a: eval_lisp(definition, ArgsMapping(signature, a, state))
elif cmd in state:
args = list(map(lambda p: eval_lisp(p, state), args))
return state[cmd](*args)
# no builtin or user-defined func, must be a list of atoms
return list(map(lambda p: eval_lisp(p, state), program ))
# variable
elif program in state:
return state[program]
# atom
return program
def lisp(program, state):
program = parse(program)
result = eval_lisp(program, state)
return result
def initial_state():
" Starting set of builtin functions. "
return {
'+': add,
}
def checkio(data):
" Sometimes Python is not powerful enough for some problems. "
a, b = data
state = initial_state()
lisp('(define sum (lambda (x y) (+ x y)))', state)
lisp('(define a %d)' % a, state)
lisp('(define b %d)' % b, state)
return lisp('(sum a b)', state)
if __name__ == '__main__':
assert checkio([5, 5]) == 10, 'First'
assert checkio([7,1]) == 8, 'Second'
print('All ok')
Nov. 27, 2012
Comments: