15
\$\begingroup\$

Challenge

We all know about normal Christmas trees - but how about an upside-down Christmas tree! This is a fairly easy, Christmas themed challenge. The objective of this challenge is to make me an ASCII upside-down Christmas tree. Here are the rules for this challenge:

  1. Accept an odd, positive integer. You can assume it will always be between 7 and 51.
  2. The base of the tree will be made of the characters:

    ___
    \ /
     |
    
  3. The top of the tree (the star), will be made up of a single *.

  4. Each line of the tree will be constructed using the format <?> where ? is any number of -s. For example, if making a line of length 5, the line should be <--->. Or if making a line of length 8, the line should be <------>.

  5. Here is how the body of the tree should be constructed:

    1. Take the odd number n given as input, and create a line of the tree that length.

    2. Subtract 4 from n and create a line of the tree that length.

    3. Subtract 2 from n and create a line of the tree that length.

    4. Decrement n by 2. After that, unless n equals 5, go back to step 2.

  6. The base (see step 2.) the star (see step 3.) and each line of the tree (see steps 4. and 5.) should all be centered using the original odd number input (see step 1.) as the maximum width.

Examples/Test Cases

odd number inputed: 7
  ___
  \ /
   |
<----->      line length -> 7
  <->        line length -> 7 - 4 = 3
 <--->       line length -> 7 - 2 = 5
   *


odd number inputed: 13
     ___
     \ /
      |
<----------->      line length -> 13
  <------->        line length -> 13 - 4 = 9
 <--------->       line length -> 13 - 2 = 11
   <----->         line length -> 11 - 4 = 7
  <------->        line length -> 11 - 2 = 9
    <--->          line length -> 9 - 4 = 5
   <----->         line length -> 9 - 2 = 7
     <->           line length -> 7 - 4 = 3 
    <--->          line length -> 7 - 2 = 5
      *


odd number inputed: 9
   ___
   \ /
    |
<------->      line length -> 9
  <--->        line length -> 9 - 4 = 5
 <----->       line length -> 9 - 2 = 7
   <->         line length -> 7 - 4 = 3
  <--->        line length -> 7 - 2 = 5
    *


odd number inputed: 17
       ___
       \ /
        |
<--------------->      line length -> 17
  <----------->        line length -> 17 - 4 = 13
 <------------->       line length -> 17 - 2 = 15
   <--------->         line length -> 15 - 4 = 11
  <----------->        line length -> 15 - 2 = 13
    <------->          line length -> 13 - 4 = 9
   <--------->         line length -> 13 - 2 = 11
     <----->           line length -> 11 - 4 = 7
    <------->          line length -> 11 - 2 = 9
      <--->            line length -> 9 - 4 = 5
     <----->           line length -> 9 - 2 = 7
       <->             line length -> 7 - 4 = 3
      <--->            line length -> 7 - 2 = 5
        *    

Rules

\$\endgroup\$
5
  • 3
    \$\begingroup\$ Seeing as the input is guaranteed to be an odd number, can we take its index in the sequence of odd numbers? \$\endgroup\$
    – FlipTack
    Commented Dec 25, 2017 at 20:26
  • \$\begingroup\$ Also - repeat the above steps until the odd number minus 2 equals 5 - in the first input, the odd number is 7, and 7-2=5, therefore the tree should end instantly (I know what you mean, but it needs rephrasing) \$\endgroup\$
    – FlipTack
    Commented Dec 25, 2017 at 20:29
  • \$\begingroup\$ @FlipTack I'm not exactly sure what you mean. If the odd number is 7, the minimum input, you would first create the three tree lines (sub-steps .1.1, .1.2, .1.3), then subtract 2 from the odd number and test if it equals 5. The instruction to check if the "odd number minus 2 equals 5" is at the end, the other three steps should be performed first. But to answer your first comment, that would be fine. \$\endgroup\$
    – Chris
    Commented Dec 25, 2017 at 20:36
  • 1
    \$\begingroup\$ @FlipTack I think he’s asking whether you have to accept 7 as input or if you can accept 4, as in the fourth odd number (or 3 if it’s 0-indexed). \$\endgroup\$
    – DonielF
    Commented Dec 26, 2017 at 16:00
  • 4
    \$\begingroup\$ From title: "Ok, you are now an upside down Christmas tree." \$\endgroup\$
    – anna328p
    Commented Dec 27, 2017 at 7:16

11 Answers 11

10
\$\begingroup\$

Python 3, 127 121 105 103 100 98 bytes

This is an unnamed lambda function which returns a list of lines:

lambda o:[s.center(o)for s in['___','\ /','|',*[f'<{"-"*(o-i+2-i%2*3)}>'for i in range(4,o)],'*']]

Try it online!

The main part of this answer is (o-i+2-i%2*3), which works out the number of dashes to have on a line. The rest of the answer is simply converting this into the desired ASCII-art.

Many thanks to Mr. Xcoder, for shaving 6 bytes, and discussing golfs with me in chat.

Thanks also to Lynn for noticing that 3*(i%2) can be i%2*3, 2 bytes shorter!

\$\endgroup\$
5
  • \$\begingroup\$ 121 bytes using some very little math tricks and f-strings \$\endgroup\$
    – Mr. Xcoder
    Commented Dec 25, 2017 at 20:50
  • 2
    \$\begingroup\$ Whenever I post a Python answer, no matter the time of day or his current location, @Mr.Xcoder has a golf to give :) \$\endgroup\$
    – FlipTack
    Commented Dec 25, 2017 at 20:52
  • \$\begingroup\$ Welp, this easily beats my 250 bytes+ Python solution. Nice job! +1 \$\endgroup\$
    – Chris
    Commented Dec 25, 2017 at 20:53
  • \$\begingroup\$ o-i+2-i%2*3 saves two bytes. \$\endgroup\$
    – lynn
    Commented Dec 26, 2017 at 16:50
  • \$\begingroup\$ @Lynn Good spot, updated. \$\endgroup\$
    – FlipTack
    Commented Dec 26, 2017 at 18:03
7
\$\begingroup\$

C, 163 bytes

#define P;printf(
i;g(l){P"%*c",1+i-l--/2,60);for(;--l P"-"))P">\n");}f(n){i=n/2 P"%*c__\n%*c /\n%*c|\n",i,95,i,92,i,32);for(g(n);n>5;g(n-=2))g(n-4)P" %*c",i,42);}

Try it online!

Unrolled:

#define P;printf(

i;
g(l)
{
    P"%*c", 1+i-l--/2, 60);
    for (; --l P"-"))
    P">\n");
}

f(n)
{
    i=n/2
    P"%*c__\n%*c /\n%*c|\n", i, 95, i, 92, i, 32);

    for(g(n); n>5; g(n-=2))
        g(n-4)

    P" %*c", i, 42);
}
\$\endgroup\$
6
\$\begingroup\$

Proton, 83 bytes

Thanks to FlipTack for saving 4 bytes, and for collaborating in chat (we actually form a great team). Indirectly saved 2 bytes thanks to Lynn.

o=>[s.center(o)for s:['___','\ /','|']+['<'+"-"*(o-i+2-i%2*3)+'>'for i:4..o]+['*']]

Try it online!

\$\endgroup\$
0
5
\$\begingroup\$

Charcoal, 28 bytes

__⸿ /⸿|F⮌…¹⊘N«⸿⊕ι>⸿⊖ι>»‖B← *

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

__⸿ /⸿|

Print the base.

F⮌…¹⊘N«

Loop from half of the input number down to 1.

⸿⊕ι>⸿⊖ι>»

Print two lines, the first with one more - than the loop index, the second with one fewer.

‖B←

Mirror to complete the tree.

 *

Place the star.

\$\endgroup\$
5
\$\begingroup\$

SOGL V0.12, 35 30 bytes

┌* <++L
%⁽⁄6‘√.⁾δ№{⁽LFL}j *+§Γ

Try it Here!

Uses Neil's Charcoal algorithm, takes input as the index in the odd numbers - so 13 would correspond to the input 7

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

Retina, 89 bytes

.+
$*->
^--
<
+`( *<)----(-+>)$
$&¶  $1$2¶ $1--$2
s`.*¶( +)<->.*
$1___¶$1\ /¶$1 |¶$&¶$1 *

Try it online! Explanation: The first stage converts the input to unary and appends a >. The second stage replaces two -s with a < to correct the line length. The third stage then replicates the branch but slightly shorter each time until the branch cannot be shortened any further. The final stage adds the base and the star.

\$\endgroup\$
2
\$\begingroup\$

Javascript 506 bytes

Golf-version:

function tree(i){const mid=(i+1)/2;const leg1=' '.repeat((mid-2))+`___
`;const leg2=' '.repeat((mid-2))+`\\ \/
`;const leg3=' '.repeat((mid-1))+`|
`;let xmasTree=leg1+leg2+leg3;for(let j=0;j<(i-4);j++){if(j%2===0){let v=j/2;let t=i-2*v-2;let body1=" ".repeat(j/2)+"<"+"-".repeat(t)+">"+`
`;xmasTree=xmasTree+body1}else{let k=1+Math.ceil(j/2);let h=i-2*k-2;let body2=' '.repeat(k)+'<'+'-'.repeat(h)+">"+`
`;xmasTree=xmasTree+body2}}
const head=' '.repeat((mid-1))+'*'
xmasTree=xmasTree+head;return xmasTree}

Ungolf-version:

function tree(i){
  const mid = (i+1)/2;
  const leg1 = ' '.repeat((mid-2)) + `___
`;
  const leg2 = ' '.repeat((mid-2)) + `\\ \/
`;
  const leg3 = ' '.repeat((mid-1)) + `|
`;
  let xmasTree = leg1 + leg2 + leg3;
  for (let j = 0; j<(i-4); j++) {
    if (j%2===0) {
      let v = j/2;
      let t = i-2*v-2;
      let body1 = " ".repeat(j/2)+"<"+"-".repeat(t) +">"+`
`;
      xmasTree = xmasTree + body1;
    } else {
      let k = 1 + Math.ceil(j/2);
      let h = i-2*k-2;
      let body2 = ' '.repeat(k)+ '<'+ '-'.repeat(h) + ">"+`
`;
      xmasTree = xmasTree + body2;
    }
  }
  const head = ' '.repeat((mid-1)) + '*'
  xmasTree = xmasTree + head;
  return xmasTree;
}

Usage: console.log(tree(13)), console.log(tree(17)),

ES6 165 bytes (from my friend)

Golf-version:

p=n=>{l=_=>console.log(`${' '.repeat((n-_.length)/2)}${_}`);t=_=>_==1?'*':'<'+'-'.repeat(_-2)+'>';x=n;l('___');l('\\ /');l('|');for(;x!==3;){l(t(x));l(t(x-4));x-=2}}

Ungolf-version:

p = n => {
  l = _ => console.log(`${' '.repeat((n-_.length)/2)}${_}`);
  t = _ => _ == 1 ? '*' : '<' + '-'.repeat(_-2)+'>';
  x = n;
  l('___');l('\\ /');l('|');
  for(;x!==3;) {
    l(t(x)); l(t(x-4));x-=2;
  }
}

Usage: p(31); p(17);

\$\endgroup\$
1
  • 1
    \$\begingroup\$ You could golf this a lot, by using only 1-letter variable names, removing const keywords, etc \$\endgroup\$
    – FlipTack
    Commented Dec 26, 2017 at 9:58
1
\$\begingroup\$

PowerShell, 131 bytes

$i=2;$x="$args"..5|%{' '*($j=if($_%2){$i-2}else{($i++)})+'<'+'-'*($_-(5,2)[$_%2])+'>'};($y=' '*++$j)+"___";"$y\ /";"$y |";$x;"$y *"

Try it online!

Well, this is a right mess to anyone not conversant in PowerShell... so, let's see how well I can explain how it works.

For the explanation, I'll be using input = 17.

We start off simple enough, with setting helper variable $i=2 and setting $x to <something>, with the <something> starting as a range from the input $args down to 5, so 17,16,15,...,6,5. That range is pumped into a for loop.

Each iteration, we start with setting helper variable $j to be the result of an if statement, if($_%2){$i-2}else{($i++)}. If it's odd, $j=$i-2, otherwise $j=($i++). This, coupled with $i=2 at the beginning, gives us the sequence 0, 2, 1, 3, 2, 4, 3, 5... which just so happens to correspond exactly to how many spaces we need to prepend to our tree line. ;-) We take ' ' and string-multiply it out by that number.

Next we need our branches. This is done with '<' plus the middle part '-' multiplied out, plus the end '>'. The multiplication is done by recognizing that the - alternate in a 2, 5, 2, 5, 2... pattern based on the input number $_, so we're selecting from a pseudo-ternary based on that pattern.

For further clarification, here are the first couple terms in each section:

$_ = 17 16 15 14 13 12 11 10
$j =  0  2  1  3  2  4  3  5
mid=  2  5  2  5  2  5  2  5
'-'= 15 11 13  9 11  7  9  5

So now we've set $x to be an array of branches (i.e., strings). Outside the loop, we now build our tree "top" with the appropriate number of spaces saved into $y, then display our branches $x, and then the tree "bottom" with the *. Each of those are left on the pipeline and output is implicit with a newline between items.

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

JavaScript (ES6), 150 147 bytes

N=>{for(s=' '[r='repeat'](N/2-1),s+=`___
${s}\\ /
${s} |
`,n=N,l=n=>' '[r](N/2-n/2)+(n-1?`<${'-'[r](n-2)}>
`:'*');n-3;n-=2)s+=l(n)+l(n-4)
return s}

f=

N=>{for(s=' '[r='repeat'](N/2-1),s+=`___
${s}\\ /
${s} |
`,n=N,l=n=>' '[r](N/2-n/2)+(n-1?`<${'-'[r](n-2)}>
`:'*');n-3;n-=2)s+=l(n)+l(n-4)
return s}

console.log(f(7))
console.log(f(9))
console.log(f(13))
console.log(f(17))

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

Canvas, 28 bytes

-×>+∔
__¶ /¶|╶┤r⇵{├⁸¹⁸}k*∔↔│

Try it here!

A port of my SOGL answer which is a port of Neil's Charcoal answer.

\$\endgroup\$
0
\$\begingroup\$
N=>{for(s=' '[r='repeat'](N/2-1),s+=`___
${s}\\ /
${s} |
`,l=n=>' '[r](N/2-n/2)+n-1?`<${'-'[r](n-2)}>
`:'*');N-=2;s+=l(N)+l(N-4);return s}

My attempt at JS ESGoogoltriplex.

f=

N=>{for(s=' '[r='repeat'](N/2-1),s+=`___
${s}\\ /
${s} |
`,l=n=>' '[r](N/2-n/2)+n-1?`<${'-'[r](n-2)}>
`:'*');N-=2;s+=l(N)+l(N-4);return s}

console.log(f(7))
console.log(f(9))
console.log(f(13))
console.log(f(17))

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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