10
\$\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\$
0

4 Answers 4

3
+200
\$\begingroup\$

APL (Dyalog Unicode), 57 bytes

¯1~⍨,1↓∘⍉∘⌽⍣4⊢{2 2⌷⍵:2⊥(~¯9↑5↑1)/,⍵⋄¯1}⌺3 3⊢⍉∘(¯1∘↑⍪⊢⍪1∘↑)⍣2⊢'X'=⎕

Try it online!

A full program which takes a binary matrix through STDIN, returns an array of codepoints.

Explanation

x¯1~⍨,1↓∘⍉∘⌽⍣4⊢{2 2⌷⍵:2⊥(~¯9↑5↑1)/,⍵⋄¯1}⌺3 3⊢⍉∘(¯1∘↑⍪⊢⍪1∘↑)⍣2⊢'X'=⎕

take input

'X'= boolean matrix where 'X's are 1s

⍉∘(...)⍣2⊢ do the following twice:

¯1∘↑⍪⊢⍪1∘↑ pad each row with its wraparound on both sides

⍉∘ and transpose

{...}⌺3 3⊢ then, do the following for each 3x3 window:

2 2⌷⍵: if the middle element is 1:

2⊥(~¯9↑5↑1)/,⍵ decode the rest of the window as binary

⋄¯1 Otherwise, return ¯1.

⍣4⊢ Do the following 4 times:

1↓∘⍉∘⌽ rotate 90°, drop first row (remove the border cells)

, flatten into a simple array

¯1~⍨ remove all ¯1s

\$\endgroup\$
2
\$\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\$
2
\$\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\$
4
  • \$\begingroup\$ Since the function ins't recursive, you don't need to assign the lambda. 162 bytes \$\endgroup\$
    – Jo King
    Commented Sep 21, 2018 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\$ Commented Sep 21, 2018 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\$ Commented Sep 23, 2018 at 5:59
  • \$\begingroup\$ You can golf your one != to a -. \$\endgroup\$ Commented Sep 23, 2018 at 6:01
1
\$\begingroup\$

Jelly, 19 bytes

=”Xµ-r1p`ẸƇ+ⱮŒṪœịµḄ

A monadic Link that accepts a list of the lines and yields a list of code-points.

Try it online!

How?

=”Xµ-r1p`ẸƇ+ⱮŒṪœịµḄ - Link: lines
 ”X                 - character = 'X'
=                   - equals? -> binary matrix from lines with X:1 and .:0
   µ             µ  - monadic chain - f(v=that):
    -               -   -1
      1             -   1
     r              -   inclusive range = [-1, 0, 1]
        `           -   use as both arguments of:
       p            -     Cartesian product
                               = [[-1,-1],[-1,0],[-1,1],[0,-1],[0,0],[0,1],[1,-1],[1,0],[1,1]]
          Ƈ         -   keep those for which:
         Ẹ          -     any? = [[-1,-1],[-1,0],[-1,1],[0,-1],[0,1],[1,-1],[1,0],[1,1]]
             ŒṪ     -   multidimensional truthy indices (v)
            Ɱ       -   map across these with:
           +        -     add
               œị   -   index into (v)
                  Ḅ - convert from binary
\$\endgroup\$

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.