4
\$\begingroup\$

Background

Puzzlang is a derivative of Brainfuck, where the symbol X executes a BF command based on three characters on top of it, and anything else does nothing.

The following is the translation table for Puzzlang, where X is the literal X and . stands for anything else:

 >      <      +      -      .      ,      [      ]

..X    X..    XXX    ...    .X.    X.X    XX.    .XX
 X      X      X      X      X      X      X      X

Also, the entire source code wraps around both horizontally and vertically at the translation step. For example, the following code is an infinite loop:

XX X

since you can view the code like this (the dots are where the wrapped X's would go)

... ..
.XX X.

and matching with the translation table gives +[] for the three X's in order.

Nightmare Puzzlang is an evil twin of the regular Puzzlang. In Nightmare Puzzlang, each X translates into a byte based on its eight neighbors. Any non-X characters translate into nothing. The wrapping rule is the same.

Since there is no "official" specification, let's assume that the following pattern (where X denotes the one to translate)

abc
dXe
fgh

translates to abcdefgh in binary (X is one, non-X is zero). Then the following code

XX...
X..X.
X..XX
X..XX
X.XX.

translates to 4a b4 66 03 56 4b bf d2 6e fd c3 2c 70 in hex, or J´fVK¿ÒnýÃ,p as a string. Note that the resulting string will very likely have ASCII unprintables.

Task

Translate the given Nightmare Puzzlang code into a string.

Input & output

For input, you can take 2D array of chars, list of strings, or a single string whose lines are delimited by newlines. You can assume that the input is rectangular in shape, i.e. row lengths are equal.

For output, you can give a single string, a list of chars, or a list of charcodes.

Test Cases

Note that the result must remain the same when any of the dots are replaced with anything else other than the capital X.

X (1 row, 1 column)
String: ÿ
Charcode: [255]

X. (1 row, 2 columns)
String: B
Charcode: [66]

X
. (2 rows, 1 column)
String: 
Charcode: [24]

X.
.X
String: ¥¥
Charcode: [165, 165]

X.X
.X.
String: 1δ
Charcode: [49, 140, 165]

X.X
XX.
X.X
String: Ómεv«
Charcode: [211, 109, 206, 181, 118, 171]

X.XX.XXX..XXXX.
String: BkÖkÿÖkÿÿÖ
Charcode: [66, 107, 214, 107, 255, 214, 107, 255, 255, 214]

X.XX.XXX.XXXXX.
XX.X..XX....X..
String: c­R){Ö9Z”JµÆïÖç
Charcode: [99, 173, 82, 41, 123, 214, 8, 24, 57, 90, 148, 74, 181, 198, 239, 214, 231]

X
X
X
.
.
X
.
X
X
.
X
String: ÿÿøø
Charcode: [255, 255, 248, 24, 31, 248, 31]

XX
X.
XX
.X
.X
XX
..
XX
XX
..
.X
String: º]ç]ºâG¸Xøø
Charcode: [186, 93, 231, 93, 186, 226, 71, 184, 88, 31, 31, 248, 248, 7]

XX XXX XX  XX
X  X X X X X 
X  X X X X XX
X  X X X X X 
XX XXX XX  XX
             
XXX XXX X  XX
X   X X X  X 
X X X X X  XX
X X X X X  X 
XXX XXX XX X 
(11 rows, 13 columns, no extra padding, result has two newlines)
zôª}òªuJ½æbÂb‚cRBBBBJ½ÇCFCDcXH¸PH°H¸

æbÂBcRBBBJ½ÃFCFCbO¾UO¾UN”C
Charcode: [122, 244, 170, 125, 242, 170, 117, 74, 189, 230, 98, 194, 98, 130, 99, 82, 66, 66, 66, 66, 74, 189, 199, 67, 70, 67, 68, 99, 88, 144, 72, 184, 80, 72, 176, 72, 184, 26, 28, 16, 10, 29, 18, 2, 10, 29, 230, 98, 194, 66, 99, 82, 2, 66, 66, 66, 74, 189, 195, 70, 67, 70, 67, 98, 79, 190, 85, 79, 190, 85, 78, 148, 67]

Rules

Standard rules apply. The shortest submission in bytes wins.

\$\endgroup\$
1
\$\begingroup\$

Python 3, 166 162 161 bytes

lambda p,r=range:[chr(int(''.join(str(+([n*2for n in p+p][y+i//3-1][x+i%3-1]=='X'))for i in r(9)if i-4),2))for y in r(len(p))for x in r(len(p[0]))if'X'==p[y][x]]

Takes as input a list of strings and returns a character array.

Try It Online!

Ungolfed (sorta):

def f(p):
    chars = []
    for y in range(len(p)):
        for x in range(len(p[0])):
            if p[y][x] != 'X':
                continue
            bits = []
            for i in range(9):
                if i == 4:
                    continue
                bit_x = x + i%3 - 1
                bit_y = y + i//3 - 1
                char_at_cell = [n*2for n in p+p][bit_y][bit_x]
                bit = str(+(char_at_cell=='X'))
                bits.append(bit)
            char_code = int(''.join(bits), 2)
            chars.append(chr(char_code))
    return chars

Edit: made shorter by 5 bytes thanks to Jo King and Jonathan Frech

\$\endgroup\$
  • \$\begingroup\$ Since the function ins't recursive, you don't need to assign the lambda. 162 bytes \$\endgroup\$ – Jo King Sep 21 '18 at 6:46
  • \$\begingroup\$ oh nice, didn't know that you could remove that, cheers. Just writing up the ungolfed version and will add in your changes \$\endgroup\$ – Cameron Aavik Sep 21 '18 at 6:49
  • 1
    \$\begingroup\$ Note that the slash's orientation matters. You used / -- a slash -- to continue a line in C-style, use a backslash: \ . \$\endgroup\$ – Jonathan Frech Sep 23 '18 at 5:59
  • \$\begingroup\$ You can golf your one != to a -. \$\endgroup\$ – Jonathan Frech Sep 23 '18 at 6:01
0
\$\begingroup\$

JavaScript (ES6), 159 bytes

Takes input as a 2D array of characters. Returns an array of character codes.

f=M=>M.map((r,y)=>r.map((v,x)=>v>f&&o.push([...'22211000'].map((k,j)=>s|=(M[(y+h+~-k)%h][(x+w+~-'21020'[j%5])%w]>f)<<j,h=M.length,w=M[s=0].length)|s)),o=[])&&o

Try it online!

Commented

f = M =>                        // f = main function taking the input matrix
                                //     it is named because we are later using '>f'
  M.map((r, y) =>               // for each row r[] at position y in M[]:
    r.map((v, x) =>             //   for each value v at position x in r[]:
      v > f &&                  //     ignore this cell if v is not equal to 'X'
      o.push(                   //     otherwise, push a new value in o[]:
        [...'22211000']         //       iterate over dy values (+1)
        .map((k, j) =>          //       for each value k at position j in this array:
          s |= (                //         update s:
            M[(y + h +          //           compute the row
              ~-k)              //           by adding dy = k - 1
              % h]              //           and applying a modulo h
            [(x + w +           //           compute the column
              ~-'21020'[j % 5]) //           by adding dx = [2,1,0,2,0,2,1,0][j] - 1
              % w]              //           and applying a modulo w
            > f                 //           test whether this cell is a 'X'
          ) << j,               //         and set the corresponding bit in s if it is
          h = M.length,         //         initialize h = matrix height
          w = M[s = 0].length   //         initialize w = matrix width and s = bitmask
        ) | s                   //       end of map() over dy; yield s
      )                         //     end of push()
    ),                          //   end of map over r[]
    o = []                      //   initialize o = output array
  ) && o                        // end of map over M[]; return o
\$\endgroup\$

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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