-1

Calculator that takes 3 user inputs: operation signs and numbers 1-5 spelled out. Then it converts them to numbers and symbols. Users can input them in any order. The problem is in my for loops in functions i(1-3) the only input that works is one any other doesn't convert to a number or symbol.

dictt = {
    'one': 1,
    'two': 2,
    'three': 3,
    'four': 4,
    'five': 5,
    'add': r"+",
    'subtract': r"-",
    'multiply': r"*",
    'divide': r"/"
}
def i1():
    i1 = (input("Please input 'add', 'subtract', 'multiply', 'divide', 'one', 'two', 'three' , 'four', or 'five': "))
    num1=0
    for k,v in dictt.items():
        if i1 == k:
            num1 = dictt[k]
        return num1

def i2():
    i2 = (input("Please input 'add', 'subtract', 'multiply', 'divide', 'one', 'two', 'three' , 'four', or 'five': "))
    num2=0
    for k,v in dictt.items():
        if i2 == k:
            num2 = dictt[k]
        return num2

def i3():
    i3 = (input("Please input 'add', 'subtract', 'multiply', 'divide', 'one', 'two', 'three' , 'four', or 'five': "))
    num3=0
    for k,v in dictt.items():
        if i3 == k:
            num3 = dictt[k]
        return num3

def main():
    x=i1()
    y=i2()
    z=i3()
    listo=[x,y,z]
    listn=[]
    for i in listo:
        if i == int:
            listn.append(i)
            listo.remove(i)
        else:
            pass
    if len(listn) == 2:
        if listo[0] == "add":
            result=listn[0]+listn[1]
            return f"{listn[0]} + {listn[1]} = {result}"
        elif listo[0] == "subtract":
            result = listn[0] - listn[1]
            return f"{listn[0]} - {listn[1]} = {result}"
        elif listo[0] == "multiply":
            result=listn[0] * listn[1]
            return f"{listn[0]} * {listn[1]} = {result}"
        elif listo[0] == "divide":
            result=listn[0] / listn[1]
            return f"{listn[0]} / {listn[1]} = {result}"
    elif len(listn) < 2:
        return "not enough numbers"
    elif len(listo) != 1:
        return "just one operator"
  • Welcome to Stack Overflow! Please take the [tour]. For debugging help, you need to make a [mre] including example input, expected output, and actual output -- or if you get an error, the full error message. It'd also help to reduce the code to only as much as is required to reproduce the issue. It looks like most of the code here is irrelevant to the problem. For more tips, see [ask]. – wjandrea May 16 '22 at 19:05
  • Python 3.1 is super out of date. You mean 3.10, right? – wjandrea May 16 '22 at 19:06
  • Welcome to Stack Overflow. In your own words: what is a `dict` in Python, and what is its main purpose? – Karl Knechtel May 16 '22 at 19:08
  • Editting an iterable while you iterate over it is generally bad form. Thus you should rework the "for i in listo: ... listo.remove(i)" business. Also, it's not clear what that for loop is supposed to accomplish. As written, it's impossible for "i" to _ever_ match "int". Perhaps you want "instanceof(i, int)" instead of "i == int"? or a "try: iint = int(i); except TypeError: pass" block? – Sarah Messer May 16 '22 at 19:11
  • BTW, reading past the issue, `i == int` doesn't do [what you think](/q/152580/4518341), and `listo.remove(i)` [might cause problems](/q/6260089/4518341). – wjandrea May 16 '22 at 19:11

2 Answers2

1

Your iteration is broken because you return too early, but you don't need to iterate through a dictionary to look up an item in it in the first place. Instead of:

def i1():
    i1 = (input("Please input 'add', 'subtract', 'multiply', 'divide', 'one', 'two', 'three' , 'four', or 'five': "))
    num1=0
    for k,v in dictt.items():
        if i1 == k:
            num1 = dictt[k]
        return num1

do:

def i1():
    i1 = input("Please input 'add', 'subtract', 'multiply', 'divide', 'one', 'two', 'three' , 'four', or 'five': ")
    return dictt.get(i1, 0)

You also don't need i2 and i3, because all of these functions do exactly the same thing, just with different names. Instead of:

    x=i1()
    y=i2()
    z=i3()
    listo=[x,y,z]

you could just do:

    listo = [i1(), i1(), i1()]

or:

    listo = [i1() for _ in range(3)]

I might suggest simplifying the overall code by putting all the inputs in a list, sorting them into numbers and functions, and then applying them, rather than having a bunch of if statements:

ops = {
    'one': 1,
    'two': 2,
    'three': 3,
    'four': 4,
    'five': 5,
    'add': ("+", int.__add__),
    'subtract': ("-", int.__sub__),
    'multiply': ("*", int.__mul__),
    'divide': ("/", int.__truediv__),
}


def get_op():
    while True:
        try:
            return ops[input(
                "Please input 'add', 'subtract', 'multiply', 'divide', "
                "'one', 'two', 'three' , 'four', or 'five': "
            )]
        except KeyError:
            print("Not a valid input.")


def main():
    while True:
        ops = [get_op() for _ in range(3)]
        nums = [n for n in ops if isinstance(n, int)]
        f = [f for f in ops if isinstance(f, tuple)]
        if len(f) == 1 and len(nums) == 2:
            break
        else:
            print("Must enter exactly two numbers and one operation.")
    symbol, func = f.pop()
    expr = f" {symbol} ".join(str(n) for n in nums)
    return f"{expr} = {func(*nums)}" 

if __name__ == '__main__':
    print(main())
Samwise
  • 68,105
  • 3
  • 30
  • 44
0

I think you make your codes a little bit complicated, which will be difficult to maintain, this can be simple if using operator

    from operator import add, sub, mul, truediv
    from typing import Callable
    
    dictt = {
        'one': 1,
        'two': 2,
        'three': 3,
        'four': 4,
        'five': 5,
        'add': add,
        'subtract': sub,
        'multiply': mul,
        'divide': truediv,
    }
    
    
    def main():
        input_msg = "Please input 'add', 'subtract', 'multiply', 'divide', 'one', 'two', 'three' , 'four', or 'five': "
    
        v1 = dictt.get(input(input_msg).strip())
        v2 = dictt.get(input(input_msg).strip())
        v3 = dictt.get(input(input_msg).strip())
    
        if isinstance(v2, Callable) and v1 and not isinstance(v1, Callable) and v3 and not isinstance(v3, Callable)::
            return v2(v1, v3)
        else:
            return 'Invalid input'
    
    
    if __name__ == '__main__':
        res = main()
        print(res)
Menglong Li
  • 2,177
  • 14
  • 19