# Reading the text of the millitext font

There is a font here that fits each character into a single, 1x5 pixel block. It does this (assuming you're using an LCD screen) by using the RGB channels of each pixel to expand the one pixel into three subcolumns, one for each channel. Your task is to take in a string of text encoded in this font and 'decode' it.

# Millitext Alphabet

CHARACTER: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
ENCODING:  WYWBMRRMMMWYWYWWWMWBMRMYGYGYCWMMMMMW
MGBWMRRMMMMMRMRRRMGBMRWMMMMMRGMMMMMB
MGWWWWWBWWWYRMWWMWGBYRWMMYMYGGMMWGGG
MGRBBBMBMBMMRMRRMMGBMRMMMRWMBGMCWMGR
WWWWBWWBWWMYWYWRWMWWMWMMGRCMYGWBMMGW


I've abbreviated each color to a one character symbol (R=red, G=green, B=blue, C=cyan, Y=yellow, M=magenta, W=white).

# Input Format

The input format for this is pretty open. You can have the input be an array containing each column, an array containing each row, a char[][], or anything like that. You can also choose to use the full words "red", "green", "blue", with uppercase/lowercase of your choice (but it must be consistent for each word! You cannot use "RED" and also do "green" or "Blue").

If your language happens to support it, you can also have input be colors (however that might work, I don't know off-hand).

You can assume that the input will ONLY contain encoded characters in the alphabet above (in particular, there will be no spaces or punctuation in your output).

# Output Format

You can either output a string or some sort of character array. You can chose whether the letters are uppercase or lowercase, but they must all have the same case.

# Example

MWRRGMGYRY
MRRRMMMMRM
WWRRMWMYRM -> HELLOWORLD
MRRRMWMMRM
MWWWGMGMWY


# Rules

This is , so shortest answer wins!

# Test set

WMWGMWWMYYGMYWGMBMMYWYGMWYWMWRWWMYGW
GMRMMGRMMMMMMRMMBMWMRMMMRMGMRRMBMMMR
GWWMMGRYYYMWMWMGBMWYWMMMWYGWWRWGGMMM -> THEQUICKBROWNFOXJUMPEDOVERTHELAZYDOG
GMRWMGRMMMMWMRMMBMMRRMMCRMGMRRMRGMMM
GMWCWWWMYMGMMRGMWWMRWYGBWMGMWWMWGYGW

• I feel like you either hardcode all letters or use a Mathematica builtin here. – my pronoun is monicareinstate Jun 10 '19 at 12:59
• Nice first challenge, BTW! – Arnauld Jun 10 '19 at 13:29
• Here is the fixed font (several other characters are wrong). – Arnauld Jun 10 '19 at 23:12
• I don't know if you wanted your test set to include all letters from the English alphabet or not, but if son that's called a pangram and "THEQUICKBROWNFOXJUMPEDOVERTHELAZYDOG" isn't one as its missing an "S", if you wanted it to be it should be "THEQUICKBROWNFOXJUMPESOVERTHELAZYDOG" – MindSwipe Jun 11 '19 at 7:20
• @JonofAllTrades JUMPS is a possibility.And you can lose two characters by changing one of the THEs for A. – Andrew Leach Jun 11 '19 at 20:02

# JavaScript (ES6),  103 100 93 92  90 bytes

Saved 9 bytes thanks to @ShieruAsakoto

Takes input as an array of columns. Returns an array of characters.

a=>a.map(s=>"H-L-D--VGQ87MR6TZ-KJ9WC05BUXF1YI2EON3S-A-P4"[parseInt(s,35)%1161%219%152%43])


Try it online!

• @ShieruAsakoto Thanks! The multiplication was not a good idea. I saved 1 more byte with 3 mod's. – Arnauld Jun 10 '19 at 15:57
• Those are some big modulos over there... maybe you can improve them more so the -s disappear! :D – Erik the Outgolfer Jun 10 '19 at 16:37
• After a whole night of brute-force I got a 90 with 4 mods: a=>a.map(s=>"H-L-D--VGQ87MR6TZ-KJ9WC05BUXF1YI2EON3S-A-P4"[parseInt(s,35)%1161%219%152%43]). – Shieru Asakoto Jun 10 '19 at 23:44
• @ShieruAsakoto Unfortunately, the font described in the challenge is wrong. Waiting for a possible update from the OP. – Arnauld Jun 10 '19 at 23:47
• @Arnauld For the fixed one my progress now is a 93: a=>a.map(s=>"UIR-L68N--W-X7B-FH-D-EZ--902-S4M5GJCQT3PKV-A1-YO"[parseInt(s,35)%464%107%99%52]) – Shieru Asakoto Jun 11 '19 at 4:52

# Jelly, 50 bytes

Oḅ⁹%211“ẎP\7ßɱðvs*Ḋ⁹UfRMJiẒVƑ).Z½Ƈ"}~ḌyH⁵Ŀ⁶Ṿ‘iⱮịØB


Try it online!

A monadic link accepting the input as a list of columns and outputting a Jelly string of the translation. Full explanation to follow, but relies on the fact that each possible set of 5 letters is unique when converted to code points, converted back from base-256 to decimal and then mod 211.

Alternative using Arnauld’s fixed font (49 bytes and using same principle.)

### Explanation

O                   | Convert to code points
ḅ⁹                 | Convert from base 256 to decimal
%211             | Mod 211
“Ẏ...Ṿ‘iⱮ    | Find indices in [209,80,92,55,21,162,24,118,115,42,193,137,85,102,82,77,74,105,189,86,146,41,46,90,10,144,34,125,126,173,121,72,133,199,134,186]
ịØB | Index into 01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ


# dzaima/APL, 80797372 71 bytes

' P  FL6BDEZQA SY574H TVOK J 08  M  U IC92XW 3G1RN'⊇⍨52|8965|2411⊥¨⎕ucs


Try it online!

• what special features does your APL have? – Jonah Jun 10 '19 at 14:33
• @Jonah Here the only used thing is ⊇ (similar to {⍵[⍺]}), other than that, these two files contain info about it – dzaima Jun 10 '19 at 14:35

# 05AB1E, 45 44 bytes

40ö98%•Wþ@»Ý¢a:µ@,–çòßuÒ¹₃©6µć‚FVÝ∊J?•2ôžLR‡


Try it online!

Takes input as array of columns, and outputs an array of characters.

Explanation:

40ö                       # convert each column from base 40
98%                    # modulo 98
•...•2ô             # compressed array: [20, 32, 82, 30, 27, 28, 76, 89, 46, 96, 36, 4, 18, 12, 80, 75, 50, 86, 42, 2, 52, 92, 48, 0, 84, 1, 88, 90, 10, 26, 70, 41, 94, 64, 14, 60]
žLR          # built-in array 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
‡         # transliterate


# R, 143 128 bytes

function(v)c(0:9,LETTERS)[match(colSums((sapply(v,U<-utf8ToInt)*194:198)%%45:41),U("#</Eb=,n9J.M4Z+%*V N[Hd\\B?1Oj>KgRYT2")+34)]


Try it online!

Function taking a vector of strings (corresponding to the columns) as input e.g. :

MWRRG
MRRRM
WWRRM -> c('MMWMM','WRWRW','RRRRW','RRRRW','GMMMG') -> HELLO
MRRRM
MWWWG


Explanation :

Performing the following operation for each encoded string (e.g 'CRGBY' = 'S') :

        TO ASCII      MULTIPLICATION             MODULO              SUM &              TO
CODEPOINT                                                    OFFSET             ASCII
---------------------------------------------------------------------------------------------

'C'        67        67 * 194 = 12998       12998 %% 45 = 38  \
'R'        82        82 * 195 = 15990       15990 %% 44 = 18  |
'G'  --->  71  --->  71 * 196 = 13916  ---> 13916 %% 43 = 27  |---> (140 - 34) = 106 ---> 'j'
'B'        66        66 * 197 = 13002       13002 %% 42 = 24  |
'Y'        89        89 * 198 = 17622       17622 %% 41 = 33  /


we obtain the following string '#</Eb=,n9J.M4Z+%*V N[Hd\B?1Oj>KgRYT2' where each character corresponds to '0123456789ABCDEFGHIJKLMNOPQR'.

So, the code performs the described operations on the input strings, then searches their correspondences inside '#</Eb=,n9J.M4Z+%*V N[Hd\B?1Oj>KgRYT2' obtaining the positions in string '0123456789ABCDEFGHIJKLMNOPQR'.

• This looks clever but it’s not clear how to use the code: What shall I pass to the function? Both a list of character vectors and a plain vector fail with “non-conformable argument”. So does a character matrix. – Konrad Rudolph Jun 12 '19 at 16:09
• @KonradRudolph: added a minimal explanation of the input (and changed the TIO in order to be more explicit). As soon as I can I'll add an explanation of the code, which I'm sure can be improved by finding an other "hashing" function for the strings returning values in the ASCII range instead of unicode... – digEmAll Jun 12 '19 at 19:00
• @digEmAll yeah I've been playing with modding down the digits to a more reasonable range of distinct characters but nothing yet – Giuseppe Jun 12 '19 at 19:12
• @digEmAll Ah that works (I had the data as col-major rather than row-major) but your example results in “HEKKN”, not “HELLO”. I’m very confused that it appears to work on TIO. Different (non-UTF-8) encoding, I guess. – Konrad Rudolph Jun 12 '19 at 19:42
• @KonradRudolph: added a brief explanation (and found a shorter code) ;) – digEmAll Jun 16 '19 at 17:12

# Charcoal, 66 bytes

ＷＳ§”*&_⟲⎇4>υ≧Y⪪ml^π≕t.A；p↶⧴q⊗Ｈε‖r¡¡ºÞd⸿σＣ⁺⮌”﹪﹪﹪⍘ιWMYCBGR³⁶⁰¦¹¹³¦⁷¹


Try it online! Link is to verbose version of code. Takes input as a list of columns terminated with a blank line. Explanation:

ＷＳ


Input strings until one is blank.

§”*&_⟲⎇4>υ≧Y⪪ml^π≕t.A；p↶⧴q⊗Ｈε‖r¡¡ºÞd⸿σＣ⁺⮌”


Cyclically index into the string OV EX8HSCF5IA L TG 17 M P9RB 4 K ZY2 0JW 63Q ND U which (with trailing space) is 56 characters long.

﹪﹪﹪⍘ιWMYCBGR³⁶⁰¦¹¹³¦⁷¹


Perform base-7 conversion using the alphabet WMYCBGR and then reduce successively modulo 360, 113, 71, and 56 implicitly via the cyclic indexing.

My base 7 approach fared really badly with @Arnauld's fixed font; after some searching I was still at 73 bytes. Using @Grimy's approach cut this down to 67 bytes. However I eventually tracked down a 66 byte solution:

ＷＳ§”*&″ÀＭ↔↓<Ｊ;×⊟ςF,Ｇηe↖ητγ´ＷＩＹ³﹪▶⟧9?δc⁶ＡxDê↷hＰiψ”﹪﹪﹪⍘ι⁴⁷¦²³⁷¦⁷³¦⁶⁷


Try it online! Link is to verbose version of code. Explanation:

ＷＳ


Input strings until one is blank.

§”*&″ÀＭ↔↓<Ｊ;×⊟ςF,Ｇηe↖ητγ´ＷＩＹ³﹪▶⟧9?δc⁶ＡxDê↷hＰiψ”


Cyclically index into the string ID HAM178 VS4F 3R EP6CQ Z UB O 0 X 9 G 5TNJKL2Y W which is 63 characters long.

﹪﹪﹪⍘ι⁴⁷¦²³⁷¦⁷³¦⁶⁷


Perform base-47 conversion using the alphabet 0-9A-Za-k and then reduce successively modulo 237, 73, 67, and 63 implicitly via the cyclic indexing.

### CJam (63 bytes)

{{Gb"õáÖÅ{a("{i%}/"@/Ö´çýß}yùÜÅ©GôÉç¢"256b43b'0f+=}%}


or in xxd format

0000000: 7b7b 4762 22f5 e1d6 c59f 7b61 2822 7b69  {{Gb".....{a("{i
0000010: 257d 2f22 0b8a 8340 982f d6b4 e793 fddf  %}/"...@./......
0000020: 7d79 f9dc c519 17a9 0e47 0ef4 c9e7 a222  }y.......G....."
0000030: 3235 3662 3433 6227 3066 2b3d 7d25 7d    256b43b'0f+=}%}


This is an anonymous block (function) which expects input as a list of columns. Online demo.

As many of the other answers, this does a base conversion followed by a chain of % to get a short lookup table. In this case I use base 16 and % chain [245 225 214 197 159 123 97 40].

# Jelly, 48 bytes

OḌ%⁽qƥ%⁹%53“ð×⁼ẎėWWæ¤jḌṛ>÷ƭÑṙsṛḌz0Ġọµḷ’b51¤iⱮịØB


A monadic Link accepting a list of lists of uppercase characters (each being a column) which yields a list of characters.

Try it online!

### How?

OḌ%⁽qƥ%⁹%53“...’b51¤iⱮịØB - Link: columns
O                         - ordinals
Ḍ                        - convert from base ten
%⁽qƥ                    - modulo 29415
%⁹                  - modulo 256
%53               - modulo 53
iⱮ    - map with first index of x in:
“...’          -     22270425059867513817410846141176204460122938458128124185752719
b         -     convert to base
51       -       51
-     ... = [38,13,19,27,10,16,20,11,35,31,4,17,9,0,50,45,24,25,34,39,22,29,41,32,3,7,46,5,48,18,6,44,28,14,1,8]
ị   - index into
ØB -   "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"


->n{n.map{|i|"6&\278$Cc\17Y9\23T\r]{v^Ox\16_+!Qj\fbH hraD*Ap".index((i.to_i(36)%245%119+8).chr).to_s(36)}*""}  Try it online! # Stax, 46 bytes é►^njÖ_╪»Θîq╪↨δXû=▀úæ5?ªoéV╫╫╩ßH‼╒C═e┼$⌠°JqUu⌡


Run and debug it

Each column is decoded as base-36. Successive modulus of 8273, then 95 are applied. This yields a unique number, looked up in a fixed string.

It takes input exactly in the format specified in the examples, and has to transpose them to get columns. I will be able to save some bytes by using some different input format, which I may do at some point.