What follows here is the description (documentation) of an esoteric programmine language I wrote up, and organized a national contest on. The purpose of this language was to be obscure and confusing, thus the challenge.
abcd is an esoteric language. In other words, it is a language deliberately made obfuscated and confusing. Trivial tasks too might be quite tough to accomplish while programming in this language. That is the point of the competition.
In Chaos ’16, you will be attempting to write computer programs to accomplish certain tasks using this language. These tasks would range from simple ones, to some really tricky ones.
Cutting to the chase, abcd is based off another similar language which had some shortcomings, and needed some fixes to be able to work properly.
Programming in this language requires you to manage values, memory and execution control flow effectively between a very restricted amount of variables you have. The execution is to a good extent very similar to how computer programs are run by CPUs in computers.
You will have 53 instructions which will give the program instructions. These will be the alphabets a-z, A-Z, and the character ?. So your program will basically look like a long gibberish string of alphabets. They will manipulate 3 regular memory values (integers), and one which is basically a tuple of 2 integers. We call these integer values as Registers, as is done for CPUs.
In addition, you will have an array of integers of size 1024 which can be used to store values outside the registers.
You can only do operations on the values inside registers. You will be able to retrieve values from the memory and put it inside the registers, and vice-verse.
Register1 and Register2
These are general purpose registers used to provide arguments to operations. For example if you need to add 2 integers, you will need to store them in these registers.
Register3 - The result register
This is the result register. This will store the result of instructions if any. For example in the above mentioned sum exercise, the result would be stored in this register.
The two registers available as a tuple are meant for specialized operations. They are modelled as follows: Register4, where Register4 is the memory pointer, and Register4 is the position pointer.
The memory pointer
One of them lets you write integer values to memory locations, and also to retrieve values from it. You can store intermediate results in the memory using this. For example, if this register stores the value 0 right now and you call the instruction to write the value of Register3 to memory, it will write that value to Memory.
The position pointer
The other lets you jump to the position in the program corresponding to the integer stored in it. For example, if that register stores 0, you can jump to the 0th location of the program, that is, to the beginning. This is useful for looping statements.
You will also have a ? instruction which will let you stop the program if the complete input has been read. This will be useful when you need to read an arbitrary amount of input.
There will be a Mode bit. This will be either 0 or 1. You have instructions to add or subtract some values to Register4[Mode]. This will come in handy if you need to modify the memory or the position pointer.
cccCISccccCIScccCIYx SGSHaaCLgDLihhhDLDLgggDL TTGaaCL SGccbbbCLDLgggDLjggggDLSHDL TTGaaaCL
Print the character ‘b’
Print the number 98
The implementation and the instructions
case "a": Register1 += 1; case "b": Register1 -= 1; case "c": Register1 += 10; case "d": Register1 -= 10; case "e": Register1 += 100; case "f": Register1 -= 100; case "g": Register2 += 1; case "h": Register2 -= 1; case "i": Register2 += 10; case "j": Register2 -= 10; case "k": Register2 += 100; case "l": Register2 -= 100; case "m": Register3 = !Register1; case "n": Register3 = !Register2; case "o": Register3 = Register1 & Register2; case "p": Register3 = Register1 | Register2; case "q": Register3 = Register1 ^ Register2; case "r": Register3 = Register1 + Register2; case "s": Register3 = Register1 - Register2; case "t": Register3 = Register1 * Register2; case "u": Register3 = Register1 / Register2; case "v": Register3 = Register1 % Register2; case "w": Register3 = Register1 ^ Register2; case "x": Register1 = 0; case "y": Register2 = 0; case "z": Register3 = 0; case "A": Register2 = Register1; case "B": Register1 = Register2; case "C": Register3 = Register1; case "D": Register3 = Register2; case "E": Register1 = Register3; case "F": Register2 = Register3; case "G": Register1 = Memory[Register4]; case "H": Register2 = Memory[Register4]; case "I": Memory[Register4] = Register3; case "J": Read the next character from input. Store it in register1 case "K": Read next character from input. Store it in register2 case "L": Basically printing the value of Register3 as a character. So 97 would print as 'a'. case "M": Printing value of Register3 as an integer. 97 would print '97' case "N": if(Register1 === Register2) Position = Register4-1; case "O": if(Register1 !== Register2) Position = Register4-1; case "P": if(Register1 >= Register2) Position = Register4-1; case "Q": if(Register1 <= Register2) Position = Register4-1; case "R": if(Register3) Position = Register4-1; case "S": Register4[Mode] += 1; case "T": Register4[Mode] -= 1; case "U": Register4[Mode] += 10; case "V": Register4[Mode] -= 10; case "W": Register4[Mode] += 100; case "X": Register4[Mode] -= 100; case "Y": Register4[Mode] = 0; case "Z": Mode = (Mode+1)%2; case "?": if(readInput >= input.length + 1) finished=1;
- Characters which are not recognized are ignored. Use this to keep your code readable. You can use spaces and newline to have that effect.
You’ll NEED this:
|34||"||Double quotes (or speech marks)|
|40||(||Open parenthesis (or open bracket)|
|41||)||Close parenthesis (or close bracket)|
|46||.||Period, dot or full stop|
|47||/||Slash or divide|
|60||<||Less than (or open angled bracket)|
|62||>||Greater than (or close angled bracket)|
|94||^||Caret - circumflex|
|126||~||Equivalency sign - tilde|