Randomly pressing buttons of a calculator

185 Views Asked by At

There's a normal scientific calculator with only $12$ buttons: from $0$ to $9$ and $+-$

Randomly press these buttons $n$ times. What will be the math expectation of the result? (Imagine that the operation "$=$" is automatically executed after you press $n$ buttons)

For example, when $n=0$, $\mathbb{E}(X)=0$; when $n=1$, $\mathbb{E}(X)=\cfrac{\left(\displaystyle\sum\limits_{i = 0}^{9} i\right) + 2\times 0}{10 + 2}=\cfrac{45}{12}=\cfrac{15}{4}$

Expressions that are not allowed (wrong expressions) should be counted $0$. Most of the wrong expressions are due to syntax error.

The following is some criteria you can refer to (if you are not familiar with calculator) but not exact specification.

Update

The following is the part of results solved by python.

This is the calculator with only $0$ to $9$, $+$ and $-$

calculator with only 0~9+-

The code is here:

from itertools import product
tar = list(range(10)) + ['+', '-'] #operator

class Stack(object):
     def __init__(self):
         self.items = []

     def isEmpty(self):
         return self.items == []

     def push(self, item):
         self.items.append(item)

     def pop(self):
         return self.items.pop()

     def last(self):
         return self.items[len(self.items)-1]

     def size(self):
         return len(self.items)

op = ('+', '-', '*', '/')
for i in range(5):
    n = i + 1
    cnt = 0
    per = product(tar, repeat=n) # product
    for tup in per:
        list1 = list(tup)
        
        # convert digits into numbers
        pos = 0
        list2 = []
        while pos < len(list1):
            if type(list1[pos]) == int:
                num = 0
                while pos < len(list1) and type(list1[pos]) == int:
                    num *= 10
                    num += list1[pos]
                    pos += 1
                list2.append(num)
            else:
                list2.append(list1[pos])
                pos += 1

        # exclude expressions that are not allowed
        #if(list2[0] in ('*', '/')):
            #continue
        if(list2[-1] in op):
            continue
        flag = 0
        for k in range(len(list2)):
            if(k != len(list2) - 1):
                if(list2[k] in op and list2[k + 1] in op):
                    flag = 1
                if(list2[k] == '/' and list2[k + 1] == 0):
                    flag = 1
        if flag:
            continue

        # First digit processing
        if(len(list2) > 1 and list2[0] == '+'):
            list2 = list2[1:]
        if(len(list2) > 1 and list2[0] == '-'):
            list2[1] *= -1
            list2 = list2[1:]

        # Prefix Expression
        res = []
        s = Stack()
        optPriorityDict = {'+': 1, '-': 1, '*': 2, '/': 2}
        for ele in list2[::-1]:
            if type(ele) == int:
                res.insert(0, ele)
            elif ele in op:
                while(not s.isEmpty() and optPriorityDict[s.last()] >= optPriorityDict[ele]):
                    res.insert(0, s.pop())
                s.push(ele)
        while not s.isEmpty():
            res.insert(0, s.pop())

        def evalPreExp(preExpList):
            s = Stack()
            for ele in preExpList[::-1]:
                if type(ele) == int:
                    s.push(ele)
                else:
                    op1 = s.pop()
                    op2 = s.pop()
                    try:
                         out = toMath(ele, op1, op2)
                    except:
                         return 0
                    s.push(out)
            return s.pop()
         
        def toMath(op, op1, op2):
            if op == '+':
                 return op1 + op2
            elif op == '-':
                 return op1 - op2
            elif op == '*':
                 return op1 * op2
            elif op == '/':
                 return op1 / op2

        cnt += evalPreExp(res)
    print("When n =", n, ", E(X)=", cnt, '/', len(tar) ** n)