Sinisterly
Bronze Challenge (1) CLI Calculator - Printable Version

+- Sinisterly (https://sinister.ly)
+-- Forum: Coding (https://sinister.ly/Forum-Coding)
+--- Forum: Python (https://sinister.ly/Forum-Python)
+--- Thread: Bronze Challenge (1) CLI Calculator (/Thread-Bronze-Challenge-1-CLI-Calculator)

Pages: 1 2


Challenge (1) CLI Calculator - m0dem - 12-14-2015

In this Python challenge, you will attempt to a make a CLI (Command Line Interface) calculator. Basically, what that means is: a calculator that can interpret simple math equations (e.g. 2+3-5*6 => -25). It must correctly compute addition, subtraction, multiplication, and division. It sounds simple, but it can get a little complicated at times. You cannot use eval() or anything like that, you MUST parse everything yourself.
I am really interested in what you come up with. Good luck! Wink
151st post! Biggrin


RE: Challenge (1) CLI Calculator - m0dem - 12-14-2015

Done!
Code:
import re

def isMore(tokens):
    for t in tokens:
        if t == "*" or t == "/":
            return True

    return False

def lex(equation):
    # remove all the whitespaces from the equation string
    equation = equation.replace(" ", "")
    return re.findall("[0-9]+|[\+, \-, \*, \/]", equation)
    
def evaluate1(tokens, isOrigin = False):
    for i in range(0, len(tokens)):
        if tokens[i] == "*":
            a = int(tokens[i - 1]) * int(tokens[i + 1])
            tokens = tokens[:i - 1]
            tokens.insert(i, a)
            break

        elif tokens[i] == "/":
            a = int(tokens[i - 1]) / int(tokens[i + 1])
            tokens = tokens[:i - 1]
            tokens.insert(i, a)
            break

    if isMore(tokens):
        tokens = evaluate1(tokens)

    return tokens

def evaluate2(tokens, isOrigin = False):  
    if tokens[1] == "+":
        a = int(tokens[0]) + int(tokens[2])
        tokens = tokens[3:]
        tokens.insert(0, a)
            
    elif tokens[1] == "-":
        a = int(tokens[0]) - int(tokens[2])
        tokens = tokens[3:]
        tokens.insert(0, a)

    if len(tokens) > 1:
        tokens = evaluate2(tokens)

    if isOrigin:
        return tokens[0]

    else:
        return tokens

equation = raw_input("Enter an equation: ")
tokens = lex(equation)
tokens = evaluate1(tokens, isOrigin = True)
print(evaluate2(tokens, isOrigin = True))

And no, I didn't search up anything about this type of calculator for help.


RE: Challenge (1) CLI Calculator - m0dem - 12-15-2015

Well, since my last code was just a lame hack... I re-wrote it to make it much neater and more professional.
No recursion this time... too clunky.
Code:
import re

def lex(equation):
    # remove all the whitespaces from the equation string
    equation = equation.replace(" ", "")
    return re.findall("[0-9]+|[\+, \-, \*, \/]", equation)

def evalMulDiv(tokens):
    i = 0
    while i < len(tokens):
        if tokens[i] == "*":
            tokens = tokens[:i - 1] + [int(tokens[i - 1]) * int(tokens[i + 1])] + tokens[i + 2:]
            i -= 2

        elif tokens[i] == "/":
            tokens = tokens[:i - 1] + [int(tokens[i - 1]) / int(tokens[i + 1])] + tokens[i + 2:]
            i -= 2

        i += 1

    return tokens

def evalAddSub(tokens):
    i = 0
    while i < len(tokens):
        if tokens[i] == "+":
            tokens = tokens[:i - 1] + [int(tokens[i - 1]) + int(tokens[i + 1])] + tokens[i + 2:]
            i -= 2

        elif tokens[i] == "-":
            tokens = tokens[:i - 1] + [int(tokens[i - 1]) - int(tokens[i + 1])] + tokens[i + 2:]
            i -= 2

        i += 1

    return tokens

def calc(equation):
    tokens = lex(equation)
    tokens = evalMulDiv(tokens)
    return int(evalAddSub(tokens)[0])

equation = raw_input("> ")
print(calc(equation))

@Megan! You try! Smile
I think I will make a guide on CLI calculators soon. (possibly non-language specific -- pseudocode)


RE: Challenge (1) CLI Calculator - meow - 12-15-2015

I'm new to Python and don't really know how your script works. Mine sucks but I did my best. Don't know if this is what you were looking for or not.

Code:
def a(n1,n2):
    return float(n1 + n2)
def s(n1,n2):
    return float(n1 - n2)
def m(n1,n2):
    return float(n1 * n2)
def d(n1,n2):
    return float(n1 / n2)
c = raw_input("Operation? (add, sub, mult, div): ")
n1 = float(raw_input("Enter the first number: "))
n2 = float(raw_input("Enter the second number: "))

if c == "add":
    print(a(n1,n2))
elif c == "sub":
    print(s(n1,n2))
elif c == "mult":
    print(m(n1,n2))
elif c == "div":
    print(d(n1,n2))
else:
    print("The operation you entered does not exist.")



RE: Challenge (1) CLI Calculator - m0dem - 12-15-2015

(12-15-2015, 04:22 AM)meow Wrote: I'm new to Python and don't really know how your script works. Mine sucks but I did my best. Don't know if this is what you were looking for or not.

Code:
def a(n1,n2):
    return float(n1 + n2)
def s(n1,n2):
    return float(n1 - n2)
def m(n1,n2):
    return float(n1 * n2)
def d(n1,n2):
    return float(n1 / n2)
c = raw_input("Operation? (add, sub, mult, div): ")
n1 = float(raw_input("Enter the first number: "))
n2 = float(raw_input("Enter the second number: "))

if c == "add":
    print(a(n1,n2))
elif c == "sub":
    print(s(n1,n2))
elif c == "mult":
    print(m(n1,n2))
elif c == "div":
    print(d(n1,n2))
else:
    print("The operation you entered does not exist.")

Well, that's not exactly what I was looking for. But it is okay; your did your best! Cool on you for learning Python though. Smile
Basically, what I meant by a CLI calculator is that it takes a string such as "2 +8/2 * 4" and outputs the correct number (18). (note the use of operator precedence -- I do not require parentheses though)
Thanks for trying!!! Wink

NOTE: Windows calc.exe doesn't even use operator precedence!?!?!


RE: Challenge (1) CLI Calculator - Nil - 12-15-2015

If you could explain your code that'd be cool, especially the eval functions.

Why tokens?


RE: Challenge (1) CLI Calculator - m0dem - 12-15-2015

(12-15-2015, 08:55 AM)God Wrote: If you could explain your code that'd be cool, especially the eval functions.

Why tokens?

Ok, I will make a separate guide on this.
Be looking for it. Smile

I've finished!
https://www.sinister.ly/Thread-Tutorial-How-My-CLI-Calculator-Works
Enjoy! Wink


RE: Challenge (1) CLI Calculator - Inori - 12-16-2015

J:
Code:
".;2}input

Python (supports addition, subtraction, multiplication, division, exponents, and modulus):
Code:
import re
import operator as op

ops={'+': op.add,'-': op.sub,'*': op.mul,'/': op.div,'^': op.pow,'%': op.mod}

while 1:
    e=raw_input('} ')
    for i in re.finditer('[\+,\-,\*,\/,\^,\%]',e): print ops[i.group()](int(e[:i.start()]),int(e[i.start()+1:]))



RE: Challenge (1) CLI Calculator - m0dem - 12-16-2015

(12-16-2015, 03:30 PM)Nevermore Wrote: J:
Code:
".;2}input

Python (supports addition, subtraction, multiplication, division, exponents, and modulus):
Code:
import re
import operator as op

ops={'+': op.add,'-': op.sub,'*': op.mul,'/': op.div,'^': op.pow,'%': op.mod}

while 1:
    e=raw_input('} ')
    for i in re.finditer('[\+,\-,\*,\/,\^,\%]',e): print ops[i.group()](int(e[:i.start()]),int(e[i.start()+1:]))
Cool! Really compact code.
But.. your code can only do one operation per input. (you can't do "5+5*5" or "4*3-2*3")
You should be able to do an equation of arbitrary length.


RE: Challenge (1) CLI Calculator - Inori - 12-16-2015

(12-16-2015, 03:51 PM)m0dem Wrote: Cool! Really compact code.
But.. your code can only do one operation per input. (you can't do "5+5*5" or "4*3-2*3")
You should be able to do an equation of arbitrary length.

I just got bored in history, I'll take it seriously and finish it later.