What Mains Numbers?
What Mains Numbers?
What Mains Numbers? is an esoteric programming language that has many functions that generate numbers. For example, you can read the time, get a random number and repeat something a few times. Here is a list of instructions:
Instruction | What it does |
---|---|
@ |
output the time in this format: weekday month day year hour:minute:second
|
? |
generates a random number between 0 and 10 |
! |
ends the program |
< |
outputs the value of the instruction counter |
> |
skip the next character in the program |
% |
generates a random number between 0 and 100 |
* |
generates a random number between 0 and 1000 |
- |
execute the previous character ten more times |
_ |
execute the previous character of "_" twenty more times |
else | say the character. |
Example programs
Generate a 10-digit random number (with periods between the digits)
?-!
Infinite loop
This program allocates enough memory to cause thrashing, and thus is unlikely to halt in a reasonable length of time (and may make your computer nonresponsive).
In order to prove that this is a valid infinite loop in a specific implementation, here is the JavaScript source code of the original interpreter (you do not have to pay too much attention to the other commands):
function scrip(){ var code = document.getElementById("code").value; var i; var roll = 0; for(i = 0; i <= 100; i++){ if(code[i] == "@"){ document.getElementById("demo").innerHTML += Date()+"."; }else if(code[i] == "?"){ document.getElementById("demo").innerHTML += Math.floor(Math.random()*10)+"."; }else if(code[i] == "!"){ var i = 100; }else if(code[i] == "<"){ document.getElementById("demo").innerHTML += i; }else if(code[i] == ">"){ i += 1; }else if(code[i] == "%"){ document.getElementById("demo").innerHTML += Math.floor(Math.random()*100)+"."; }else if(code[i] == "*"){ document.getElementById("demo").innerHTML += Math.floor(Math.random()*Math.random()*1000)+"."; }else if(code[i] == "-"){ if(roll != 10){ i -= 2; roll++ } }else if(code[i] == "_"){ if(roll != 20){ i -= 2; roll++ } }else{ document.getElementById("demo").innerHTML += code[i]; } }}
In this JavaScript program, there is only one variable roll
to indicate the number of repetitions neccecary, and it will dynamically be changed for every repetition of the previous character. However, there is a problem in this source code: the roll variable was not re-set after 10 (or 20) permutations, and the conditional has problems (the loop stops only when roll is equal to 10 or 20); this problem can be abused to create an infinite loop. After a 1_
permutation, roll will be set to 20 because the 1 was repeated 20 more times, and the if expression will be false only roll is 10 or 20. (If you use the -
loop, you can still make 10 more permutations, as roll is less then 20 when roll is 10.)
Now when you call the -
loop, it is evident that roll is always not 10 (because roll is larger then 10), and it will not convert to 10 no matter how you increment it (integers are unbounded in JavaScript. Using the mathematical induction, we will first start with the fact that 10<20. Now when we increment 20 by 1, 10<21 is also true. If we repeat the second step multiple times, we come up to the conclusion that x<y then x<y+1. The result is incremented by 1 because in JavaScript, the ++
increments a value by 1).
As a result, it will execute the previous character indefinitely. The program counter (i
) will move back two characters, move forward one character, execute that character, and then go back to the previous -
character, where it will repeat the prodecure described above only to execute the previous character again.
1_2-!
Comment sample
>H>e>l>l>o> >W>o>r>l>d>!!
Hello, world! program
Hello, World!
Computational class
What Mains Numbers? is a Finite-state automaton, as the program and the program counter acts as finite states.
Implementations
For the original implementation you may go here.
Another one with improvements (clear output after exec, multi-line programs, no abundant memory consumption, etc.), in HTML.
This is a What Mains Numbers? compiler to Python; use eval to execute the program after the iter function.
import time import random def iter(a): b="\"\"" i=0 while i<len(a): if a[i]=="_": b+="*20" elif a[i]=="-": b+="*10" elif a[i]=="@": b+="+\'"+time.asctime(time.localtime(time.time()))+"\'" elif a[i]=="?": b+="+\'"+str(random.randint(0,10))+"\'" elif a[i]=="%": b+="+\'"+str(random.randint(0,100))+"\'" elif a[i]=="*": b+="+\'"+str(random.randint(0,1000))+"\'" elif a[i]=="<": b+="+\'"+str(i)+"\'" elif a[i]==">": i+=1 elif a[i]=="!": pass else: b+=("+\'"+a[i]+"\'") i+=1 return b