Ndim

From Esolang
Jump to navigation Jump to search

Ndim is an esoteric programming language created by User:Schlafhase

In Ndim there are n dimensions. Every program starts with

[number]dim

where number sets the amount of dimensions. So for example

2dim

would be the start of a 2 dimensional ndim program. There is a pointer that points either in the positive or negative direction of an axis in the n dimensional space. Ndim stores 2 values. (similar to a stack). Let's call the first value a and the second value b for this documentation. Every command is stored in a n dimensional coordinate system. You can also store values in the coordinate system. The pointer moves in a specified direction until it hits a command or value. Commands get executed and values get pushed to the stack. The pointer points in the positive direction of the first axis (or `1` in ndim syntax) at the start of every program. And every value is an integer. This language is inspired by befunge

The "stack"

Ndim has a stack-like structure storing two values called a and b. a and b are 0 by default.
Pushing to the stack is done by overwriting the value of b with the current value of a. And then overwriting the value of a with the integer.
Popping from the stack is done by overwriting the value of a with value of b. And then overwriting the value of b with 0.

What does left or right mean?

To get the coordinate to the right of the current coordinate in ndim you use the following code

right = currentCoordinate
right[Math.Abs(pointerDirection) % n] += 1

left is the same but with "-="instead of "+=" so

left = currentCoordinate
left[Math.Abs(pointerDirection) % n] -= 1

Example

n = 2
currentCoordinate = <10, 20>
pointerDirection = -2

right = currentCoordinate //right is <10, 20> after this line
right[2 % 2] += 1 //right is <11, 20> after this line

Syntax

Ndim's Syntax looks like this:

[command]<[coordinate]>;

Where command stands for the command and coordinate for the coordinate in the n dimensional coordinate system.
Every line ends with a ";"
Everything behind the ";" will be ignored. Another way to make comments is by writing // at the start of a line.
Note: Every line matching the following regular expression is (probably) a valid line of ndim code

^\s*((-?\d+|\?|jump)|(#\d|pop|swap|duplicate|\+|-|\*|/|\^|&|\||!|<|>)|if\s+\d+|(assignHere|assign|toggleEat|input|printChar|print)|end) *(<)([\d, -]+)(>);

Syntax Highlighting

Download a Highlighting Extension for vscode and use the Ndim configuration file

Commands

Note: Every command needs to have its coordinate specified in <> brackets behind it like described above. The [] brackets stand for parameters of the commands. They are not actually valid syntax.

Ndim commands
Command Description
[number]dim Specify how many dimensions the program has. Every program must begin with this line. It will throw a Syntax Error if it appears anywhere but on the first line.
[axis] Set direction of the pointer to the positive direction of the specified axis. (axis is an integer like everything else)
-[axis] Set direction of the pointer to the negative direction of the specified axis.
? Set direction of the pointer to a random direction.
jump Skip any command that comes immediately after this command.
#[digit] Push digit to the stack.
pop Pop a value from the stack and discard it.
swap Swap the values of a and b.
duplicate Overwrite the value of b with a's value.
+ Pop the values a and b from the stack and push a + b to the stack.
- Pop the values a and b from the stack and push b - a to the stack.
* Pop the values a and b from the stack and push a * b to the stack.
/ Pop the values a and b from the stack and push b / a to the stack.
^ Pop the values a and b from the stack and push b ^ a to the stack. (Math.Pow(b, a) not XOR)
< Pop the values a and b from the stack. If b < a push 1 to the stack.
> Pop the values a and b from the stack. If b > a push 1 to the stack.
& Pop the values a and b from the stack. If a and b are both greater than 0 push 1 to the stack.
| Pop the values a and b from the stack. If a or b is greater than 0 push 1 to the stack.
! Pop a value a from the stack. If a is greater than 0 push 0 to the stack else push 1.
if [value] Pop a value a from the stack. If a is equal to value point the pointer to the right else point the pointer to the left.
input Ask for an input and then push it to the stack. Throw Exception if the input is not an integer.
assign Pop a value a from the stack and store it to the right of the pointer. (this will overwrite commands and other values stored at that position)
assignHere Pop a value a from the stack and store it at the current position of the pointer. (this will overwrite itself)
toggleEat Toggles the eat mode. When the eat mode is enabled, commands and values get deleted from the coordinate system after the pointer hit them. (they still get processed one last time)
print Pop a value from the stack and output it.
printChar Pop a value of the stack and output it as a character.
end Ends the program. (programs not containing this will run forever)

Interpreter

You can find a Ndim Interpreter by User:Schlafhase here.

Esoteric IDE

EsotericIDE also supports Ndim. It supports debugging and shows a visualised version of the Ndim program in the Watch window which makes it alot easier to program in Ndim

Examples

Hello, World!

2dim;
#9 <0,0>;
#8 <1,0>;
* <2,0>; //9*8 = 72
assign <3,0>; //store 72 at <3,1>
#7 <4,0>;
duplicate <5,0>;
* <6,0>; //7*7 = 49
#2 <7,0>;
* <8,0>; //49*2 = 98
#3 <9,0>;
+ <10,0>; //98+3 = 101
duplicate <11,0>;
assign <12,0>; //store 101 at <12,1>
#7 <13,0>;
+ <14,0>; //101+7 = 108
duplicate <15,0>;
assign <16,0>; //store 108 at <16,1>
duplicate <17,0>;
assign <18,0>; //store 108 at <18,1>
#3 <19,0>;
+ <20,0>; //108+3 = 111
assign <21,0>; //store 111 at <21,1>
#6 <22,0>;
#7 <23,0>;
* <24,0>; //6*7 = 42
#2 <25,0>;
+ <26,0>; //30+2 = 44
duplicate <27,0>;
assign <28, 0>; //store 44 at <28,1>
#9 <29,0>;
- <30,0>; //44-9 = 35
#3 <31,0>;
- <32,0>; //35-3 = 32
assign <33,0>; //store 32 at <33,1>
#9 <34,0>;
duplicate <35,0>;
* <36,0>; //9*9 = 81
#6 <37,0>;
+ <38,0>; //81+6 = 87
duplicate <39,0>;
assign <40,0>; //store 87 at <40,1>
#9 <41,0>;
+ <42,0>; //87+9 = 96
#9 <43,0>;
+ <44,0>; //96+9 = 105
#6 <45,0>;
+ <46,0>; //105+6 = 111
duplicate <47,0>;
assign <48,0>; //store 111 at <48,1>
#3 <49,0>;
+ <50,0>; //111+3 = 114
duplicate <51,0>;
assign <52,0>; //store 114 at <52,1>
#6 <53,0>;
- <54,0>; //114-6 = 108
duplicate <55,0>;
assign <56,0>; //store 108 at <56,1>
#8 <57,0>;
- <58,0>; //108-8 = 100
assign <59,0>; //store 100 at <59,1>
#5 <60,0>;
#6 <61,0>;
* <62,0>; //5*6 = 30
#3 <63,0>;
+ <64,0>; //30+3 = 33
assign <65,0>; //store 33 at <65,1>
2 <68,0>; //point the pointer "up"
-1 <68,2>; //point the pointer "left"
-2 <0,2>; //point the pointer "down"
1 <0,1>; //point the pointer "right"
printChar <5,1>;
printChar <13,1>;
printChar <17,1>;
printChar <19,1>;
printChar <22,1>;
printChar <29,1>;
printChar <34,1>;
printChar <41,1>;
printChar <49,1>;
printChar <53,1>;
printChar <57,1>;
printChar <60,1>;
printChar <66,1>;
end <67,1>;

readable code

You can use comments to make your code more readable.

2dim;
input <0, 0>;
if 0 <2, 0>;
//{
    input <2, 1>;
    #2 <2, 2>;
    * <2, 3>;
    print <2, 4>;
    end <2, 5>;
//}
//else
//{
    input <2, -1>;
    #3 <2, -2>;
    * <2, -3>;
    print <2, -4>;
    end <2, -5>;
//}

But since the order doesn't matter you can arrange the commands however you like!
For example alphabetically:

2dim; //except this line because it has to be at the top
#2 <2, 2>;
#3 <2, -2>;
* <2, 3>;
* <2, -3>;
end <2, -5>;
end <2, 5>;
if 0 <2, 0>;
input <0, 0>;
input <2, -1>;
input <2, 1>;
print <2, -4>;
print <2, 4>;

Factorial

Here is a Ndim program that takes an input x and outputs x! (x factorial). This took me over 5 hours.

3dim;
input <0, 0, 0>; //ask for input
duplicate <5, 0, 0>;
assign <10, 0, 0>; //store input at <10, 1, 0>
#2 <15, 0, 0>;
< <20, 0, 0>;
if 0 <25, 0, 0>;
//if input was not smaller than 2
//{
    -1 <25, 5, 0>;
    #1 <24, 5, 0>; //push 1 as starting value
    2 <23, 5, 0>; 

    //get previous value
    -1 <23, 6, 0>;
    jump <8, 6, 0>;
    -2 <6, 6, 0>;
    1 <6, 4, 0>;
    2 <22, 4, 0>;
    -1 <22, 5, 0>;
    //add one to previous value
    #1 <20, 5, 0>;
    + <15, 5, 0>;
    duplicate <14, 5, 0>;
    //store new previous value
    assign <13, 5, 0>; //<13, 6, 0>
    //get original input
    -2 <12, 5, 0>;
    -1 <12, 1, 0>;
    2 <9, 1, 0>;
    -1 <9, 5, 0>;
    2 <8, 5, 0>;
    > <8, 10, 0>;
    if 1 <8, 15, 0>;
    //if the current value is greater than the original input
//  {
        //get previous multiplied result and print it
        -2 <8, 15, 4>;
        -1 <8, 6, 4>;
        -3 <-4, 6, 4>;
        -1 <-4, 6, 0>;
        print <-6, 6, 0>;
        end <-7, 6, 0>;
//  }
//  else 
//  {
        //get previous value then go to line <7, 7, 0>
        -2 <8, 15, -1>;
        1 <8, 6, -1>;
        3 <13, 6, -1>;
        -1 <13, 6, 3>;
        2 <7, 6, 3>;
        -3 <7, 7, 3>;
        //get previous multiplied value
        -2 <7, 7, 0>;
        3 <7, 6, 0>;
        -1 <7, 6, 1>;
        -3 <-5, 6, 1>;
        -1 <-5, 6, -1>;
        2 <-6, 6, -1>;
        1 <-6, 7, -1>;
        -2 <1, 7,-1>;
        3 <1, 5, -1>;
        -1 <1, 5, 0>;
        //multiply both then store the new value
        * <0, 5, 0>;
        assign <-5, 5, 0>; //<-5, 6, 0>
        #1 <-5, 6, 0>;
        2 <-13, 5, 0>;
        1 <-13, 13, 0>;
        //go to line 15
        -2 <23, 13, 0>;
//  }
//}
//else
//{
    #1 <25, -5, 0>;
    print <25, -10, 0>;
    end <25, -15, 0>;
//}

You can also do it like this if you like to have your code sorted.

3dim;
#1 <-5, 6, 0>;
#1 <20, 5, 0>;
#1 <24, 5, 0>;
#1 <25, -5, 0>;
#2 <15, 0, 0>;
* <0, 5, 0>;
+ <15, 5, 0>;
-1 <-4, 6, 0>;
-1 <-5, 6, -1>;
-1 <1, 5, 0>;
-1 <12, 1, 0>;
-1 <13, 6, 3>;
-1 <22, 5, 0>;
-1 <23, 6, 0>;
-1 <25, 5, 0>;
-1 <7, 6, 1>;
-1 <8, 6, 4>;
-1 <9, 5, 0>;
-2 <1, 7,-1>;
-2 <12, 5, 0>;
-2 <23, 13, 0>;
-2 <6, 6, 0>;
-2 <7, 7, 0>;
-2 <8, 15, -1>;
-2 <8, 15, 4>;
-3 <-4, 6, 4>;
-3 <-5, 6, 1>;
-3 <7, 7, 3>;
1 <-13, 13, 0>;
1 <-6, 7, -1>;
1 <6, 4, 0>;
1 <8, 6, -1>;
2 <-13, 5, 0>;
2 <-6, 6, -1>;
2 <22, 4, 0>;
2 <23, 5, 0>;
2 <7, 6, 3>;
2 <8, 5, 0>;
2 <9, 1, 0>;
3 <1, 5, -1>;
3 <13, 6, -1>;
3 <7, 6, 0>;
< <20, 0, 0>;
> <8, 10, 0>;
assign <-5, 5, 0>;
assign <10, 0, 0>;
assign <13, 5, 0>;
duplicate <14, 5, 0>;
duplicate <5, 0, 0>;
end <-7, 6, 0>;
end <25, -15, 0>;
if 0 <25, 0, 0>;
if 1 <8, 15, 0>;
input <0, 0, 0>;
jump <8, 6, 0>;
print <-6, 6, 0>;
print <25, -10, 0>;