Evaluating Dotty Strings Write a program that takes in an odd length string containing only the characters . and :. With the aid of an initially empty stack, generate a number from this string as follows:

For every character c in the string (going from left to right)...


If c is . and the stack has less than 2 elements, push 1 on the stack.
If c is . and the stack has 2 or more elements, pop the two top values off the stack and push their sum onto the stack.
If c is : and the stack has less than 2 elements, push 2 on the stack.
If c is : and the stack has 2 or more elements, pop the two top values off the stack and push their product onto the stack.


The resulting number is the value at the top of the stack. Your program should print this number to stdout (with an optional trailing newline).

(A little analysis shows that there is only ever one number left unless the string has even length, which is why we are ignoring those. In fact, the stack never has more than 2 elements.)

For example, the number for ::...:.:. is 9:

  2   1   2   2    /______ stack just after the character below is handled
2 2 4 4 5 5 7 7 9  \
: : . . . : . : .  &lt;-- string, one character at a time


As a sanity check, here are the numbers for all strings of length 1, 3, and 5:

. 1
: 2
... 2
..: 1
.:. 3
.:: 2
:.. 3
:.: 2
::. 4
::: 4
..... 3
....: 2
...:. 4
...:: 4
..:.. 2
..:.: 1
..::. 3
..::: 2
.:... 4
.:..: 3
.:.:. 5
.:.:: 6
.::.. 3
.::.: 2
.:::. 4
.:::: 4
:.... 4
:...: 3
:..:. 5
:..:: 6
:.:.. 3
:.:.: 2
:.::. 4
:.::: 4
::... 5
::..: 4
::.:. 6
::.:: 8
:::.. 5
:::.: 4
::::. 6
::::: 8


The shortest program in bytes wins. Tiebreaker is earlier post.


You may assume the input is always valid, i.e. a string containing only . and : whose length is odd.
Instead of writing a program, you may write a function that takes in a valid string and prints or returns the generated number.
CJam, 27 24 23 22 bytes
q{i]_,+~3&lt;-&quot;1+2* &quot;=~}/

Pretty straight forward. I use CJam's stack as the stack mentioned in the question ;)
Algorithm
First lets look at the ASCII code for . and :.
'.i ':ied


[46 58]

Since in CJam, index wraps around, lets see if we can use these values directly to get the desired operation ..
'.i4% ':i4%ed


[2 2]

So I cannot simply use the ASCII codes in a 4 length operation string. Lets try some other values
'.i 10% ':i 10%ed


[6 8]

which on a 4 length string boils down to

[2 0]

I can use this mod 10 operation but that will cost be 2 bytes. Lets try something else
'.i5% ':i5%ed


[1 3]

Nice!, now we just subtract 1 for the stack size condition to get the indexes 0, 1, 2 and 3 and use a 5 length array (&quot;1+2* &quot;) as a switch case. The last space is just a filler to make it of length 5. This is just 1 extra byte as compared to modding operation.
q{                  }/    e# parse each input character in this loop
  i]                      e# convert '. or ': into ASCII code and wrap everything
                          e# in stack in an array
    _,+                   e# Copy the stack array, take its length and add the length to
                          e# the stack array 
       ~3&lt;                e# unwrap the stack array and check if stack size is less than 3
                          e# 3 because either . or : is also on stack
          -               e# subtract 0 or 1 based on above condition from ASCII code
           &quot;1+2* &quot;        e# string containing the operation to perform
                  =~      e# chose the correct operation and evaluate it

Try it online here
1 byte saved thanks to cosechy