title: Treasure Map Drawing Bot

text:
# Question
Title: Treasure Map Drawing Bot
You're organizing a treasure hunt for your friends. To conduct things more easily, you want to draw a map of all locations where you hid the precious objects.

## Input

Any form of input denoting a list of points consisting of (nonnegative) x- and y-coordinate, `0 0` being the upper left corner is permitted (Note: You may also use 1-based indexing in your answer, please comment on that if you do). Example:

```
1 2
3 0
0 1

```

## Challenge

Your function or program should be able to construct a map denoting every given location with an `x` where the mark is found in row y + 1 and column x + 1 in the output. Unmarked locations are represented with a . The map also consists of a frame where the corners are `+`s, the vertical lines are `|`s and the horizontal lines are `-`s. Your solution should output the smallest possible frame. Map for the input example given above:

```
+----+
|   x|
|x   |
| x  |
+----+

```

## Possible Test Cases

---

```
"0 0"
=>
+-+
|x|
+-+

```

---

```
"0 10
 5 5
 10 0"
=>
+-----------+
|          x|
|           |
|           |
|           |
|           |
|     x     |
|           |
|           |
|           |
|           |
|x          |
+-----------+

```

---

```
""
=>
++
++

```

---

```
"0 0
 0 2
 2 0"
=>
+---+
|x x|
|   |
|x  |
+---+

```

---

Of course, this is , meaning that the solution with the lowest byte count wins! Explanations of your solution are encouraged.

# Answer
# , ~~37~~ 34 bytes

```
0<@|:' x'{~((i.@]e.#.~)1+>./) ::#:

```

Try it online!

```
                       1+>./          maximum for each coordinate + 1
             i.@]                     make an array with these dimensions filled with 0..x*y
                                      /* if the input is empty,
                                         1+>./ is negative infinity
                                         and i.@] throws an error  */
                   #.~                mixed base conversion of input
                 e.                   replace the elements of i.@]
                                        with 1 if it's present in the
                                        converted input, 0 otherwise
           (                ) ::      if there's an error do the other thing instead
                                #:    "to binary", for empty input this returns a 0x0 matrix
0<@|:' x'{~                           index into character string, transpose and put in a box

```
> 7 votes

# Answer
# JavaScript (ES6), 150 bytes

Takes input as a list of 1-indexed coordinates in `[x,y]` format. Returns a string.

```
a=>(g=w=>y<h?' |-+x'[4*a.some(a=>a+''==[x,y])|2*(-~y%h<2)|++x%w<2]+[`
`[x=x<w?x:+!++y]]+g(w):'')((M=i=>Math.max(2,...a.map(a=>a[i]+2)))(x=y=0),h=M(1))

```

Try it online!
> 4 votes

# Answer
# Haskell, ~~127~~ 123 bytes

This defines the operator `(!)` which takes a list of *x*-coordinates and a list of the corresponding *y*-coordinates:

```
x!y|l<-'+':('-'<$m x)++"+"=unlines$l:['|':[last$' ':['x'|(i,j)`elem`zip x y]|i<-m x]++"|"|j<-m y]++[l];m x=[1..maximum$0:x]

```

Try it online!

### Ungolfed/Explanation

The helper function `m` expects a list and returns indices (1-based) up to the maximum, if the list is empty it returns `[]`:

```
m x | null x    = []
    | otherwise = [1 .. maximum x]

```

The actual operator `(!)` is just a list-comprehension, traversing all the coordinates and choosing a  or `x` character, which gets joined with newlines:

```
x ! y
  -- construct the top and bottom line
  | l <- "+" ++ replicate (maximum (0:x)) '-' ++ "+"
  -- join the list-comprehension with new-lines
  = unlines $
  -- prepend the top line
      [l]
  -- the actual map:
    -- begin the line with | and add the correct chars for each coordinate
      ++ [ "|" ++ [ if (i,j) `elem` zip x y then 'x' else ' '
    -- "loop" over all x-coordinates
                 | i <- m x
                 ]
    -- end the line with a |
           ++ "|"
    -- "loop" over all y-coordinates
         | j <- m y
         ]
  -- append the bottom line
      ++ [l]

```
> 4 votes

# Answer
# Canvas, 22 bytes

```
ø╶｛X；┤╋｝ｌ|＊ｅＬ┤-×+ｅ：└∔∔

```

Try it here!

Takes 1-indexed inputs.

Finally decided to fix a bug that's been annoying me for ages and golfed this down to 21 bytes.

Explanation (half-ASCII-fied for monospace):

```
ø╶{X;┤╋}l|*eL┤-×+e:└++  full program, implicitly outputting ToS at the end
ø                       push an empty Canvas - the map
 ╶{    }                for each array in the input array
   X                      push "X"
    ;┤                    and push the two coordinates separately on the stack
      ╋                   and overlap the "X" there in the map
        l               get the vertical length of the map
         |*             repeat "|" vertically that many times
           e            encase the map in two of those vertical bars
            L           get the horizontal length of the map
             ┤          subtract 2 (leave place for the "+"es)
              -×        repeat "-" that many times
                +e      encase that line in "+"es
                  :└    push a copy of that below the map
                    ++  and join the 3 items vertically

```
> 3 votes

# Answer
# Python 2, ~~151~~ ~~140~~ 138 bytes

-2 bytes thanks to Jo King.

Input is 1-indexed.

```
m=input()
w,h=map(max,zip((0,0),*m))
b=['+'+'-'*w+'+']
M=b+['|'+' '*w+'|']*h+b
for x,y in m:M[y]=M[y][:x]+'x'+M[y][x+1:]
print'\n'.join(M)

```

Try it online!
> 3 votes

# Answer
# Charcoal, 37 bytes

```
≔Ｅ²⁺²⌈Ｅθ§λιηＢ⊟⮌η⊟ηＦθ«Ｊ⊟⮌ι⊟ιx

```

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

```
¿¬ＬθＵＲ²+«

```

Special-case empty input by drawing a 2x2 rectangle of `+`s.

```
≔Ｅ²⁺²⌈Ｅθ§λιη

```

Transpose the input, take the maximum of each column (now row) and add 2 to get the box size in Charcoal co-ordinates.

```
Ｂ⊟⮌η⊟η

```

Draw the box.

```
Ｆθ«

```

Loop over each co-ordinate.

```
Ｊ⊟⮌ι⊟ι

```

Jump to its position.

```
x

```

Mark with a cross.
> 2 votes

# Answer
# Stax, ~~32~~ ~~31~~ 24 bytes

```
╩╠ee%╙æM■↓^⌐╧ΩΓ¡c¥èf¢○ [

```

Run and debug it

Takes 0-based indices as array of `[y, x]` pairs.

Explanation:

```
zs'X&|<cM%'-*'+|S]s{'||Smn++m Unpacked program, implicit input
zs                            Tuck empty array under input
  'X                          Push "X"
    &                         Assign element at all indices (create map)
                                As the indexing arrays are an array of arrays, treat them as a path to navigate a multidimensional array.
                                Extend array if needed.
     |<                       Left-align all to the length of the longest.
       cM%                    Copy, transpose, length (width)
          '-*                 Repeat "-"
             '+|S             Surround with "+"
                 ]s           Make a singleton and tuck it below the map
                   {    m     Map:
                    '||S        Surround with "|"
                         n++  Surround with the above/below border (built above)
                            m Map:
                                Implicit output

```
> 2 votes

# Answer
# , ~~133 125~~ 122 bytes

```
function(m)cat(z<-c("+",rep("-",u<-max(m[,1])),"+","
"),rbind("|",`[<-`(matrix(" ",u,max(m[,2])),m,"x"),"|","
"),z,sep="")

```

Try it online!

1-indexed. Takes a matrix as argument. Saved 8 bytes thanks to digEmAll, 3 thanks to Giuseppe! Explanation (earlier version of code):

```
function(m){                           #x and y are the 1st and 2nd col of m
s=matrix(32,u<-max(m[,1]),max(m[,2]))  #s (treasure map) has dim max(x), max(y)
s[m]=120                               #place the X's on the map
cat(                                   #print:
    z<-c("+",rep("-",u),"+","\n"),     #the top line
    intToUtf8(rbind(124,s,124,13)),    #the map
    z,                                 #the bottom line.
    sep="")
}

```
> 2 votes

# Answer
coords taken of the format \[y,x\]

# JavaScript (Node.js), 191 184 bytes

```
c=f=a=>{a.map(([y,x])=>(c[M<++y?M=y:y]=c[y]||[])[m<++x?m=x:x]="x",M=m=0)
m++
M++
s=""
for(i=0;i<=M;s+=`
`,i++)for(j=0;j<=m;j++)s+=(c[i]||0)[j]||(j%m?i%M?" ":"-":i%M?"|":"+")
return s}

```

Try it online!
> 1 votes

# Answer
# JavaScript, 180 bytes

```
F =

s=>s.map(([x,y])=>(t[y]=t[Y<y?Y=y:y]||[])[X<x?X=x:x]='x',t=[X=Y=0])&&[...t,0].map((_,y)=>[...Array(X+2)].map((_,x)=>[(t[y]||0)[x]||' ',...'-|+'][!(y%~Y)+2*!(x%~X)]).join``).join`
`

console.log(F([[1,11],[6,6],[11,1]]))
```
> 1 votes

# Answer
# C (gcc), 246 234 bytes

Thanks to ceilingcat for the suggestion.

Zero-indexed. The function takes a list of co-ordinates and buffer, finds the maximum x and y values, fills the buffer with spaces, generates the frame, and then plots the 'x's.

```
f(int*a,char*c){int*b=a,x,y=x=-1,i=0;for(;~*b;*++b>y?y=*b:0,++b)*b>x?x=*b:0;for(x+=4,y+=3,memset(c,32,x*y);++i<x;c[i]=c[y*x-i]=45);for(i=0;i<y;c[x*++i-1]=10*(i<=y))c[x*i]=c[x*i+x-2]=i&&y/i?124:43;for(b=a;~*b;b+=2)c[*b+1-~b[1]*x]='x';}

```

Try it online!
> 1 votes

# Answer
# Java 10, ~~238~~ ~~223~~ ~~220~~ 219 bytes

```
c->{var r="";int w=0,h=0,x,y;for(var l:c){w=(x=l.get(0))>w?x:w;h=(y=l.get(1))>h?y:h;}for(w++,h-=x=-1;x++<w;r+="\n")for(y=-1;y++<h;)r+=x%w+y%h<1?"+":x%w<1?"-":y%h<1?"|":(c+r).contains("["+x+", "+y+"]")?"x":" ";return r;}

```

-3 bytes thanks to *@ceilingcat*.

1-indexed coordinates.

Try it online.

**Explanation:**

```
c->{                      // Method with 2D Lists as parameter and String return-type
  var r="";               //  Result-String, starting empty
  int w=0,h=0,            //  Width and height, starting at 0
      x,y;                //  Temp x,y coordinates
  for(var l:c){           //  Loop over the Inner Lists containing the coordinates
    w=(x=l.get(0))>w?x:w; //   Determine width based on max x-coordinate
    h=(y=l.get(1))>h?y:h;}//   Determine height based on max y-coordinate
  for(w++,h-=             //  Increase both the width and height by 1
      x=-1;x++<w;         //  Loop `x` in the range [0, width]:
      r+="\n")            //    After every iteration: append a new-line to the result
    for(y=-1;y++<h;)      //   Inner loop `y` in the range [0, height]:
      r+=                 //    Append the following character to the result-String:
         x%w+y%h<1?       //    If it's one of the corners:
          "+"             //     Append "+"
         :x%w<1?          //    Else-if it's the top or bottom row:
          "-"             //     Append "-"
         :y%h<1?          //    Else-if it's the right or left column:
          "|"             //     Append "|"
         :(c+r).contains("["+x+", "+y+"]")?
                          //    Else-if the current `x,y` is part of the input-coordinates:
          "x"             //     Append "x"
         :                //    Else:
          " ";            //     Append " "
  return r;}              //  Return the result-String

```
> 1 votes

# Answer
# 05AB1E, ~~44~~ 42 bytes

```
ζεZ}>`UX'-×'+.ø©,F'|NVXF¹YN‚.å„ xè}'|J,}®,

```

Try it online!

---

```
 ζεZ}>`                                     # Push the max of X and Y to the stack +1.
       UX                                   # Store the max X.
         '-×'+.ø©,                          # Print the top border.
                  F                     }   # From 0 to Y...
                   '|                       # Push left border.
                     NV                     # Store current Y in Y.
                       XF          }        # From 0 to X...
                         ¹                  # Push input.
                          YN‚               # Group current X and Y.
                             .å             # Exists in original input ? 1 : 0
                               „ xè         # Exists ? 'X' : ' '
                                    '|J,    # Right border, join, print.
                                         ®, # Print bottom border.

```

X and Y may be reversed, didn't know if that mattered at all.

---

~~I think I have this in less bytes, but we'll see...~~ ***Nope.***

```
ζεZ}>`D'-×'+.øUð×'|.øs.D)X.ø©svy>`s®sUXès'xsǝXǝ}

```
> 1 votes

# Answer
# C (gcc), ~~229~~ ~~220~~ 216 bytes

-9 bytes thanks to ceilingcat.

Zero-indexed. Takes coordinates as list of numbers, where even numbers are X and odd numbers are Y.

```
X,Y,i,j,k,x,z;f(l,n)int*l;{for(X=Y=0,i=n*=2;i--;X=fmax(l[i],X))Y=fmax(l[i--],Y);n&&X++-Y++;for(--i;i++<Y;puts(""))for(j=-1;j<=X;z=i<0|i==Y,putchar(j++<0|j>X?z?43:'|':x?z?45:32:'x'))for(x=k=n;k--;)x*=l[k--]-i|l[k]-j;}

```

Try it online!
> 0 votes

---
Tags: code-golf, ascii-art
---


title: Morse the New Year

text:
# Question
Title: Morse the New Year
This is **Weekly Challenge #1.** Theme: **Audio Processing**

Your task is to write a program, which writes an audio file to disc (in a format of your choice), which contains the Morse code for `2015`, i.e.

```
..--- ----- .---- .....

```

You are free to choose any sort of sound for the segments, like a single-frequency sine wave, a chord, noise, some instrument (e.g. using MIDI files), as long as it's audible. However, there are some constraints on the timing:

* Short segments need to be at least 0.2 seconds in length.
* Long segments need to be at least 3 times as long as short segments.
* Breaks between segments within a digit should be the same length as short segments.
* Breaks between digits should be the same length as long segments.
* Each segment and break may deviate up to 10% from the average length of that type of segment/break.
* The entire audio file may not be longer than 30 seconds.

The breaks don't need to be completely silent, but the Morse segments should be audibly louder than the breaks.

Note that you *have* to write an audio file. You cannot just play the sound, e.g. using system beeps. You're allowed to use any sort of library to handle the file format and audio generation, but you must not use built-in features for Morse encoding.

This is code golf, so the shortest answer (in bytes) wins.

Please consider linking to an upload of the resulting audio file (on SoundCloud or similar), so people can check out the result without having to run your code. If you upload to SoundCloud, please make sure to enable downloads in the Permissions tab of the track.

If your output uses a rather uncommon file format, please add some information about how to play it back and/or convert it to a more common format and upload it.

### Example track

This is a manually generated example track which conforms with the spec and uses noise for the Morse segments (microphone background noise, to be precise). **Here is a link to SoundCloud** if the embedded player doesn't work for you.

## Bounty Details

I will award the bounty to the shortest submission in an audio programming language, i.e. a language that is designed to synthesise sound. That list is not complete, so feel free to use another audio programming language, if you know one. If you're not sure whether some language you want to use classifies as an audio programming language, please let me know in the comments or in chat, and we can discuss that.

Note that your submission still has to comply with all the rules - in particular, it has to write a file, which might not be possible in all audio programming languages. E.g., as far as I can tell, gibber can only play the sound and not save it to a file.

# Answer
## ~~AWK~~ BASH: ~~66~~ ~~86~~ ~~67~~ 74 bytes

As requested by Martin Büttner, I added a tempo since after checking the ABC Notation standard, it seems there is no defined default value for this (thanks nutki for pointing this).
I also write into a disk file (a) instead of STDOUT since the question wanted explicitly "a file on disc".

```
a=C3z;echo "X:1
K:A
Q:99
CzCz$a$a$a3$a$a$a$a${a}3Cz$a$a$a${a}3CzCzCzCzC">a

```

I put a tempo of 99 which causes the audio file to last 22 seconds; It's slower than my previous version, but at least now it is supposed to be the same length on every ABC player, and it fit under 30 seconds.

It looks ... very much like the previous version as you can see:

Here is the new midi file.

## First BASH version (tempo is missing)

Why didn't I think to this first... :o)

That's 22 less bytes than with AWK, for the same result

```
a=C3z;echo "X:1
K:A
CzCz$a$a$a3$a$a$a$a${a}3Cz$a$a$a${a}3CzCzCzCzC"

```

Like the previous version in AWK, it write on stdout a valid "ABC" notation file (thanks Tobia for finding out that the "L" statement was optional)

It looks like this:

And it sounds exactly like the previous version.

## Previous version in AWK (86 Bytes)

Here is a new version; a little longer, but with a more accurate timing. I let the first version bellow for comparison/reference:

```
BEGIN{a="C3z";print"X:1\nK:A\nL:1/8\nCzCz"a a a"3"a a a a a"3Cz"a a a a"3CzCzCzCzCz";}

```

This is still a valid "abc" file, which looks like this:

Here is the new midi file (I accelerated the tempo to stay under the 30 seconds limit).

## First version in AWK (66 Bytes):

This is a lot less interesting than my previous answer, but it is a lot shorter, so:

```
BEGIN{print"X:1\nK:A\nL:1/4\nCCC2C2C2zC2C2C2C2C2zCC2C2C2C2zCCCCC"}

```

This outputs a valid "abc" file, which can be read into (among others) EasyABC. It will look like this:

and it will sound like this (midi file). +
> 4 votes

# Answer
# x86 machine code (.COM file): ~~121~~ ~~120~~ ~~113~~ 109 bytes

Hexdump:

```
00000000  b4 3e bb 01 00 cd 21 b4  3c 31 c9 ba 3e 01 cd 21  |.>....!.<1..>..!|
00000010  4a b4 09 cd 21 be 56 01  8a 0c 46 e8 0c 00 b1 32  |J...!.V...F....2|
00000020  e8 07 00 81 fe 6d 01 75  ef c3 88 cb c0 e3 07 c1  |.....m.u........|
00000030  e1 04 30 d2 b4 02 00 da  cd 21 e2 fa c3 2e 73 6e  |..0......!....sn|
00000040  64 00 00 00 18 ff ff ff  ff 00 00 00 02 00 00 10  |d...............|
00000050  00 00 00 00 01 24 33 33  99 99 99 66 99 99 99 99  |.....$33...f....|
00000060  99 66 33 99 99 99 99 66  33 33 33 33 33           |.f3....f33333|
0000006d

```

Can be easily run under DosBox; the output is a .SND file named `SND`. Here is a FLAC version of its output (and here the .COM file).

Commented assembly:

```
    org 100h

start:
    ; close stdout
    mov ah,3eh
    mov bx,1
    int 21h
    ; open snd
    mov ah,3ch
    xor cx,cx
    mov dx,filename
    int 21h
    ; write the header
    ; we used the `snd` part of the header as file name, back off one byte
    dec dx
    mov ah,9h
    int 21h
    mov si,data
.l:
    ; data read cycle
    ; read the current byte in cl (zero-extending to 16-bit)
    ; notice that ch is already zero (at the first iteration it's 0 from the
    ; int 21h/3ch, then we are coming from gen, which leaves cx to zero)
    mov cl,[si]
    ; move to next byte
    inc si
    ; generate the tone
    call gen
    ; generate the pause
    mov cl,50
    call gen
    ; repeat until we reach the end of data
    cmp si,eof
    jne .l
    ; quit
    ret

gen:
    ; generate a sawtooth wave at sampling frequency/2 Hz
    ; receives length (in samples>>4) in cx, with lowest bit indicating if
    ; it has to write a wave or a pause
    mov bl,cl
    ; shift the rightmost bit all the way to the left; this kills the
    ; unrelated data and puts a 128 in bl (if cx & 1 != 0)
    shl bl,7
    ; rescale the samples number
    shl cx,4
    ; zero the starting signal
    xor dl,dl
    ; prepare the stuff for int 21h
    mov ah,2h
.l:
    ; increment the signal
    add dl,bl
    ; write it
    int 21h
    ; decrement iteration count and loop
    loop .l
    ret

    ; .SND file header (4096 samples, mono, PCM)
header:
    db "."
    ; we also use "snd" as the file name
filename:
    db "snd",0,0,0,24,0xff,0xff,0xff,0xff,0,0,0,2,0,0,0x10,0,0,0,0,1
    ; terminator for int 21h/ah=9h
    db '$'
data:
    ; generated by gendata.py
    incbin "data.dat"
eof:

```

The `data.dat` included above is an easy-to-use representation of the morse string (lower bit: sound on/sound off, upper 7 bits: sound length in samples \>\> 4) generated by a Python script:

```
#!/usr/bin/env python2
import sys

# source string
s = "..--- ----- .---- ....."
# samples
sr = 4096
conv =  {
            '.': 1 | (((sr/5) >> 4) & ~1),    # dot:   1/5 second, dI/dt=1
            '-': 1 | (((sr/5*3) >> 4) & ~1),  # line:  3/5 second, dI/dt=1
            ' ':     ((sr/5*2) >> 4) & ~1     # space: 2/5 second (+1/5 from the always-present pause), dI/dt=0 (silent)
        }
sys.stdout.write(''.join(chr(conv[a]) for a in s))

```
> 13 votes

# Answer
# Mathematica - 130

```
r = Riffle;
s = SoundNote;
Export["m.mid",
 Sound@
   r[Flatten@
     r[
       s[0,.4(Boole@#+.5)]&/@Array[#>4&,5,5-#]&/@{2,0,1,5},
       (b=None~s~#&)@.6
     ],b@.2
   ]
]

```

Play online
> 8 votes

# Answer
# Python, 155

Uses the python built-in wave module.

```
import wave
n=wave.open(*"nw")
k=17837
n.setparams((2,2,k,0,"NONE",0))
h=k*1314709609
while h:[n.writeframes(`i%9`)for i in[0]*(2-h%2)*k+range(h%4*k)];h/=4

```

Writes to a file called `n`.

Thanks Sp3000 for suggestion on using list comprehension for loop (this helped remove a bit of indentation).

**Listen to it:**

https://soundcloud.com/bitpwner/morse-the-new-year-2015

**Here is a link to SoundCloud** if the embedded player doesn't work for you.

**Commented code:**

```
import wave
n=wave.open("n.wav","w")         # Open a wav file for writing
k=44100
n.setparams((2,2,k,0,"NONE","")) # Sets the minimal params for the wav file
w=n.writeframes
h=23450475295733                 # Contains base-4 morse: '.'=1, '-'=3, ' '=0
while h:
    for i in range(h%2*k):w(h%4*chr(i%99)) # Writes saw-tooth signal using i%99
    w((2-h%2)*k*" ")                       # Writes the pauses
    h/=4

```
> 7 votes

# Answer
# Perl 5: 94 122 140

SND files have simpler headers, no need to print in binary. This versions produce 8khz mono SND file named 'a':

```
open A,'>a';print
A".snd",pack"N*",24,-1,2,8e3,1,map{(--$|x3)x(894261072>>$_&1?1600:400)}0..39

```

The result file.

Old solution. Produces a 1khz 8-bit mono WAV file named 'a':

```
open
A,'>a';print
A pack"A4lA8lssllssA4ls*",RIFF,17040,WAVEfmt,16,1,1,(1e3)x2,1,8,data,17004,map{($_)x(894261072>>$v++&1?400:100)}(255,0)x20

```

The result file.

To get to 122 characters I had to paste the header in binary instead of packing it which makes the code hard to copy here. The escaped version is:

```
open
A,'>a';print
A"RIFF\x90B\0\0WAVEfmt \0\0\0\0\0\xe8\0\0\xe8\0\0\0\0datalB\0\0",pack"s*",map{($_)x(894261072>>$v++&1?400:100)}(255,0)x20

```

Base64 encoding of the actual 122 bytes solution:

```
b3BlbgpBLCc+YSc7cHJpbnQKQSJSSUZGkEIAAFdBVkVmbXQgEAAAAAEAAQDoAwAA6AMAAAEACABk
YXRhbEIAACIscGFjayJzKiIsbWFweygkXyl4KDg5NDI2MTA3Mj4+JHYrKyYxPzQwMDoxMDApfSgy
NTUsMCl4MjA=

```
> 7 votes

# Answer
## AWK: ~~172~~ 170 bytes

...and without using any wave library! (\*)

```
BEGIN{for(;++i<204;){d=d"\177\177\n";D=D"\n\n"}t=d d d D;d=d D;T=D D D;u=t t t;print".snd\0\0\0\30\0\0\221\306\0\0\0\2\0\0\20\0\0\0\0\1"d d u T u t t T d u t T d d d d d}

```

This outputs a Sun au audio file on stdout which can be played by vlc (among others). While the au fileformat don't have any sample rate limitation, VLC refuses to play any file with a sampling rate inferior to 4096 Hz, so I used this frequency

EDIT: Link to resulting audio file on DropBox

---

(\*) Shouldn't there be a bonus for this? ;o)
> 7 votes

# Answer
# C#, ~~556~~ ~~552~~ ~~536~~ ~~535~~ ~~516~~ ~~506~~ ~~503~~ ~~491~~ 483 bytes

Uses the library Wav.Net.

```
using System;using System.Linq;namespace WavDotNet.Core{using S=Samples<float>;class P{static void Main(){var w=new WavFileWrite<float>("a",9999);var b=new Tools.Generators.Sawtooth(9999);Func<long,float,S>g=(t,a)=>b.Generate32Bit(new TimeSpan(t),99,a);var l=2500000;S x=g(l,1),y=g(l*3,1),z=g(l*3,0),_=g(l,0),v=new S(new[]{x,_,x,_,y,_,y,_,y,z,y,_,y,_,y,_,y,_,y,z,x,_,y,_,y,_,y,_,y,z,x,_,x,_,x,_,x,_,x}.SelectMany(c=>c).ToList());w.AudioData.Add(new Channel<float>(v,0));w.Flush();}}}

```

Outputs to a file named `a`.

**Result hosted on Dropbox**

Ungolfed code:

```
using System;
using System.Linq;
namespace WavDotNet.Core
{
    using FloatSamples = Samples<float>;
    class P
    {
        static void Main()
        {
            var file = new WavFileWrite<float>("output.wav", 9999);
            var sawtoothGen = new Tools.Generators.Sawtooth(9999);
            Func<long, float, FloatSamples> generate = (t, amplitude) => sawtoothGen.Generate32Bit(new TimeSpan(t), 99, amplitude);
            var length = 2500000;
            FloatSamples shortBeep = generate(length, 1),
            longBeep = generate(length * 3, 1),
            shortPause = generate(length * 3, 0),
            longPause = generate(length, 0),
            allSamples = new FloatSamples(new[] { shortBeep, longPause, shortBeep, longPause, longBeep, longPause, longBeep, longPause, longBeep, shortPause,
                longBeep, longPause, longBeep, longPause, longBeep, longPause, longBeep, longPause, longBeep, shortPause,
                shortBeep, longPause, longBeep, longPause, longBeep, longPause, longBeep, longPause, longBeep, shortPause,
                shortBeep, longPause, shortBeep, longPause, shortBeep, longPause, shortBeep, longPause, shortBeep }
                .SelectMany(c => c).ToList());
            file.AudioData.Add(new Channel<float>(allSamples, 0)); // 0 == ChannelPositions.Mono
            file.Flush();
        }
    }
}

```
> 6 votes

# Answer
# Python ~~3~~ 2, ~~191~~ ~~188~~ ~~174~~ 171 (no libraries)

Wav files are incredibly simple. Wanted to try without libraries. For some reason my files seem to crash Windows Media Player. Quicktime ~~works~~ bugs out halfway into the file. Conversion to a larger sample rate using Audition fixes this.

**Update**: Implemented some optimizations from the Perl answer. Now outputs with just the name `n` and in 1000Hz sampling. Edited info above accordingly.

```
w,s=200*" ",50*"~~  "
a,b,c=s+w,3*s+w,2*w
open(*"nw").write("RIFF\xD46\0\0WAVEfmt \20\0\0\0\1\0\1\0\xE8\3\0\0\xE8\3\0\0\1\0\10\0data\xB06\0\0"+a*2+b*3+c+b*5+c+a+b*4+c+a*5)

```

### Old version

```
w,s=1600*" ",200*"~~~~    "
a,b,c=s+w,3*s+w,2*w
open("n.wav","wb").write("RIFF\244\265\1\0WAVEfmt \20\0\0\0\1\0\1\0@\x1f\0\0@\x1f\0\0\1\0\10\0data\200\265\1\0"+a*2+b*3+c+b*5+c+a+b*4+c+a*5)

```
> 5 votes

# Answer
# C# ~ 485 bytes

Using the Wav.Net library.

```
using WavDotNet.Core;namespace System.Collections.Generic{using f=Single;class T{static void Main(){var i=new WavFileWrite<f>("x",8000);Func<long,Samples<f>>g=d=>new WavDotNet.Tools.Generators.Sawtooth(8000).Generate32Bit(new TimeSpan(d),600,1);var s=new List<f>();var k="..--- ----- .---- .....";foreach(var c in k){s.AddRange(c=='.'?g(2000000):g(6000000));s.AddRange(new f[1600]);if(c==' '){s.AddRange(new f[3200]);}}i.AudioData.Add(new Channel<f>(new Samples<f>(s),0));i.Flush();}}}

```

And here's the output.

Readable version,

```
using WavDotNet.Core;

namespace System.Collections.Generic
{
    using f = Single;

    class T
    {
        static void Main()
        {
            var i = new WavFileWrite<f>("x", 8000);
            Func<long, Samples<f>> g = d => new WavDotNet.Tools.Generators.Sawtooth(8000).Generate32Bit(new TimeSpan(d), 600, 1);
            var s = new List<f>();
            var k = "..--- ----- .---- .....";

            foreach (var c in k)
            {
                s.AddRange(c == '.' ? g(2000000) : g(6000000));
                s.AddRange(new f[1600]);

                if (c == ' ')
                {
                    s.AddRange(new f[3200]);
                }
            }

            i.AudioData.Add(new Channel<f>(new Samples<f>(s), 0));
            i.Flush();
        }
    }
}

```
> 4 votes

# Answer
# C# ~~382~~ 333bytes

Doesn't use any non-standard libraries, writes out an 8bits-per-sample 44100samples-per-second wav, with what I hope is a valid header (seems to play/load happily in WMP/.NET/Audacity).

The header is base64 encoded, and the morse is encoded as signal on/off which is stored in a single long (64bits) because the last 5 bits are the same as the first.

The result can be found here

Golfed code:

```
using System.IO;class P{static void Main(){using(var w=new FileStream("w.wav",FileMode.Create)){int i=0,d=9980;w.Write(System.Convert.FromBase64String("UklGRhCCCgBXQVZFZm10IBAAAAABAAEARKwAAESsAAABAAgAZGF0YeyBCgA="),0,44);for(var k=5899114207271221109L;i++<d*69;w.WriteByte((byte)(System.Math.Sin((k>>(i/d)%64&1)*i*0.1)*127+127)));}}}

```

With comments:

```
using System.IO;

class P
{
    static void Main()
    {
        using(var w=new FileStream("w.wav",FileMode.Create))
        {
            int i=0,d=9980; // d is samples per tone

            // write wav header
            w.Write(System.Convert.FromBase64String("UklGRhCCCgBXQVZFZm10IBAAAAABAAEARKwAAESsAAABAAgAZGF0YeyBCgA="),0,44);

            for(var k=5899114207271221109L; // 0101000111011101110111010001110111011101110111000111011101110101 as long
                i++<d*69; // 69 is number of bits
                w.WriteByte((byte)(
                    System.Math.Sin(
                        (k>>(i/d)%64&1) // read bit (0 or 1)
                        *i*0.1) // mul by ticker (sin(0) = 0)
                    *127+127)) // make sensible
            );
        }
    }
}

```
> 4 votes

# Answer
# SuperCollider, ~~625~~ 605 bytes

Audio programming language submission!

Output is written to a file `b` in AIFF format. Windows Media Player fails to open it, but it works fine in VLC media player. The generated file `a` is an OSC file.

```
c=0;d=0;f={c=c+d;d=0.2;[c,[\s_new,\w,1001,0,0,\freq,800]]};g={c=c+d;d=0.2;[c,[\n_free,1001]]};h={c=c+d;d=0.6;[c,[\s_new,\w,1001,0,0,\freq,800]]};i={c=c+d;d=0.6;[c,[\n_free,1001]]};x=[f.value,g.value,f.value,g.value,h.value,g.value,h.value,g.value,h.value,i.value,h.value,g.value,h.value,g.value,h.value,g.value,h.value,g.value,h.value,i.value,f.value,g.value,h.value,g.value,h.value,g.value,h.value,g.value,h.value,i.value,f.value,g.value,f.value,g.value,f.value,g.value,f.value,g.value,f.value,i.value];Score.recordNRT(x,"morse.osc","Morse2015.aiff");SynthDef("w",{arg freq=440;Out.ar(0,SinOsc.ar(freq,0,0.2))}).writeDefFile;

```

I created a few SuperCollider functions: `f` generates a short beep, `g` a short break, `h` a long beep and `i` a long break. SuperCollider needs the starting positions for each sine wave and not a length, so I had to create functions that generate a wave with the correct starting position and I have to call the functions each time I need a sine wave. (I could not store a wave with a specific length in a variable to reuse). The `\w` definition is created at the end of the code block.

On my Windows computer, it did not save the audio file in the same directory as my code, but in this directory:

```
C:\Users\MyName\AppData\Local\VirtualStore\Program Files (x86)\SuperCollider-3.6.6

```

**Result hosted on Dropbox**

Code with indentation:

```
c = 0;
d = 0;
f = { c=c+d;d=0.2;[ c, [ \s_new, \w, 1001, 0, 0,  \freq, 800 ] ] };
g = { c=c+d;d=0.2; [ c, [\n_free, 1001]] };
h = { c=c+d;d=0.6; [ c, [ \s_new, \w, 1001, 0, 0, \freq, 800]]};
i = { c=c+d;d=0.6;[ c, [\n_free, 1001]] };

x = [ f.value, g.value, f.value, g.value, h.value, g.value, h.value, g.value, h.value, i.value,
      h.value, g.value, h.value, g.value, h.value, g.value, h.value, g.value, h.value, i.value,
      f.value, g.value, h.value, g.value, h.value, g.value, h.value, g.value, h.value, i.value,
    f.value, g.value, f.value, g.value, f.value, g.value, f.value, g.value, f.value, i.value
];

Score.recordNRT(x, "morse.osc", "Morse2015.aiff");

SynthDef("w",{ arg freq = 440;
    Out.ar(0,
         SinOsc.ar(freq, 0, 0.2)
    )
}).writeDefFile;

```
> 2 votes

# Answer
# ChucK - ~~1195~~ ~~217~~ ~~201~~ ~~147~~ ~~145~~ 144

ChucK is an audio programming language. bitpwner helped me get this down from 201 bytes to 147 bytes.

```
SinOsc s;WvOut w=>blackhole;"y"=>w.wavFilename;int j;for(1016835=>int i;i>0;2/=>i){s=>w;j++;(i%2?200:600)::ms=>now;s=<w;(j%5?200:600)::ms=>now;}

```

**Here is a direct link to SoundCloud** if the embedded player doesn't work for you.
> 2 votes

# Answer
# Csound, 140 + 40 = 180

Audio programming language.

This is the Orchestra file:

```
instr 1
a1 oscil 2^15,990,1
out a1
endin

```

and this is the Score file:

```
f1 0 512 10 1
t0 300
i1 0 1
i1 2
i1 40
i1 60
i1 62
i1 64
i1 66
i1 68
i1 4 3
i1 8
i1 12
i1 18
i1 22
i1 26
i1 30
i1 34
i1 42
i1 46
i1 50
i1 54

```

The sizes are computed assuming no extra whitespace, single line terminator (UNIX) and no terminator after the last line.

You invoke them using the csound command:

```
csound morse.org morse.sco

```

which will produce an output file in the current directory, by default named "test.aif"

https://soundcloud.com/whatfireflies/morse-code-golf-in-csound/s-qzsaq

I could have shaved two or three bytes by choosing an uglier waveform, but I like the sound of the traditional Morse sine wave.

PS: I'm a total newbie at Csound, any golfing tips are appreciated, especially concerning the score file!
> 2 votes

# Answer
# brainfuck, 649 bytes

```
++[>-[+>++[++<]>]>[>..........-..........+<-]-[+>++[++<]>]>[....................-]<<<<<-]+++[>+++[>-[+>++[++<]>]>[>..........-..........+<-]<<<-]-[+>++[++<]>]>[....................-]<<<-]-[+>++[++<]>]>[....................-]+++++[>-[+>++[++<]>]>[....................-]+++[>-[+>++[++<]>]>[>..........-..........+<-]<<<-]<<<-]+++[>-[+>++[++<]>]>[....................-]<<<-]-[+>++[++<]>]>[>..........-..........+<-]++++[>-[+>++[++<]>]>[....................-]+++[>-[+>++[++<]>]>[>..........-..........+<-]<<<-]<<<-]++[>-[+>++[++<]>]>[....................-]<<<-]+++++[>-[+>++[++<]>]>[....................-]-[+>++[++<]>]>[>..........-..........+<-]<<<<<-]

```

This generates a sequence of 8 bit unsigned samples that may be played at 8000 samples per second with a tool such as `aplay` on Linux. Credit to table of BF constants.

Try it online!

Somewhat less golfed

```
DIT DIT DAH DAH DAH
++[>
 -[+>++[++<]>]>[>..........-..........+<-]
 -[+>++[++<]>]>[....................-]
<<<<<-]
+++[>
 +++[>
  -[+>++[++<]>]>[>..........-..........+<-]
 <<<-]
 -[+>++[++<]>]>[....................-]
<<<-]
-[+>++[++<]>]>[....................-]
DAH DAH DAH DAH DAH
+++++[>
 -[+>++[++<]>]>[....................-]
 +++[>
  -[+>++[++<]>]>[>..........-..........+<-]
 <<<-]
<<<-]
+++[>
 -[+>++[++<]>]>[....................-]
<<<-]
DIT DAH DAH DAH DAH
-[+>++[++<]>]>[>..........-..........+<-]
++++[>
 -[+>++[++<]>]>[....................-]
 +++[>
  -[+>++[++<]>]>[>..........-..........+<-]
 <<<-]
<<<-]
++[>
 -[+>++[++<]>]>[....................-]
<<<-]
DIT DIT DIT DIT DIT
+++++[>
 -[+>++[++<]>]>[....................-]
 -[+>++[++<]>]>[>..........-..........+<-]
<<<<<-]

```
> 1 votes

---
Tags: kolmogorov-complexity, audio, code-golf, morse
---


# Question
Title: Convert an ASCII art table to a UTF-8 table
When I write documentation, comments, etc. I love making ASCII tables. They usually end up looking pretty good, but I always feel that they could look even better - especially since UTF-8/Unicode includes the box drawing characters. However, these characters are very burdensome to use, requiring several key presses to insert. Your task? Write a program or a function that can automatically convert ASCII tables to the UTF-8/Unicode equivalent.

This challenge was sandboxed.

## Challenge

Write a program, that given an ASCII table as an input string, outputs the table redrawn with the Unicode/UTF-8 box drawing characters. Specifically, the characters that are a part of the table should be translated as follows:

```
(Unicode, 3 bytes each in UTF-8)
- to ─ (\u2500)
| to │ (\u2502)
= to ═ (\u2550)

and + to one of:
   ┌ (\u250C), ┐ (\u2510), └ (\u2514), ┘ (\u2518),
   ├ (\u251C), ┤ (\u2524), ┬ (\u252C), ┴ (\u2534),
   ┼ (\u253C)
or, if '=' on either side:
   ╒ (\u2552), ╕ (\u2555), ╘ (\u2558), ╛ (\u255D),
   ╞ (\u255E), ╡ (\u2561), ╤ (\u2564), ╧ (\u2567),
   ╪ (\u256A)

```

## Details

**I/O:**

* Default I/O is allowed
* You may take input in any reasonable format, including the table as a string, or a path to a file containing the table.
* You may output to a file and take the file name as an additional argument.
    + However, **you may not modify the input file**. (It should be retained for ease of future editing)

**Input:**

* You may assume that every row of input has been padded to be the same length with .
* You may not assume that the first character after a newline is a part of the table borders (as it may be whitespace).
* Input is considered a valid table if all characters (that are a part of the table) `-=|` are connected to exactly two characters and `+` are connected to at least one character both horizontally and vertically.
* Your program may not produce any errors with valid inputs.
* If the input is not valid the behavior is undefined and you may produce any output.
* The input may contain any UTF-8 characters, including the box drawing characters.

**Output:**

* Any of the characters `-=|+` that are not a part of the table **must** be left as-is.
* Similarly, any other characters must be left as-is.
* A single leading and/or trailing newline is allowed.

**Other:**

* Standard loopholes are forbidden, as per usual.
* If your preferred language has a built-in that solves this problem, you may not use it.
    + This means programs, functions, subroutines or instructions that would be valid submissions for this challenge with no additions.
* Each of the characters needed in this challenge are three bytes long when they're encoded in UTF-8.

**Connected characters**:

A character is connected to another, if:

* It is `|` and is directly above or below `+` or `|`;
* It is `-` and is directly before or after `+` or `-`;
* It is `=` and is directly before or after `+` or `=`;
* It is `+` and is directly above or below `|` or `+`, or is directly before or after `-`, `=` or `+`.

A character is considered a part of the table, if it is connected to any character that is a part of the table. By definition, the first `+` in the input is a part of the table.

## Examples

Examples available here as a copy-pastable version.

```
 Input:                    Output:
+------------------+      ┌──────────────────┐
|   Hello+World!   |      │   Hello+World!   │
+==================+      ╞══════════════════╡
| This is+my first |  ->  │ This is+my first │
|+-+ code|golf  +-+|      │+-+ code|golf  +-+│
|+-+chall|enge! +-+|      │+-+chall|enge! +-+│
+------------------+      └──────────────────┘

     +===+===+===+             ╒═══╤═══╤═══╕
     | 1 | 2 | 3 |             │ 1 │ 2 │ 3 │
 +---+===+===+===+         ┌───╪═══╪═══╪═══╡
 | 1 | 1 | 2 | 3 |         │ 1 │ 1 │ 2 │ 3 │
 +---+---+---+---+    ->   ├───┼───┼───┼───┤
 | 2 | 2 | 4 | 6 |         │ 2 │ 2 │ 4 │ 6 │
 +---+---+---+---+         ├───┼───┼───┼───┤
 |-3 |-3 |-6 |-9 |         │-3 │-3 │-6 │-9 │
 +===+---+---+---+         ╘═══╧───┴───┴───┘

      +-----+         ->      <Undefined>

      +-----+         ->      ┌─────┐
      +-----+                 └─────┘

+-----------------+
|  Hello, World!  |
| This is invalid |   ->      <Undefined>
|      input      |
 -----------------+

       ++++                      ┌┬┬┐
       ++++           ->         ├┼┼┤
       ++++                      └┴┴┘

       +--+
       ++++           ->      <Undefined>
       +--+

```

## Finally...

This is , so the least amount of bytes wins. Happy golfing!

# Answer
# Python 3, ~~392~~ 281 bytes

Golfed it quite a bit more and converted to a recursive solution instead of an iterative one:

```
def h(a):
 def g(i):
  k=-3;d=a[i]=='=';z[i]=''
  for p,j,r in zip((1,2,4,8),(i+1,i+w,i-1,i-w),('+-=','+|')*2):
   if 0<=j<len(a)and{a[i],a[j]}<={*r}:k+=p;d|=a[j]=='=';z[j]and g(j)
  z[i]="┌╒!!─═┐╕┬╤@@└╘││├╞┘╛┴╧┤╡┼╪"[2*k+d]
 w=a.find('\n')+1;z=[*a];g(a.find('+'))
 return''.join(z)

```

Takes a string of equal length rows separated by newlines, and returns a string in the same format. May throw an exception on invalid input.

Previous solution:

```
def h(a):
 i=a.find('+');q=[i];w=a.find('\n')+1;z=[*a]
 while q:
  i=q.pop();c=a[i];k=-5
  for p,j in enumerate((i+1,i-1,i+w,i-w)):
   r='++-|='[p>1::2]
   if 0<=j<len(a)and a[i]in r and a[j]in r:
    k+=1<<p;q+=[j][:z[j]<'─']
  z[i]='│'if c>'='else'─═'[a[i]>'-']if c>'+'else"┌╒┐╕┬╤@@└╘┘╛┴╧##├╞┤╡┼╪$$"['='in a[abs(i-1):i+2]::2][k]
 return''.join(z)

```

Ungolfed version:

```
def h(a):
    i = a.find('+')         # find index of first '+'. It is first node
    q = [i]                 # in the queue of indexes to convert to unicode
    w = a.find('\n')+1      # width of the table
    z = [*a]                # strings are immutable, so copy it to a list

    while q:                # while the queue isn't empty
        i=q.pop()           # get the next index to process
        c=a[i]              # and the associated character

        k=-5                # 'k' is the index into the unicode string, U.  The way they
                            # are encoded, the first unicode value is at index 5.

                 # directions  E   W   S   N
        for p,j in enumerate((i+1,i-1,i+w,i-w)):  # j is the index of an adjacent cell

            # r='++-|='[p>1::2] is equivalent to:
            if p > 1:
                r = '+|'    # compatible symbols for vertical connections
            else:
                r = '+-='   # compatible symbols for horizontal connections

            # if adjacent cell index is valid and the characters are compatible
            if 0 <= j < len(a) and a[i] in r and a[j] in r:
                k += 1<<p                 # update the unicode symbol index

                # q += [j][:z[j]<'─'] is equivalent to:
                if z[j] < '-':            # if the adjacent cell hasn't been converted already
                    q.append(j)           #  append it's index to the queue

            if c > '=':
                z[i] = '│'                # replace a '|' with a '│'

            elif c > '+':
                z[i] = '─═'[a[i]>'-']     # replace a '-' or '=' with '─' or '═' respectively

            else:                                      # it's a '+'
                U = "┌╒┐╕┬╤@@└╘┘╛┴╧##├╞┤╡┼╪$$"         # even indexes are single horizontal line,
                                                       # double horizontal lines are at odd indexes

                z[i] = U['='in a[abs(i-1):i+2]::2][k]  # '='in a[abs(i-1):i+2] is true if there is an '=' to the left or right
                                                       # so this selects the odd chars from U
                                                       #  then [k] selects the correct char

 return''.join(z)

```
> 2 votes

# Answer
# Python 3, ~~914~~ ~~898~~ ~~827~~ ~~823~~ ~~594~~ ~~587~~ ~~569~~ ~~540~~ 469 bytes

Edit: significantly changed strategy, now making a bitfield of neighbors (similar to dead-possum's answer). I've left the earlier version below.

```
H='─│═-|=└╘++++┌╒├╞++┘╛++┴╧┐╕┤╡┬╤┼╪'
def n(l):
 def j(r,c,t=0):O=(0,r-1,c),(1,r,c+1),(2,r+1,c),(3,r,c-1);v=f(r,c);b=t|any(f(Y,X)=='='for i,Y,X in O);l[r][c]={'+':H[b+2*sum((f(Y,X)in H)<<x for x,Y,X in O)],**dict(zip(H[3:6],H))}.get(v,v);[f(Y,X)!=';'and v in'+++-|='[i%2::2]and j(Y,X,v=='=')for i,Y,X in O]
 for i,I in enumerate(l):
  if'+'in I:f=lambda r,c:l[r][c]if len(l)>r>=0and 0<=c<len(l[r])else';';j(i,I.index('+'));break

```

Try it online!

Input is in the form of a list of lists of characters, which is modified in place. Recurses from the first + that it finds.

```
x=range
C='┌┐└┘','╒╕╘╛'
D='┬┤┴├','╤╡╧╞'
A='┼╪'
H,V,T='─│═'
J={'-':H,'|':V,'=':T}
K=C[1]+D[1]+A[1]+'='+T
E=('+|','+-=')*2
F=['+|'+V,'+-='+H+T]*2
O=(0,-1,0),(1,0,1),(2,1,0),(3,0,-1)
for i in x(4):
 for j in{0,1,2,3}-{i}:F[i+2&3]+=D[0][j]+D[1][j]
 h=C[0][i]+C[1][i];F[i&2]+=h;F[3-2*(i&1)]+=h
def n(l):
 for i,I in enumerate(l):
  if'+'in I:r=i;c=I.index('+');break
 else:return l
 def f(r,c):
  try:assert c>=0 and r>=0;return l[r][c]
  except:return'\0'
 def j(r,c):
  v=f(r,c)
  l[r][c]=J.get(v,v)
  if v=='+':
   X=[f(r+Y,c+X)for i,Y,X in O];B=any(x in K for x in X);X=[X[x]in F[x]for x in x(4)];L=sum(X)
   if L in(2,3,4):l[r][c]=D[B][X.index(False)]if L==3 else C[B][X[0]*2+X[3]]if L==2 else A[B]
  for i,Y,X in O:
   if v in E[i]and f(r+Y,c+X)in E[i]:j(r+Y,c+X)
 j(r,c);return l

```

Try it online!

Here's the closest thing I have to an ungolfed version:

```
def tr(s):
    t='┌┐└┘','╒╕╘╛'
    t2='┬┤┴├','╤╡╧╞'
    A = '┼','╪'
    H,V,T = '─│═'
    Th = ''.join(x[1]for x in (t,t2,A))+'='+T
    ps = ['+|'+V, '+-='+H+T, '+|'+V, '+-='+H+T]
    ps2 = ('+|', '+-=')*2
    for i in range(4):
        for j in {0,1,2,3}-{i}:
            ps[(i+2)%4] += t2[0][j]+t2[1][j]
        h=t[0][i] + t[1][i]
        ps[i & 2] += h
        ps[3 - 2 * (i & 1)] += h

    l = [list(x) for x in s.split('\n')]
    r = 0
    for i,I in enumerate(l):
        if'+'in I:
            r=i;c=I.index('+')
            break
    def g(r,c): return l[r][c]
    def G(r,c):
        if r >= 0 and r < len(l) and c >= 0 and c < len(l[r]):
            return g(r,c)
        return '\0'
    def process(r,c):
        v = g(r,c)
        if v == '-': l[r][c] = H
        elif v == '|': l[r][c] = V
        elif v == '=': l[r][c] = T
        elif v == '+':
            all=[G(r-1,c),G(r,c+1),G(r+1,c),G(r,c-1)]
            bold=any(x in Th for x in all)
            for i in range(4):all[i] = all[i] in ps[i]
            N,E,S,W=all
            tt=sum(all)
            if tt == 3:
                l[r][c]=t2[bold][all.index(False)]
            elif tt == 2:
                l[r][c]=t[bold][N*2+W]
            elif tt == 4:
                l[r][c]=A[bold]
            else: return
        for i,(dy,dx) in enumerate(((-1,0),(0,1),(1,0),(0,-1))):
            if v in ps2[i] and G(r+dy,c+dx) in ps2[i]:
                process(r+dy,c+dx)
    process(r,c)
    return l

```
> 3 votes

# Answer
# JavaScript, ~~311~~ 307 bytes

```
X=>(O=[...X],P=(I,j=0,_=0)=>!P[I]&&(P[I]=1,['-─1','|│','=═1'].map(([a,b,n=X.indexOf('\n')+1])=>[-n,+n].map(n=>{for(i=I;X[i+=n]==a;)O[i]=b
if(X[i]=='+')j|=[1,2,4,8,I-i>1&&17,i-I>1&&18][_],P(i)
_++})),O[I]='┘└┴ ┐┌┬ ┤├┼     ╛╘╧ ╕╒╤ ╡╞╪'[j-5]),P(X.indexOf`+`),O.join``)

```

```
f=
X=>(W=X.indexOf('\n')+1,O=[...X],P=(I,j=0,_=0)=>!P[I]&&(P[I]=1,['-─1','|│','=═1'].map(([a,b,n=W])=>[-n,+n].map(n=>{for(i=I;X[i+=n]==a;O[i]=b);if(X[i]=='+')j|=[1,2,4,8,I-i>1&&17,i-I>1&&18][_],P(i);_++})),O[I]='┘└┴ ┐┌┬ ┤├┼     ╛╘╧ ╕╒╤ ╡╞╪'[j-5]),P(X.indexOf`+`),O.join``)

console.log(
f(
`+------------------+
|   Hello+World!   |
+==================+
| This is+my first |
|+-+ code|golf  +-+|
|+-+chall|enge! +-+|
+------------------+`
))

console.log(
f(
`     +===+===+===+
     | 1 | 2 | 3 |
 +---+===+===+===+
 | 1 | 1 | 2 | 3 |
 +---+---+---+---+
 | 2 | 2 | 4 | 6 |
 +---+---+---+---+
 |-3 |-3 |-6 |-9 |
 +===+---+---+---+`
))

console.log(
f(
`+-----+
+-----+`))

console.log(
f(
`++++
++++
++++`))
```

## Explanation

Starting at the first found `+` junction, the program attempts to find paths to other junctions in every direction, performing replacements as it goes. It stores the found directions and the "double-bordered" state in a bitmap, which then determines the appropriate junction character.

```
// Take an input string X
f = X => {
    // Copy the input string into an array so characters can be overwritten and eventually output
    O = [...X]

    // Define a function that processes a junction ("+" symbol) at index I in the input string X:
    P = I => {
        // Make a bitmap to keep track of the direction coming out of the junction and double borders
        // Bits from right to left: west, east, north, south, double border
        // E.g. a double-bordered south/east junction corresponds to the binary number 11010 ("╒")
        let j = 0

        // A counter
        let _ = 0

        // Ensure this junction hasn't already been processed
        if(!P[I]){
            P[I] = 1,

            // We'll walk away from the junction in each of the four directions, then west and east again to check for double borders
            // i.e. walk along `a`, replace with `b`, move index `i` by `n`
            // 1st pass: walk along "-", replace with "─", move index by 1
            // 2nd pass: walk along "|", replace with "│", move index by the width of the input (plus 1 for the newline) to traverse vertically
            // 3rd pass: walk along "=", replace with "═", move index by 1
            ['-─1','|│','=═1'].map(([a, b, n = X.indexOf('\n') + 1])=>
                // We'll walk in the negative and positive directions for each pass
                [-n,+n].map(n=>{
                    // Start the walk
                    i=I
                    // Keep walking (incrementing by n) as long as we're on a "path" character, "a"
                    while(i += n, X[i] == a)
                        // Replace the corresponding character in the output with "b"
                        O[i] = b

                    // Upon reaching another junction at index i:
                    if(X[i] == '+'){
                        // OR the bitmap according to the direction we walked
                        j |= [
                            // Pass 1: Horizontal
                            1, // west
                            2, // east

                            // Pass 2: Vertical
                            4, // north
                            8, // south

                            // Pass 3: Double Horizontal (only if we've walked more than 1 step)
                            I-i > 1 && 17, // west, double border
                            i-I > 1 && 18 // east, double border
                        ][_]

                        // Process the junction we walked to
                        P(i)
                    }
                    _++
                })
            )

            // Finally, replace the "+" with a proper junction character based on the bitmap value
            O[I] = '     ┘└┴ ┐┌┬ ┤├┼     ╛╘╧ ╕╒╤ ╡╞╪'[j]
        }
    }

    // Process the first junction to kick off the recursion
    P(X.indexOf`+`)

    // Return our modified character array as a joined string
    return O.join``
}

```
> 1 votes

# Answer
# Python 3, 599 bytes

I'm not really good at golfing in Python 3, but (to my shame) I couldn't get normal output of UTF-8 chars in Python 2. So here we are.

I guess the only interesting trick here is deciding of `+` tranformation.
I've encoded all possible variants with 4-bit adresses. Each bit of adress resembles connection to neightbour cell. So 0 - no connection and 1 - connection.
`1111` is
`0011` is
etc
Some configurations of connections are invalid and replaced with dummy values: `'012┐45┌┬8┘0┤└┴├┼'`

If any neightbour cell contains `=`, second list will be used with doubled lines.

```
['012┐45┌┬8┘0┤└┴├┼','012╕45╒╤8╛0╡╘╧╞╪']['='in r]

```

Adress is combined here.

```
r=''.join([str(int(V(y,x)))+W(y,x)for y,x in[(Y-1,X),(Y,X+1),(Y+1,X),(Y,X-1)]])

```

`r` contains string lenght 8, where every two chars are 1/0 and actuals neightbour char.
For example: `1+0y1-1|`.
This is used to choose list of substitutions as shown before. And then contracted to adress: `int(r[0::2],2)`

This lambda used to verify that cell coordinates are valid and cell's char is one of '+-|='

```
V=lambda y,x:~0<x<len(I[0])and~0<y<len(I)and I[y][x]in'+-|='

```

This lambda used to receive char from cell. Returns `' '` if coordinates are invalid. (definately can be golfed away)

```
W=lambda y,x:V(y,x)and I[y][x]or' '

```

Conditions for recursion. Might be golfable too.

```
if Z in'+-=':F(Y,X+1);F(Y,X-1)
if Z in'+|':F(Y-1,X);F(Y+1,X)

```

---

```
I=eval(input())
J=[i[:]for i in I]
V=lambda y,x:~0<x<len(I[0])and~0<y<len(I)and I[y][x]in'+-|='
W=lambda y,x:V(y,x)and I[y][x]or' '
def F(Y,X):
 if V(Y,X)and I[Y][X]==J[Y][X]:
  Z=I[Y][X]
  if','>Z:
   r=''.join([str(int(V(y,x)))+W(y,x)for y,x in[(Y-1,X),(Y,X+1),(Y+1,X),(Y,X-1)]])
   J[Y][X]=['012┐45┌┬8┘0┤└┴├┼','012╕45╒╤8╛0╡╘╧╞╪']['='in r][int(r[0::2],2)]
  else:J[Y][X]=dict(zip('|-=','│─═'))[Z]
  if Z in'+-=':F(Y,X+1);F(Y,X-1)
  if Z in'+|':F(Y-1,X);F(Y+1,X)
e=enumerate
F(*[(y,x)for y,r in e(I)for x,c in e(r)if'+'==c][0])
for r in J:print(''.join(r))

```

Try it online!
> 1 votes

---
Tags: code-golf, ascii-art
---


title: Read a date in xkcd notation

text:
# Question
Title: Read a date in xkcd notation
In his xkcd about the ISO 8601 standard date format Randall snuck in a rather curious alternative notation:

The large numbers are all the digits that appear in the current date in their usual order, and the small numbers are 1-based indices of the occurrences of that digit. So the above example represents `2013-02-27`.

Let's define an ASCII representation for such a date. The first line contains the indices 1 to 4. The second line contains the "large" digits. The third line contains the indices 5 to 8. If there are multiple indices in a single slot, they are listed next to each other from smallest to largest. If there are at most `m` indices in a single slot (i.e. on the same digit, and in the same row), then each column should have be `m+1` characters wide and left-aligned:

```
2  3  1  4
0  1  2  3  7
5     67    8

```

*See also the companion challenge for the opposite conversion.*

## The Challenge

Given a date in xkcd-notation, output the corresponding ISO 8601 date (`YYYY-MM-DD`).

You may write a program or function, taking input via STDIN (or closest alternative), command-line argument or function argument and outputting the result via STDOUT (or closest alternative), function return value or function (out) parameter.

You may assume that the input is any valid date between years `0000` and `9999`, inclusive.

There won't be any leading spaces in the input, but you may assume that the lines are padded with spaces to a rectangle, which contains at most one trailing column of spaces.

Standard rules apply.

## Test Cases

```
2  3  1  4
0  1  2  3  7
5     67    8
2013-02-27

2  3  1     4
0  1  2  4  5
   5  67 8
2015-12-24

     1234
1    2
5678
2222-11-11

   1     3  24
0  1  2  7  8
57    6     8
1878-02-08

2   4   1   3
0   1   2   6
5       678
2061-02-22

      1 4 2 3
0 1 2 3 4 5 6 8
6 5 7         8
3564-10-28

1234
1
5678
1111-11-11

1 2 3 4
0 1 2 3
8 5 6 7
0123-12-30

```

# Answer
# CJam, 35 bytes

```
ll{1$e>}*](l+eeWf%$-8>Wf=\f=2/(o'-*

```

Try it here. It expects the input lines to be padded with spaces.

## Explanation

`ll` reads two lines of input, and `{1$e>}*` performs a "scan" on the second one: it it takes all prefixes of its input and computes the maximum of each prefix. For the input line `"0 1 2 7 8"`, this pushes `"0001112227778"`. Our stack now looks like this:

```
"first line" '0 '0 '0 '1 '1 '1 ...

```

We need to re-capture the values into a list ourselves using `]`; this captures our first line as well, so we pop it back out using `(`, to get

```
"0001112227778" "first line"

```

as expected.

`eelee+` enumerates this line, then does the same for a third input line, and concatenates the results, leaving something like this on the top of the stack:

```
[[0 '5] [1 ' ] [2 ' ] [3 ' ] [4 ' ] [5 ' ] [6 ' ] [7 ' ] [8 '6] [9 '7] [10 '8] [11 ' ] [12 ' ]
 [0 '2] [1 ' ] [2 ' ] [3 ' ] [4 '4] [5 ' ] [6 ' ] [7 ' ] [8 '1] [9 ' ] [10 ' ] [11 ' ] [12 '3]]

```

Now our stack is `["0001112227778" X]` where `X` is the enumerated list above.

We flip each pair in `X` (`Wf%`), sort the pairs lexicographically (`$`), and leave the last 8 pairs `-8>`. This gets us something like:

```
[['1 8] ['2 0] ['3 12] ['4 4] ['5 0] ['6 8] ['7 9] ['8 10]]

```

This works, because the sort places all the pairs with key `'` (space) before all the digits in ascending order.

These are the "*x*-positions" of the characters `12345678` on the first and third lines: we only need to retrieve the characters from our (modified) second line that are vertically aligned with them.

To do this, we take each position (`Wf=`), index into the string we made earlier (`\f=`). We have `"20610222"` on the stack now: to add the dashes, first we split into segments of length two (`2/`), print the first segment without a newline (`(o`) and join the remaining segments with dashes (`'-*`).

**EDIT**: cool scan trick, Martin! Saved four bytes.

**EDIT 2**: saved two more bytes by replacing `eelee+` with `l+ee`; this works, because the lines all have the same lengths, and list indexing in CJam is automatically modulo the list length, so the indices `n+0`, `n+1`, `n+2`... nicely map to `0`, `1`, `2`...

**EDIT 3**: Martin saved another byte in the final step of the process. Nice!
> 8 votes

# Answer
# Pyth, ~~48~~ 43

```
j\-cj\-ctuuXN.xsTZK?qJhtHdKJ+hHeHGC.z*9d4 7

```

Test Suite

Requires padding with spaces into a rectangle.

I don't think this is the best approach, but basically it writes the middle value to the index in a string pointed at by the top or bottom value. Well I guess I had enough time to golf most of the obvious stuff I saw. :P
> 6 votes

# Answer
# JavaScript (ES7), 115

Anonymous function. Using template strings, there is a newline that is signifiocant and included in byte count.

Requirement: the middle input line cannot to be shorter than the first or the last. This requirement is satisfied when the input is padded with spaces to form a rectangle.

```
x=>([a,z,b]=o=x.split`
`,d=i=0,[for(c of z)o[a[i]-1]=o[b[i++]-1]=d=+c||d],o.splice(4,2,'-',o[4],o[5],'-'),o.join``)

```

**ES6** version **117** using .map instead of array comprehension

```
x=>([a,z,b]=o=x.split`
`,d=0,[...z].map((c,i)=>o[a[i]-1]=o[b[i]-1]=d=+c||d],o.splice(4,2,'-',o[4],o[5],'-'),o.join``)

```

**Less golfed**

```
x=>(
  o=[],
  [a,z,b] = x.split`\n`,
  d=i=0,
  [ for(c of z) (
      d = +c||d, // each new digit found in z goes in d (but not the spaces and not the '0' (d starts at 0 anyway)
      o[a[i]-1] = o[b[i]-1] = d, // if the index char is space, that gives index -1 that is ignored when joining later
      ++i
  )],
  o.splice(4,2,'-',o[4],o[5],'-'), // add the dashes in the right places
  o.join``
)

```

**Test snippet**

```
f=x=>(
  [a,z,b]=o=x.split`\n`,
  d=i=0,[for(c of z)o[a[i]-1]=o[b[i++]-1]=d=+c||d],
  o.splice(4,2,'-',o[4],o[5],'-'),o.join``
)

console.log=x=>O.textContent+=x+'\n';

[['2  3  1  4\n0  1  2  3  7\n5     67    8','2013-02-27']
,['2  3  1     4\n0  1  2  4  5\n   5  67 8','2015-12-24']
,['      1234\n1     2   \n5678','2222-11-11']
,['   1     3  24\n0  1  2  7  8 \n57    6     8','1878-02-08']
,['2   4   1   3\n0   1   2   6  \n5       678','2061-02-22']
,['      1 4 2 3\n0 1 2 3 4 5 6 8\n6 5 7         8','3564-10-28']
,['1234\n1   \n5678','1111-11-11']
,['1 2 3 4\n0 1 2 3\n8 5 6 7','0123-12-30']]
.forEach(t=>(k=t[1],r=f(t[0]),console.log(t[0]+'\n'+r+'\n'+(r==k?'OK\n':'Fail\n'))))
```

```
<pre id=O></pre>
```
> 4 votes

# Answer
## Haskell, ~~125~~ ~~106~~ 103 bytes

```
a#' '=a
a#b=b
f i|[a,b,c]<-('-':)<$>lines i=[o|m<-"1234-56-78",(n,o,p)<-zip3 a(scanl1(#)b)c,m==n||m==p]

```

Requires padding with spaces to a full rectangle.

Usage example: `f " 1 3 24\n0 1 2 7 8 \n57 6 8 "` -\> `"1878-02-08"`.

How it works:

```
[a,b,c]<-('-':)<$>lines i          -- split input into lines, prepend a '-' to
                                   -- each, call them a, b and c
               (scanl1(#)b)        -- fill spaces of the middle line with the
                                   -- previous char, e.g.
                                   -- "-0  1  2  7  8 " -> "-00011122277788"
        zip3 a (scanl...) c        -- combine the lines element wise into triples.
                                   -- This is our lookup table for "1234-56-78"
o|m<-"1234...",  (n,o,p)<-zip...,  m==n||m==p
                                   -- whenever m equals n or p (i.e. was originally
                                   -- in the first or last line), take the
                                   -- corresponding char o (middle line)

```
> 3 votes

# Answer
# JavaScript ES6, 231

```
a=>{r=[];var b=[d,f,e]=a.split`
`.map(n=>n.split``);Array(Math.max(...b.map(n=>n.length))).fill().map((m,i)=>{(m=f[i])&&m!=" "&&(c=m);[d,e].map(m=>(g=m[i])&&g!=" "&&(r[g-1]=c))}),r.splice(4,0,"-"),r.splice(7,0,"-");return r.join``}

```

Test cases.
> 2 votes

# Answer
# Perl, 154 bytes

```
sub{$_=$_[1];@n=/\d/g;/ +/;map{map{$p[$i++].=$_}unpack"(a$+[0])*";$i=0}@_[0,2];map{map{$r[$_-1]=$n[$i]if/\d/}s plit$"='';$i++}@p;"@r"=~s/....\K(..)/-$1-/r}

```

### Ungolfed & explained

```
sub{
    $_=$_[1]; # $_[1] is 2nd argument (i.e., 2nd line)
    @n=/\d/g; # @n now contains all digits in 2nd line
    / +/;     # $+[0] now the chunk length in 2nd line
              # Equivalent to /( +)/;$l = 1 + length $1;
    map{      # Perl golfer's for-loop
        map{
            $p[$i++] .= $_    # @p contains positions of each digit
        } unpack "(a$+[0])*"; # Split line into same chunk width
        $i=0 # At end of loop so we don't need $i=0 before next one
    } @_[0,2];# Outer map works on 1st and 3rd lines
    map{
        map{
            # Shove $n[$i] into ($_-1)th slot in @r if $_ is a number
            $r[$_-1] = $n[$i] if /\d/
        } split $"=''; # Equivalent to split '', but sets $"='' for free
        $i++
    }@p;
    # Concatenate @r, convert 20130227 to 2013-02-27, and return
    "@r"=~s/....\K(..)/-$1-/r
};

```
> 1 votes

# Answer
# JavaScript (ES6), 131 bytes

```
s=>[...(r=[,,,,"-",,,"-"],l=s.split`
`)[1]].map((c,i)=>(c>"-"?n=c:0,y=+l[0][i],d=+l[2][i],y?r[y-1]=n:0,d?r[d+(d>6)]=n:0))&&r.join``

```

## Explanation

Requires input to be padded with spaces to form a rectangle.

```
s=>
  [...(
    r=[,,,,"-",,,"-"], // r = array of result characters, prefill with "-" symbols
    l=s.split`
`                      // l = array of lines
  )[1]].map((c,i)=>(   // for each character on the middle line
    c>"-"?n=c:0,       // n = the most recent digit encountered
    y=+l[0][i],        // y = index on the year line at the current position
    d=+l[2][i],        // d = index on the date line at the current position
    y?r[y-1]=n:0,      // if y is a number, put n at the index y of the result
    d?r[d+(d>6)]=n:0   // if d is a number, put n at the index d (accounting for "-"s)
  ))
  &&r.join``           // return the result as a string

```

## Test

```
var solution = s=>[...(r=[,,,,"-",,,"-"],l=s.split`
`)[1]].map((c,i)=>(c>"-"?n=c:0,y=+l[0][i],d=+l[2][i],y?r[y-1]=n:0,d?r[d+(d>6)]=n:0))&&r.join``
```

```
<textarea id="input" rows="3" cols="30">   1     3  24
0  1  2  7  8
57    6     8 </textarea><br />
<button onclick="result.textContent=solution(input.value)">Go</button>
<pre id="result"></pre>
```
> 0 votes

# Answer
# Powershell, 119 bytes

```
$r=,'-'*99
($a=$args-split'
')[1]|% t*y|%{if($_-32){$d=$_}
$a[0,2]|%{$r[$_[+$p]-48]=$d}
$p++}
-join$r[1..4+0+5+6+0+7+8]

```

Ungolfed test script:

```
$f = {

$r=,'-'*99                       # init a result as an array of '-' repeated 99 times
($a=$args-split"`n")[1]|% t*y|%{ # split argument string, store a top, middle and bottom to $a, then for each char of the middle line...
    if($_-32){$d=$_}             # store a digit to $d if the current character of the middle is not a space
    $a[0,2]|%{                   # for the top and the bottom lines...
        $r[$_[+$p]-48]=$d        # store a digit to the result array
    }                            # Note: if char in the current position is a space, then expression $_[+$p]-48 less then 0.
                                 # In this case, the expression $r[32-48]=$d changes unused element in a end of the array.
                                 # That is why the array was created by a large.
    $p++                         # next position
}
-join$r[1..4+0+5+6+0+7+8]        # return joined char with specified numbers
                                 # Note: element with index 0 has value '-'
}

@(
,(@"
2  3  1  4
0  1  2  3  7
5     67    8
"@,"2013-02-27")

,(@"
2  3  1     4
0  1  2  4  5
    5  67 8
"@,"2015-12-24")

,(@"
     1234
1    2
5678
"@,"2222-11-11")

,(@"
1     3  24
0  1  2  7  8
57    6     8
"@,"1878-02-08")

,(@"
2   4   1   3
0   1   2   6
5       678
"@,"2061-02-22")

,(@"
      1 4 2 3
0 1 2 3 4 5 6 8
6 5 7         8
"@,"3564-10-28")

,(@"
1234
1
5678
"@,"1111-11-11")

,(@"
1 2 3 4
0 1 2 3
8 5 6 7
"@,"0123-12-30")

) | % {
    $a,$expected = $_
    $result = &$f $a
    "$(""$result"-eq"$expected"): $result"
}

```

Output:

```
True: 2013-02-27
True: 2015-12-24
True: 2222-11-11
True: 1878-02-08
True: 2061-02-22
True: 3564-10-28
True: 1111-11-11
True: 0123-12-30

```
> 0 votes

# Answer
# Jelly, 38 bytes

```
Ỵṙ-Zn⁶Ṫ€œṗƊḊZḟ⁶V€$€;2/p/Ʋ€ẎṢṪ€s2Ḣ;jɗ”-

```

Try it online!

The helper is only there to make input easier; this is actually a full program. **Be sure to care for**:

* The first and last lines (`'''`), as well as the lines next to them (empty, there for clarity).
    + The actual input format doesn't have the second and penultimate empty lines, and the string starts and ends directly next to the quotes, without a newline in-between, like this:
    ```
    '''   1     3  24
    0  1  2  7  8
    57    6     8 '''
    ```
    You can leave the footer in while using this format. This is really a Python multi-line string, and the quotes are necessary for some inputs.
* Pad the input with trailing spaces! Any correct output without correctly padded input is entirely coincidental, and isn't endorsed by me.
> 0 votes

---
Tags: code-golf, ascii-art, date
---


title: Convert a date to xkcd notation

text:
# Question
Title: Convert a date to xkcd notation
In his xkcd about the ISO 8601 standard date format Randall snuck in a rather curious alternative notation:

The large numbers are all the digits that appear in the current date in their usual order, and the small numbers are 1-based indices of the occurrences of that digit. So the above example represents `2013-02-27`.

Let's define an ASCII representation for such a date. The first line contains the indices 1 to 4. The second line contains the "large" digits. The third line contains the indices 5 to 8. If there are multiple indices in a single slot, they are listed next to each other from smallest to largest. If there are at most `m` indices in a single slot (i.e. on the same digit, and in the same row), then each column should have be `m+1` characters wide and left-aligned:

```
2  3  1  4
0  1  2  3  7
5     67    8

```

*See also the companion challenge for the opposite conversion.*

## The Challenge

Given an ISO 8601 date (`YYYY-MM-DD`), output the corresponding xkcd date notation.

You may write a program or function, taking input via STDIN (or closest alternative), command-line argument or function argument and outputting the result via STDOUT (or closest alternative), function return value or function (out) parameter.

Any year from `0000` to `9999` is valid input.

Trailing spaces are allowed, leading spaces are not. You may optionally output a single trailing newline.

Standard rules apply.

## Test Cases

```
2013-02-27
2  3  1  4
0  1  2  3  7
5     67    8

2015-12-24
2  3  1     4
0  1  2  4  5
   5  67 8

2222-11-11
     1234
1    2
5678

1878-02-08
   1     3  24
0  1  2  7  8
57    6     8

2061-02-22
2   4   1   3
0   1   2   6
5       678

3564-10-28
      1 4 2 3
0 1 2 3 4 5 6 8
6 5 7         8

1111-11-11
1234
1
5678

0123-12-30
1 2 3 4
0 1 2 3
8 5 6 7

```

# Answer
> 1 votes
# Pyth, 86 78 bytes

```
JS{K-z\-=GheS.nmmlkd=N,mf<T5d=ZmmhkxdcK1Jmf>T4dZjbmjkmj"".[|k\ \ Gd[hNm]dcJ1eN

```

I will try to golf this down as soon as my brain has recovered. I was happy just to see it work.

# Answer
> 5 votes
# JavaScript (ES6), 168 ~~173~~

As an anonymous function. Using template strings, there is a newline near the end that is significant and included in the byte count.

```
d=>d.replace(/\d/g,c=>m=(l=((o[c]=o[c]||[b,c,b])[p/2&~1]+=++p).length)>m?l:m,t=[m=p=b='',b,b],o=[])&o.map(x=>x&&x.map((x,i)=>t[i]+=(x+'     ').slice(0,m+1)))||t.join`
`

```

**Less golfed**

```
f=d=>(
  // get the indices in o and the columns width in m
  m=0,
  p=0,
  o=[],
  d.replace(/\d/g,c=>(
    o[c] = o[c]||['',c,''], // for each found digit :array with top indices, digit, bottom indices
    o[c][p/2 & ~1] += ++p, // (p/2 and not 1) maps 0..3 to 0, 4..7 to 2
    l = o[c].length,
    m = l>m ? l : m // max indices string length in m
  )),
  // build the output in t
  t=['','',''],
  o.map(x=> x && x.map(
    (x,i) => t[i]+=(x+'     ').slice(0,m+1)) // left justify, max value of m is 4
  ),
  t.join`\n` // return output as a newline separated string
)

```

**Test snippet**

```
f=d=>
  d.replace(/\d/g,c=>m=(l=((o[c]=o[c]||[b,c,b])[p/2&~1]+=++p).length)>m?l:m,t=[m=p=b='',b,b],o=[])&
  o.map(x=>x&&x.map((x,i)=>t[i]+=(x+'     ').slice(0,m+1)))
  ||t.join`\n`

console.log=x=>O.textContent+=x+'\n'

;['2013-02-27','2015-12-24','2222-11-11','1878-02-08','2061-02-22','3564-10-28','1111-11-11']
.forEach(t=>console.log(t+'\n'+f(t)+'\n'))
```

```
<pre id=O></pre>
```

# Answer
> 4 votes
# Ruby, ~~200~~ ~~195~~ ~~189~~ ~~178~~ ~~162~~ 157 characters

(156 characters code + 1 character command line option)

```
o={}
i=0
$_.gsub(/\d/){o[$&]||=['','']
o[$&][i/4]+="#{i+=1}"}
o=o.sort.map &:flatten
puts [1,0,2].map{|i|o.map{|c|c[i].ljust o.flatten.map(&:size).max}*' '}

```

Sample run:

```
bash-4.3$ ruby -n xkcd-date.rb <<< '2013-02-27'
2  3  1  4
0  1  2  3  7
5     67    8

bash-4.3$ ruby -n xkcd-date.rb <<< '2222-11-11'
     1234
1    2
5678

bash-4.3$ ruby -n xkcd-date.rb <<< '3564-10-28'
      1 4 2 3
0 1 2 3 4 5 6 8
6 5 7         8

```

# Answer
> 2 votes
# Python 2.7, ~~308~~ 310 bytes

```
i=raw_input().replace("-","")
s,w=sorted(set(i)),len
x,m={},0
for c in s:
    q,v=i,[""]*2
    while c in q:a=str(-~q.index(c)+(w(i)-w(q)));v[int(a)>4]+=a;q=q[q.index(c)+1:]
    m,x[c]=max(m,max(map(w,v))),v
for l in[0,1]:print"".join((lambda x:x+(-~m-w(x))*" ")("".join(x[n][l]))for n in s)+"\n"+(" "*m).join(s)*(-l+1)

```

Wow, fixing it only costed 2 bytes!

The date doesn't have to be separated, the date can be any length, it doesn't have to be a date, it could be any string (but dashes are removed). The middle part looks pretty golfable to me.

# Answer
> 1 votes
# Python 3, 306 bytes

I'm investigating ways to determine, before assembling the top and bottom lines, what the maximum width of any given column will be. Once I've got that, I should be able to build the spaces into the lines directly instead of using all those `join` functions.

```
j=''.join
def t(d):
 c,*l={},;i,*n=0,
 for e in d.replace('-',''):
  i+=1
  try:c[e]+=[i]
  except:c[e]=i,
 m=sorted(c)
 for x in m:
  l+=[j(str(p)for p in c[x]if p<5)]
  n+=[j(str(p)for p in c[x]if p>4)]
 f='<'+str(max(map(len,l+n)))
 return'\n'.join(map(lambda o:' '.join(format(i,f)for i in o),(l,m,n)))

```

# Answer
> 1 votes
## C#, 456

Golfed:

```
string  x(string p){string s=p.Replace("-", ""),a="",d="",e="";var u=new Dictionary<char,List<int>>();for(int i=0;i<s.Length;i++)if(u.ContainsKey(s[i]))u[s[i]].Add(i+1);else u.Add(s[i],new List<int>{i+1});foreach (var c in u.Keys.OrderBy(k=>k)){var t=String.Join("",u[c].Where(i=>i<5));var b=String.Join("",u[c].Where(i=>i>4));var l=Math.Max(t.Length,b.Length);var m=c+"".PadRight(l);a+=t.PadRight(l)+" ";e+=m;d+=b.PadRight(l)+" ";}return a+"\n"+e+"\n"+d;}

```

Ungolfed:

```
string  x(string p)
    {
        string s = p.Replace("-", ""),a = "", d = "", e = "";;
        var u = new Dictionary<char, List<int>>();
        for (int i = 0; i < s.Length; i++) if (u.ContainsKey(s[i])) u[s[i]].Add(i + 1); else u.Add(s[i], new List<int>{ i + 1 });
        foreach (var c in u.Keys.OrderBy(k => k))
        {
            var t = String.Join("", u[c].Where(i => i < 5));
            var b = String.Join("", u[c].Where(i => i > 4));
            var l = Math.Max(t.Length, b.Length);
            var m = c + "".PadRight(l);
            a += t.PadRight(l) + " ";
            e += m;
            d += b.PadRight(l) + " ";
        }
        return a + "\n" + e + "\n" + d;
    }

```

# Answer
> 1 votes
# Perl6, 265 bytes

Golfed

```
my$i=get;$i~~s:g/\-//;my@b=$i.comb.unique.sort;my$f={$i.comb[$_[1]-1]eq$_[0]??$_[1]!!''};my$g={[~] .map: $f};my$h={(@b X @^a).rotor(4).map: $g}my@a=$h(1..4);my@c=$h(5..8);my$s=max(|@a».chars,|@c».chars)+1;my$x='%-'~$s~'s';for @a,@b,@c {say [~] @_.map: *.fmt($x)}

```

Ungolfed (slightly)

```
my $i = get;
$i ~~ s:g/\-//;
my @b = $i.comb.unique.sort;
my $f = { $i.comb[$_[1]-1] eq $_[0] ?? $_[1] !! '' };
my $g = { [~] .map: $f };
my $h = { (@b X @^a).rotor(4).map: $g }
my @a = $h(1..4);
my @c = $h(5..8);
my $s = max(|@a».chars, |@c».chars)+1;
my $x = '%-'~$s~'s';
for @a,@b,@c { say [~] @_.map: *.fmt($x) }

```

# Answer
> 0 votes
# Powershell, ~~174~~ ~~170~~ ~~168~~ 167 bytes

```
$a=@{}
$args|% t*y|?{$_-45}|%{if(!$a.$_){$a.$_="","","$_"}$a.$_[++$i-gt4]+=$i}
0,2,1|%{$r=$_
-join($a.Keys|sort|%{$a.$_[$r]}|% p*ht(1+($a|% v*|%{$_|% l*h}|sort)[-1]))}

```

Less golfed test script:

```
$f = {

$a=@{}                              # a hash table for a result
$args|% toCharArray|?{$_-45}|%{     # for each digit from argument strings except a '-'
    if(!$a.$_){$a.$_="","","$_"}    #   create an array if there are no values for the current digit
    $a.$_[++$i-gt4]+=$i             #   append the character to the relative row (0 - top, 1 - bottom) and increment position number
}                                   # the result is a hash table in which the key is a char of a digit and the value is an array of string
                                    # for example, first lines for the first test case:
                                    # @{
                                    #     [char]48: ("2","5","0")
                                    #     [char]49: ("3","","1")
                                    #     [char]50: ("1","67","2")
                                    #     ...
                                    # }
$l=1+($a|% Values|%{$_|% Length}|sort)[-1]      # calc the maximum width of strings
0,2,1|%{                            # for each number 0,2,1
    $r=$_                           # store it as row number
    -join(
        $a.Keys|sort|               # for each keys (digit of the dates) in the sorted order
            %{$a.$_[$r]}|           # push to pipe the relative string
            % padRight $l           # for which to execute the 'padright' method to pad with spaces
    )                               # and finally join the row
}

}

@(

,("2013-02-27",
"2  3  1  4   ",
"0  1  2  3  7",
"5     67    8")

,("2015-12-24",
"2  3  1     4",
"0  1  2  4  5",
"   5  67 8   ")

,("2222-11-11",
"     1234 ",
"1    2    ",
"5678      ")

,("1878-02-08",
"   1     3  24 ",
"0  1  2  7  8  ",
"57    6     8  ")

,("2061-02-22",
"2   4   1   3 ",
"0   1   2   6 ",
"5       678   ")

,("3564-10-28",
"      1 4 2 3   ",
"0 1 2 3 4 5 6 8 ",
"6 5 7         8 ")

,("1111-11-11",
"1234 ",
"1    ",
"5678 ")

,("0123-12-30",
"1 2 3 4 ",
"0 1 2 3 ",
"8 5 6 7 ")

) | % {
    $d, $expected = $_
    $result = &$f $d

    $d
    $j=0
    $result|%{
        "$($_.trimEnd() -eq $expected[$j].TrimEnd()): |$_|"   # Vertical bars only to see trailing and leading spaces
        $j++
    }
}

```

Output (vertical bars only to see trailing and leading spaces):

```
2013-02-27
True: |2  3  1  4     |
True: |0  1  2  3  7  |
True: |5     67    8  |
2015-12-24
True: |2  3  1     4  |
True: |0  1  2  4  5  |
True: |   5  67 8     |
2222-11-11
True: |     1234 |
True: |1    2    |
True: |5678      |
1878-02-08
True: |   1     3  24 |
True: |0  1  2  7  8  |
True: |57    6     8  |
2061-02-22
True: |2   4   1   3   |
True: |0   1   2   6   |
True: |5       678     |
3564-10-28
True: |      1 4 2 3   |
True: |0 1 2 3 4 5 6 8 |
True: |6 5 7         8 |
1111-11-11
True: |1234 |
True: |1    |
True: |5678 |
0123-12-30
True: |1 2 3 4 |
True: |0 1 2 3 |
True: |8 5 6 7 |

```

---
Tags: code-golf, ascii-art, date
---


title: Maximize Sudoku King's tour

text:
# Question
Title: Maximize Sudoku King's tour
## Background

**Sudoku** is a number puzzle where, given an \\$ n \times n \\$ grid divided into boxes of size \\$ n \\$, each number of \\$ 1 \\$ to \\$ n \\$ should appear exactly once in each row, column and box.

In the game of Chess, the **King** can move to any of (at most) 8 adjacent cells in a turn. "Adjacent" here means horizontally, vertically or diagonally adjacent.

The **King's tour** is an analogy of the Knight's tour; it is a (possibly open) path that visits every cell exactly once on the given board with Chess King's movements.

## Task

Consider a 6-by-6 Sudoku grid:

```
654 | 321
123 | 654
----+----
462 | 135
315 | 246
----+----
536 | 412
241 | 563

```

and a King's tour (from `01` to `36`):

```
01 02 03 | 34 35 36
31 32 33 | 04 05 06
---------+---------
30 23 28 | 27 26 07
22 29 24 | 25 09 08
---------+---------
21 19 16 | 10 14 13
20 17 18 | 15 11 12

```

The tour forms the 36-digit number `654654564463215641325365231214123321`.

Taking a different King's tour gives larger numbers; for example, I can find a path that starts with `65<6>56446556...` which is definitely greater than the above. You can change the Sudoku board to get even higher numbers:

```
... | ...
.6. | ...
----+----
..6 | ...
.5. | 6..
----+----
.45 | .6.
6.. | 5..

```

This incomplete board gives the starting sequence of `666655546...` which is the optimal sequence of 9 starting digits.

Your task is to **find the largest such number for standard 9-by-9 Sudoku with 3-by-3 boxes**, i.e.

```
... | ... | ...
... | ... | ...
... | ... | ...
----+-----+----
... | ... | ...
... | ... | ...
... | ... | ...
----+-----+----
... | ... | ...
... | ... | ...
... | ... | ...

```

Note that **this challenge is not** ; the focus is to actually find the solutions rather than to write a small program that theoretically works.

## Scoring & winning criterion

**The score of a submission is the 81-digit number found by your program.** The submission with the highest score wins. Your program should also output the Sudoku grid and the King's tour in human-readable form; please include them in your submission.

Your program may output multiple results; your score is the maximum of them.

There's no time limit for your program. If your program continues to run and finds a higher number afterwards, you can update the submission's score by editing the post. Tiebreaker is the earliest time to achieve the score, i.e. either the time of post (if it's not edited yet) or the time of edit when the score was updated (otherwise).

# Answer
# Python + Z3, 999899898789789787876789658767666545355432471632124566352413452143214125313214321, optimal

Runs in about half an hour, producing

```
1 3 4 8 9 7 6 2 5
2 9 7 1 5 6 8 3 4
5 6 8 4 2 3 7 9 1
4 7 6 2 1 5 9 8 3
8 5 1 6 3 9 2 4 7
9 2 3 7 8 4 1 5 6
3 8 5 9 6 1 4 7 2
6 4 9 5 7 2 3 1 8
7 1 2 3 4 8 5 6 9
81 79 78 14 15 16 54 57 56
80 12 13 77 52 53 17 55 58
34 33 11 51 76 75 18  1 59
35 10 32 50 74 72  2 19 60
 9 36 49 31 73  3 71 61 20
 8 48 37 30  4 69 70 62 21
47  7 38  5 29 68 65 22 63
46 43  6 39 28 67 66 64 23
44 45 42 41 40 27 26 25 24
999899898789789787876789658767666545355432471632124566352413452143214125313214321

```

### Code

```
import z3

def adj(a):
    x, y = a
    for x1 in range(max(0, x - 1), min(9, x + 2)):
        for y1 in range(max(0, y - 1), min(9, y + 2)):
            if (x1, y1) != a:
                yield x1, y1

solver = z3.SolverFor("QF_FD")

squares = list((x, y) for x in range(9) for y in range(9))
num = {(x, y): z3.Int(f"num{x}_{y}") for x, y in squares}
for a in squares:
    solver += 1 <= num[a], num[a] <= 9
for cells in (
    [[(x, y) for y in range(9)] for x in range(9)]
    + [[(x, y) for x in range(9)] for y in range(9)]
    + [
        [(x, y) for x in range(i, i + 3) for y in range(j, j + 3)]
        for i in range(0, 9, 3)
        for j in range(0, 9, 3)
    ]
):
    solver += z3.Distinct([num[x, y] for x, y in cells])
    for k in range(1, 10):
        solver += z3.Or([num[x, y] == k for x, y in cells])

move = {
    ((x0, y0), (x1, y1)): z3.Bool(f"move{x0}_{y0}_{x1}_{y1}")
    for x0, y0 in squares
    for x1, y1 in adj((x0, y0))
}
tour = {(x, y): z3.Int(f"tour{x}_{y}") for x, y in squares}
for a in squares:
    solver += 0 <= tour[a], tour[a] < 81
for a in squares:
    solver += z3.PbEq([(move[a, b], 1) for b in adj(a)] + [(tour[a] == 80, 1)], 1)
for b in squares:
    solver += z3.PbEq([(move[a, b], 1) for a in adj(b)] + [(tour[b] == 0, 1)], 1)
solver += z3.Distinct([tour[a] for a in squares])
for t in range(81):
    solver += z3.Or([tour[a] == t for a in squares])
for a in squares:
    for b in adj(a):
        solver += move[a, b] == (tour[a] + 1 == tour[b])

value = [z3.Int(f"value{t}") for t in range(81)]
for t in range(81):
    solver += 1 <= value[t], value[t] <= 9
for a in squares:
    for t in range(81):
        solver += z3.Implies(tour[a] == t, num[a] == value[t])

assert solver.check() != z3.unsat
opt = 0
while opt < 81:
    model = solver.model()
    for y in range(9):
        print(*(model[num[x, y]] for x in range(9)))
    for y in range(9):
        print(*(f"{model[tour[x, y]].as_long() + 1:2}" for x in range(9)))
    best = [model[value[t]].as_long() for t in range(81)]
    print(*best, sep="")
    print()
    while opt < 81:
        improve = z3.Bool(f"improve{opt}_{best[opt]}")
        solver += improve == (value[opt] > best[opt])
        if solver.check(improve) != z3.unsat:
            break
        solver += value[opt] == best[opt]
        opt += 1

```
> 21 votes

---
Tags: code-challenge, sudoku
---


title: Print a layered cake

text:
# Question
Title: Print a layered cake
## Challenge

Given an input `n`, print an ASCII art cake `n` layers tall, viewed from the side, with two candles on top. Refer to the examples below for details.

## Output

```
>> cake(1)

 _|_|_
|     |
+-----+

>> cake(3)

     _|_|_
    |     |
  +---------+
  |         |
+-------------+
|             |
+-------------+

```

...and so on.

## Rules

* Standard loopholes prohibited
* Please make an attempt at a clever solution
* This is , so shortest answer in bytes wins. However, the answer will not be selected.

## Have fun!

# Answer
# Python 2, 238 chars

```
i=input()
m=["+"+"-"*(i*4+1)+"+","|"+" "*(i*4+1)+"|"]
for v in range(i,1,-1):
 m+=[" "*(i-v)*2+"+"+"-"*(v*4+1)+"+"," "*(i-v+1)*2+"|"+" "*((v-1)*4+1)+"|"]
m.pop()
m+=[" "*(i-1)*2+"|"+" "*5+"|"," "*(i-1)*2+" _|_|_"]
print'\n'.join(m[::-1])

```

The missing example of Cake 2:

```
   _|_|_
  |     |
+---------+
|         |
+---------+

```
> 6 votes

# Answer
# Ruby, 109 107 bytes

```
->n{p=->t{puts t.center 3+4*n}
p['_|_|_']
(1..n).map{|i|p[?|+' '*(1+4*i)+?|]
p[?++?-*((i<n ?5:1)+4*i)+?+]}}

```
> 4 votes

# Answer
## JavaScript (ES6), 134 bytes

A recursive cake.

```
f=(n,i=--n,r=(n,c)=>'- '[+!c].repeat(n),p=r((i-n)*2),j=n*4+5,x=p+`+${r(j,1)}+
`)=>(n?f(n-1,i)+x:p+` _|_|_
`)+p+`|${r(j)}|
`+(n-i?'':x)

```

### Demo

```
let f=(n,i=--n,r=(n,c)=>'- '[+!c].repeat(n),p=r((i-n)*2),j=n*4+5,x=p+`+${r(j,1)}+
`)=>(n?f(n-1,i)+x:p+` _|_|_
`)+p+`|${r(j)}|
`+(n-i?'':x)

console.log(f(4))
```
> 4 votes

# Answer
## Batch, 233 bytes

```
@echo off
set i=
for /l %%j in (2,1,%1)do call set i=  %%i%%
echo %i% _^|_^|_
set s=-----
for /l %%j in (2,1,%1)do call:l
echo ^|%s:-= %^|
echo +%s%+
exit/b
:l
echo %i%^|%s:-= %^|
set i=%i:~2%
set s=----%s%
echo %i%+%s%+

```

Shorter than Python? Something must be wrong...
> 3 votes

# Answer
# Haskell, 103 bytes

```
f(a:b)n=a:([0..4*n]>>b)++[a]
x!n=x:[f"| "n,f"+-"n]
g 1=" _|_|_"!1
g n=map("  "++)(init.g$n-1)++f"+-"n!n

```

Defines a function `g` which returns a list of strings containing the lines of the output
> 3 votes

# Answer
# 05AB1E, ~~115~~, 101 chars

```
>UXð×?" _|_|_",Xð×?"|     |",X<U0<VXGNVXY-ð×?'+?8Y·+G'-?}'+,XY-ð×?'|?7Y·+ð×?'|,}XY-ð×?'+?8Y·+G'-?}'+,

```

Saved 14 chars thanks to Adnan!
Definitely some room for golfing here.

Try it online!

Note that this does print everything offset by one space.
> 2 votes

# Answer
# Python 2, 122 bytes

```
a='  '*input()
b='+-+'
c=d=' '
while a:b='+----'+b[1:];c=d*4+c;a=a[2:];print a+[' _|_|_',b][c>d*5]+'\n%s|%%s|'%a%c
print b

```
> 2 votes

# Answer
# Python 3, 162 characters

```
p=print
t=int(input())
d=4*'-'
s='  '
a='+\n'
r=(t-1)*s
p(r+' _|_|_\n'+r+'|     |')
for i in range(2,t+1):b=(t-i)*s;p(b+'+-'+i*d+a+b+'| '+i*2*s+'|')
p('+-'+t*d+a)

```

It's not very clever, but I've never done one of these before. (Edit: removed unnecessary parentheses; reduced by one more character)
> 2 votes

# Answer
# Pyth, 73 bytes

```
+K*dtyQ"_|_|_"+tK"|     |"jP.iJms[*\ yt-Qd\+*+5*4d\-\+)+StQtQmXd"+-""| "J

```

A program that takes input of an integer on STDIN and prints the result.

There is probably still some golfing to be done here.

Try it online

*Explanation coming later*
> 2 votes

# Answer
# JavaScript (ES6), 171 bytes

```
n=>[(s="  "[R='repeat'](n-1))+" _|_|_",s+"|     |",...Array(n-1),`+${"-"[R](n*4+1)}+`].map((_,i)=>_||(s="  "[R](n-i))+`+${"-"[R](i=i*4+1)}+`+`
${s}|${" "[R](i)}|`).join`
`

```

First pass, probably not optimal...
> 1 votes

# Answer
# PHP, ~~150~~ ~~147~~ ~~138~~ ~~136~~ ~~130~~ 140 bytes

new approach:

```
echo$p=str_pad("",-2+2*$n=$argv[1])," _|_|_";for($x="    ",$b=$y="----";$n--;){$a.=$x;if($n)$b.=$y;echo"
$p| $a|
",$p=substr($p,2),"+-$b+";}

```

old version for reference:

```
$p=str_pad;for($o=["_|_|_"];$i++<$n=$argv[1];$o[]="+".$p("",($i<$n)*4+$e,"-")."+")$o[]="|".$p("",$e=$i*4+1)."|";foreach($o as$s)echo$p($s,$n*4+3," ",2),"
";

```
> 1 votes

# Answer
# Vimscript, ~~116~~ 115 bytes

Pretty messy but it works!

```
fu A(n)
let @z="Vkyjply4lpjy4hp"
exe "norm 2i+\e5i-\eo||\e5i \e".a:n."@zddl4xggd$i_|_|_"
exe "%ce ".(a:n*4+3)
endfu

```

To call it: `call A(3)` in an *empty* buffer. To load the function, `source cake.vim`

## Explanation

* `2i+<Esc>5i-<Esc>` writes the first line `+-----+`
* `o||<Esc>5i<Space><Esc>` adds `| |` on the second line
* `Vkyjply4lpjy4hp` is saved in the macro `@z` \- it visually selects both lines, yanks them, pastes them under and adds 4 dashes and spaces to them.
* `#@z` repeats this `#` times
* `ddl4x` deletes the last lines and remove for dashes to the bottom of the cake to make it equal with the top of the bottom layer
* `ggd$i_|_|_` replaces the first line by the top of the cake
* `%ce` then centers the whole cake to the width of the bottom layer! !
> 1 votes

# Answer
# SOGL V0.12, ~~27~~ 26 bytes

```
∫4*I:┌*╗1Ο;@*┐1Ο}⁴¹k┐╔2ΟΚ╚

```

Try it Here!

Explanation:

```
∫               }           for each in 1..input inclusive, pushing counter
 4*                           multiply by 4
   I                          increase by 1
    :                         duplicate; this will be used later
     ┌*                       repeat a dash pop times
       ╗1Ο                    encase them in plusses
          ;                   get the duplicate on the stacks top
           @*                 repeat a space pop times
             ┐1Ο              encase in vertical bars
                 ⁴          duplicate the item below ToS - the last line
                  ¹         wrap the stack in an array
                   k        remove the arrays first item
                    ┐       push "_"
                     ╔      push "|"
                      2Ο    encase 2 copies of the vertical bar in underscores
                        Κ   and prepend that to the array
                         ╚  center the array horizontally

```
> 1 votes

# Answer
# Excel VBA, <sub>~~139~~ ~~130~~</sub> 127 Bytes

Anonymous VBE immediate window that takes input from cell `A1` and outputs a cake to the VBE immediate window

```
For i=1To[A1]:s=Space(2*([A1]-i)):x=String(1+4*i,45):?s &IIf(i=1," _|_|_","+" &x &"+"):?s"|"Replace(x,"-"," ")"|":Next:?s"+"x"+

```
> 0 votes

# Answer
# CJam, 79 bytes

```
l~4*):Z5:X{D'+'-C}:A{D'|SC}:B{X*1$N}:C];{SZX-Y/*}:D~" _|_|_"NB{XZ<}{X4+:X;AB}wA

```

Try it online
> 0 votes

# Answer
# C (gcc), ~~158~~ 153 bytes

-5 bytes thanks to ceilingcat.

```
i,l,s;p(c,s){printf("%*c%*.*s%c\n",i-~i,c,l,l,s,c);}f(n){s=memset(malloc(5*n),45,5*n);l=1;for(i=n;i--;p('|',""))l+=4,n+~i?p(43,s):p(32,"_|_|_");p(43,s);}

```

Try it online!
> 0 votes

# Answer
# QBasic, 115 bytes

```
INPUT n
?SPC(n*2-1)"_|_|_
FOR i=1TO n
s=n*2-i*2
?SPC(s)"|"SPC(i*4+1)"|
?SPC(s-2)"+"STRING$(i*4+(i=n)*4+5,45)"+
NEXT

```

### Ungolfed

Print the top line with the candles; then print the rest of the cake two lines at a time.

```
INPUT n
PRINT SPC(n * 2 - 1); "_|_|_"
FOR i = 1 TO n
  indent = n * 2 - i * 2
  PRINT SPC(indent); "|"; SPC(i * 4 + 1); "|"
  PRINT SPC(indent - 2); "+"; STRING$(i * 4 + (i = n) * 4 + 5, 45); "+"
NEXT

```

`SPC`, when used in a `PRINT` statement, emits the given number of spaces. Conveniently, when given a negative argument, it treats it as 0, so the fact that `indent - 2` is `-2` in the last iteration isn't a problem. `STRING$` takes a count and a character code (here, 45 for `-`) and repeats the character that number of times. Here, we have to special-case the last line (when `i=n`) to be 4 hyphens shorter than it would otherwise be.
> 0 votes

---
Tags: code-golf, ascii-art, kolmogorov-complexity
---