23
\$\begingroup\$

Introduction

Cacti come in various different sizes, shapes and colors. However, the most iconic cactus and must-have in every Western has to be the saguaro. Important features are its size and arms, which have defined the stereotypical cactus appearance.

Your task is to bring the saguaro in the ASCII world. However, -- as in the real world -- no saguaro is like another, so your program has to be able to generate saguaros with varying arm configurations.

An example saguaro

  • Input: [0b10, 0b11] ([2, 3] in decimal, input length of 2)
     _     
    / \    
 _  | |    
/ \ | |    
| | | |    
\ \_| |    
 \__  |    
    \ |    
 _  | |  _ 
/ \ | | / \
| | | | | |
\ \_| |_/ /
 \__   __/ 
    \ /    
    | |    
    | |    

Specifications

A saguaro always has a base and a top, with variable amounts of stem in between. The stem parts can have no arms, an arm on the right, one on the left or two arms.

Saguaro growth patterns are given as an input list containing two-bit values. 00 means no arms, 01 an arm on the right, 10 an arm on the left and 11 two arms (all in binary). The input list's length determines the saguaro's height.

Saguaro sections look like the following. Cactus parts are surrounded by octothorps, #, for clarity which shall not be printed.
A saguaro's height is always equal to 4+6*k characters for nonnegative integers k.

#############
#     _     # Saguaro top
#    / \    #
#############
# _  | |  _ # Stem, both arms
#/ \ | | / \# Stem id: 11
#| | | | | |#
#\ \_| |_/ /#
# \__   __/ #
#    \ /    #
#############
# _  | |    # Stem, left arm
#/ \ | |    # Stem id: 10
#| | | |    #
#\ \_| |    #
# \__  |    #
#    \ |    #
#############
#    | |  _ # Stem, right arm
#    | | / \# Stem id: 01
#    | | | |#
#    | |_/ /#
#    |  __/ #
#    | /    #
#############
#    | |    # Stem, no arms
#    | |    # Stem id: 00
#    | |    #
#    | |    #
#    | |    #
#    | |    #
#############
#    | |    # Saguaro base
#    | |    #
#############

Input

As previously said, the input consists of a list of two-bit values (0, 1, 2, 3 in decimal). It can be given in any reasonable format. The list's first element corresponds to the saguaro's highest stem part, the second element to its second highest stem part, etc.
If you want, you can require the input list's length as an additional input. Please specify it in your answer if you do so.

Output

Your output ASCII saguaro should be built using the exact stem parts as described above. Trailing spaces on a line and trailing new lines are ignored; you may print more, fewer or as many as specified above.

Rules

Test cases

  • An outlier. Input: [0b01, 0b00, 0b01, 0b11]
     _     
    / \    
    | |  _ 
    | | / \
    | | | |
    | |_/ /
    |  __/ 
    | /    
    | |    
    | |    
    | |    
    | |    
    | |    
    | |    
    | |  _ 
    | | / \
    | | | |
    | |_/ /
    |  __/ 
    | /    
 _  | |  _ 
/ \ | | / \
| | | | | |
\ \_| |_/ /
 \__   __/ 
    \ /    
    | |    
    | |    

  • Alternating arms. Input: [0b10, 0b01, 0b10]
     _     
    / \    
 _  | |    
/ \ | |    
| | | |    
\ \_| |    
 \__  |    
    \ |    
    | |  _ 
    | | / \
    | | | |
    | |_/ /
    |  __/ 
    | /    
 _  | |    
/ \ | |    
| | | |    
\ \_| |    
 \__  |    
    \ |    
    | |    
    | |    

  • An abundance of arms. Input: [0b11, 0b11]
     _     
    / \    
 _  | |  _ 
/ \ | | / \
| | | | | |
\ \_| |_/ /
 \__   __/ 
    \ /    
 _  | |  _ 
/ \ | | / \
| | | | | |
\ \_| |_/ /
 \__   __/ 
    \ /    
    | |    
    | |    

  • No arms, also known as a spear. Input: [0b00]
     _     
    / \    
    | |    
    | |    
    | |    
    | |    
    | |    
    | |    
    | |    
    | |    

  • No body, some call it a young cactus. Input: []
     _     
    / \    
    | |    
    | |    

\$\endgroup\$
  • \$\begingroup\$ can I take the input as the amount of parts and then each parts number separately? (e.g. 1st test-case would be 4 1 0 1 3) \$\endgroup\$ – dzaima Sep 26 '17 at 13:37
  • \$\begingroup\$ can we ignore the trailing spaces? \$\endgroup\$ – Brian H. Sep 26 '17 at 13:41
  • \$\begingroup\$ @dzaima You may. \$\endgroup\$ – Jonathan Frech Sep 26 '17 at 13:58
  • \$\begingroup\$ @BrianH. Yes; trailing spaces are ignored on every line. \$\endgroup\$ – Jonathan Frech Sep 26 '17 at 13:59
10
\$\begingroup\$

Charcoal, 50 49 bytes

↘_\¶/F²«J¹¦²Fθ¿﹪÷Iκ⁺¹ι²”{➙∧⊟≕δaL7YF¬⊕ρ↥↖_K”↓⁶↓²‖T

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

↘_\¶/

Draw the top.

F²«

Loop over each side.

J¹¦²

Jump to just under the right side of the top.

Fθ

Loop over each stem part.

¿﹪÷Iκ⁺¹ι²

Test whether there is an arm.

”{➙∧⊟≕δaL7YF¬⊕ρ↥↖_K”

If so print an arm.

↓⁶

Otherwise just print a vertical line.

↓²

After printing the stem, print the base.

‖T

Reflect ready to draw the other side. Once both sides are drawn, the sides are then reflected back into their final position.

\$\endgroup\$
7
\$\begingroup\$

JavaScript (ES6), 210 bytes

I spent far too long on another solution before realising there was a better way, which didn't leave me as much time as I would've liked to work on this.

a=>`     _
    / \\`+a.map(([x,y])=>`
 1  | |  2
3 5 | | 4 6
7 7 | | 8 8
5 51| |24 4
 511${`| `[x]} ${`| `[y]}224
    ${`|\\`[x]} `.replace(/\d/g,m=>` _/\\|`[m%2?x*-~m/2:y*m/2])+`|/`[y],s=`
    | |`).join``+s+s

Try it

o.innerText=(f=
a=>`     _
    / \\`+a.map(([x,y])=>`
 1  | |  2
3 5 | | 4 6
7 7 | | 8 8
5 51| |24 4
 511${"| "[x]} ${"| "[y]}224
    ${"|\\"[x]} `.replace(/\d/g,m=>` _/\\|`[m%2?x*-~m/2:y*m/2])+"|/"[y],s=`
    | |`).join``+s+s
)(i.value=["11","10","01","00"]);oninput=_=>o.innerText=f(i.value.split`,`)
<input id=i><pre id=o>

\$\endgroup\$
  • \$\begingroup\$ this in taking literal 00,01,10,11 as input, instead of binary input or 0,1,2,3. using OP test cases this fails. \$\endgroup\$ – Brian H. Sep 26 '17 at 14:14
  • \$\begingroup\$ @BrianH.: Quoting the challenge spec on input: "It can be given in any reasonable format" \$\endgroup\$ – Shaggy Sep 26 '17 at 14:15
  • 1
    \$\begingroup\$ but it states "the input consists of a list of two-bit values (0, 1, 2, 3 in decimal)." right before that... (btw im not downvoting or anythin, this is insanely clever, it's just that per my interpretation of the rules the input doesn't match) \$\endgroup\$ – Brian H. Sep 26 '17 at 14:36
5
\$\begingroup\$

Python 2, 189 bytes

lambda l:'     _\n    / \\\n'+'\n'.join(('    |',' /|\  _   \  \|\_    __ |||| \\'[j::6])[i/2]+' '+('|','|||| /   __  /|/_ _   /  \|/'[j::6])[i%2]for i in l for j in range(6))+'\n    | |'*2

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Python 2, 256 253...205 203 199 bytes

r=[('     _',''),('/','\ ')]
for a in input()+[0]:r+=zip(*[['|'*6,'_|    |_,,/|  \/  |\,,||  ||  ||,,\| _\/_ |/,,\ ____ /,,\/'[i::2].split(',')][2-i&a>0]for i in 0,1])
for l in r[:-4]:print'%5s %s'%l

Try it online!

\$\endgroup\$
  • \$\begingroup\$ As you do in other string literals, in the first line you can omit the escaping backslash. \$\endgroup\$ – Jonathan Frech Sep 26 '17 at 7:13
  • \$\begingroup\$ It looks like you could save 18 bytes by removing all the trailing spaces. \$\endgroup\$ – Shaggy Sep 26 '17 at 8:17
  • \$\begingroup\$ for ...:\n r...\n r... -> for ...:r...;r... saves three bytes. \$\endgroup\$ – Jonathan Frech Sep 26 '17 at 8:30
1
\$\begingroup\$

PowerShell, 235 bytes

param($a)'     _
    / \'
($a|%{((,'1|'*6),('1|  _
1| / \
1|2
1|_/ /
1 __/ 
1/'),(' _ 2
/ \2
| |2
\ \_| |
 \__  |
    \ |'),(' _ 2  _
/ \2 / \
| |22
\ \_| |_/ /
 \__   __/
    \ /'))[$_]})-replace1,'    | '-replace2,' | |'
,'    | |'*2

Try it online!

PowerShell doesn't have a map or zip or a real easy way to reverse strings, so we're left with something else -- simple replacements of repeated sections.

The first two lines take input as an array of integers and output the top of the cactus. Then we loop through $a and select into an array of four strings based on the current value. Those strings are left on the pipeline and then we use our -replace to fill in the appropriate spots. We then put the bottom of the cactus onto the pipeline as well.

Everything is gathered from the pipeline and an implicit Write-Output happens at program completion, inserting a newline between every element.

\$\endgroup\$
1
\$\begingroup\$

05AB1E, 76 75 bytes

„ _…/ \‚4ú»,v6F'|4ú"_ |/\"•Aö¡Èèj{^ë•5вèJ5ôNè©‚y1›èð'|®∞2äθ‚yÉèJ,}}„| 4úû=,

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ Meh, I'ma try to beat ya, doubt it though. \$\endgroup\$ – Magic Octopus Urn Sep 27 '17 at 19:29
  • \$\begingroup\$ @MagicOctopusUrn: Good luck! Hope you manage it (and maybe turn it into a skirmish :P) \$\endgroup\$ – Emigna Sep 27 '17 at 20:34
  • \$\begingroup\$ My one good idea to beat this was squashed by like 30 bytes b/c of the command I posted in the "oasis/05AB1E" chat. Nice golf, if I tried now it'd just be too close. \$\endgroup\$ – Magic Octopus Urn Sep 27 '17 at 20:43
1
\$\begingroup\$

Java (OpenJDK 8), 626 566 499 466 398 312 310 308 bytes

Can be golfed a tonne

a->{String r=" |,",g="    |",n="     _,    / \\,";boolean j,k;for(int e:a)n+=((k=e>1)?" _  |":g)+((j=e%2>0)?" |  _,":r)+(k?"/ \\ |":g)+(j?" | / \\,":r)+(k?"| | |":g)+(j?" | | |,":r)+(k?"\\ \\_|":g)+(j?" |_/ /,":r)+(k?" \\__ ":g)+(j?"  __/,":r)+(k?"    \\":g)+(j?" /,":r);return(n+g+r+g+r).replace(",","\n");}

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ You can save 2 bytes by changing {j=e>1;k=e%2>0;n+=(k?" _ |":g)+(j?" | _,":r)+ to n+=((k=e%2>0)?" _ |":g)+((j=e>1)?" | _,":r)+ and removing the closing } of the for-loop as well. \$\endgroup\$ – Kevin Cruijssen Sep 26 '17 at 15:22
  • \$\begingroup\$ You have the "arms" the wrong way 'round for 1 and 2. \$\endgroup\$ – Shaggy Sep 26 '17 at 22:28
0
\$\begingroup\$

SOGL V0.12, 56 54 53 bytes

5⁷yΙ‚‘∑≡`a#¾‘O.{@.2%i»¹{"⁸G‘6∙;?X"j1>ζ╔²i[n¹‘5n}┼±↔}O

Try it Here!

Explanation:

..‘                   push the ending part - "    | |\n    | |"
   ..‘O               output the starting part - "     _ \n    / \"
       .{             input times do
         @              push a space
          .2%           push input%2
             i»         push floor(prevInput/2)
               ¹        wrap the two in an array

{                   }   for each of the two numbers
 "..‘                     push "|    " - base stem
     6∙                   multiply vertically 6 times
       ;?       }         if the current item iterating over is truthy (i.e. != 0)
         X                  remove ToS - the regular stem - from the stack 
          "..‘              push "|  _ | / \| | ||_/ / __/ /    " - stem with an arm
              5n            split it into line lengths of 5
                 ┼        add that horizontally to the space pushed earlier (or whatever it's become)
                  ±↔      reverse ToS - the stem currently - horizontally
                     O  output the array of the current part
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.