Posted by: dresstosurvive | December 21, 2007

Six Function Calculator in One Line of Python

Usage Instructions

  • Copy
  • Paste
  • Press Enter
  • Type one simple expression (i.e. 2 + 2 or -42 ^ 16) per line
  • Press Ctrl-D (EOL) to evaluate all the expressions

print map((lambda environ:environ[0]['ops'][(environ[0]['re'].match(environ[1]).group(’op’)or’+')](int((environ[0]['re'].match(environ[1]).group(’lvalue’)or 0)),int((environ[0]['re'].match(environ[1]).group(’rvalue’)or 0)))),(environ for environ in(({’ops’:{’+':__import__(”operator”).add,’-':__import__(”operator”).sub,’*':__import__(”operator”).mul,’^':pow,’%':__import__(”operator”).mod,’/':__import__(”operator”).div},’re’:__import__(”re”).compile(r’^(?P[\+\-]{,1}(\s*)\d+)(\s*)((?P[\+\-\*\^\%/])(\s*)(?P[\+\-]{,1}(\s*)\d+)(\s*)){,1}$’)},line)for line in __import__(”sys”).stdin.readlines())))

Commented Version

# Here, we print out the final list of evaluated expressions
# returned by mapping a lambda over a generator comprehension
print map(
    # This lambda evaluates one line
    (lambda environ:
        # Environ is a tuple containing the tools and the current line
        environ[0]['ops']
            # This gets the right operation to perform
            [(environ[0]['re'].match(environ[1]).group(’op’) or ‘+’)](
                # Grab our lvalue and our rvalue from the expression
                int((environ[0]['re'].match(environ[1]).group(’lvalue’) or 0)),
                int((environ[0]['re'].match(environ[1]).group(’rvalue’) or 0))
           &nbsp ;)
    ),
    # This is a generator comprehension returning the tuple
    (environ for environ in (
        # The first item of the tuple is a dict containing useful modules
        # and “variables” such as the regex matcher
        ( {
                # Available operations, stolen from the operator module
                ’ops’: {
                            ’+': __import__(”operator”).add,
                            ’-': __import__(”operator”).sub,
                            ’*': __import__(”operator”).mul,
                            ’^': pow,
                            ’%': __import__(”operator”).mod,
                            ’/': __import__(”operator”).div
                        },
                # The regex matcher to split up an expression into groups
                # Tweaking the last {,1} into {,} or * would allow you to parse
                # more complicated expressions, albeit requiring a change to
                # the lambda
                ’re’: __import__(”re”).compile(r’^(?P[\+\-]{,1}(\s*)\d+)(\s*)((?P[\+\-\*\^\%/])(\s*)(?P[\+\-]{,1}(\s*)\d+)(\s*)){,1}$’)
            },
            # The current line
            line)
        # Grab all lines until the user hits Ctrl-D (EOF)
        for line in __import__(”sys”).stdin.readlines())
   &nbsp ;)
)

Responses

2 problems:
- your code will “leak” memory as map returns a list not a iterator and will collect all the iterations
- import overhead on each iteration (acceptable though)

solutions:
- __import__(”itertools”).imap instead of map, though you’l have to loop it. eg, use itertools.count for a purely functional approach

- wrap the imports in another “environ”. eg:
apply(
lambda a,b,c:
# we have the imports bound to names here
,
(__import__(”a”),
__import__(”b”),
__import__(”c” ;)
)
)

Somehow i missed the point. Probably lost in translation :) Anyway … nice blog to visit.

cheers, Bolero!

Leave a response

Your response:

Categories