16
\$\begingroup\$

2fuck is a simple 2D variation on brainfuck. Like traditional brainfuck, there is an 1D memory tape that extends 30000 bytes to the right from its beginning, consisting of values between 0 and 255.

Arithmetic should wrap around, adding 1 to 255 sets the cell to 0, and moving right from memory cell 29999 should move the pointer back to 0. The converse should happen when decrementing or moving left.

The input is an 1D unidirectional string/stream.

It has the following commands:

  • < change the direction of the instruction pointer to left.
  • > change the direction of the instruction pointer to right.
  • ^ change the direction of the instruction pointer to up.
  • v change the direction of the instruction pointer to down.
  • [ decrement the data pointer.
  • ] increment the data pointer.
  • - decrement the value of the tape under the data pointer.
  • + increment the value of the tape under the data pointer.
  • ? if the value under the data pointer is not 0, rotate the instruction pointer counterclockwise 90 degrees.
  • . Output the value of the tape under the data pointer as a character.
  • , Read a character from standard input and copy it to the position in the tape under the data pointer. If EOF is reaches this should NOOP.
  • Any other character should be ignored.

The instruction pointer starts in the top left corner, moving right, execution terminates if it ever goes out of bounds in any direction, aka when it would be impossible to reach any more instructions.

The program can be passed to the interpreter as a two dimensional array or a simple string featuring line breaks. The input might be passed as an additional parameter or concatenated to the program with a separator like a null byte. However, do not assume that all lines in the program are the same length.

Test cases

"Hello World"

v                >]++]+++]+++]+[[[[-v
v                           >[v
v         >]++++>?]+]+]-]]+>?[ -v
>++++++++>?]].]- --.+++++++ .. + ++. ]].[-.[.+++.------.--------.]]+.]++.
         ^                      <
                           ^  <
                ^                   <

Cat

Copies the input to the output

v     >-v
v  >.>?, v
>,>?
  ^      <
     ^  <

Print the ASCII code page

Thanks Matteo_C

v      >-[v
v   >->?]] +[v
v                          >-[++++]v
v                             >-[[. +]]v
v                                            >-v
v                 >-]]++++>?[>?++++ +++ +++.>?[ v
>]->?] -]+ ++ +++>?
                 ^                              <
                                            ^  <
                             ^         <
                          ^        <
   ^         <
      ^   <
\$\endgroup\$
14
  • \$\begingroup\$ How is the program passed to the interpreter? Can we say that it's in a two dimensional array? Or must the input be in a single string? \$\endgroup\$
    – raddish0
    Commented Jan 23, 2023 at 15:35
  • 2
    \$\begingroup\$ @Jacob Going out of the sides of the rectangle covering the multi-line string \$\endgroup\$
    – mousetail
    Commented Jan 23, 2023 at 15:59
  • 1
    \$\begingroup\$ What if the top left corner cell is not > nor v? \$\endgroup\$ Commented Jan 23, 2023 at 19:55
  • 1
    \$\begingroup\$ @VictorStafusa-BozoNaCadeia You may not assume all lines are the same length, but it's your choice if you deal with this by padding or skip these lines in a different way \$\endgroup\$
    – mousetail
    Commented Jan 24, 2023 at 5:38
  • 2
    \$\begingroup\$ codegolf.meta.stackexchange.com/a/25275/91213 \$\endgroup\$
    – mousetail
    Commented Jan 24, 2023 at 13:59

8 Answers 8

9
\$\begingroup\$

C (gcc), 317 268 250 bytes

X,Y=1;E;Z['zz'];P;*Q=Z;main(M,s)char**s;{for(;Q=(Q-Z+'u0')%'u0'+Z,X+0u<Y*(E=strlen(s[Y]),M=M<E?E:M);P%2?Y-=2-P%4:(X+=1-P%4))X<E?write(E=s[Y][X]-45,Q,1),P=E-15?E-17?E-49?E-73?P+(E==18&&*Q%256):3:1:0:2,E-46?E-48?E?E+2?read(~E,Q,1):++*Q:--*Q:++Q:--Q:0;}

Try it online!

60 bytes saved(45 direct + some indirect) by c--

Segfault when going down outside of range, correct output

Assume only stdin and stdout. (/ writes to stderr, but it's fine to ignore them)

\$\endgroup\$
7
  • \$\begingroup\$ building on @ceilingcat's suggestion: 263 \$\endgroup\$
    – c--
    Commented Jan 26, 2023 at 0:02
  • \$\begingroup\$ Alternative pointer :(Q-='u/'):--Q Q+=Q<Z?'u0':0 \$\endgroup\$
    – l4m2
    Commented Jan 26, 2023 at 0:30
  • \$\begingroup\$ X+0u<Y%n*(E=strlen(s[Y]),M=M<E?E:M) will segfault if Y == n (s[n] = NULL), which is why I suggested Y%n&&X+0u<(E=strlen(s[Y]),M=M<E?E:M) instead. But I think it's acceptable for the program to segfault as long as it produces the expected output; the only problem might be that it relies on IO being unbuffered. \$\endgroup\$
    – c--
    Commented Jan 26, 2023 at 3:32
  • \$\begingroup\$ @c-- Then extra 2 bytes saved \$\endgroup\$
    – l4m2
    Commented Jan 26, 2023 at 3:52
  • \$\begingroup\$ @c-- Do read(E,Q,1) works fine? \$\endgroup\$
    – l4m2
    Commented Jan 26, 2023 at 4:01
8
\$\begingroup\$

Vyxal, 113 bytes

₌L↵r⅛⅛k2T0ẋ⅛k≈N→0{:k□i←+:¾hÞẏ$c¬ßQ→¾h←Þi:¨□›[¨□N$_|`?.,+-][`$v=÷N+&+N+^¼¥k2T%:£~i„+„[¼ḣ⅛:[C$]_]₈%:‟Ȧ⟑;⅛^$[:C₴]∧[‹

Try it Online!

It takes the program as a string and the input as a string. Here is a version with 90 cells.

₌L↵            # parallel apply length and split on newline
   r           # pad with spaces to given length 
    ⅛          # push to global array
     ⅛         # push input to global array
k2T0ẋ⅛         # push a list of 30000 zeros to global array 
k≈N→           # save [0, -1] to a variable with empty name
    0          # push 0
# Together this sets up the global array as [code, input, tape],
# the position in a variable and the direction on stack.
{              # start a while loop
 :             # duplicate
  k□i          # index into [[0,1],[1,0],[0,-1],[-1,0]]
     ←         # load variable
      +        # add
# Stack: direction position
:→             # duplicate and store variable
  ¾h           # push the global array and get the first item, this     pushes code
    Þẏ         # multidimensional indices
      $c       # check if it contains current position
        §Q    # if not stop execution
# Stack: direction
¾h←            # push code and position
   Þi          # index into, this gets the current instruction
     :¨□›[     # if it is an arrow:
¨□N$_          #   convert to integer, negate and remove the previos direction from the stack
     |         # else:
`?.,+-][`$v=÷  #   for each of the characters in the string push 1 if it's equal to current instruction and 0 otherwise
# Stack: direction ? . , + - ] [
N              #   negate
 +             #   sum the top two elements
  &+           #   add top of stack to the register (the register represents the data pointer)
    N+         #   negate and add
      ^        #   reverse the stack
       ¼       #   pop from global array
        ¥      #   push register
# Stack: value_delta , . ? direction tape ptr
30T%:£         #   modulo 30000 and store to the register
      ~i       #   index into without popping
# Stack: value_delta , . ? direction tape ptr value
„+             #   rotate stack left and add
  „            #   rotate stack left
   [           #   if the instruction was ",":
    ¼ḣ⅛        #     pop from global array, extract head, push to global array
               #       this gets the next character from input
       :[C$]_  #     if non-empty conver to number and replace the current value
             ] #   end if
# Stack: . ? direction tape ptr value
₈%             #   modulo 256
  :‟           #   duplicate and rotate stack right
    Ȧ          #   tape[ptr] = value
     ⟑;⅛       #   push tape to global array
        ^$     #   reverse stack and swap the top two items
# Stack: direction ? value .
[:C₴]          #  if instruction was "." print value
     ∧[‹       #  if value != 0 and the instruction was "?" decrement direction
\$\endgroup\$
7
\$\begingroup\$

JavaScript (ES6), 224 bytes

-16 thanks to @l4m2
+8 to deal with unpadded input :-(

Expects (code)(input), where code is an array of strings and input is an array of bytes. Returns another array of bytes.

c=>i=>{for(o=[],T=[x=y=d=p=j=0];c[v=T[p%=3e4]&=255,y]+0&&(c+0)[x];d&=3,x-=~-d%2,y+=~-~-d%2)(q='?[]-+.,v>^<'.indexOf(c[y][x]))>6?d=q:eval("d+=!!v;p+=29999;p++;T[p]--;T[p]++;o.push(v);T[i[j]*0+p]=i[j++]".split`;`[q]);return o}

Try it online!

Commented

Main code

c =>                      // c[] = code, as a list of strings
i => {                    // i[] = input array
  for(                    // main loop:
    o = [],               //   o[] = output array
    T = [                 //   T[] = tape array
      x = y =             //   (x, y) = position of the program pointer
      d =                 //   d = direction
                          //       (0:right, 1:up, 2:left, 3:down)
      p =                 //   p = tape pointer
      j = 0               //   j = input pointer
    ]                     //
    ;                     //   before each iteration:
    c[v = T[p %= 3e4]     //     force the tape pointer in [0 .. 29999]
          &= 255,         //     coerce the current tape cell to a byte
      y                   //     and save it in v
    ] + 0 && (c + 0)[x]   //     stop if we're out of bounds
    ;                     //   after each iteration:
    d &= 3,               //     force d in [0 .. 3]
    x -= ~-d % 2,         //     x <- x + dx
    y += ~-~-d % 2        //     y <- y + dy
  )                       //   at each iteration:
    ( q =                 //     let q be the index
        '?[]-+.,v>^<'     //       in this lookup string
        .indexOf(c[y][x]) //       of the current instruction
    ) > 6 ?               //     if this is a direction instruction:
      d = q               //       update d accordingly
    :                     //     else:
      eval(               //       evaluate some specific code
        "..."             //       (detailed below)
        .split`;`[q]      //       for this instruction, or just do
      );                  //       eval(undefined) if unrecognized
  return o                // end of loop: return the output string
}                         //

Instructions

d += !!v                  // '?': conditional 90° turn
p += 29999                // '[': decrement the tape pointer
p++                       // ']': increment the tape pointer
T[p]--                    // '-': decrement the value of the tape
T[p]++                    // '+': increment the value of the tape
o.push(v)                 // '.': output the value of the tape
T[i[j] * 0 + p] = i[j++]  // ',': load a new value from the input
\$\endgroup\$
2
  • \$\begingroup\$ 243 \$\endgroup\$
    – l4m2
    Commented Jan 24, 2023 at 4:50
  • \$\begingroup\$ 1 / i[j] && p => i[j]*0+p \$\endgroup\$
    – l4m2
    Commented Jan 24, 2023 at 19:13
6
\$\begingroup\$

Python, 264 260 bytes

-4 bytes thanks to @gsitcia by replacing r,x,y,p=[0]*4 with r=x=y=p=0

def g(i,t,L=30000):
 d,c=[0]*L,-1;r=x=y=p=0
 while x*y>=0:
  if(s:="v<^>[]-+?.,".find(i[y][x]))==9:print(chr(d[p]))
  d[p]=s>9and-~c<len(t)and ord(t[c:=c+1])or(d[p]+(s==7)-(s==6))%256;r=[r-(s==8and 0<d[p]),s][0<=s<4]%4;x+=r-2&-r;y+=7%~r+1;p=(p+(s==5)-(s==4))%L

Attempt This Online!

Since the utilities in Python for taking in single characters from standard input are bad, this program instead takes in the input as a string (and the instructions as a list of strings or a 2D array of characters). It terminates with an error if the pointer goes off the right or bottom edge of the instructions.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ You can save 4 bytes by replacing r,x,y,p=[0]*4 with r=x=y=p=0 \$\endgroup\$
    – gsitcia
    Commented Jan 24, 2023 at 20:25
5
\$\begingroup\$

JavaScript

422...396 425...372 bytes

f=q=>i=>{k=q.split`
`;x=[a=b=p=n=t=d=0,1,0,-1,0];k.every(o=>t=Math.max(t,o.length));m=Array(z=3e4).fill(0);for(u="";a<t&b<k.length&a>=0&b>=0;m[p%=z]&=255,b-=x[d&=3],a+=x[1+d])(c=k[b][a])=="["?p++:c=="]"?p+=z-1:c=="+"?m[p]++:c=="-"?m[p]--:c=="."?u+=String.fromCharCode(m[p]):c==","&n<i.length?m[p]=i.codePointAt(n++):c=="?"&&m[p]?d++:d=(e=">^<v".indexOf(c))+1?e:d;return u}

Although JS is not the best language for golfing, it is fun for not being something too obscure and is one where many people would actually try to understand what is going on. In fact, is the most used programming language in the world, so it should not be missed.

If you really want to see all of that running, just click the "Show code snippet" link below and then hit the "Run snippet button" button.

In the snippet code (see below), for legibility, I added spaces and new lines. For golfing purposes, those should not be counted. All but one of the spaces and all but one of the line breaks are unnecessary. So I present the code with spaces and line breaks and remove them before actually running. Also, I added a lot of JS, HTML and CSS for easy testing with different programs and different inputs. Feel free to reuse them if you want to.

// Here is the code. For legibility, I added spaces and new lines.
// For golfing purposes, those should not be counted.
// All but one of the spaces are unnecessary.

/// Starts here.
w = q => i => {
  k = q.split`
`;
  x = [a = b = p = n = t = d = 0, 1, 0, -1, 0];
  k.every(o => t = Math.max(t, o.length));
  m = Array(z = 3e4).fill(0);
  for (
      u = "";
      a < t & b < k.length & a >= 0 & b >= 0;
      m[p %= z] &= 255, b -= x[d &= 3], a += x[1 + d]
  ) (c = k[b][a]) == "[" ? p++
      : c == "]" ? p += z - 1
      : c == "+" ? m[p]++
      : c == "-" ? m[p]--
      : c == "." ? u += String.fromCharCode(m[p])
      : c == "," & n < i.length ? m[p] = i.codePointAt(n++)
      : c == "?" && m[p] ? d++
      : d = (e = ">^<v".indexOf(c)) + 1 ? e : d;
  return u
}
/// Ends here.

// How many characters? Take out the spaces and new lines and count them.
// We prepend the "f=" because it would be unfair to not count them.
// We call it f instead of w to ensure that f is the variant without
// spaces and line breaks. The only significant space are the "return u"
// and the `\n` which I special case for them.
const code = ("f=" + w.toString())
    .replace(/ |\n/gi, "")
    .replace("returnu", "return u")
    .replace("``", "`\n`");
const howMany = code.length;
eval(code); // Make f come to existence.
document.querySelector("#howMany").value = "" + howMany;
document.querySelector("#golfed").value = code;

// The Let's run button.
document.querySelector("#run").onclick = () => {
  const program = document.querySelector("#program").value;
  const input = document.querySelector("#input").value;
  const output = f(program)(input);
  document.querySelector("#output").value = output;
}

// Convenience for preloading Hello World, cat and ascii table example programs.

const loader = t => () => document.querySelector("#program").value = t;

const helloWorld = [
  "v                >]++]+++]+++]+[[[[-v",
  "v                           >[v",
  "v         >]++++>?]+]+]-]]+>?[ -v",
  ">++++++++>?]].]- --.+++++++ .. + ++. ]].[-.[.+++.------.--------.]]+.]++.",
  "         ^                      <",
  "                           ^  <",
  "                ^                   <"
].join("\n");
document.querySelector("#helloWorld").onclick = loader(helloWorld);

const cat = [
  "v     >-v",
  "v  >.>?, v",
  ">,>?      ",
  "  ^      <",
  "     ^  <"
].join("\n");
document.querySelector("#cat").onclick = loader(cat);

asciiTable = [
  "v      >-[v",
  "v   >->?]] +[v",
  "v                          >-[++++]v",
  "v                             >-[[. +]]v",
  "v                                            >-v",
  "v                 >-]]++++>?[>?++++ +++ +++.>?[ v",
  ">]->?] -]+ ++ +++>?",
  "                 ^                              <",
  "                                            ^  <",
  "                             ^         <",
  "                          ^        <",
  "   ^         <",
  "      ^   <"
].join("\n");
document.querySelector("#asciiTable").onclick = loader(asciiTable);
/*
    I used the StackOverflow snippet for making testing easier,
    and I also added a few CSS and HTML for that. Feel free to reuse
    it for other answers.
*/

all {
    width: 100%;
    padding-left: 10px;
    padding-right: 10px;
}

div, input:not(#howMany), textarea {
    width: 90%;
}

textarea {
    height: 200px;
}

.warning {
    color: red;
}

button {
    width: 50%;
}
<!--
    I used the StackOverflow snippet for making testing easier,
    and I also added a few CSS and HTML for that. Feel free to reuse
    it for other answers.
-->

<div class="all">
    <h2>How many characters?</h2>
    <input type="text" readonly="true" id="howMany" />

    <h2>How is it golfed</h2>
    <input type="text" readonly="true" id="golfed" />

    <h2>Type the program here</h2>

    <textarea id="program"></textarea>
    
    <button id="helloWorld">Load a Hello World program above</button>
    <br>
    <button id="cat">Load the cat program above</button>
    <br>
    <button id="asciiTable">Load the ASCII table dumper program above</button>

    <h2>Type the input here</h2>
    <input type="text" id="input" value="Some cool input here!"/>

    <h2>And finally...</h2>

    <button id="run">Let's run!</button>

    <div>This is the output</div>
    <textarea type="text" readonly="true" id="output" /></textarea>
</div>

Contributions from comments:

q.split("\n"); can be q.split`\n`; for -2. –  Kevin Cruijssen

I think what @KevinCruijssen meant was q.split`literal newline`; –  Jacob

\$\endgroup\$
3
  • 1
    \$\begingroup\$ q.split("\n"); can be q.split`\n`; for -2. \$\endgroup\$ Commented Jan 25, 2023 at 7:55
  • 3
    \$\begingroup\$ I think what @KevinCruijssen meant was q.split`literal newline`; \$\endgroup\$ Commented Jan 26, 2023 at 0:08
  • 1
    \$\begingroup\$ @Jacob Ah, I did had \n in my head, but a literal newline is indeed even 1 byte less. Forgot about that tbch. :) \$\endgroup\$ Commented Jan 26, 2023 at 7:44
4
\$\begingroup\$

Pyth, 191 bytes

K*30000]0JE=.tQd=G,ZZ=H,1ZW.A+-VlMhBQGhMG=Y@@QhGeG=T@KZ [&qY\v=H,01&qY\^=H,0_1&qY\<=H,_1 0&qY\>=H,1 0&&TqY\?=H,eH_hH &qY\[=tZ&qY\]=hZ&qY\-XZK_1&qY\+XZK1&qY\.pC@KZ&qY\,&J,XKZChJ=tJ=+VGH=%R255K

Try it online!

Could definitely be golfed some more. Takes the program as an array of strings first, and any input as the second input. It's very slow since the whole tape is run through mod 255 on every instruction, but here's a TIO link to a version with a tape of length 30 which doesn't time out.

\$\endgroup\$
0
4
\$\begingroup\$

Charcoal, 126 bytes

WS⊞υιUO⌈EυLιLυ P⪫υ¶≔⪪⮌S¹θ≔E׳⁰φ⁰η≔⁰ζ≔⁰εWKK«≔﹪§ηζ²⁵⁶δ≡ι<≔⁴ε>≔⁰ε^≔²εv≔⁶ε[≦⊖ζ]≦⊕ζ-§≔ηζ⊖δ+§≔ηζ⊕δ?≧⁺∧δ²ε.≔⁺ω℅δω,F¬¬θ§≔ηζ℅⊟θP⁰M✳ε»⎚ω

Try it online! Link is to verbose version of code. Takes the program as a list of newline-terminated strings, then the input follows after a blank line (if there is no input you need a second blank line). Explanation:

WS⊞υι

Input the program.

UO⌈EυLιLυ 

Fill a rectangle of the canvas with spaces.

P⪫υ¶

Overprint the program without moving the cursor.

≔⪪⮌S¹θ

Split the input into characters and reverse it.

≔E׳⁰φ⁰η

Create an array of 30,000 cells.

≔⁰ζ

Initialise the data pointer.

≔⁰ε

Initialise the direction pointer.

WKK«

Repeat while the current instruction is not off limits.

≔﹪§ηζ²⁵⁶δ

Get the value of the cell at the data pointer, modulo 256.

≡ι

Switch over the current instruction.

<≔⁴ε

If it's a < then set the direction pointer to left.

>≔⁰ε

If it's a > then set the direction pointer to right.

^≔²ε

If it's a ^ then set the direction pointer to up.

v≔⁶ε

If it's a v then set the direction pointer to down.

[≦⊖ζ

If it's a [ then decrement the data pointer.

]≦⊕ζ

If it's a ] then increment the data pointer.

-§≔ηζ⊖δ

If it's a - then decrement the cell at the data pointer.

+§≔ηζ⊕δ

If it's a + then increment the cell at the data pointer.

?≧⁺∧δ²ε

If it's a + and the current cell is nonzero then rotate the direction pointer.

.≔⁺ω℅δω

If it's a . then append the character of the current cell to the output string.

,F¬¬θ§≔ηζ℅⊟θ

If it's a , and the input is not empty then replace the current cell with the ordinal of the next input character.

P⁰

Otherwise do nothing. (The newer version of Charcoal on ATO supports switch_delimited which avoids this but itself requires two extra bytes anyway.)

M✳ε

Move one step in the current direction.

»⎚ω

Clear the canvas and print the final output string.

\$\endgroup\$
1
  • \$\begingroup\$ The is actually unnecessary but the deverobsifier doesn't know that... \$\endgroup\$
    – Neil
    Commented Jan 27, 2023 at 1:17
2
\$\begingroup\$

Java 10, 343 339 336 317 bytes

m->i->{int l=0,M=30000,x=0,y=0,p=0,d=0,c,I=0,q;for(var t=new byte[M];;d=(q=">^<v?".indexOf(c))<0?d:q>3?t[p]!=0?-~d%3:d:q,p+=c==91?1:c==93?M-1:0,t[p%=M]-=c>42&c<46?c-44:0,System.out.print(c==46?(char)t[p]:""),y+=d%2-d%3%2*2,x+=3%-~d-d-~d%2)if((c=x>=(q=m[y].length)&(l=q>l?q:l)>x?0:m[y][x])==44&I<i.length)t[p]=i[I++];}

-3 bytes thanks to @ceilingcat.

Input 2fuck program as a 2D array of bytes, and optional input-characters as a second byte-array. Stops the execution of the input-programs with ArrayIndexOutOfBoundsExceptions.

Try it online.

Explanation:

m->i->{                   // Method with byte-matrix & byte-array parameters and no return
  int l=0,                //  Longest line integer, starting at 0
      M=30000,            //  Memory size, set to 30,000
      x=0,y=0,            //  x,y-coordinates, starting at 0,0
      p=0,                //  Data pointer integer, starting at 0
      d=0,                //  Direction integer, starting at 0 (right)
      c,                  //  Character value, uninitialized
      I=0,                //  Index integer for potential inputs, starting at 0
      q;                  //  Temp integer, uninitialized
  for(var t=new byte[M]   //  Tape byte-array, starting at 30k amount of 0s
      ;                   //  Start an infinite loop:
      ;                   //    After every iteration:
       d=                 //     Update the direction to:
         (q=">^<v?".indexOf(c))
                          //      Set `q` to the index of the character in ">^<v?",
                          //      or -1 if the character is not in this String
         <0?              //      If this `q` is -1, thus not one of those characters:
            d             //       Keep the direction the same
         :q>3?            //      Else-if `q` is 4 (thus '?'):
              t[p]!=0?    //       If the current tape-value at the pointer is 0:
               -~d%3      //        Set the direction to (d+1)%3 (90 degrees counterclockwise)
              :           //       Else ('?', but the tape-value is 0):
               d          //        Keep the direction the same
         :                //       Else (`q` is one of 0,1,2,3 / >,^,<,v):
          q,              //        Set the direction accordingly to this `q`
       p+=                //     Increase the data-pointer by:
          c==91?          //      If the character is '[':
           1              //       Increase the data pointer by 1
          :c==93?         //      Else-if the character is ']':
           M-1            //       Increase the data pointer by 29,999
          :               //      Else (a different character):
           0,             //       Keep the data pointer the same by increasing with 0
       t[p%=M             //     Modulo the data pointer by 30,000
             ]-=          //     Decrease the tape-value at the data pointer by:
                c>42&c<46?//      If the character is 43/44/45 (+/,/-):
                 c-44     //       Decrease it by c-44 (+→-1; ,→0; -→1)
                :         //      Else (a different character):
                 0,       //       Keep the tape-value the same by decreasing with 0
       System.out.print(  //     Print to STDOUT:
         c==46?           //      If the character is '.':
          (char)          //       Convert the following integer to a character:
                t[p]      //        The tape-value at the current data pointer
         :                //      Else (a different character)
          ""),            //       Print an empty string (aka nothing) instead
       y+=d%2-d%3%2*2,    //     Update `y` based on the direction†
       x+=3%-~d-d+-~d%2)  //     Update `x` based on the direction†
    if((c=                //   Set `c` to:
          (q=m[y].length) //    Set `q` to length of the current line
          <=x             //    Check whether `x` is out of bounds for the current line
          &(l=            //    Set `l` to:
              q>l?        //     If `q` (length of the current line) is larger than `l`:
               q          //      Set `l` to this new longest line `q`
              :           //     Else (the current line is shorter than `l`):
               l)         //      Keep `l` the same
           >x             //    Check whether this `l` is larger than `x`
             ?            //    If both these checks were truthy (so `x` is out of bounds
                          //    for the current line, but in bounds for the longest line):
              0           //     Set `c` to 0
             :            //    Else:
              m[y][x]     //     If `x` is in bounds for the current line:
                          //      Set `c` to the `x,y`'th character of the input-program
                          //     If `x` is out of bounds for the full program-block:
                          //      Stop the program with an ArrayIndexOutOfBoundsException
       )==44              //   If the current character `c` is ','
       &I<i.length)       //   and there are input-characters left:
         t[p]=            //    Set the tape-value of the current data pointer to:
              i[I         //     The current input-character (at index `I`)
                 ++];}    //     And increase index `I` by 1 afterwards with `I++`

d is used to update the x,y-coordinate like this:
(I'm pretty bad at magic numbers, so both can most likely be golfed)

d d%2 d%3 d%3%2 d%3%2*2 d%2-d%3%2*2 y
\$0\$ 0 0 0 0 \$0\$ y
\$1\$ 1 1 1 2 \$-1\$ y-1
\$2\$ 0 2 0 0 \$0\$ y
\$3\$ 1 0 0 0 \$1\$ y+1
d -~d 3%-~d 3%-~d-d ~d ~d%2 3%-~d-d-~d%2 x
\$0\$ 1 0 0 -1 -1 \$1\$ x+1
\$1\$ 2 1 0 -2 0 \$0\$ x
\$2\$ 3 0 -2 -3 -1 \$-1\$ x-1
\$3\$ 4 3 0 -4 0 \$0\$ x
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.