Print a layered cake

14

4

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!

dkudriavtsev

Posted 2016-09-17T04:56:38.687

Reputation: 5 781

Answers

6

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:

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

edelbitter

Posted 2016-09-17T04:56:38.687

Reputation: 61

Hello, and welcome to the site! You could take input from STDIN and take off 24 chars. For example, i=int(input()) – James – 2016-09-17T05:59:13.230

If you want, you should be able to change to Python 2 and change int(input()) to input() and the print statement, plus you can change the four spaces to one (if it's a tab, change it to a space to make it more obvious that it's one character). Plus your bytecount is 4 too high for some reason. – ASCII-only – 2016-09-17T06:29:38.557

@Mars Ultor oops, yes, I'm not sure why I chose python 3 to begin with. Thanks. – edelbitter – 2016-09-17T06:45:51.810

You may also be able to save a few bytes using percent formatting – ASCII-only – 2016-09-17T06:54:14.650

4

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)+?+]}}

m-chrzan

Posted 2016-09-17T04:56:38.687

Reputation: 1 390

3

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...

Neil

Posted 2016-09-17T04:56:38.687

Reputation: 95 035

3

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))

Arnauld

Posted 2016-09-17T04:56:38.687

Reputation: 111 334

3

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

dianne

Posted 2016-09-17T04:56:38.687

Reputation: 1 049

2

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.

Luke

Posted 2016-09-17T04:56:38.687

Reputation: 81

Welcome to Programming Puzzles and Code Golf! Very nice first answer :) – Adnan – 2016-09-17T23:12:19.117

1

Maybe string multiplication helps, which is the × command. This is an example on how it's used.

– Adnan – 2016-09-17T23:13:50.250

@Adnan That does help! Thanks! – Luke – 2016-09-17T23:39:14.873

2

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

Lynn

Posted 2016-09-17T04:56:38.687

Reputation: 55 648

2

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)

Zoetrophy

Posted 2016-09-17T04:56:38.687

Reputation: 21

Welcome to the site, and nice first answer! – James – 2016-09-18T02:53:25.200

2

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

TheBikingViking

Posted 2016-09-17T04:56:38.687

Reputation: 3 674

1

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

dzaima

Posted 2016-09-17T04:56:38.687

Reputation: 19 048

1

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...

ETHproductions

Posted 2016-09-17T04:56:38.687

Reputation: 47 880

1

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),"
";

Titus

Posted 2016-09-17T04:56:38.687

Reputation: 13 814

I’m curious; how does this read input? – Lynn – 2016-09-18T01:04:05.997

@Lynn: damn I forgot that this time.10 bytes overhead for $argv. :-/ – Titus – 2016-09-18T01:54:36.323

1

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! !

Christian Rondeau

Posted 2016-09-17T04:56:38.687

Reputation: 301

0

Excel VBA, 139 130 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"+

Taylor Scott

Posted 2016-09-17T04:56:38.687

Reputation: 6 709

0

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

Chiel ten Brinke

Posted 2016-09-17T04:56:38.687

Reputation: 201

0

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!

gastropner

Posted 2016-09-17T04:56:38.687

Reputation: 3 264

0

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.

DLosc

Posted 2016-09-17T04:56:38.687

Reputation: 21 213