18
\$\begingroup\$

Given an input of any valid Glypho program, output its "human-readable" counterpart.

Glypho is an interesting esolang idea:

The instruction reference is given here. For each instruction, the characters abcd represent the symbols composing each instruction. a refers to the first unique symbol, b refers to the second unique symbol, etc.

aaaa ..... n NOP - no operation; do nothing
aaab ..... i Input - push input onto top of stack
aaba ..... > Rot - pops top stack element and pushes to bottom of stack
aabb ..... \ Swap - swaps top two stack elements
aabc ..... 1 Push - pushes a 1 onto the top of stack (creates new element)
abaa ..... < RRot - pops bottom element and pushes to top of stack
abab ..... d Dup - Duplicates top stack element
abac ..... + Add - pops top two elements and pushes their sum
abba ..... [ L-brace - skip to matching ] if top stack element is 0
abbb ..... o Output - pops and outputs top stack element
abbc ..... * Multiply - pops top two elements and pushes their product
abca ..... e Execute - Pops four elements and interprets them as an instruction
abcb ..... - Negate - pops value from stack, pushes -(value)
abcc ..... ! Pop - pops and discards top stack element
abcd ..... ] R-brace - skip back to matching [

(credit: Brian Thompson aka Wildhalcyon)

So, for example, PPCG would represent the Push instruction—PPCG matches the pattern aabc, where a represents P, b represents C, and c represents G.

The input will be a single string consisting of only printable ASCII characters. It will always have a length divisible by four (duh).

The output is each group of four characters in the input string replaced by which instruction they designate. Use the single-letter instruction names (the ones right after the five dots in the table quoted above).

Since this is , the shortest code in bytes will win.

Test cases:

In                                Out
------------------------------------------------
Programming Puzzles & Code Golof  ]!]!]]]+
nananananananana batman!          dddd]]
;;;;;;;:;;:;;;::                  ni>\
llamas sleep                      1-*
8488133190003453                  <[oe
<empty string>                    <empty string>
\$\endgroup\$
1
  • 7
    \$\begingroup\$ Ah yes Code Golof. My favorite sporot. \$\endgroup\$ Feb 2, 2016 at 17:18

8 Answers 8

5
\$\begingroup\$

Pyth, 37 35 34 bytes

The code contains unprintable characters, so here is the xxd hexdump:

0000000: 5663 7a34 7040 2e22 216f d78c 40bf d4f0  Vcz4p@."!o..@...
0000010: 38d6 7dfe 7312 3ff8 ea22 6958 4e7b 4e55  8.}.s.?.."iXN{NU
0000020: 5433                                     T3

Here's a printable version at 36 bytes:

Vcz4p@"ni >\\1   <d+[o*e-!]"iXN{NUT3

Try it online. Test suite.

Explanation

Vcz4p@."…"iXN{NUT3       implicit: z = input
  z                      input
 c 4                     split to 4-character blocks
V                        loop over that in N
           X               replace...
            N                in current part
             {N              unique chars in current part, in order
               UT            with numbers 0-9
          i      3         interpret as base 3
     @                     take that item of
      ."…"                   string "ni >\\1   <d+[o*e-!]"
    p                      and print without newline
\$\endgroup\$
4
\$\begingroup\$

CJam, 42 39 35 bytes

Saved 4 bytes borrowing user81655's idea of using base 3 instead of base 4.

l4/{__&f#3b"ni >\1   <d+[o*e-!]"=}%

Run all test cases.

There's gotta be a better way to compress the lookup table of commands...

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

JavaScript (ES6), 97

For each block of 4 characters, I substitute each symbol with its position in the block, getting a base 4 number. For instance 'aabc' -> '0023'. The possibile numbers are in the range 0..0123, that is 0..27 in decimal. I use the number as an index to find the right instruction character from a 28 chars string.

s=>s.replace(/.{4}/g,s=>'n..i....>.\\1....<d.+[o.*e-!]'[[...s].map(c=>n=n*4+s.indexOf(c),n=0),n])

Test

F=s=>s.replace(/.{4}/g,s=>'n..i....>.\\1....<d.+[o.*e-!]'[[...s].map(c=>n=n*4+s.indexOf(c),n=0),n])

function test() { O.textContent=F(I.value) }

test();
#I { width:90% }
<input id=I value="nananananananana batman!" oninput="test()">
<br><span id=O></span>

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

MATLAB, 291 bytes

I hesitated for quite a long time if I should commit my answer. I was just playing around with MATLAB. I am aware that it's not really possible to generate dense code (a low number of instructions/bytes; about 3 times larget than your ~100 byte solutions) and that MATLAB might not be too suitable for code golf and I am new to code golf. But I simply wanted to try, and the code works (newline characters kept). Any hints welcome. :P

i=input('','s');
l=reshape(i,4,length(i)/4)';
m=']!- e';m(9)='*';m(12:22)='o[   + d  <';m(33:34)='1\';m(39)='>';m(57)='i';m(64)='n';
s='';
for k = 1:size(l,1)
n=l(k,:);
c=combvec(n,n);
t=triu(reshape(c(1,:)==c(2,:),4,4),1);
t=sum(t([5,9:10,13:15]).*2.^[5:-1:0]);
s=[s,m(t+1)];
end
display(s)
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Welcome to Programming Puzzles & Code Golf! All answers are welcome, even if they get outgolfed by a ridiculous amount (has definitely happened to me before). ;) Nice first answer! \$\endgroup\$
    – Doorknob
    Feb 2, 2016 at 12:15
3
\$\begingroup\$

JavaScript (ES6), 115 101 bytes

s=>s.replace(/..../g,g=>"ni >\\1   <d+[o*e-!]"[[...g].map(c=>r=r*3+(m[c]=m[c]||++i)-1,i=r=0,m={})|r])

Saved 14 bytes thanks to @edc65!

Explanation

Stores the list of instructions in a string with each character at it's base-3 index. For example, + corresponds to abac which can be represented in base-3 as 0102, or 11 in decimal. The only instruction that cannot be represented in base-3 is ], but with the algorithm used to compute the base-3 number, it conveniently ends up needing to be at position 18 at the end of the string.

s=>
  s.replace(/..../g,g=>    // replace each four-character group with it's instruction
    "ni >\\1   <d+[o*e-!]" // list of instructions at their base-3 index
    [
      [...g].map(c=>       // for each character c
        r=r*3+(m[c]=m[c]   // shift r left and add the number associated with c to r
          ||++i)-1,        // if nothing is associated, associate the next number to c
                           // save i + 1 to m[c] so that it is truthy for 0
        i=                 // i = current number to assign to the next unique character
        r=0,               // r = 4-character group as a base-3 number
        m={}               // m = map of numbers assigned to each character
      )
      |r                   // return r
    ]
  )

Test

var solution = s=>s.replace(/..../g,g=>"ni >\\1   <d+[o*e-!]"[[...g].map(c=>r=r*3+(m[c]=m[c]||++i)-1,i=r=0,m={})|r])
<input type="text" id="input" value="Programming Puzzles & Code Golof" />
<button onclick="result.textContent=solution(input.value)">Go</button>
<pre id="result"></pre>

\$\endgroup\$
2
  • \$\begingroup\$ You can save many bytes not using parseInt and computing the number with repeated sum and multiply. This avoid the problem with '0123' that is invalid in base 3 but gives 1*9+2*6+3==18 that is a good position. Result: F=s=>s.replace(/..../g,g=>"ni]>\\1 <d+[o*e-!]"[[...g].map(c=>r=r*3+(m[c]=m[c]||++i)-1,r=i=0,m={})|r]) \$\endgroup\$
    – edc65
    Feb 1, 2016 at 11:13
  • \$\begingroup\$ @edc65 Great suggestion. Thanks! \$\endgroup\$
    – user81655
    Feb 1, 2016 at 11:52
1
+300
\$\begingroup\$

Zsh, 118 bytes

0="n  i      > \1${(l:11:)}<d + [o * e-!]"
for s (`tr \  £|fold -4`)(eval ';n+=$s[(i)$s['{2..4}]];printf $0[5#$n-30])

Try it online!

  • 0="n i > \1${(l:11:)}<d + [o * e-!]" - store this string in the variable $0. ${(l:11:)} generates 11 spaces (literally, left-padding an empty string to a length of 11), and is 1 byte shorter than writing them literally.
  • tr \ £ - replace spaces (\ ) with £s. This is because spaces in the input will be eaten when word splitting, messing up the 4 character grouping. Word splitting is useful though, because it allows us to loop over each line, which is how fold splits things. I used £ because it's outside the printable ASCII range that we're required to accept and only 2 bytes in UTF-8 (I could probably technically save a byte if I used a different encoding, but that's not worth the effort). Unfortunately I can't use a control character because zsh doesn't like them.
  • fold -4 - group into 4 characters per line
  • for s (``) - for each group, $s, of 4 characters:
    • ';n+=$s[(i)$s['{2..4}]]: generate the string ;n+=$s[(i)$s[2]];n+=$s[(i)$s[3]];n+=$s[(i)$s[4]]
    • evaluate that as zsh code:
      • $s[X] - the Xth character of $s (1-indexed)
      • $s[(i)] - find the index of the first appearance of that character within $s
      • n+= - append that to $n (which implicitly starts out empty)
      • eval with brace expansion (like {2..4}) is a shorter way to do a simple loop than using for
      • We only need to use {2..4} as the first index of the first character of the string will obviously always be 1. This lets us save a byte when subtracting later (otherwise it would be -155 rather than -30)
      • 5#$n - interpret n as a base-5 integer (if zsh used 0-based indexing, this could be base 4, we wouldn't need to subtract anything, and the $0 string could be shorter)
    • -30 - the minimum base-5 value we can get from any combination of characters is 31, and since zsh is 1-indexed, we subtract 30 to get an index into the string $0
    • $0[] - get that index into the string $0 for the relevant character to print. The spaces in $0 are padding to make the right characters appear in the right places since the possible base-5 values aren't contiguous.
    • printf - print that with no newline
      • () - subshell; any changes to variables do not persist outside the brackets. This is used to reset $n to an empty string on each iteration.
\$\endgroup\$
1
\$\begingroup\$

J, 37 bytes

'ni >\1   <d+[o*e-!]'{~_4(3#.~.i.])\]

Try it online!

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

Python 2, 158 bytes

Takes input like "test". Output is a list of characters.

def b(s,i=0):
    for c in s:i=i*4+s.index(c)
    return"n..i....>.\\1....<d.+[o.*e-!]"[i]
print map(b,(lambda l,n:[l[i:i+n]for i in range(0,len(l),n)])(input(),4))

Try it Online!

Ungolfed:

def chunks(l, n):
    return (l[i:i+n] for i in range(0, len(l), n))
    
def convert(inst):
    i = 0
    for c in inst:
        i = i*4 + inst.index(c)
    
    return "n..i....>.\\1....<d.+[o.*e-!]"[i]

print map(convert, chunks(input(), 4))
\$\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.