# Implement Casio's M

Most Casio calculators featured a variable M, which has 3 operators related to it: M, M+, and M-

M, as you can expect, returns the value stored in the variable.

M+ takes the number on the left and add it to M.

M- does the same thing as M+, but subtract instead.

To make the challenge just a bit more difficult, we will add an extra operator: MR, which is short for Memory reset. As you can guess from the name, it resets the variable M back to 0.

Your task is to parse a string of Casio M expression, then print the value of M.

Here's an example:

9M+9M+


Here, we add 9 to variable M twice, so the output will be 18.

## Specifications

• M will be 0 when first initialized
• For this challenge, you don't need to handle basic arithmetics, just those operators.
• However, you do need to handle implicit multiplications, so 9M will become 81 for M = 9
• If the expression given is invalid, you can return any value of your choice
• M+ and M- must not have an operator behind them (except for M), so cases like MRM+ and 9M+M+ are invalid, but 9M+MM+ is valid.

## Input/Output

The input should be a string and the output is either the variable M or an invalid value of your choice.

## Testcases

Input -> Output
9M+9M+ -> 18
9MR9M+ -> 9
9M+MM+ -> 18
9M-9M-9M+ -> -9
9M+MMM+ -> 90
81M+81M+56M-35M-12M+ -> 83
9M+MRM+ -> Invalid
9M+M+  -> Invalid
9 -> 0 (Explanation: does not modify M with an operator)
9M+MM -> 9 (Same as the above test case)
2M+2M2MM+ -> 18

• Could you please clarify 9M+MMM+ -> 90? Nov 19, 2022 at 0:21
• @WheatWizard I have also thought of relaxing the invalid output, but couldn't think of a language in the time. Edited.
– oeuf
Nov 19, 2022 at 14:36
• Would something like 2M+2M2MM+ be valid? If so, I assume the answer would be 18? Nov 19, 2022 at 17:48
• @Jonah Yes, that is valid, and yes, you are right that the answer is 18
– oeuf
Nov 20, 2022 at 0:16
• @oeuf You may want to add 2M+2M2MM+ to the test case, because only one of the current four answers handles it correctly.. :/ Nov 21, 2022 at 15:42

# Python3, 287 bytes:

import re
R=re.findall
V=lambda m,x,k=1:k if[]==x else V(m,x[1:],k*(int(x)if x.isdigit()else m))
E=lambda x,M=0:M if[]==x else E(x[1:],M+[-1,1][x[-1]!='-']*V(M,R('\d+|M',x))*(x!='MR'))
f=lambda x:''.join(map(''.join,k:=R('([M\d]+)(M(?:\-|\+)|MR)',x)))==x and E(k)


Try it online!

• 279 bytes Nov 19, 2022 at 7:47

# Python, 172 179 174 169 164 156 153 bytes

def f(x,M=0):
try:exec(s("M(?=\d|M)","M*",s("(\d|M)M","\\1*M",s("R=","*=0M",s("(.*?)(M[-+R])",r"\2=\1;",x))))+"\nprint(M)")
except:0
import re
s=re.sub


Attempt This Online!

-3 bytes thanks to @The Thonnu

# Python, 148 155 150 145 140 137 bytes

lambda x,M=0:exec(s("M(?=\d|M)","M*",s("(\d|M)M","\\1*M",s("R=","*=0M",s("(.*?)(M[-+R])",r"\2=\1;",x))))+"\nprint(M)")
import re
s=re.sub


Attempt This Online!

Shorter version which throws an error for invalid expressions.

+7 bytes to both versions due to bug in code.

# 05AB1E, 52 47 bytes

0U…+-RS©D¶«.:¶¡ε®'Mì„X+…Xs-‚…)\0ª'U«:'M„XP:.V}X


Explanation:"

0U            # Set variable X to 0 (it's 1 by default)
…+-RSD¶«.:¶¡  # Split the (implicit) input after each "+"/"-"/"R":
…+-RS         #  Push triplet ["+","-","R"]
©        #  Store it in variable ® (without popping)
D       #  Duplicate it
¶«     #  Append a newline to the values in the pair
.:   #  Replace all "+"/"-"/"R" with "+\n"/"-\n"/"R\n" respectively in the
#  (implicit) input
¶¡ #  Then split on newlines
ε             # Map over each substring:
# (used as a foreach, where all will have their own separated stack):
®            #  Push triplet ["+","-","R"] from variable ®
'Mì        '#  Prepend an "M" in front of each
„X+          #  Push string "X+"
‚        #  Pair it with
…Xs-         #  String "Xs-"
ª        #  And also append
…)\0         #  String ")\0"
'U«    '#  Append an "U" after all three: ["X+U","Xs-U",")\0U"]
:            #  Replace all "M+"/"M-"/"MR" with "X+U"/"Xs-U"/")\0U" respectively
'M„XP:      '#  Then replace all remaining "M" with "XP"
.V           #  Execute it as 05AB1E code (see below)
}X            # After the map: push value X
# (which is output implicitly as result)

)\0U          # MR:
)             #  Wrap the entire stack into a list
0U          #  Reset X to 0

X+U           # M+:
X+            #  Add X to the top value
U           #  Pop and store it as new value X

Xs-U          # M-:
X             #  Push X
s            #  Wrap the top two values on the stack
-           #  Subtract the value from X
U          #  Pop and store it as new value X

XP            # Remaining M:
X             #  Push value X
P            #  Get the product of all values on the stack (for the current group)


# VyxalD, 40 bytes

⁽±ḊƛǍ[f;f(nw‛MR‛¥⁼½dĿ÷Ė‟n±ß¥£!3=ß*)¥D⌊=*


Test suite. Returns blank in the case of an invalid expression.

Explanation:

⁽±Ḋ                                      # group digits and non-digits together, preserving order
ƛǍ[f;                                 # split into list of chars for non-digit items
f                                # flattened
(                        )      # for each item:
nw                             #  item, wrapped in a single list
‛MR                          #  literal "MR"
‛¥⁼½d                     #  list ["¥¥","⁼⁼"] (D flag: do not decompress string)
Ŀ                    #  transliterate
÷Ė                  #  unwrap and execute the item:
#    M: push register twice
#    R: always 0, also makes stack length to 1
#    + & -: add and subtract respectively
#      concatenates with input if stack is insufficient
#    <number>: push <number> as int
‟                 #  rotate the item to the back of stack
n±ß¥             #  if the current item is numeric, push register
#    (preventing the number from being stored)
£            #  store to register
!3=ß*       #  if stack length == 3, multiply
¥     # push register
D⌊=* # multiply depending on being an integer
# implicit output


# Retina, 248 bytes

\d+|M
¶$& \d+ * {^(.*)¶(_*¶)?MR|^.*¶M[-+](¶.*)* +^(.*)(¶-?_*¶?)M(?!.)$1$2$1
^(.*¶-?)(_*)¶(-?)(_*)(?!.)
$1$3$.2*$4
--

^(.*)¶(.*)¶M([-+])
$1$3$2 \+- - -- + ^(_*)\+|^(-_*)-|^-(_*)\+\3|^(-_*?)(_*)\+\5$1$2$4
)(_+)-\1(\B)?
$#2*- L$^(-?)(_*)
$1$.2


Try it online! Link includes test cases. Explanation:

\d+|M
¶$&  Insert newlines before each number or memory operation. The newline before the very first operation serves to set the initial memory to zero. \d+ *  Convert all the numbers to unary. { )  Repeat until all of the numbers and memory operations have been processed. ^(.*)¶(_*¶)?MR|^.*¶M[-+](¶.*)*  MR will reset just the memory and M- or M+ in an invalid place will clear everything resulting in an output of zero. +^(.*)(¶-?_*¶?)M(?!.)$1$2$1


M either immediately after an MR, M- or M+, or with a number in between, will read the memory.

^(.*¶-?)(_*)¶(-?)(_*)(?!.)
$1$3$.2*$4
--



Two values (at least one of which will have been the result of a memory read) will multiply together.

^(.*)¶(.*)¶M([-+])
$1$3$2 \+- - -- + ^(_*)\+|^(-_*)-|^-(_*)\+\3|^(-_*?)(_*)\+\5$1$2$4
(_+)-\1(\B)?
$#2*-  M+ and M- after the value will add it to or subtract it from the memory. L$^(-?)(_*)
$1$.2


Convert the final memory to decimal, ignoring any pending value.

• Seems to fail for 2M+2M2MM+ -> 18 Nov 21, 2022 at 15:43
• @KevinCruijssen At the time it wasn't obvious that numbers after M needed to be supported, but I guess I'll look at it at some point.
– Neil
Nov 21, 2022 at 17:05

# Charcoal, 78 72 bytes

≔¹ηＦ⪪⁺RθM«¿⊙ι№-+Rκ«≡§ι⁰-¿υ≧⁻Πυζ≔⁰η+¿υ≧⁺Πυζ≔⁰η≔⁰ζ≔⟦⟧υ≔Φιλι»⊞υζ¿ι⊞υＩι»¿ηＩζ


Try it online! Link is to verbose version of code. Explanation:

≔¹η


Start by assuming the expression is valid.

Ｆ⪪⁺RθM«


Split the input on M and loop over the parts, however prefix an R to the first part to get a free memory reset.

¿⊙ι№-+Rκ«


If this part contains a -, + or R, then:

≡§ι⁰


Switch over the first character in the part.

-¿υ≧⁻Πυζ≔⁰η


If it's a - then subtract the product of the stack from the memory, but if the stack is empty then mark the expression as invalid.

+¿υ≧⁺Πυζ≔⁰η


Similarly for +.

≔⁰ζ


Otherwise, this is an R, so clear the memory.

≔⟦⟧υ


Clear the stack.

≔Φιλι


Remove the leading character from the part.

»⊞υζ


Otherwise, push the memory to the stack.

¿ι⊞υＩι


If the part isn't empty then push its value to the stack.

»¿ηＩζ


If the expression was valid then output the memory.

• Seems to fail for 2M+2M2MM+ -> 18 Nov 21, 2022 at 15:43
• @KevinCruijssen At the time it wasn't obvious that numbers after M needed to be supported, but I guess I'll look at it at some point.
– Neil
Nov 21, 2022 at 17:04
• @KevinCruijssen I took the opportunity to change my approach and as a bonus it's now 10% shorter!
– Neil
Nov 27, 2022 at 9:53

# JavaScript (Node.js), 146 bytes

s=>eval(s.replace(/\d+|M[-+R]?/g,b=>_${c?"*":""}=${b<":"?(d=c++,b):d&&b?"m=//":m${(d=b)||";a"}=_;${c=!d,b>"M-"&&"m=0"}};,m=c=d=0)+"m")


Try it online!

Creates a program based on the input and then evaluates it. Returns the empty string for invalid inputs. My favorite aspect of this solution is using b<":" to separate numeric strings from the other kinds of strings that can appear here.

# JavaScript (Node.js), 138 bytes

s=>eval(s.replace(/\d+|M[-+R]?/g,b=>_${c?"*":""}=${b<":"?(d=c++,b):d&&b||m${(d=b)||";a"}=_;${c=!d,b>"M-"&&"m=0"}};,m=c=d=0)+"m")


Try it online!

Similar to @Mukundan314's reasoning, this version throws an error instead of returning a specific value.