# Translate a Glypho program

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>

• Ah yes Code Golof. My favorite sporot. – KoreanwGlasses Feb 2 '16 at 17:18

# Pyth, 3735 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


### 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


## CJam, 4239 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...

# 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>

# 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)

• 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! – Doorknob Feb 2 '16 at 12:15

# 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>

• 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]) – edc65 Feb 1 '16 at 11:13
• @edc65 Great suggestion. Thanks! – user81655 Feb 1 '16 at 11:52

# 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.

# J, 37 bytes

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


Try it online!

# 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))