18
\$\begingroup\$

Given a text input such as:

THE QUICK
BROWN FOX
JUMPS OVER
THE LAZY
DOG

render the following output:

                            /\
                            \ \
                            /  \
                           / /\/
                          / /   /\
                         / /   / /
                      /\ \/   / / /\
                     /  \    /  \/ /
                    / /\/   / /\  / /\
                   /  \/\   \/ / / /  \
                  / /\/\/ /\  / / / /\ \
                  \ \/\  /  \ \/ /  \ \/
                   \/\/ / /\/   / /\/
                       /  \/\   \ \
                  /\  / /\/\/ /\ \ \
             /\  / /  \/ /\  /  \ \/       /\
            / / / / /\  / / / /\ \        /  \
            \ \/ / / /  \/ / / / /       / /\ \
          /\ \  / / / /\  / / / / /\    / / / /
          \ \ \/ / / / /  \ \/ / / /   / / / /
          /  \  / / / / /\ \  / / /    \ \/ /   /\
         / /\/  \ \/ / / /  \/ / / /\   \  /   / /
        / /   /\ \  / /  \     \/ / / /\ \ \  / / /\
       / /   / /  \/ / /\/     /\/ / / /  \/ / / / /
    /\ \/   / / /\  / / /\/\/\ \/\/ / / /\  / / / / /\
   /  \    /  \/ /  \/  \/\  /   /\/ / / /  \ \/ / / /
  / /\/   / /\  / /\      / / /\ \/\/ /  \   \  / / / /\
 / / /\   \/ / / /  \    / / /  \    / /\/    \/ / / /  \
/ / / / /\  / / / /\ \  / / / /\/   / / /\  /\  / / / /\ \
\ \/ / /  \ \/ /  \ \/  \/ /  \/\   \/  \/ / /  \/ / /  \/
 \/\/ / /\ \  / /\/       / /\/\/ /\    /\/ /     / /     /\
     / / / /  \ \         \/     /  \   \  /      \ \    / /
    / / / / /\ \ \              / /\ \  / /        \ \  / / /\
    \ \/ / /  \ \/       /\     \ \ \/  \/       /\ \/ /  \/ /
     \  / / /\ \        / /   /\ \ \            /  \  / /\/\/
      \/ / /  \/       / /    \ \/ /           / /\ \ \/ /\
        / / /\        / /      \  /           /  \ \/   / /
        \ \/ /       / /     /\ \/       /\  / /\/   /\ \/
         \  /        \ \    /  \        /  \ \/     /  \
          \/          \ \  / /\ \      / /\ \      / /\ \
                       \/ /  \/ /     / / / /     / / / /
                         / /\  / /\  / / / / /\  / / / / /\
                         \/ / /  \ \ \ \/ / / /  \ \/ / / /
                           / /    \ \ \  / / / /\ \  /  \/ /\
                           \/ /\/\/ /  \/ / / / /  \/ /\/\/ /
                             / /\/\/ /\   \/ / / /\  / /\/\/
                             \ \    / /   /\/ / /  \ \/ /\
                              \ \  / / /\ \/\/ / /\ \  / /
                               \/  \ \/ /     /  \ \/  \/
                                   /   /     / /\/   /\
                                  / /\/      \ \    /  \
                                  \/          \ \  / /\/
                                               \/ /  \/\
                                                 / /\/\/
                                                 \/ /\
                                                   / /
                                                   \/

Rules

  • The program only needs to work for upper-case A–Z, spaces and newlines. Everything else is allowed to produce undefined behaviour.
  • The program is allowed to output any number of extraneous leading or trailing spaces or newlines, as long as the block of text is contiguous as shown.
  • Your output may use ‘/’ (U+002F) and ‘\’ (U+005C), or (for prettier Unicode rendering) ‘╱’ (U+2571) and ‘╲’ (U+2572).
  • The font must look exactly as shown above. The example contains all the letters A–Z. Arnauld has kindly provided a bitmappy version of the font here.
\$\endgroup\$
11
  • 1
    \$\begingroup\$ What are the specifications for the output? Do the letters have to look exactly as shown? Do the spaces have to be the same width as shown? Can the output be scaled up or down? If so, by how much? \$\endgroup\$
    – Makonede
    Jun 5, 2023 at 16:48
  • 1
    \$\begingroup\$ @Makonede The letters must have this exact shape and the spaces must be this exact width. \$\endgroup\$
    – Timwi
    Jun 5, 2023 at 17:30
  • 1
    \$\begingroup\$ @ShaunBebbington That sounds amazing! Can’t wait to see it! If the limitations of the system require scrolling then I’ll allow it. \$\endgroup\$
    – Timwi
    Jun 5, 2023 at 17:31
  • 1
    \$\begingroup\$ @Kaddath Indeed. As it so happens, jackdaws love my big sphinx of quartz. Pack my box with five dozen liquor jugs! The five boxing wizards jump quickly. \$\endgroup\$
    – Timwi
    Jun 7, 2023 at 23:15
  • 4
    \$\begingroup\$ I didn't VTC but I guess the problem is that a large part of the specification must be deduced from the example. It would be clearer and more convenient if the font was also included as a standard matrix (see the link in my comment above) and the width of the space and the padding between characters were specified in plain English. I got both wrong in my first version (invalid shape for the 'P' and invalid space width). \$\endgroup\$
    – Arnauld
    Jun 9, 2023 at 16:26

3 Answers 3

21
\$\begingroup\$

JavaScript (Node.js), 418 bytes

Expects a list of strings.

a=>(m=[]).map(r=>r.join``,a.map((s,Y)=>(F=y=>~y--&&F(y,Buffer(s).map(c=>(G=x=>x^'2672020001'[c*31%87%33]^4&&G(-~x,(m[X=(a.length-Y)*6-++y+o,Y*6+y+o++]||=Array(X).fill` `).splice(X,2," /"[g(~-x)^g(x)]," \\"[v^g(x,y--)])))(g=x=>v=parseInt(['757553535371117355537131771311715575575511111444575535511117hrlhhhjlph75557353117555f3535571747722225555755552hllla552555572274217'[c*5-325+y]],32)>>x&31>>y&1),o=0)))(5))).join`
`

Attempt This Online!

Font encoding

Each character is horizontally mirrored, right-aligned and converted to five 5-bit values expressed in base-32.

For instance, N is encoded as "hjlph":

X...X    10001    17    'h'
X..XX    10011    19    'j'
X.X.X -> 10101 -> 21 -> 'l'
XX..X    11001    25    'p'
X...X    10001    17    'h'

All letter encodings are concatenated together to get a single lookup string of 130 characters. The encoding of the space ("00000") is not explicitly stored.

 7575535353..hrlhhhjlph..5572274217
 \___/\___/  \___/\___/  \___/\___/
   A    B      M    N      Y    Z

To get the state of the 'pixel' at \$(x,y)\$ of the character whose ASCII code is \$c\$, we do:

parseInt([ lookup_string[c * 5 - 325 + y] ], 32) >> x & 31 >> y & 1

This code supports \$-1\le x\le 5\$ and \$-1\le y\le 5\$ so that a 1-pixel character border can be tested as well.

Width encoding

Right padding included, most characters have a width of 4. The exceptions are as follows:

  • I has a width of 2
  • Q has a width of 5
  • M, N and W have a width of 6
  • the space has a width of 3

We use a lookup string, a hash function and a XOR with 4 to turn any valid ASCII code into the corresponding width:

'2672020001'[c * 31 % 87 % 33] ^ 4

Attempt This Online!

Drawing algorithm

Basic principles:

  • We draw by filling a matrix \$m\$, whose exact size is decided on the fly.

  • We compare the pixel at \$(x-1,y)\$ with the pixel at \$(x,y)\$ to figure out if we must draw the / boundary.

  • We compare the pixel at \$(x,y-1)\$ with the pixel at \$(x,y)\$ to figure out if we must draw the \ boundary.

Pseudo-code:

for each string s at index Y in a[]:
  for y = 5 to 0:
    let o = 0
    for each character c in s:
      for x = 0 to width(c) - 1:
        let X = (a.length - Y) * 6 - y + o
        let R = Y * 6 + y + o
        if pixel(c, x, y) != pixel(c, x - 1, y):
          m[R][X] = "/"
        else:
          m[R][X] = " "
        end
        if pixel(c, x, y) != pixel(c, x, y - 1):
          m[R][X + 1] = "\"
        else:
          m[R][X + 1] = " "
        end
        o = o + 1
      end
    end
  end
end
\$\endgroup\$
9
  • 5
    \$\begingroup\$ I did it!! I managed to disentangle your code and fully understand how it works. Here’s my disentangled code, which I posted to gist before I saw your link (which I’ll look at now). I can now see that you loop over the text pixels in reading order but place the / \ characters in the array at their intended positions. This is very clever and also minimizes the number of extra spaces/empty lines. I’m truly impressed. \$\endgroup\$
    – Timwi
    Jun 6, 2023 at 22:15
  • 8
    \$\begingroup\$ What I found most impressive about this solution: • Using x^w as a loop-ending condition to save the parentheses due to operator precedence; • Using additional unused arguments to perform computation before the call happens; • Using parseInt([x], 32) instead of parseInt(x, 32) to make undefined turn into 0 instead of 33790067563981; • The way you manipulate y when you call g so it cancels out; • The way you use v to avoid two identical calls to g. — Just amazing all around! \$\endgroup\$
    – Timwi
    Jun 6, 2023 at 22:17
  • 1
    \$\begingroup\$ @TImwi -~x and ~-x are actually required because x is initialized to the NaN'ish declaration of g rather than 0 (declaring g there saves a byte). \$\endgroup\$
    – Arnauld
    Jun 6, 2023 at 22:28
  • 3
    \$\begingroup\$ This was a brute force search, injecting random values on predefined patterns (with or without the multiplication and with different numbers of chained modulos). This one was found quickly -- maybe in 1 minute or so. (But there's no guarantee it's the shortest solution, nor the most efficient formula.) \$\endgroup\$
    – Arnauld
    Jun 7, 2023 at 0:25
  • 2
    \$\begingroup\$ You always have impressive solutions, but this one is a real beast! \$\endgroup\$
    – Kaddath
    Jun 7, 2023 at 12:19
13
\$\begingroup\$

Funciton, non-competitive

Big dramatic reveal! This coding challenge was actually suggested to me by a friend. I originally wrote it in C# but then decided that this might be an excuse to flex my old Funciton muscles again. I haven’t written Funciton code in several years and this was a refreshing trip down memory lane.

If I had to do it all over again, I imagine I might implement this very differently. This is the implementation I came up with on my own before being influenced by the other answers posted here.

Try it online!

                           ╔═════════════════╗    ╓┬──╖
                           ║↓  Lookup table  ║    ╟┘➫ ║
                           ╚═════════════════╝    ╙─┬─╜
                                                 ┌──┴──────────────────────────────────────────────────────────────────────────────┐
                           ┌─────────────────────┴──────────────────────┐                                       ┌──────────────────┴─────────────────┐
                           │                               ┌────────────┴───────────┐                 ┌─────────┴────────┐                  ┌────────┴────────┐
                           │                   ╔════╗      │      ╔═══╗    ╔════╗   │   ╔═══╗ ╔═══╗   │   ╔════╗ ╔═══╗   │   ╔════╗ ╔═══╗   │   ╔═══╗ ╔═══╗   │   ╔═══╗
                           │                   ║ 16 ╟─┬────┴────┬─╢ 8 ║    ║ 16 ╟─┬─┴─┬─╢ 8 ║ ║ 4 ╟─┬─┴─┬─╢ 16 ║ ║ 8 ╟─┬─┴─┬─╢ 16 ║ ║ 8 ╟─┬─┴─┬─╢ 4 ║ ║ 2 ╟─┬─┴─┬─╢ 1 ║
                           │                   ╚════╝┌┴┐       ┌┴┐╚═══╝    ╚════╝┌┴┐ ┌┴┐╚═══╝ ╚═══╝┌┴┐ ┌┴┐╚════╝ ╚═══╝┌┴┐ ┌┴┐╚════╝ ╚═══╝┌┴┐ ┌┴┐╚═══╝ ╚═══╝┌┴┐ ┌┴┐╚═══╝
    ╔═════════════════╗    │                         └┬┘       └┬┘               └┬┘ └┬┘           └┬┘ └┬┘            └┬┘ └┬┘            └┬┘ └┬┘           └┬┘ └┬┘
    ║↓  Main program  ║    │                          │         │                 │   │             │   │              │   │              │   └────────────┐└┐ ┌┘
    ╚═════════════════╝    │                          │         │                 │   │             │   │              │   │              └──────────────┐ │ │ │
                           │                  ┌───────┴───────┐ │                 │   └─────┐ ┌─────┘   └───────┐      │   └───────────────────┐         │ │ │ │
    ╔════╗ ┌───╖ ╔═══╗     │ ╔═════╗ ╔══════╗ │ ╔═══╗ ╔═════╗ │ │ ╔═════╗ ╔═════╗ │ ╔═════╗ │ │ ╔═════╗ ╔═════╗ │      │    ╔═════╗ ╔════════╗ │         │ │ │ │
    ║ 10 ╟─┤ ǁ ╟─╢   ║     │ ║57419║ ║385324║ │ ║127║ ║56199║ │ │ ║57417║ ║57419║ │ ║25859║ │ │ ║57417║ ║57419║ │      └──┐ ║57419║ ║25312128║ │         │ │ │ │
    ╚════╝ ╘═╤═╝ ╚═══╝     │ ║47683║ ║282504║ │ ║496║ ║46254║ │ │ ║79243║ ║37781║ │ ║43344║ │ │ ║79243║ ║37781║ │         │ ║37781║ ║56720763║ │         │ │ │ │
     ╔═══╗ ┌─┴─╖           │ ║02700║ ║754621║ │ ║773║ ║80982║ │ │ ║08922║ ║62235║ │ ║36197║ │ │ ║08911║ ║62172║ │ ╔═════╗ │ ║62176║ ║11198970║ │ ╔═════╗ │ │ │ │
     ║ 0 ╟─┤ ≭ ╟─┬─┐       │ ║91420║ ║004585║ │ ║380║ ║96636║ │ │ ║39781║ ║19366║ │ ║71362║ │ │ ║32975║ ║24436║ │ ║57419║ │ ║16428║ ║26960857║ │ ║57419║ │ │ │ │
     ╚═══╝ ╘═╤═╝ └─┘       │ ║13362║ ║913748║ │ ║488║ ║66983║ │ │ ║52695║ ║61768║ │ ║83996║ │ │ ║65107║ ║21417║ │ ║47644║ │ ║21732║ ║44720451║ │ ║37781║ │ │ │ │
           ┌─┴─╖           │ ║17373║ ║829211║ │ ║444║ ║78457║ │ │ ║33243║ ║30029║ │ ║77254║ │ │ ║77280║ ║53549║ │ ║34204║ │ ║28458║ ║11713714║ │ ║62235║ │ │ │ │
           │ ʝ ╟─          │ ║1297 ║ ║812321║ │ ║9  ║ ║1361 ║ │ │ ║0305 ║ ║0529 ║ │ ║82262║ │ │ ║9697 ║ ║6673 ║ │ ║69971║ │ ║8513 ║ ║89      ║ │ ║19366║ │ │ │ │
           ╘═╤═╝           │ ╚══╤══╝ ╚═══╤══╝ │ ╚═╤═╝ ╚══╤══╝ │ │ ╚══╤══╝ ╚══╤══╝ │ ║05066║ │ │ ╚══╤══╝ ╚══╤══╝ │ ║31884║ │ ╚══╤══╝ ╚═══╤════╝ │ ║61766║ │ │ │ │
           ╔═╧══╗          │    │      ┌─┴─╖  │   │    ┌─┴─╖  │ │    │     ┌─┴─╖  │ ║58254║ │ │    │     ┌─┴─╖  │ ║27401║ │    │      ┌─┴─╖    │ ║15326║ │ │ │ │
           ║ 10 ║          │    └──────┤ ? ╟──┘   └────┤ ? ╟──┘ │    └─────┤ ? ╟──┘ ║60705║ │ │    └─────┤ ? ╟──┘ ║6737 ║ │    └──────┤ ? ╟────┘ ║5633 ║ │ │ │ │
           ╚════╝          │           ╘═╤═╝           ╘═╤═╝    │          ╘═╤═╝    ╚══╤══╝ │ │          ╘═╤═╝    ╚══╤══╝ │           ╘═╤═╝      ╚══╤══╝ │ │ │ │
                           │             │             ┌─┴─╖    │            │       ┌─┴─╖  │ │            │       ┌─┴─╖  │             │         ┌─┴─╖  │ │ │ │
                           │             └─────────────┤ ? ╟────┘            └───────┤ ? ╟──┘ │            └───────┤ ? ╟──┘             └─────────┤ ? ╟──┘ │ │ │
                           │                           ╘═╤═╝                         ╘═╤═╝    │                    ╘═╤═╝                          ╘═╤═╝    │ │ │
                           │                             │                           ┌─┴─╖    │                      │                            ┌─┴─╖    │ │ │
                           │                             └───────────────────────────┤ ? ╟────┘                      └────────────────────────────┤ ? ╟────┘ │ │
                           │                                                         ╘═╤═╝                                                        ╘═╤═╝      │ │
                           │                                                           │                                                          ┌─┴─╖      │ │
                           │                                                           └──────────────────────────────────────────────────────────┤ ? ╟──────┘ │
                           │                                                                                                                      ╘═╤═╝        │
                           │                                                    ┌────────────────────────────────────────────┐                    ┌─┴─╖        │
                   ┌───────┴────────────────────────────────────────────────────┤                                            │                  ┌─┤ ? ╟────────┘
                   │  ┌─────────────────────┐                   ┌───────────────┴────────────────┐                  ┌────────┴────────┐         │ ╘═╤═╝
                   └──┤   ╔════╗    ╔═══╗   │   ╔════╗  ╔═══╗   │   ╔═══╗               ╔════╗   │   ╔═══╗ ╔════╗   │   ╔═══╗ ╔═══╗   │   ╔═══╗ │   │
                      └─┬─╢ 16 ║    ║ 8 ╟─┬─┴─┬─╢ 16 ║  ║ 8 ╟─┬─┴─┬─╢ 4 ║               ║ 16 ╟─┬─┴─┬─╢ 8 ║ ║ 16 ╟─┬─┴─┬─╢ 8 ║ ║ 4 ╟─┬─┴─┬─╢ 2 ║ │
                       ┌┴┐╚════╝    ╚═══╝┌┴┐ ┌┴┐╚════╝  ╚═══╝┌┴┐ ┌┴┐╚═══╝               ╚════╝┌┴┐ ┌┴┐╚═══╝ ╚════╝┌┴┐ ┌┴┐╚═══╝ ╚═══╝┌┴┐ ┌┴┐╚═══╝ │
                       └┬┘               └┬┘ └┬┘             └┬┘ └┬┘                          └┬┘ └┬┘            └┬┘ └┬┘           └┬┘ └┬┘      │
 ╔═══╗                  │          ┌──────┘   └──────┐        └┐ ┌┘                            │   └───┐          │   └───────────┐ └┐ ┌┘       │
 ║837║         ┌────────┴────────┐ │                 │         │ │                 ┌───────────┴─────┐ │          └──────┐        └┐ │ │        │
 ║432║ ╔═════╗ │ ╔═════╗ ╔═════╗ │ │ ╔═════╗ ╔═════╗ │         │ │ ╔═════╗ ╔═════╗ │ ╔═════╗ ╔═════╗ │ │ ╔═════╗ ╔═════╗ │ ╔═════╗ │ │ │        │
 ║805║ ║56199║ │ ║57419║ ║57419║ │ │ ║56204║ ║56199║ │         │ │ ║56204║ ║57419║ │ ║57419║ ║57417║ │ │ ║56199║ ║56204║ │ ║25859║ │ │ │        │
 ║150║ ║16423║ │ ║47683║ ║47644║ │ │ ║21587║ ║46138║ │         │ │ ║21548║ ║47644║ │ ║37781║ ║79243║ │ │ ║16423║ ║21587║ │ ║43343║ │ │ │        │
 ║183║ ║50812║ │ ║02700║ ║34204║ │ │ ║36609║ ║75184║ │ ╔═════╗ │ │ ║68109║ ║34204║ │ ║62235║ ║09099║ │ │ ║50635║ ║51721║ │ ║27309║ │ │ │        │
 ║327║ ║18427║ │ ║91420║ ║69971║ │ │ ║90066║ ║41781║ │ ║57417║ │ │ ║99683║ ║69948║ │ ║19366║ ║48636║ │ │ ║09595║ ║67539║ │ ║22544║ │ │ │        │
 ║828║ ║74945║ │ ║13364║ ║58272║ │ │ ║25838║ ║38014║ │ ║79243║ │ │ ║79356║ ║80052║ │ ║52971║ ║39834║ │ │ ║66024║ ║42131║ │ ║21530║ │ │ │        │
 ║094║ ║88960║ │ ║32075║ ║67052║ │ │ ║24098║ ║54677║ │ ║08911║ │ │ ║07744║ ║24853║ │ ║92198║ ║60629║ │ │ ║48808║ ║97528║ │ ║04309║ │ │ │        │
 ║25 ║ ║8161 ║ │ ║6193 ║ ║3873 ║ │ │ ║1473 ║ ║6545 ║ │ ║32908║ │ │ ║9697 ║ ║5521 ║ │ ║5873 ║ ║3473 ║ │ │ ║3937 ║ ║3169 ║ │ ║76132║ │ │ │        │
 ╚═╤═╝ ╚══╤══╝ │ ╚══╤══╝ ╚══╤══╝ │ │ ╚══╤══╝ ╚══╤══╝ │ ║09671║ │ │ ╚══╤══╝ ╚══╤══╝ │ ╚══╤══╝ ╚══╤══╝ │ │ ╚══╤══╝ ╚══╤══╝ │ ║04007║ │ │ │        │
   │    ┌─┴─╖  │    │     ┌─┴─╖  │ │    │     ┌─┴─╖  │ ║82407║ │ │    │     ┌─┴─╖  │    │     ┌─┴─╖  │ │    │     ┌─┴─╖  │ ║73755║ │ │ │        │
   └────┤ ? ╟──┘    └─────┤ ? ╟──┘ │    └─────┤ ? ╟──┘ ║3185 ║ │ │    └─────┤ ? ╟──┘    └─────┤ ? ╟──┘ │    └─────┤ ? ╟──┘ ║94977║ │ │ │        │
        ╘═╤═╝             ╘═╤═╝    │          ╘═╤═╝    ╚══╤══╝ │ │          ╘═╤═╝             ╘═╤═╝    │          ╘═╤═╝    ╚══╤══╝ │ │ │        │
          │               ┌─┴─╖    │            │       ┌─┴─╖  │ │            │               ┌─┴─╖    │            │       ┌─┴─╖  │ │ │        │
          └───────────────┤ ? ╟────┘            └───────┤ ? ╟──┘ │            └───────────────┤ ? ╟────┘            └───────┤ ? ╟──┘ │ │        │
                          ╘═╤═╝                         ╘═╤═╝    │                            ╘═╤═╝                         ╘═╤═╝    │ │        │
                            │                           ┌─┴─╖    │                              │                           ┌─┴─╖    │ │        │
 ╔═════════════════════╗    └───────────────────────────┤ ? ╟────┘                              └───────────────────────────┤ ? ╟────┘ │        │
 ║  Decode the base-4  ║                 ╓┬───╖         ╘═╤═╝                                                               ╘═╤═╝      │        │
 ║  representation    ↓║                 ╟┘⊁p ║           │                                                                 ┌─┴─╖      │        │
 ╚═════════════════════╝    ╔═══╗        ╙─┬──╜           └─────────────────────────────────────────────────────────────────┤ ? ╟──────┘        │
    ╔═══╗ ┌───╖             ║ 3 ╟───┬──────┴───────────┐                              ╔════╗ ┌────╖                         ╘═╤═╝               │
    ║ 2 ╟─┤ = ╟─────────┐   ╚═══╝  ┌┴┐   ╔═══╗ ┌────╖  │                              ║ 21 ╟─┤ >> ╟───────────┬─────────────┐ └─────────────────┘
    ╚═══╝ ╘═╤═╝ ╔════╗  │          └┬┘   ║ 2 ╟─┤ >> ╟──┴──────────┐ ╔═══════════════╗ ╚════╝ ╘══╤═╝         ╓─┴─╖     ╔═══╗ │
            │   ║ 32 ║  │           │    ╚═══╝ ╘═╤══╝             │ ║  Render a     ║         ┌─┴─╖         ║ ⊅ ║     ║ 6 ║ │
            │   ╚═╤══╝  ├───────────┴─┐        ┌─┴─╖              │ ║  row of text →║ ┌───────┤ ⊅ ╟─────┐   ╙───╜     ╚═╤═╝ │
 ╔══════╗ ┌─┴─╖ ┌─┴─╖ ┌─┴─╖      ┌────┴────────┤ · ╟────────────┐ │ ╚═══════════════╝ │       ╘═══╝   ┌─┴─╖             │   │
 ║ 9585 ╟─┤ ? ╟─┤ ? ╟─┤ = ║      │             ╘═╤═╝            │ │       ┌───╖       │         ┌─────┤ · ╟─────────┐ ┌─┴─╖ │
 ╚══════╝ ╘═╤═╝ ╘═╤═╝ ╘═╤═╝      │   ╔════╗    ┌─┴──╖           │ │     ┌─┤ ‼ ╟─┐     │ ┌───╖ ┌─┴─╖   ╘═╤═╝   ┌───╖ ├─┤ − ║ │
       ╔════╧═╗  ┌┴┐  ╔═╧═╗      │   ║ 21 ║ ┌──┤ ⊁p ╟────┐      │ │     │ ╘═╤═╝ │     └─┤ ʭ ╟─┤ ȶ ║     └─────┤ + ╟─┘ ╘═╤═╝ │
       ║ 9586 ║  └┬┘  ║ 1 ║      │   ╚═╤══╝ │  ╘════╝    │      │ │   ┌─┴─╖ │   │       ╘═╤═╝ ╘═╤═╝           ╘═╤═╝   ┌─┴─╖ │
       ╚══════╝   │   ╚═══╝ ┌┐ ┌─┴─╖ ┌─┴──╖ │   ┌─┐      │      │ │ ┌─┤ · ╟─┘ ┌─┘       ┌─┴─╖ ┌┬┘ ┌───╖ ╔═══╗ ┌─┴─╖   │ ɕ ║ │
                  └─────┬───┤├─┤ · ╟─┤ << ║ │   ├─┘   ┌──┴──┐   │ │ │ ╘═╤═╝   │     ┌───┤ · ╟─┘├──┤ ⁞ ╟─╢ 0 ╟─┤ ? ╟─┐ ╘═╤═╝ │
 ┌──────────┐   ╔═══╗ ┌─┴─╖ └┘ ╘═╤═╝ ╘═╤══╝ │ ╔═╧═╕ ┌─┴─╖ ┌─┴─╖ │ │ │   │     │     │   ╘═╤═╝  └┐ ╘═══╝ ╚═══╝ ╘═╤═╝ │ ┌─┴─╖ │
 │ ╓┬──╖    │   ║ 0 ╟─┤ ? ╟──────┘     └────┴─╢   ├─┤ · ╟─┤ ? ╟─┘ │ │ ╔═╧═╕ ╔═╧═╕ ┌─┴─╖ ┌─┴─╖ ┌─┴─╖            ─┘   └─┤ · ╟─┴─┐
 │ ╟┘⊁ ║    │   ╚═╤═╝ ╘═╤═╝                   ╚═╤═╛ ╘═╤═╝ ╘═╤═╝   │ └─╢   ├─╢   ├─┤ · ╟─┤ ʑ ╟─┤ ʭ ║ ┌─┬─────────────┐ ╘═╤═╝   │
 │ ╙─┬─╜    │     │   ┌─┴─╖                     └─────┘     │     │   ╚═╤═╛ ╚═╤═╛ ╘═╤═╝ ╘═╤═╝ ╘═╤═╝ │ │ ┌───╖ ┌───╖ └───┘     │
 │ ┌─┴──╖ ╔═╧═╕   └───┤ ? ╟───────────────────────┐ ╔═══╗ ┌─┴─╖   │     │   ╔═╧═╗ ┌─┴─╖ ┌─┴─╖   └───┘ └─┤ ⊁ ╟─┤ ➫ ╟───────┐   │
 └─┤ ⊁p ╟─╢   ├─┬─┐   ╘═╤═╝                       │ ║ 0 ╟─┤ ? ╟─┐ │     └───╢ 0 ║ │ ȶ ╟─┤ ? ╟─┐         ╘═══╝ ╘═══╝      ┌┴┐  │
   ╘════╝ ╚═╤═╛ └─┘    ─┘                         │ ╚═══╝ ╘═╤═╝ ├─┘         ╚═══╝ ╘═╤═╝ ╘═╤═╝ │              ╔═════════╗ └┬┘  │
    ╓───╖   │   ╔════════════╗                    │         └─  │                 ╔═╧═╗   └─  │              ║ 2097151 ╟──┴─┐ │
    ║ ✰ ║       ║  Generate  ║                    └─────────────┘                 ║ 6 ║       │              ╚═════════╝    ├─┘
    ╙─┬─╜       ║  padding  ↓║                                                    ╚═══╝       └─────────────────────────────┘
  ┌───┴───┐     ╚════════════╝   ╔═══════════╗   ┌───────────────────────────────────────────────────────┐
  │     ┌─┴─╖ ┌───╖       ╔═══╗  ║  Prepend  ║   │ ┌───╖                                                 │
  │     │ + ╟─┤ ♫ ╟───────╢ 0 ║  ║  a row    ║ ┌─┴─┤ < ╟─────────────────┐                               │
  │     ╘═╤═╝ ╘═╤═╝   ┌─┐ ╚═╤═╝  ║  of text →║ │   ╘═╤═╝               ┌─┴─╖                             │
  │     ╔═╧═╗   │   ┌─┴─╖ ╔═╧═╕  ╚═══════════╝ │   ┌─┴─╖ ┌─────────────┤ · ╟─────────────┐               │
  │     ║ 6 ║   └───┤ ɱ ╟─╢   ├──────────────┐ │ ┌─┤ ? ╟─┤ ┌───╖ ┌───╖ ╘═╤═╝             │   ╔═══╗ ╓───╖ │
  │     ╚═══╝       ╘═══╝ ╚═╤═╛              │ │ │ ╘═╤═╝ └─┤ + ╟─┤ ~ ╟─┐ │ ┌───╖         │   ║ 0 ║ ║ ≭ ╟─┘
  │   ┌───╖ ┌───╖           │                │ └─┤   │     ╘═╤═╝ ╘═══╝ │ ├─┤ ⊅ ╟───┐     │   ╚═╤═╝ ╙─┬─╜
  │ ┌─┤ + ╟─┤ ~ ╟───────────┴───┐            │ ┌─┘   │     ┌─┴─╖       ├─┘ ╘═╤═╝ ┌─┴─╖ ┌─┴─╖ ┌─┴─╖   │
  └─┤ ╘═╤═╝ ╘═══╝             ┌─┴──╖         │ │     └─────┤ · ╟───────┴─┐   └───┤ · ╟─┤ · ╟─┤   ╟───┴───────────┐
    │ ┌─┴──╖    ┌───╖ ╔════╗  │ << ╟──┐      │ │           ╘═╤═╝         │       ╘═╤═╝ ╘═╤═╝ └─┬─╜               │
    │ │ << ╟────┤ + ╟─╢ 11 ║  ╘═╤══╝  │      │ │           ┌─┴─╖         │   ╔═══╗ │ ┌───┘     │                 │
    │ ╘═╤══╝    ╘═╤═╝ ╚════╝  ╔═╧═╗ ┌─┴─╖    │ │           │ ✰ ║         │   ║ 0 ║ │ │   ┌─────┘                 │
    │ ╔═╧═╗       │  ╔════╗   ║ 1 ║ │ ♯ ║    │ │           ╘═╤═╝         │   ╚═╤═╝ │ │   │                       │
    │ ║ 1 ║       │  ║ 12 ╟─┐ ╚═══╝ ╘═╤═╝    │ │           ┌─┴─╖ ┌───╖ ┌─┴─╖ ┌─┴─╖ │ │ ┌─┴─╖                     │
    │ ╚═══╝ ┌───╖ │  ╚════╝ │ ┌───╖   │      │ │           │ ʭ ╟─┤ ʭ ╟─┤ ȶ ║ │ ⁞ ║ │ └─┤ ≭ ╟─────────────┐       │
  ┌─┴──╖  ┌─┤ > ╟─┴─────┐ ┌─┴─┤ > ╟───┴───┐  │ │           ╘═╤═╝ ╘═╤═╝ ╘═╤═╝ ╘═╤═╝ │   ╘═╤═╝ ╔═══╗ ┌───╖ │       │
  │ << ╟──┤ ╘═╤═╝       │ │   ╘═╤═╝       │  │ │             │   ┌─┴─╖   ├─────┘   │     │   ║ 5 ╟─┤ + ╟─┴─────┐ │
  ╘═╤══╝  │ ┌─┴─╖       │ │   ┌─┴─╖       │  │ │     ┌─────┐ └───┤ · ╟───┴─┐       │     │   ╚═══╝ ╘═╤═╝       │ │
  ╔═╧═╗   └─┤ ? ╟───┐   │ └───┤ ? ╟───┐   │  │ │   ┌─┴─╖ ┌─┴─╖   ╘═╤═╝   ┌─┴─╖ ┌───┘     │         ┌─┴─╖       │ │
  ║ 1 ║     ╘═╤═╝ ┌─┴─╖ │     ╘═╤═╝ ┌─┴─╖ │  │ │ ┌─┤ · ╟─┤ ‼ ║   ┌─┴─╖ ┌─┤ ʭ ║ │ ┌───────┘     ┌───┤ + ║       │ │
  ╚═══╝       └───┤ · ╟─┘       └───┤ · ╟─┘  │ │ │ ╘═╤═╝ ╘═╤═╝ ┌─┤ ʑ ╟─┘ ╘═╤═╝ │ │     ┌───╖ ┌─┴─╖ ╘═╤═╝       │ │
                  ╘═╤═╝ ┌───╖       ╘═╤═╝    │ │ │ ╔═╧═╕ ╔═╧═╕ │ ╘═╤═╝     └───┘ │ ┌───┤ ʝ ╟─┤ ȶ ║ ┌─┴─╖       │ │
                  ┌─┴───┤ > ╟───────┐ │      │ │ └─╢   ├─╢   ├─┤ ┌─┴─╖     ┌─────┘ │   ╘═╤═╝ ╘═╤═╝ │ ~ ║       │ │
                  │     ╘═╤═╝       ├─┘      │ │   ╚═╤═╛ ╚═╤═╛ └─┤ ʑ ╟─┐ ┌─┴─╖   ╔═╧═╗ ╔═╧═╕ ┌─┴─╖ ╘═╤═╝       │ │
                  │     ┌─┴─╖       │        │ │   ╔═╧═╗   │     ╘═╤═╝ └─┤ ʭ ║   ║ 0 ╟─╢   ├─┤ · ╟───┘         │ │
                  └─────┤ ? ╟───┐   │        │ │   ║ 0 ╟───┘     ┌─┴─╖   ╘═╤═╝   ╚═╤═╝ ╚═╤═╛ ╘═╤═╝             │ │
                        ╘═╤═╝ ┌─┴─╖ │ ╔════╗ │ │   ╚═╤═╝ ┌───────┤ ? ╟───┐ │     ┌─┴─╖ ┌─┴─╖ ┌─┴─╖ ╔═══╗ ┌───╖ │ │
                          └───┤ · ╟─┘ ║ 32 ║ │ │     │ ┌─┴─╖     ╘═╤═╝   │ └─────┤ · ╟─┤ ɱ ║ │ ⁞ ║ ║ 6 ╟─┤ + ╟─┘ │
                              ╘═╤═╝   ╚═╤══╝ │ │   ┌─┴─┤ · ╟─────┐ │     │       ╘═╤═╝ ╘═╤═╝ ╘═╤═╝ ╚═══╝ ╘═╤═╝   │
                  ╔═══╗ ┌───╖ ┌─┴─╖   ┌─┴─╖  │ │   │   ╘═╤═╝   ┌─┴───┐   │ ╔═══╗ ┌─┴─╖   │  ╔══╧═╗ ╔═══╗ ┌─┴─╖   │
                  ║ 0 ╟─┤ ʝ ╟─┤ ȶ ║   │ ⁞ ║  │ │ ┌─┴─╖ ┌─┴─╖ ╔═╧═╕ ┌─┴─╖ │ ║ 6 ║ │ ♫ ╟───┘  ║ 32 ║ ║ 0 ╟─┤ ? ╟─┐ │
                  ╚═══╝ ╘═╤═╝ ╘═╤═╝   ╘═╤═╝  │ │ │ ♫ ╟─┤ ɱ ╟─╢   ├─┤ ʝ ║ │ ╚═╤═╝ ╘═╤═╝      ╚════╝ ╚═══╝ ╘═╤═╝ ├─┘
                          │     └───────┘    │ │ ╘═╤═╝ ╘═══╝ ╚═╤═╛ ╘═╤═╝ │   └─────┘                       └─  │
                          └──────────────────┘ └───┘  ┌────────┘     └─┐ └─────────────────────────────────────┘
                                                      │ ╔════╗ ┌───╖ ┌─┴─╖
                                                      │ ║ 32 ╟─┤ ⁞ ╟─┤ ȶ ╟─┐
                                                      │ ╚════╝ ╘═══╝ ╘═══╝ │
                                                      └────────────────────┘

How it works

  • First, there is a lookup-table-like function () that maps ASCII codes to a number which represents the letter’s shape in base-4. For example, I maps to a number which is 1012301212012120121201212013201 in base-4. This function looks at just enough least-significant bits to identify just the letters A–Z and the space. Any other Unicode character will therefore be mapped to one of those. For example, the digits 0–9 become letters P–Y.
  • Then there’s a function () that turns this base-4 representation into a sequence of strings, one per line, turning 1 into space, 2 into , 3 into , and appending to the sequence and starting a new string when encountering a 0. Thus, I becomes ·\n·╱╲\n·╱·╱\n·╱·╱\n·╱·╱\n·╱·╱\n·╲╱\n·. This string representation includes both a single space after each character and one on top of each character, so as to create the one-space margin.
  • The next function, , takes a string (e.g. DOG) and simply concatenates these string representations at the appropriate offsets (D at the start, O 6 lines down, and G 12 lines down). It also calculates the total width of this row of text.
  • The main logic (implemented in ) operates as a recursive function that iterates over the lines of text in the input:
    • The function first calls to render the current line and calculate its width.
    • Then the recursive call happens, and we pass the maximum width to the next level of recursion. This way, each invocation knows how wide the widest line of text above it is.
    • At the base of the recursion, we know the widest width we need to accommodate and we can generate the bottom-left triangle of spaces (shown as in the example below).
    • After the recursive call, we prepend the current line of text. This is done in three steps:
      • 6 new lines are added at the top, containing the necessary spaces at the start (shown as (iteration 2) and (iteration 1) in the example below). With each returning iteration, the amount of spaces to be added is incremented by 6.
      • The rendered letter shapes are appended (starting at the top).
      • Extra spaces are generated (by ) to bring the width all the way to the widest width we need (shown as in the example below).
  • Finally, the main program just splits the input at \ns, calls with that, and then joins the resulting strings with newlines.

Here’s the example for the input W\nA:

■■■■■■■■■■■·
■■■■■■■■■■╱╲·
■■■■■■■■■╱·╱··
■■■■■■■■╱·╱····
■■■■■■■╱·╱·╱╲···
■■■■■■·╲╱·╱·╱·╱╲·
●●●●●··╱╲╱·╱·╱·╱·
●●●●╱╲·╲╱╲╱·╱·╱·
●●●╱··╲··╱╲╱·╱·
●●╱·╱╲·╲·╲╱╲╱·
●╱··╲╱·╱·▲···
╱·╱╲··╱·▲▲▲·
╲╱·╱·╱·▲▲▲▲
•·╱·╱·▲▲▲▲
••╲╱·▲▲▲▲
•••·▲▲▲▲
••••▲▲▲
•••••▲

Example output:

Console window showing output for “THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG”

\$\endgroup\$
12
\$\begingroup\$

Charcoal, 177 143 141 bytes

WSF⁶⊞υE⭆ι⁺?§⪪”‴!⊟γ←B)1F»$g'~δZ@↷➙O'no⦄℅ψzY´´A⭆≦μ6δTK⮌´κ?C…p⌊*RUUρ⁻Ee℅²«êSQe¹AAK›Σ↓^⬤ωε!⬤fº”¶℅λ§↨℅λ²κP↘⪫Eυ⭆ι§╲ ⁼§§υ⊕κμλ¶→P↘⪫Eυ⭆ι§╱ ⁼§ι⊕μλ¶

Try it online! Link is to verbose version of code. Takes input as a list of newline-terminated strings and outputs the prettier rendering at a cost of 4 bytes. Explanation:

WS

Loop over each input string.

F⁶⊞υE⭆ι⁺?§⪪”...”¶℅λ§↨℅λ²κ

Look up each letter in the input string in a large compressed lookup table of ASCII encoded horizontally flipped character bitmaps. The encoded bitmaps are joined with ? (representing blank values) before being decoded, converted into 6-bit binary (all the values are in the range 32-63), and transposed, and the bitmaps for all of the lines are collected together.

P↘⪫Eυ⭆ι§╲ ⁼§§υ⊕κμλ¶→

Output s where each bit changes from the next row.

P↘⪫Eυ⭆ι§╱ ⁼§ι⊕μλ¶

Output s at each change in bit in each row.

Edit: Saved 34 bytes by taking inspiration from @Arnauld's encoding method, but inverting the bits because that simplifies the Charcoal code. Saved 2 bytes by building up the entire bitmap at once rather than a line at a time. Note that although the bitmap has a ragged right edge the joining rows are all blank so it makes no difference. The bitmap is output rotated as compared to the previous version which explains the adjustments to the output code.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ @Arnauld Thanks, fixed. I wonder how I managed to make the same mistake... \$\endgroup\$
    – Neil
    Jun 6, 2023 at 10:20
  • \$\begingroup\$ "I initially got the 'P' wrong. I've posted a link to the fixed font as a comment to the question. – Arnauld" was the comment that my above comment is a reply to, but it has since been removed for some reason. \$\endgroup\$
    – Neil
    Jun 6, 2023 at 22:18
  • \$\begingroup\$ Well, I tend to remove my comments once they've been 'processed'. :-) I guess I took a copy of O and turned it into a P the way I would have done it without double-checking the shape described in the challenge. Maybe you did the same thing. \$\endgroup\$
    – Arnauld
    Jun 6, 2023 at 22:38

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.