Words within words within words within words . . .

17

4

In this pixelated font of uppercase letters of the alphabet, all the characters are 5 units wide and 5 tall.

 ███  ████   ███  ████  █████ █████  ████ █   █ █████     █ █   █ █     █   █
█   █ █   █ █   █ █   █ █     █     █     █   █   █       █ █  █  █     ██ ██
█████ ████  █     █   █ ████  ████  █  ██ █████   █       █ ███   █     █ █ █
█   █ █   █ █   █ █   █ █     █     █   █ █   █   █   █   █ █  █  █     █   █
█   █ ████   ███  ████  █████ █      ████ █   █ █████  ███  █   █ █████ █   █

█   █  ███  ████   ███  ████   ████ █████ █   █ █   █ █   █ █   █ █   █ █████
██  █ █   █ █   █ █   █ █   █ █       █   █   █ █   █ █   █  █ █   █ █     █ 
█ █ █ █   █ ████  █   █ ████   ███    █   █   █  █ █  █ █ █   █     █     █  
█  ██ █   █ █     █  ██ █  █      █   █   █   █  █ █  █ █ █  █ █    █    █   
█   █  ███  █      ████ █   █ ████    █    ███    █    █ █  █   █   █   █████

There is also 1 unit of space between letters and between lines, as can be seen. So each letter can take up to 6×6 units of space.

Suppose that instead of using the full block character () to directly form the shapes of the letters, we wanted to use other letters in the same font. This involves increasing the dimensions of the text 6-fold so that letters made of full-blocks can be used as full-block replacements in the larger text.

If that didn't make sense hopefully this example will. Here is an A made of B's using the pixelated font:

      ████  ████  ████       
      █   █ █   █ █   █      
      ████  ████  ████       
      █   █ █   █ █   █      
      ████  ████  ████       
                             
████                    ████ 
█   █                   █   █
████                    ████ 
█   █                   █   █
████                    ████ 
                             
████  ████  ████  ████  ████ 
█   █ █   █ █   █ █   █ █   █
████  ████  ████  ████  ████ 
█   █ █   █ █   █ █   █ █   █
████  ████  ████  ████  ████ 
                             
████                    ████ 
█   █                   █   █
████                    ████ 
█   █                   █   █
████                    ████ 
                             
████                    ████ 
█   █                   █   █
████                    ████ 
█   █                   █   █
████                    ████ 

The B's are made of full blocks and the A is made of B's. Notice that the B's still have one unit between them horizontally and vertically.

We can extend this idea by using words instead of just letters. Here is "WATER" made of "FIRE":

█████                   █████             ████  █████ █████             █████ ████  █████ █████ █████       ████  █████ █████ █████ ████        █████ █████ █████ ████       
█                         █               █   █ █     █                   █   █   █ █     █       █         █   █ █     █       █   █   █       █     █       █   █   █      
████                      █               ████  ████  ████                █   ████  ████  ████    █         ████  ████  ████    █   ████        ████  ████    █   ████       
█                         █               █  █  █     █                   █   █  █  █     █       █         █  █  █     █       █   █  █        █     █       █   █  █       
█                       █████             █   █ █████ █                 █████ █   █ █████ █     █████       █   █ █████ █     █████ █   █       █████ █     █████ █   █      
                                                                                                                                                                             
█████                   █████       ████                    █████                   █████                   █████                               ████                    █████
█                         █         █   █                   █                       █                         █                                 █   █                   █    
████                      █         ████                    ████                    ████                      █                                 ████                    ████ 
█                         █         █  █                    █                       █                         █                                 █  █                    █    
█                       █████       █   █                   █████                   █                       █████                               █   █                   █████
                                                                                                                                                                             
█████       █████       ████        █████ █████ █████ ████  █████                   █████                   █████ ████  █████ █████             █████ ████  █████ █████      
█             █         █   █       █     █       █   █   █ █                       █                         █   █   █ █     █                   █   █   █ █     █          
████          █         ████        ████  ████    █   ████  ████                    ████                      █   ████  ████  ████                █   ████  ████  ████       
█             █         █  █        █     █       █   █  █  █                       █                         █   █  █  █     █                   █   █  █  █     █          
█           █████       █   █       █████ █     █████ █   █ █████                   █                       █████ █   █ █████ █                 █████ █   █ █████ █          
                                                                                                                                                                             
█████       █████       ████        █████                   █████                   █████                   ████                                █████             █████      
█             █         █   █       █                       █                         █                     █   █                               █                 █          
████          █         ████        ████                    ████                      █                     ████                                ████              ████       
█             █         █  █        █                       █                         █                     █  █                                █                 █          
█           █████       █   █       █████                   █                       █████                   █   █                               █████             █          
                                                                                                                                                                             
      █████       █████             ████                    █████                   █████                   █████ ████  █████ █████ █████       ████                    █████
      █             █               █   █                   █                       █                         █   █   █ █     █       █         █   █                   █    
      ████          █               ████                    ████                    ████                      █   ████  ████  ████    █         ████                    ████ 
      █             █               █  █                    █                       █                         █   █  █  █     █       █         █  █                    █    
      █           █████             █   █                   █████                   █                       █████ █   █ █████ █     █████       █   █                   █████

Notice how "FIRE" appears repeatedly on each line, and always in order, no matter how much space is between the letters. Three of the rightmost instances of "FIRE" were cut off early because of how "WATER"'s letters are shaped.

This idea can be expanded even further, by using these words made of words to make words made of words made of words, or even words made of words made of words made of words. There is no limit theoretically.

Another example would put this post over the 30k character limit, but you can see what is meant by "words made of words made of words" by running this nifty Stack Snippet. Just leave the parameters at their defaults and press "Go!". You should see the word "DOG" made of the word "CAT" made of the word "MOUSE".

alphabet = {A:[[0,1,1,1,0,0],[1,0,0,0,1,0],[1,1,1,1,1,0],[1,0,0,0,1,0],[1,0,0,0,1,0],[0,0,0,0,0,0]],C:[[0,1,1,1,0,0],[1,0,0,0,1,0],[1,0,0,0,0,0],[1,0,0,0,1,0],[0,1,1,1,0,0],[0,0,0,0,0,0]],B:[[1,1,1,1,0,0],[1,0,0,0,1,0],[1,1,1,1,0,0],[1,0,0,0,1,0],[1,1,1,1,0,0],[0,0,0,0,0,0]],E:[[1,1,1,1,1,0],[1,0,0,0,0,0],[1,1,1,1,0,0],[1,0,0,0,0,0],[1,1,1,1,1,0],[0,0,0,0,0,0]],D:[[1,1,1,1,0,0],[1,0,0,0,1,0],[1,0,0,0,1,0],[1,0,0,0,1,0],[1,1,1,1,0,0],[0,0,0,0,0,0]],G:[[0,1,1,1,1,0],[1,0,0,0,0,0],[1,0,0,1,1,0],[1,0,0,0,1,0],[0,1,1,1,1,0],[0,0,0,0,0,0]],F:[[1,1,1,1,1,0],[1,0,0,0,0,0],[1,1,1,1,0,0],[1,0,0,0,0,0],[1,0,0,0,0,0],[0,0,0,0,0,0]],I:[[1,1,1,1,1,0],[0,0,1,0,0,0],[0,0,1,0,0,0],[0,0,1,0,0,0],[1,1,1,1,1,0],[0,0,0,0,0,0]],H:[[1,0,0,0,1,0],[1,0,0,0,1,0],[1,1,1,1,1,0],[1,0,0,0,1,0],[1,0,0,0,1,0],[0,0,0,0,0,0]],K:[[1,0,0,0,1,0],[1,0,0,1,0,0],[1,1,1,0,0,0],[1,0,0,1,0,0],[1,0,0,0,1,0],[0,0,0,0,0,0]],J:[[0,0,0,0,1,0],[0,0,0,0,1,0],[0,0,0,0,1,0],[1,0,0,0,1,0],[0,1,1,1,0,0],[0,0,0,0,0,0]],M:[[1,0,0,0,1,0],[1,1,0,1,1,0],[1,0,1,0,1,0],[1,0,0,0,1,0],[1,0,0,0,1,0],[0,0,0,0,0,0]],L:[[1,0,0,0,0,0],[1,0,0,0,0,0],[1,0,0,0,0,0],[1,0,0,0,0,0],[1,1,1,1,1,0],[0,0,0,0,0,0]],O:[[0,1,1,1,0,0],[1,0,0,0,1,0],[1,0,0,0,1,0],[1,0,0,0,1,0],[0,1,1,1,0,0],[0,0,0,0,0,0]],N:[[1,0,0,0,1,0],[1,1,0,0,1,0],[1,0,1,0,1,0],[1,0,0,1,1,0],[1,0,0,0,1,0],[0,0,0,0,0,0]],Q:[[0,1,1,1,0,0],[1,0,0,0,1,0],[1,0,0,0,1,0],[1,0,0,1,1,0],[0,1,1,1,1,0],[0,0,0,0,0,0]],P:[[1,1,1,1,0,0],[1,0,0,0,1,0],[1,1,1,1,0,0],[1,0,0,0,0,0],[1,0,0,0,0,0],[0,0,0,0,0,0]],S:[[0,1,1,1,1,0],[1,0,0,0,0,0],[0,1,1,1,0,0],[0,0,0,0,1,0],[1,1,1,1,0,0],[0,0,0,0,0,0]],R:[[1,1,1,1,0,0],[1,0,0,0,1,0],[1,1,1,1,0,0],[1,0,0,1,0,0],[1,0,0,0,1,0],[0,0,0,0,0,0]],U:[[1,0,0,0,1,0],[1,0,0,0,1,0],[1,0,0,0,1,0],[1,0,0,0,1,0],[0,1,1,1,0,0],[0,0,0,0,0,0]],T:[[1,1,1,1,1,0],[0,0,1,0,0,0],[0,0,1,0,0,0],[0,0,1,0,0,0],[0,0,1,0,0,0],[0,0,0,0,0,0]],W:[[1,0,0,0,1,0],[1,0,0,0,1,0],[1,0,1,0,1,0],[1,0,1,0,1,0],[0,1,0,1,0,0],[0,0,0,0,0,0]],V:[[1,0,0,0,1,0],[1,0,0,0,1,0],[0,1,0,1,0,0],[0,1,0,1,0,0],[0,0,1,0,0,0],[0,0,0,0,0,0]],Y:[[1,0,0,0,1,0],[0,1,0,1,0,0],[0,0,1,0,0,0],[0,0,1,0,0,0],[0,0,1,0,0,0],[0,0,0,0,0,0]],X:[[1,0,0,0,1,0],[0,1,0,1,0,0],[0,0,1,0,0,0],[0,1,0,1,0,0],[1,0,0,0,1,0],[0,0,0,0,0,0]],Z:[[1,1,1,1,1,0],[0,0,0,1,0,0],[0,0,1,0,0,0],[0,1,0,0,0,0],[1,1,1,1,1,0],[0,0,0,0,0,0]]}

empty = ['\xA0', '.']
full = ['\u2588', 'X']
w = 6
h = 6

function makeGrid(height, width) {
    var grid = new Array(height)
    for(var y = 0; y < height; y++) {
        grid[y] = new Array(width)
    }
    return grid
}

function unfoldGrid(grid) {
    var newGrid = makeGrid(h * grid.length, w * grid[0].length)
    for (var y = 0; y < newGrid.length; y++) {
        for (var x = 0; x < newGrid[0].length; x++) {
            var yf = Math.floor(y / h), xf = Math.floor(x / w)
            if (grid[yf][xf] != 0) {
                newGrid[y][x] = grid[yf][xf][y % h][x % w]
            } else {
                newGrid[y][x] = 0
            }
        }
    }    
    return newGrid
}

function makeWords(words, empty, full) {
    var grid = makeGrid(1, words[0].length)
    for (var i = 0; i < words[0].length; i++) {
        grid[0][i] = alphabet[words[0][i]]
    }
    console.log(grid.length)
        console.log(grid[0].length)
    grid = unfoldGrid(grid)
    
        console.log(grid.length)
        console.log(grid[0].length)
    for(var i = 1; i < words.length; i++) {
        for (var y = 0; y < grid.length; y++) {
            var offset = 0
            for (var x = 0; x < grid[0].length; x++) {
                if (grid[y][x]) {
                    grid[y][x] = alphabet[words[i][offset++ % words[i].length]]
                }
            }
        }
        grid = unfoldGrid(grid)
    }
    
    var output = ''
    
    var height = Math.pow(h, words.length) - (Math.pow(h, words.length) - 1) / (h - 1)
    var width = words[0].length * Math.pow(w, words.length) - (Math.pow(w, words.length) - 1) / (w - 1)
    
    for (var y = 0; y < height; y++) {
        for (var x = 0; x < width; x++) {
            output += grid[y][x] ? full : empty                                    
        }
        if (y + 1 != height) {
            output += '\r\n'
        }
    }
    
    return output
}

function go() {
    plain = document.getElementById('plain').checked ? 1 : 0
    document.getElementById('canvas').value = makeWords(document.getElementById('words').value.split(' '), empty[plain], full[plain])
    resize()
}

function resize() {
    document.getElementById('canvas').style.fontSize = document.getElementById('size').value
}

function zoom(magnify) {
    canvas = document.getElementById('canvas')
    match = canvas.style.fontSize.match(/^(\d+(?:\.\d+)?)(.*)$/)
    if (match !== null) {
        number = parseFloat(match[1])
        unit = match[2]
        canvas.style.fontSize = document.getElementById('size').value = (number + (magnify ? 0.1 : -0.1)) + unit
    }
}
#canvas {
    font-family: Consolas, "Courier New", sans-serif;
    white-space: nowrap; overflow: auto;
    width: 6in;
    height: 3in;
}
<p>Words: <input type='text' id='words' value='DOG CAT MOUSE'> <button type='button' onclick='go()'>Go!</button> Plain ASCII <input type='checkbox' id='plain'></p>
<p>Font Size: <input type='text' id='size' value='0.4mm'> <button type='button' onclick='resize()'>Resize</button> <button type='button' onclick='zoom(1)'>+</button> <button type='button' onclick='zoom(0)'>-</button> (use any unit: in, cm, mm, em, pt, px)</p>
<textarea id='canvas'></textarea>

Typing any space separated list of words containing only capital letters in the textbox will produce the first word made of the second word made of the third, made of the fourth, made of ... etc.

WARNING: Entering more than 4 or even 3 words will produce A LOT of text and take a LONG time. It may crash your browser/computer/car.

Challenge

The goal of this challenge is to mirror what the Stack Snippet does in the fewest number of characters.

You must write a program that takes in a space separated string of words containing only capital letters, and outputs the first word "made of" the second "made of" the third and so on, using the pixelated font given above.

The "Plain ASCII" checkbox and the font size features of the snippet do not need to be supported in your program. Mirroring the transformation from lists of words to words made of words is the main point and only requirement.

Details

  • Input should come from stdin, the command line, or you may just write a function that takes a string.

  • You may assume the input is always valid, i.e. a string of words made of capital letters, separated by exactly one space, with no leading or trailing spaces.

  • Output should go to stdout (or similar alternative) or to a file with the name of your choice.

  • The output should consist entirely of empty-space characters, full-space characters, and newlines.

    • The empty/full-space characters should either be space and full block (, ) respectively, or period and X (., X) respectively.
  • The output should not contain any leading columns containing only empty-space characters, though any combination of trailing empty-space characters on any lines is allowed.

    • So this is allowed:

      X...X.XXXXX..
      X...X.X
      X.X.X.XXXX....
      X.X.X.X..
      .X.X..XXXXX..
      
    • But this isn't:

      .X...X.XXXXX..
      .X...X.X
      .X.X.X.XXXX....
      .X.X.X.X..
      ..X.X..XXXXX..
      
  • There should be no leading or trailing rows containing only empty-space characters. A single trailing newline is optionally allowed.

Here is a more string-friendly version of the font:

.XXX.
X...X
XXXXX
X...X
X...X

XXXX.
X...X
XXXX.
X...X
XXXX.

.XXX.
X...X
X....
X...X
.XXX.

XXXX.
X...X
X...X
X...X
XXXX.

XXXXX
X....
XXXX.
X....
XXXXX

XXXXX
X....
XXXX.
X....
X....

.XXXX
X....
X..XX
X...X
.XXXX

X...X
X...X
XXXXX
X...X
X...X

XXXXX
..X..
..X..
..X..
XXXXX

....X
....X
....X
X...X
.XXX.

X...X
X..X.
XXX..
X..X.
X...X

X....
X....
X....
X....
XXXXX

X...X
XX.XX
X.X.X
X...X
X...X

X...X
XX..X
X.X.X
X..XX
X...X

.XXX.
X...X
X...X
X...X
.XXX.

XXXX.
X...X
XXXX.
X....
X....

.XXX.
X...X
X...X
X..XX
.XXXX

XXXX.
X...X
XXXX.
X..X.
X...X

.XXXX
X....
.XXX.
....X
XXXX.

XXXXX
..X..
..X..
..X..
..X..

X...X
X...X
X...X
X...X
.XXX.

X...X
X...X
.X.X.
.X.X.
..X..

X...X
X...X
X.X.X
X.X.X
.X.X.

X...X
.X.X.
..X..
.X.X.
X...X

X...X
.X.X.
..X..
..X..
..X..

XXXXX
...X.
..X..
.X...
XXXXX

Scoring

This is so the shortest submission in bytes wins. Any instance of a full block () can be counted as 1 byte instead of 3 so submissions that use X don't have an advantage.

Calvin's Hobbies

Posted 2015-01-25T02:49:39.023

Reputation: 84 000

5

You can run the following JavaScript snippet (ex. by typing javascript: into the URL bar and pasting it) to make the ASCII art here much, much easier to read: $('#question pre').css('line-height',1). Result: http://i.stack.imgur.com/XmB8C.png

– Doorknob – 2015-01-25T04:53:21.577

1Or to include the answers $('#question pre, .answer pre').css('line-height',1) – Martin Ender – 2015-01-25T10:40:51.747

I know it's a little too late to make this joke, but I couldn't resist: i.imgur.com/vAZi1Zt.png.

– algorithmshark – 2015-07-14T21:11:17.057

How did I miss this challenge?! – Magic Octopus Urn – 2017-07-20T15:52:36.750

Answers

8

CJam, 171 165 162 161 bytes

qS/_0=,0a*a\{{W:I;{'[{RI):I=}?i65-"c¿»ÐòO*4Õ]%ÐÎ<à IX]{-ïèq=ô}s×o)½2~û³'é¨1ÃlØeúN!Ö3~4ÜË|ÕÇäaepý®"255b2b5/5/=}%z1af*}%R,1a*a*}fR2a*"█ 
"f=

I am treating as 1 byte. Rest all characters are well within ASCII range, so treating them as 1 byte too.

You can use this pastebin for the exact code

Example output for input:

FIRST HELLO WORLD

enter image description here

How it works

First of all

"c¿»ÐòO*4Õ]%ÐÎ<à IX]{-ïèq=ô}s×o)½2~û³'é¨1ÃlØeúN!Ö3~4ÜË|ÕÇäaepý®"255b2b5/5/

is simply the pattern for each of the 27 characters (A-Z and space) which is made up of 0 (at X positions) and 1 (at . positions). After decoding, this gives a 27 element array of 2D arrays of 5 rows and 5 columns representing X and . for each of the 27 characters. Let us call this array as L.

Now the remaining code:

qS/                      "Read the input and split it on space to get array Q";
   _0=                   "Get a copy of the first element of the above array";
      ,0a*               "Create an array filled with 0 with length of the first element";
          a\             "Wrap that array in another array and swap to get Q on top";
{  ...  }fR              "This is a for each loop on the array Q with R having the";
                         "current element value in each loop";
 {...}%                  "In the first iteration, the 0 array we created will be the";
                         "only thing on stack, in subsequent iterations, the result";
                         "of previous iteration will be on stack";
  W:I;                   "Initialize variable I with -1";
      {...}%             "Run this block on each element of the current array";
{'[{RI):I=}?i65-L=}%     "This is the above code block. In each iteration, we figure";
                         "out what character needs to be be put at the current index";
                         "Then we get the pattern of 0 and 1 for that character";
 '[{      }?             "Stack contains either 0 or 1. If it is 1, we want to leave";
                         "that index blank, so we put pattern of '[ which is 5X5 spaces";
    RI_:I=               "When we do not want a blank character, we get the next"
                         "character from R to fill the non empty space";
            i65-         "Convert A-Z  to 0-27 notation";
                L=       "Get the corresponding pattern from the pattern array L";
z1af*                    "After the above iterations, for each line of the previous";
                         "iteration's output, we get a vertical 2D array for next";
                         "iteration. We transpose it and join each character in";
                         "this line using a space";
      R,1a*a*            "After getting all lines from current iteration, we join them";
                         "with one full line of space characters";

 2a*                     "After all iterations, we have the 0 1 based 2D array for the";
                         "final output ASCII with each row representing a line. We join";
                         "these lines with 2, to get a 0 1 2 based array";
     "█                  "A brick, a space and a newline. Mapping 1 to 1 with 0 1 2";
"                        "based array";
 f=                      "For each of the 0 1 2 based array element, convert them to";
                         "one of the brick, space and new line character";

Try it online here

Optimizer

Posted 2015-01-25T02:49:39.023

Reputation: 25 836

9

Python 3, 437 bytes

from numpy import*
s=input().split()
d=fromstring('NONO__^Q_PQAQQNONO^_QQQQQ_QQQQAAAQDPIA[SQQQQADQQQJJH_OAQOOY_DPGAUUQOQONDQJUDDDQQQQAAQQDQIAQYQAYIPDQJUJDBQONO_A^Q_NQ_QQNA^QODNDJQD_',byte)[:,None]>>arange(5)&1
b=0
x=1
y=len(s[0])
n=[[1]*y]
for w in s:
 g=n;b+=x;x*=6;n=zeros((x,x*y),int);i=-6
 for q in g:
  o=j=0;i+=6
  for p in q:n[i:i+5,j:j+5]|=d[ord(w[o%len(w)])-65::26]*p;o+=p;j+=6
for r in n[:-b]:print(''.join(' █'[x] for x in r))

The character shapes are encoded in ASCII. Each ASCII byte corresponds to one row of one character, with bits representing unit blocks. It isn't a very efficient scheme, but it's easy to unpack into NumPy bitmasks for each character.

We start off with a 2d array of 1s. It has one column for each character in the first word and a single row. Then, for each word, we create a new array of 0s, six times higher and six times wider than the previous array. Where the previous array had a 1, the corresponding 6x6 section of the new array is filled with the appropriate character's bitmask.

Here's an example (with an extremely small font):

enter image description here

grc

Posted 2015-01-25T02:49:39.023

Reputation: 18 565

5

CJam, 181 174 170 bytes

All those non-ASCII characters are still within the extended ASCII range, so they can all be encoded in a single byte. (Except for the , but that one is treated specially according to the challenge spec.) Therefore, I'm counting each character as a byte.

"Á  :½A%õ­Íú£à˪ë8!Õ*j4¶fVËa¡ùÔ¯{+ÛyéâõKn#@?
9Ôia)(Ñç;~LÒª"257b2bYYb" █"er5/5/:L;lS/_0=,'█*a\{f{W:T;\{' ={S5*a5*}{T):T1$='A-L=}?\}%W<zSf*}Sa*}/N*

Stack Exchange has probably mangled some of the unprintable characters, so you might have to copy the code from this pastebin.

Test it here.

Takes input via STDIN as a space-separated list of words. The first word is the largest scale. For instance:

HOLISM REDUCTIONISM

yields

████                    █████             ████  █   █  ███              █████                               █████  ███  █   █ █████  ████             █   █ ████  █████ ████        █   █                    ███ 
█   █                   █                 █   █ █   █ █   █               █                                   █   █   █ ██  █   █   █                 ██ ██ █   █ █     █   █       █   █                   █   █
████                    ████              █   █ █   █ █                   █                                   █   █   █ █ █ █   █    ███              █ █ █ ████  ████  █   █       █   █                   █    
█  █                    █                 █   █ █   █ █   █               █                                   █   █   █ █  ██   █       █             █   █ █  █  █     █   █       █   █                   █   █
█   █                   █████             ████   ███   ███                █                                 █████  ███  █   █ █████ ████              █   █ █   █ █████ ████         ███                     ███ 

████                    █████       ████                    █   █        ███                                            █████                   █████                                ███  █   █       █████  ████
█   █                   █           █   █                   █   █       █   █                                             █                       █                                 █   █ ██  █         █   █    
████                    ████        █   █                   █   █       █                                                 █                       █                                 █   █ █ █ █         █    ███ 
█  █                    █           █   █                   █   █       █   █                                             █                       █                                 █   █ █  ██         █       █
█   █                   █████       ████                     ███         ███                                              █                     █████                                ███  █   █       █████ ████ 

████  █████ ████  █   █  ███        █████                   █████        ███                                            █   █                         █████  ████ █   █             ████        █████       ████ 
█   █ █     █   █ █   █ █   █         █                       █         █   █                                           ██  █                           █   █     ██ ██             █   █       █           █   █
████  ████  █   █ █   █ █             █                       █         █   █                                           █ █ █                           █    ███  █ █ █             ████        ████        █   █
█  █  █     █   █ █   █ █   █         █                       █         █   █                                           █  ██                           █       █ █   █             █  █        █           █   █
█   █ █████ ████   ███   ███          █                     █████        ███                                            █   █                         █████ ████  █   █             █   █       █████       ████ 

████                    █████       ████                    █   █        ███                                            █████                                           █████        ███                    █   █
█   █                   █           █   █                   █   █       █   █                                             █                                               █         █   █                   ██  █
████                    ████        █   █                   █   █       █                                                 █                                               █         █   █                   █ █ █
█  █                    █           █   █                   █   █       █   █                                             █                                               █         █   █                   █  ██
█   █                   █████       ████                     ███         ███                                              █                                             █████        ███                    █   █

████                    █████             ████  █   █  ███              █████ █████  ███  █   █ █████        ████ █   █ ████  █████ ████        █   █  ███  █████ █████              ███                    █   █
█   █                   █                 █   █ █   █ █   █               █     █   █   █ ██  █   █         █     ██ ██ █   █ █     █   █       █   █ █   █   █     █               █   █                   ██  █
████                    ████              █   █ █   █ █                   █     █   █   █ █ █ █   █          ███  █ █ █ ████  ████  █   █       █   █ █       █     █               █   █                   █ █ █
█  █                    █                 █   █ █   █ █   █               █     █   █   █ █  ██   █             █ █   █ █  █  █     █   █       █   █ █   █   █     █               █   █                   █  ██
█   █                   █████             ████   ███   ███                █   █████  ███  █   █ █████       ████  █   █ █   █ █████ ████         ███   ███    █   █████              ███                    █   █

Explanation

First, we store a lookup table for letter shapes in L:

"Á  :½A%õ­Íú£à˪ë8!Õ*j4¶fVËa¡ùÔ¯{+ÛyéâõKn#@?
9Ôia)(Ñç;~LÒª"257b2bYYb" █"er5/5/:L;

The first string just a compressed number. We treat the code points as base-257 digits, then we convert the resulting number to binary. YYb is 2 is in base 2, so it gives [1 0]. We use element substitution with " █" to turn the digits into spaces and block characters. Lastly, we split the string into rows of 5 characters, and again into blocks of 5 rows. The result is stored in L and discarded from the stack.

Now the general idea is to start with a single line of of the length of the largest-scale word. And then for each word we go through the existing grid, and expand all blocks to the corresponding character at the next smaller scale (while inserting empty rows and columns for separation). Here is the input preparation:

lS/_0=,'█*a\
lS/          "Read input, split on spaces.";
   _0=       "Duplicate and get first word.";
      ,'█*   "Get length repeat █ that many times.";
          a  "Wrap in array, to make the grid two-dimensional.";
           \ "Swap with word list.";

Let's look at the outermost structure of the remaining program first. The next block {...}/ is run for every word, and expands each of the block characters.

{f{...}Sa*}/N*
{         }/   "Process each word in the input.";
 f{...}        "Map this block onto each line of the grid, passing in the current word as well.";
       Sa*     "Since each original line will be turned into 5 lines, the grid is still grouped
                into blocks of 5 lines. We join them together with empty lines as required.";
            N* "Join all lines together with newlines.";

Lastly, let's look at how a single line is expanded:

W:T;\{' ={S5*a5*}{T):T1$='A-L=}?\}%
W:T;                                "Store -1 in T.";
    \                               "Swap word with line.";
     {                           }% "Map this block onto each character.";
      ' =                           "Check if the character is a space.";
         {      }{            }?    "If it is, run the first block, otherwise the second.";
          S5*                       "Create a string of five spaces.";
             a5*                    "Create an array of five such strings.";
                  T):T              "Push T, increment, store in T.";
                      1$=           "Copy the word and access the T'th character, cyclically.";
                         'A-        "Subtract A from the letter.";
                            L=      "Use the result to get the character shape from L.";
                                \   "Swap resulting block with word.";

"At this point each character is replaced with a 5x5 array of new characters.
 So we actually have a 3D array right now. Since we used a map operation, the
 current word will also be at the end of the array, which we need to get rid off.";

W<zSf*
W<     "Discard last array element - the current word.";
  z    "Zip or transpose the top two levels of the array.";
   Sf* "Join each line together with spaces.";

The result is printed automatically at the end of the program.

Martin Ender

Posted 2015-01-25T02:49:39.023

Reputation: 184 808