15
\$\begingroup\$

RoboCritters (etymology) is a brand new esoteric programming language (don't bother searching for it, I just invented it). It's a variant of Brainfuck (BF), slightly more complex than the usual operator substitution schemes. Every program in RoboCritters is a rectangular grid of text that only contains the seven characters . []/\|, plus newlines to shape the grid.

Example RoboCritters program:

|\/||./|[]||
[..][][]   |
|/\|[..][..]
[..]    \/\/

To translate a RoboCritters program into BF, look at each non-newline character in the grid in the normal reading order (left-to-right then top-to-bottom), e.g. |\/||./|[]||[..][][] ||/\|[..][..][..] \/\/.

If the 4×2 section of the grid extending right and down from the current character exactly matches one of the eight robot critters listed below, append the corresponding BF command (><+-.,[]) to the (initially empty) BF program.

If the 4×2 grid section does not match any of the robot critters or goes out of bounds, nothing is added to the BF program.

  1. Joybot, > command:

    [..]
    \][/
    
  2. Calmbot, < command:

    [..]
    /][\
    
  3. Squidbot, + command:

    [..]
    //\\
    
  4. Spiderbot, - command:

    [..]
    ||||
    
  5. Bunnybot, . command:

    [][]
    [..]
    
  6. Toothbot, , command:

    [..]
    |/\|
    
  7. Foxbot, [ command:

    |\/|
    [..]
    
  8. Batbot, ] command:

    [..]
    \/\/
    

So, reading the example program

|\/||./|[]||
[..][][]   |
|/\|[..][..]
[..]    \/\/

we can see that we first encounter a Foxbot (at column 1, row 1), then a Toothbot (c1,r2), then a Bunnybot (c5,r2), and finally a Batbot (c9,r3). This corresponds to the BF program [,.].

Notice that the Foxbot and Toothbot overlap. This is intentional; robot critters are not interpreted any differently when they overlap.

Challenge

Write the shortest program possible that takes in a RoboCritters program and outputs its BF equivalent. You don't need to run the BF or check that it's valid, only translate the RoboCritters code to BF code.

Details

  • All input RoboCritters programs will be valid, that is they will be an exactly rectangular block of text only containing the seven characters . []/\|, plus newlines to shape it. The newlines may be in any convenient common representation. You may optionally assume the programs have a single trailing newline.

  • You must support RoboCritters programs that are smaller than 4×2, including the 0×0 empty (or single newline) program. These all correspond to the empty BF program (the empty string).

  • The output BF program should be a one-line string only containing the eight BF command characters ><+-.,[]. There may optionally be a single trailing newline.

  • Take input in any usual way (stdin/text file/command line) and output to stdout or your language's closest alternative.

  • Instead of a program you may write a function that takes the RoboCritters program as a string and prints or returns the BF program string.

Examples

  1. Input: (variant of example above)

    |\/|[][]
    [..][][]
    |/\|[..]
        \/\/
    

    Output: [,.]

  2. Input: (tests all robot critters)

    [..][[[[[..]]. ]|\/|
    \][/[..]//\\[..][..]
    [..]/][\[][]|/\|[..]
    ||||/\| [..]|  |\/\/
    

    Output: >+[<,-.]

  3. Input:

    [..] [..] [..] [..] [..] [..] [..] [..] |\/| [..] [..] [..] [..] [..] |\/| [..] [..] [..] [..] [..] [..] [..] [..] [..] [..] [..] [..] [..] [..] [..] [..] [..] [..] [..] [..] [..] [..] [..] [..] [..] [..] [..] [..] |\/| [..] [..] [..] [..] [..] [..] [..] [][] [..] [..] [..] [..] [][] [..] [..] [..] [..] [..] [..] [..] [][] [][] [..] [..] [..] [][] [..] [..] [][] [..] [..] [][] [..] [][] [..] [..] [..] [][] [..] [..] [..] [..] [..] [..] [][] [..] [..] [..] [..] [..] [..] [..] [..] [][] [..] [..] [..] [][] [..] [..] [..] [][]
    //\\ //\\ //\\ //\\ //\\ //\\ //\\ //\\ [..] \][/ //\\ //\\ //\\ //\\ [..] \][/ //\\ //\\ \][/ //\\ //\\ //\\ \][/ //\\ //\\ //\\ \][/ //\\ /][\ /][\ /][\ /][\ |||| \/\/ \][/ //\\ \][/ //\\ \][/ |||| \][/ \][/ //\\ [..] /][\ \/\/ /][\ |||| \/\/ \][/ \][/ [..] \][/ |||| |||| |||| [..] //\\ //\\ //\\ //\\ //\\ //\\ //\\ [..] [..] //\\ //\\ //\\ [..] \][/ \][/ [..] /][\ |||| [..] /][\ [..] //\\ //\\ //\\ [..] |||| |||| |||| |||| |||| |||| [..] |||| |||| |||| |||| |||| |||| |||| |||| [..] \][/ \][/ //\\ [..] \][/ //\\ //\\ [..]
    

    Output: (BF Hello World program)

    ++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
    
  4. Input: (no robot critters present)

    /\\\[].
    ]..[..]
    \\//||\
    

    Output: (empty string)

Scoring

The shortest submission in bytes wins. (Handy byte counter.) Tiebreaker is highest voted post.

\$\endgroup\$
0

2 Answers 2

9
\$\begingroup\$

CJam, 86 85 bytes

qN/S4*f+_W<\1>]z:z4few:~"¨Ý³5&ágûò{wÉ](Ý"296b6b"|[\.]/"f=2/4/"><+-.,[]":Ler{L&},

Test it here.

Explanation

qN/    e# Read input and split into lines.
S4*f+  e# Append four spaces to each line. This has two purposes. a) We can later join all
       e# the lines together without worrying about critters appearing across the line
       e# edges because no critter contains spaces. b) It works around a bug in CJam where
       e# the command `ew` crashes when the substring length is longer than the string.
_W<    e# Copy the lines and discard the last one.
\1>    e# Swap with the other copy and discard the first one.
]z     e# Wrap both in an array and zip them up. Now we've got an array which contains
       e# all consecutive pairs of lines.
:z     e# Zip up each of those pairs, such it becomes an array of two-character strings.
       e# We can now find the critters as 4-element subarrays in each of those arrays.
4few   e# Turn each of those arrays into a list of its (overlapping) 4-element subarrays.
:~     e# Flatten those lists, such that we get one huge array of all 4x2 blocks, in order.
"gibberish"296b6b
       e# This is an encoded form of the critters. The above produces a string of the
       e# critters in column-major order, all joined together, where the characters are
       e# represented by numbers 0 to 5.
"|[\.]/"f=
       e# Turn each number into the correct character.
2/4/   e# Split first into columns, then into critters. Now all we need to do is find these
       e# the elements of this array in the processed input.
"><+-.,[]":L
       e# A string of all BF characters in the same order as the critters. Store this in L.
er     e# Do an element-wise replacement. This will leave non-critter blocks untouched.
{L&},  e# Filter the result. The elements are now either characters, or still full 4x2
       e# blocks. We take the set intersection with the array (string) of BF characters.
       e# If the current element is itself a character, it will be coerced into an array
       e# containing that character, such that we get a non-empty intersection. If the
       e# current element is a block instead, if contains arrays itself, so the set
       e# intersection will always be empty.

       e# The resulting array of characters is the desired BF program and will be printed
       e# automatically at the end of the program.

The critters were encoded with this script. I found the base 296 for the encoding with the following, rather naive Mathematica script (which is still running in search for a better base):

b = 256;
While[True,
  If[
    FreeQ[
      d = IntegerDigits[15177740418102340299431215985689972594497307279709, b], 
      x_ /; x > 255
    ], 
    Print@{b, Length@d}
  ];
  b += 1;
]
\$\endgroup\$
4
\$\begingroup\$

JavaScript ES6, 209 198 192 bytes

f=c=>{s=''
b=o=>c.substr(o,4)||1
for(i in c)s+=!~(d='1\\][/1/][\\1//\\\\1||||[][]11|/\\||\\/|11\\/\\/'.replace(/1/g,'[..]').indexOf(b(i)+b(++i+c.search(`
`))))|d%8?'':'><+-.,[]'[d/8]
return s}

The Stack Snippet below contains ungolfed code that you can easily run in any browser.

var f = function(c) {
  var s = '';
  var b = function(o) {
    // If it is looking on the last line, this will return an empty string
    // the second time, which could cause an inaccurate match.
    // `||1` makes it return 1 instead of '', which won't match.
    return c.substr(o, 4) || 1;
  }
  for (var i in c) {
    r = b(i) + b(++i + c.search('\n'));
    d = '1\\][/1/][\\1//\\\\1||||[][]11|/\\||\\/|11\\/\\/'.replace(/1/g, '[..]').indexOf(r);
    s += !~d || d % 8 ? '' : '><+-.,[]' [d / 8];
  }
  return s;
}

// GUI code below
function run(){document.getElementById('s').innerHTML=f(document.getElementById('t').value);};document.getElementById('run').onclick=run;run()
<textarea id="t" cols="30" rows="10">
[..][[[[[..]]. ]|\/|
\][/[..]//\\[..][..]
[..]/][\[][]|/\|[..]
||||/\| [..]|  |\/\/</textarea><br /><button id="run">Run</button><br /><code id="s"></code>

\$\endgroup\$

Your Answer

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

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