Code Golf: Letter-Ception

The Challenge:

For an input of one letter X (upper or lower case from A to Z) and one digit N (0-9) print the corresponding letter X made of N * X.

The letter has to be from this list:

 AAA      BBBB       CCCC     DDDD      EEEEE     FFFFF      GGG      H   H
A   A     B   B     C         D   D     E         F         G         H   H
AAAAA     BBBB      C         D   D     EEEE      FFFF      G  GG     HHHHH
A   A     B   B     C         D   D     E         F         G   G     H   H
A   A     BBBB       CCCC     DDDD      EEEEE     F          GGG      H   H

IIIII         J     K   K     L         M   M     N   N      OOO
I           J     K  K      L         MM MM     NN  N     O   O
I           J     KKK       L         M M M     N N N     O   O
I       J   J     K  K      L         M   M     N  NN     O   O
IIIII      JJJ      K   K     LLLLL     M   M     N   N      OOO

PPPP       QQQ      RRRR       SSSS     TTTTT     U   U     V   V     W   W
P   P     Q   Q     R   R     S           T       U   U     V   V     W   W
PPPP      Q   Q     RRRR       SSS        T       U   U     V   V     W   W
P         Q  QQ     R  R          S       T       U   U      V V      W W W
P          QQQQ     R   R     SSSS        T        UUU        V        W W

X   X     Y   Y     ZZZZZ
X X       Y Y         Z
X         Y         Z
X X        Y        Z
X   X       Y       ZZZZZ


Examples:

input: a 1

output:

 AAA
A   A
AAAAA
A   A
A   A


input: A 0

output: A

input: A 2

output:

      AAA  AAA  AAA
A   AA   AA   A
AAAAAAAAAAAAAAA
A   AA   AA   A
A   AA   AA   A
AAA                 AAA
A   A               A   A
AAAAA               AAAAA
A   A               A   A
A   A               A   A
AAA  AAA  AAA  AAA  AAA
A   AA   AA   AA   AA   A
AAAAAAAAAAAAAAAAAAAAAAAAA
A   AA   AA   AA   AA   A
A   AA   AA   AA   AA   A
AAA                 AAA
A   A               A   A
AAAAA               AAAAA
A   A               A   A
A   A               A   A
AAA                 AAA
A   A               A   A
AAAAA               AAAAA
A   A               A   A
A   A               A   A


input: A -1

output: what ever: it doesn't matter

• The input parameters can be separated by what ever character you want.
• Each letter must use the capital of itself as the ascii-character to draw it.
• Trailing spaces, new lines etc. are allowed
• Instead of a program, you may write a function that takes the digit string as an argument. The output should be printed normally.
• Stdout / Stderr doesn't matter, just pick one. If stuff gots printed on the other doesn't matter either.
• Possible output formats can be printed to STDOUT, returned as a list of strings, returned as a character matrix, etc. as long as the result can simply be printed using the languages default print method.*

*: like the function f(a,1) returns the string and one can simply say print(f(a,1)) dont make the print() call part of the answer. (This was pointed out by Kevin Cruijssen and Arnauld).

Winning:

This is code-golf, lowest byte-count wins. Have fun!

Edit: this question seems very identical to this however I would say it is not, as it should not only work for H but for each letter from the alphabet.. Guess you decide rather or not it is a duplicate.

• – AdmBorkBork Dec 11 '18 at 16:28
• @ElPedro Thank you! I did not know about the sandbox yet, thank you very much I will take a closer look at it! – whme Dec 11 '18 at 20:24
• Nice first challenge! However, your question currently suggests that we may only print the result. The default rule is that functions are allowed to just return it. Generally speaking, I/O formats are very flexible. You may want to have a look at this post in meta which explains why. – Arnauld Dec 12 '18 at 1:22
• @Arnauld as it is about ASCII art I would say to print the result is somewhat crucial to the task, but I guess if your code returns the result and the returned string could simply be printed using the languages default print method (like your function f(a,1) return the string and I can just say print(f(a,1)) the print() call has not to be part of the answer code. If this is somewhat understandable and you agree I may add this to the challenge description. – whme Dec 12 '18 at 7:46
• @KevinCruijssen I slightly updated the question, please tell me if its understandable the way I wrote it :) – whme Dec 12 '18 at 10:13

JavaScript (ES8), 281 bytes

Takes input as (letter)(N). Returns a string.

c=>n=>(g=y=>y--?''.padEnd(w).replace(/./g,(_,x)=>(h=d=>~~(d/=5)?(P=parseInt)('hhvhefhfhfu111ufhhhfv1f1v11f1vehp1ehhvhhv444vehgggh979hv1111hhlrhhpljhehhhe11fhfuphheh9fhffge1u4444vehhhh4ahhhalhhhha4ah444ahv248v'[y/d%5+5*P(c,36)-50|0],36)>>x/d%5&1?h(d):' ':c)(w))+
+g(y):'')(w=5**n)


Try it online!

How?

Font encoding

The letters are $$\5\times5\$$, which means that each row can be encoded as a 5-digit binary value, i.e. $$\0\$$ to $$\31\$$ in decimal. These values can conveniently be stored as a single digit in Base36.

The pattern that is stored is mirrored both horizontally and vertically.

Example for 'F':

#####     ....#     00001      1     '1'
#....     ....#     00001      1     '1'
####. --> .#### --> 01111 --> 15 --> 'f' --> '11f1v'
#....     ....#     00001      1     '1'
#....     #####     11111     31     'v'


The whole font is stored as a single string of $$\26\times5 = 130\$$ characters.

To test the 'pixel' at $$\(x,y)\$$ for the $$\n^{\text{th}}\$$ letter, we do:

parseInt('hhvhefhfh...'[y + 5 * n], 36) >> x & 1


Main algorithm

Given $$\n\$$, we define $$\w=5^n\$$, which is the width of the final output.

For $$\0\le x and $$\0\le y, we want to know if the output pixel at $$\(x,y)\$$ is set or not. We use the recursive function $$\h\$$, which tests the letter pixel located at:

$$\left(\left\lfloor\frac{x}{5^k}\right\rfloor\bmod 5,\left\lfloor\frac{y}{5^k}\right\rfloor\bmod 5\right)$$

for all $$\k\$$ in $$\[0 \dots n-1]\$$.

The function returns a space as soon as a blank pixel is detected at some depth, or the character corresponding to the input letter if all iterations are successful.

• It works really good, congratulations! Can you try to explain the code a bit please ? – whme Dec 12 '18 at 8:09
• Why has the pattern that is stored to be mirrored both horizontally and vertically? would it take more bytes to not mirror it at all for storing ? And tyvm for the explanation *.* – whme Dec 12 '18 at 16:33
• @NicolasBrauer It's mirrored vertically because $y$ is decreasing from $w-1$ to $0$. And it's mirrored horizontally because the leftmost 'pixel' is mapped to the least significant bit (i.e. on the right of the number it's mapped to). The decoding would be a bit longer if it was not mirrored at all. – Arnauld Dec 12 '18 at 16:40
• (Although I think we could drop the vertical mirror at no cost.) – Arnauld Dec 12 '18 at 16:41

R, 348 bytes

function(K,N){if(N)for(i in 1:N)T=T%x%matrix(c(15269425,32045630,16269839,32032318,33061407,33061392,15224366,18415153,32641183,1082926,18444881,17318431,18732593,18667121,15255086,32045584,15255151,32045649,16267326,32641156,18400814,18400580,18400938,18157905,18157700,32575775)[utf8ToInt(K)-64]%/%2^(24:0)%%2,5,5)
write(c(" ",K)[T+1],1,5^N,,"")}


Try it online!

Uses an encoding nearly identical to Ouros'; however, it does not reverse the bits, instead opting to use them directly.

It then creates a 5x5 matrix of bits and builds the Kronecker Power matrix to generate the necessary pattern, writing the results to stdout.

• This is a great use of Kronecker ! – digEmAll Dec 13 '18 at 10:29
• 272 using another compression method – digEmAll Dec 13 '18 at 11:30
• @digEmAll the heart of this challenge is the compression method (from a code-golf perspective anyway). Why don't you post it as an answer so you can explain it, too? – Giuseppe Dec 13 '18 at 14:12
• Ok, fine thanks ! – digEmAll Dec 13 '18 at 14:21

Clean, 436 372 bytes

Significantly shorter with new IO format.

import StdEnv,StdLib
t=transpose
f=flatten
$0c=[[c]]$n c=f[t(f[t(\$(n-1)if(isOdd({#18415150,16301615,31491134,16303663,32554047,1096767,15262766,18415153,32641183,15254032,18128177,32539681,18405233,18667121,15255086,1097263,32294446,18136623,16267326,4329631,15255089,4539953,11191857,18157905,4329809,32575775}.[toInt(max'A'c)-65]>>p))c' ')\\p<-[i..i+4]])\\i<-[0,5..20]]


Try it online!

Compresses the letter patterns into the bits of integer literals to save ~700 bytes. For example, A:

1. Flatten [[' AAA '],['A A'],['AAAAA'],['A A'],['A A']]
2. Reverse [' AAA A AAAAAAA AA A']
3. Turn ['A AA AAAAAAA A AAA '] into binary ('A' = 1, ' ' = 0)
4. Turn 0b1000110001111111000101110 into decimal
5. Get 18415150

R, 259 bytes

function(K,N,!=utf8ToInt){if(N)for(i in 1:N)T=T%x%(sapply(!"			




",intToBits)[1:5,5*(-64+!K)-4:0]>0)
write(c(" ",K)[T+1],1,5^N,,"")}


Try it online!

Disclaimer :
this solution has been obtained by taking @Giuseppe's answer and replacing the matrix compression with another approach very very similar to the one used in @Arnauld's answer, so first of all go upvote them :)

The idea is the following :

Given this 5 x 26*5 matrix of 0/1 :

(1 replaced by '#', 0 replaced by '.' and '|' added for readability)

.####|#####|.###.|#####|#####|#####|.###.|#####|#...#|...#.|#####|#####|#####|
#.#..|#.#.#|#...#|#...#|#.#.#|#.#..|#...#|..#..|#...#|....#|..#..|....#|.#...|
#.#..|#.#.#|#...#|#...#|#.#.#|#.#..|#...#|..#..|#####|....#|..#..|....#|..#..|
#.#..|#.#.#|#...#|#...#|#.#.#|#.#..|#.#.#|..#..|#...#|....#|.#.#.|....#|.#...|
.####|.#.#.|#...#|.###.|#...#|#....|..##.|#####|#...#|####.|#...#|....#|#####| ...
^     ^     ^     ^     ^     ^     ^     ^     ^     ^     ^     ^     ^
|     |     |     |     |     |     |     |     |     |     |     |     |
A     B     C     D     E     F     G     H     I     J     K     L     M


each column is considered as binary number and converted to an integer. These integer are then converted to unprintable ASCII in the range 1...31 :

e.g. for the columns of "B" the final string will be "\017\021\017\021\017" (unprintable chars written in octal representation):

#####                   ####.     11110          15            '\017'
#.#.#                   #...#     10001          17            '\021'
#.#.#      ------->     ####. --> 11110  ------> 15   ------>  '\017'
#.#.#                   #...#     10001          17            '\021'
.#.#.                   ####.     11110          15            '\017'

(transposed                  bin to int   int to ASCII
for reability)


Hence, given the final string of 5*26 = 130 characters, we convert that string back to the matrix of 0/1 using :

sapply(utf8ToInt(STRING),intToBits)


then we simply subsect the matrix selecting only the first 5 rows (intToBits returns 32 bits) and only the columns corresponding to the letter passed as input and finally we apply kronecker as explained in @Giuseppe's answer.

• you can also use unprintables to shave off the -48 piece, and use ! in place of U: try it online – Giuseppe Dec 14 '18 at 18:05
• @Giuseppe : great ! I made the answer a community wiki since it's the result of a collaboration :) Feel free to edit my poor english :D – digEmAll Dec 14 '18 at 19:25