112
\$\begingroup\$

Given a number N, how can I print out a Christmas tree of height N using the least number of code characters? N is assumed constrained to a minimum value of 3, and a maximum value of 30 (bounds and error checking are not necessary). N is given as the one and only command line argument to your program or script.

All languages appreciated, if you see a language already implemented and you can make it shorter, edit if possible - comment otherwise and hope someone cleans up the mess. Include newlines and White Spaces for clarity, but don't include them in the character count.

A Christmas tree is generated as such, with its "trunk" consisting of only a centered "*"

N = 3:

   *
  ***
 *****
   *

N = 4:

    *
   ***
  *****
 *******
    *

N = 5:

     *
    ***
   *****
  *******
 *********
     *

N defines the height of the branches not including the one line trunk.

Merry Christmas PPCG!

\$\endgroup\$
0

116 Answers 116

1 2 3
4
1
\$\begingroup\$

Zsh, 77 64 bytes

Since all these old questions are now open, I think the oldest q. on codegolf.se needs a zsh answer!
Try it Online!

s=*;for ((;i<$1;))printf %$[$1+i++]s\\n $s&&s+=**
printf %$1s \*

Hat-tip to Alastair from Boxing Day 2008
NB: Putting the printf stuff in a function is no advantage...
NB2: original for 77 bytes.. saved 12 bytes by eliminating quotes, braces, trailing newline

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

Wren, 91 bytes

Fn.new{|n|
for(i in 0...n)System.print(" "*(n-i)+"*"*(2*i+1))
System.print(" "*n+"*")
}

Try it online!

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

Charcoal, 12 bytes

G<N*‖↑¶M⊖θ←*

Try it online

explanation

G<N*             #Draw a triangle size input N with character "*"
      ‖↑           #Mirror the triangle so it is the right way round
        ¶          #Newline
         M⊖θ←    #move left input-1 
               *   #"*" character
                   #the result is implicitly printed
\$\endgroup\$
2
  • \$\begingroup\$ Nice answer! I took the liberty of creating a TIO link so others can see it in action, if you'd liked to edit it into your post: tio.run/##ASkA1v9jaGFyY29hbP//… \$\endgroup\$
    – Malivil
    Dec 19, 2019 at 18:25
  • \$\begingroup\$ my bad @Malivil! I meant to add one, but forgot, thank you :) \$\endgroup\$
    – mabel
    Dec 19, 2019 at 18:33
1
\$\begingroup\$

Keg, 42 38 32 23 bytes

:&1ɧ1⑷:⑻$-⑬*$⑵;`*`*⑸(
'

Try it online!

-9 bytes due to generating odd numbers inside of the map

Answer History

32 Bytes

¿&1(⑻|:2+)1^⑷:;½ℤ⑻$-⑬*^`*`*⑸(,
,

Try it online!

-6 bytes due to using a mapping approach

38 Bytes

:&®l1(©l|⑬©l*,:`*`*,
,2+©l;®l)&⑬*,`*`,

-4 bytes due to operator (space string)

Funny story: I almost said this was 40 bytes before I realised that I forgot how to count.

Try it online!

I might as well place up the Keg Christmas tree for the year seeing as how it's almost December!

Explained

:&®l    #Store the amount of lines in variable l and the register
1   #Push the number of stars per row
(©l|    #Repeat variable l times
    ⑬©l*,   #Print that amount of spaces
    :`*`*,  #Print that amount of stars

    ,   #Print a literal newline
    2+  #Increment the number of stars
    ©l;®l   #Update the amount of spaces to print
)
&⑬*,`*`,    #Print the bottom row
\$\endgroup\$
1
\$\begingroup\$

Java, 180 chars

interface a{static void main(String[]a){for(int N=new Byte(a[0]),i=-1;i++<N;p('*',i%N*2),p('\n',0))p(' ',N-i%N-1);}static<T>void p(T c,int i){System.out.print(c);if(i-->0)p(c,i);}}

I believe this is a new record for Java for this question!

interface a
{
    static void main(String[]a){
        for(int N=new Byte(a[0]),i=-1;i++<N;p('*',i%N*2),p('\n',0))p(' ',N-i%N-1);
    }
    static<T>void p(T c,int i){
        System.out.print(c);
        if(i-->0)p(c,i);
    }
}

This program uses a recursive method to get rid of unnecessary for loops and print calls. Everything in main is run in one for loop.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ The whitespace is there to make it easier to read. The 180 char count is for the necessary characters only. \$\endgroup\$ Apr 30, 2020 at 2:37
  • 1
    \$\begingroup\$ Nice. I see that you have already included the reduced version as well. That would have been what I suggested, and it is generally best to include both versions. \$\endgroup\$
    – Wheat Wizard
    Apr 30, 2020 at 3:39
1
\$\begingroup\$

MAWP, 45 bytes

=M@![![32;1-]`M[42;1-]`M2+=M10;1-]`[32;1-]42;

Try it!

Takes a while for N bigger than 10

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

C++, 188 bytes

#include<iostream>    
using namespace std;
#define s string
int main(int a,char**c){int h=atoi(c[1]);for(int i=0;i<h;i++){cout<<s(h-i,' ')<<s(i*2+1,'*')<<endl;}cout<<s(h,' ')<<'*'<<endl;}

Ungolfed:

#include<iostream>

using namespace std;

int main(int a,char**c)
{
    int h = atoi(c[1]);
    for(int i=0; i<h; i++)
    {
        cout << string(h-i, ' ') << string(i*2+1, '*') << endl;
    }
    cout << string(h, ' ') << '*' << endl;
}
\$\endgroup\$
1
\$\begingroup\$

C# 3.0, 158 bytes

int n=int.Parse(a[0]);Console.WriteLine(Enumerable.Range(1,n).Concat(new int[]{1}).Select(x=>new string('*',x*2-1).PadLeft(x+n)).Aggregate((x,y)=>x+"\n"+y));

Ungolfed:

using System;
using System.Linq;
class Program
{
    static void Main(string[] a)
    {
        int n = int.Parse(a[0]);
        Console.WriteLine(Enumerable.Range(1, n).Concat(new int[] { 1 })
            .Select(x => new string('*', x * 2 - 1).PadLeft(x + n))
            .Aggregate((x, y) => x + "\n" + y));
    }
}
\$\endgroup\$
1
\$\begingroup\$

Lua, 113 significant chars

s=string.rep;n=tonumber(arg[1]);r=print;for i=0,n do l=s(" ", n-i)..s("*",(n-(n-i))*2+1);r(l)end r(s(" ",n).."*")
\$\endgroup\$
1
  • \$\begingroup\$ The two ns in s("*",(n-(n-i))*2+1) can be canceled out, yielding s("*",i*2+1). \$\endgroup\$ Dec 23, 2018 at 0:47
1
\$\begingroup\$

Rockstar, 107 bytes

listen to N
X's0
while N-X
let X be+1
let Y be N-X
let Z be X*2-1
say " "*Y+"*"*Z

let N be-1
say " "*N+"*"

Try it here (Code will need to be pasted in)

\$\endgroup\$
2
  • \$\begingroup\$ A good idea would be to append the name of a related rock song to each of your rockstar programs. \$\endgroup\$
    – Razetime
    Sep 23, 2020 at 16:56
  • \$\begingroup\$ Not a bad idea, @Razetime, I might just do that - I already use song names for all my challenge titles. Of course, if I was anyway skilled at such things, I'd actually write a song in Rockstar related to the challenge! \$\endgroup\$
    – Shaggy
    Sep 23, 2020 at 16:59
1
\$\begingroup\$

sed 4.2.2, 62 bytes, -r flag

s/0\B/ /g
:
H
s/ (0+)/0\10/
//b
:a
s/0(0+)0/ \1/
ta
H
x
y/0/*/

Takes input in unary (e.g. 3 is 000), allowed as per meta consensus.

Try it online!

With comments:

#Replace all zeroes except the last by a space
s/0\B/ /g
#Unnamed branch label
:
#Append to hold buffer
H
#Put zeroes around a stretch of zeroes
s/ (0+)/0\10/
#Jump to unnamed label if there are any spaces left
//b
#Create a label a, and recursively remove initial/final zeroes
:a
s/0(0+)0/ \1/
ta
#Append to hold buffer
H
#Exchange hold/pattern buffers
x
#Replace 0s with asterisks
y/0/*/
\$\endgroup\$
1
\$\begingroup\$

Ruby 2.7, 50 bytes

->h{t=(0...h).map{" "*(h-_1)+?**(_1*2+1)};t<<t[0]}

Try it online!

TIO uses an older version of Ruby, whereas in Ruby 2.7, we've numbered parameters, which saves a byte.

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

Pip, 18 bytes

@PPZsXa-_.'*X_M\,a

Try it online!

I don't know how pip recognizes this lambda, but it somehow does.

-3 from DLosc.

Explanation

YPPZsXa-_.'*X_M\,ay@0 a → input
              M\,a    map inclusive range of 0 - a, loop var '_'
    sXa-_             repeat space (input - _) times
         .'*X_        repeat * _ times
         .            join them:               
  PZ                  palindromize the result: ' ***' → ' ***** '
YP                    print each item of the array with newline
                      and assign the array to variable y
                  y@0 return first element of y (always a single *)
                      implicitly print it

@y cannot be used here, since it changes \,a in the first statement.

\$\endgroup\$
1
  • \$\begingroup\$ Nice! Here's 18 bytes, taking advantage of the fact that P returns its operand. \$\endgroup\$
    – DLosc
    Oct 12, 2021 at 5:31
1
\$\begingroup\$

Clojure, 214 bytes

(defn p[n](let[c(map #(inc(* % 2))(range n))l(map #(apply str %)(partition 2(interleave(map #(apply str(repeat(/ % 2)" "))(reverse c))(map #(apply str(repeat % "*"))c))))](doseq[a l](println a))(println(first l))))

Try it online!

Ungolfed:

(defn print-xmas-tree-of-height [n]
  (let [asterisk-counts       (map #(inc (* % 2)) (range n))
        asterisk-strings      (map #(apply str (repeat % "*")) asterisk-counts)
        leading-spaces        (map #(apply str (repeat (/ % 2) " ")) (reverse asterisk-counts))
        lines                 (map #(apply str %) (partition 2 (interleave leading-spaces asterisk-strings)))
        ]
    (doseq [aLine  lines]
      (println aLine))
    (println (first lines))))
\$\endgroup\$
2
  • \$\begingroup\$ I think you can make this a lambda instead of a named function \$\endgroup\$
    – Seggan
    Dec 1, 2022 at 21:29
  • \$\begingroup\$ @Seggan You can't use #() because you can't nest them, but you could do (fn[n](...)) \$\endgroup\$
    – naffetS
    Dec 2, 2022 at 2:50
1
\$\begingroup\$

Raku, 50 48 46 bytes

(45 characters, but » is 2 bytes)

{(|^$^n,0)».&{printf "%{$n+$_}s
",\*x$_*2+1}}

Try it online!

Original 50-byte version:

-> \n{(|^n,0)».&{printf "%{n+$_}s
",'*'x 2*$_+1}}

48-byte version:

-> \n{(|^n,0)».&{printf "%{n+$_}s
",\*x$_*2+1}}
\$\endgroup\$
4
  • \$\begingroup\$ '*' can be \*, instead of -> \n you can use a placeholder parameter ($^n) and you can rarrange the 2*$_+1 to have $_ first to save that space \$\endgroup\$
    – Jo King
    Dec 7, 2022 at 7:38
  • \$\begingroup\$ @jo Thanks! But I don't think I can use a placeholder, because I'm using it inside a nested block. \$\endgroup\$
    – Mark Reed
    Dec 7, 2022 at 17:05
  • \$\begingroup\$ You can, just don't add the ^ to the second instance of $n, like {(|^$^n,0)».&{printf "%{$n+$_}s ",\*x$_*2+1}} \$\endgroup\$
    – Jo King
    Dec 7, 2022 at 20:45
  • \$\begingroup\$ Oh! Well, then. Thanks again! \$\endgroup\$
    – Mark Reed
    Dec 7, 2022 at 21:28
0
\$\begingroup\$

Language: Erlang, Char count: 151

A little bit shorter Erlang version:

-module(x).
-export([t/1]).
t(N)->[H|_]=T=t(N,1),io:format([T,H]).
t(0,_)->[];t(N,M)->[[d(N,32),d(M,42),10]|t(N-1,M+2)].
d(N,C)->lists:duplicate(N,C).

When should run with command line argument

-module(x).
-export([t/1]).
t([N])->[H|_]=T=t(list_to_integer(N),1),io:format([T,H]),init:stop().
t(0,_)->[];t(N,M)->[[d(N,32),d(M,42),10]|t(N-1,M+2)].
d(N,C)->lists:duplicate(N,C).

Invocation:

$ erl -noshell -noinput -run x t 11
           *
          ***
         *****
        *******
       *********
      ***********
     *************
    ***************
   *****************
  *******************
 *********************
           *
\$\endgroup\$
0
\$\begingroup\$

GolfScript, 34 characters

Another GolfScript entry:

~:x,-1%[x(]+{." "*x@- 2*("*"*n.},;

Explanation:

~:x                   #read input, store into x
,                     #create array [0,1,2,...,x-1]
-1%                   #reverse it
[x(]+                 #append x-1 to the array
{." "*x@- 2*("*"*n.}, #map each element in array to this block, outputs each line
;                     #remove results of map from stack

The block does:

{.                    #duplicate value given by map (stack is now: i i)
" "*                  #push " ", times it by i (stack now: i "   ") 
x                     #push x, stack is: (i "   " x), and bring i
@                     #bring i to the front (stack is: "   " x i)
- 2*(                 #pop x,i, push ((x-i)*2-1)
"*"*                  #print that many *'s
n.}                   #print newline, duplicate it so the map doesn't kill it
\$\endgroup\$
0
\$\begingroup\$

JavaScript, 137 bytes

function k(a){var b="";for(i=0;i<a;i++){for(j=0;j<a*2;j++)b+=j>a-2-i
&&j<a+i?"*":" ";b+="\n"}for(i=0;i<a*2;i++)b+=i==a-1?"*":" ";return b}

Test case (formatting disorder is due to the first " marking a string):

k(3)

"  *   
 ***  
***** 
  *   "
\$\endgroup\$
0
\$\begingroup\$

Python 2, 119 116

This one generates the tree on one line:

import sys
h=int(sys.argv[1])
print '\n'.join([" "*(h-i)+"*"*(i*2-1) for i in range(h,0,-1)][::-1]+[" "*(h-1)+"*"])

It's too bad you have to import the sys module in Python before being able to read argv.

Being used from Command Prompt:

C:\Users\User4\Desktop>treeprint.py 6
     *
    ***
   *****
  *******
 *********
***********
     *

I have a Linux box but it can't connect to the Internet and only has Python 2.4, in case you're wondering why I'm using Windows.

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

SOGL V0.12, 11 10 bytes

ƨ*αak} *¹╚

Try it Here!

Explanation:

     }      implicitly started loop, repeated input times
ƨ*          push "**"
  α         append that to the variable A, here defaulted to an empty string
   a        load the variable A
    k       remove the first characters
       *    push "*"
        ¹   wrap in an array
         ╚  center horizontally
\$\endgroup\$
0
\$\begingroup\$

Excel VBA, 72 Bytes

Anonymous VBE immediate window function that takes input from range [A1] and outputs to the VBE immediate window

For i=1To[A1]:[B1]=i:?Spc([A1]-i)[Rept("*",2*B1-1)]:Next:?Spc([A1-1])"*"
\$\endgroup\$
0
\$\begingroup\$

Python 3, 83 bytes

f=lambda n:'\n'.join([' '*(n-1-i)+'*'*(i*2+1)for i in range(n)])+'\n'+' '*(n-1)+'*'
\$\endgroup\$
0
\$\begingroup\$

JavaScript, 90 89 bytes

f=(l,n=1,s="")=>l+1?s+=f(l-1,n+2,l?`*`.repeat(n).padStart(l+n)+`
`:"*".padStart(n/2+1)):s

Try it online!


Alternative:

f=(l,n=1)=>l+1&&f(l-1,n+2,console.log(l?"*".repeat(n).padStart(l+n):"*".padStart(n/2+1)))

Try it online!

\$\endgroup\$
1
  • 2
    \$\begingroup\$ There's a padStart function in JavaScript?? And who says you never learn anything useful in CodeGolf... \$\endgroup\$ Apr 30, 2020 at 6:59
0
\$\begingroup\$

x86 machine code, 42 40 bytes

Same limitation as in previous x86 answer (N < 10) applies. It may be lifted by replacing the first four lines with the following six (+6 bytes):

start:
    mov si, 82h
    lodsw
    xchg al, ah
    and ax, 0F0Fh
    aad

Assembly source code:

start:
    mov si, 82h
    lodsb
    aaa
    xchg ax, cx
    mov dx, 0A2Ah
    mov di, dx
    push cx
_loop:
    push cx
    rep stosb
    xchg ax, dx
    mov cx, bx
    rep stosb
    stosw
    inc bx
    inc bx
    pop cx
    xchg ax, dx
    loop _loop
    pop cx
    rep stosb
    xchg ax, dx
    stosw
    xchg ax, dx
    mov ax, 0924h
    stosb
    int 21h
    ret
\$\endgroup\$
0
\$\begingroup\$

SmileBASIC, 55 Bytes

Takes input from variable 'N'

FOR I=1TO N?" "*(N-I);"*"*(1+(I-1)*2)NEXT?" "*(N-1);"*"

I think it may be possible to shorten line 2 or 3 in the breakdown below

FOR I=1TO N                                                Iterate values of 'I' from 1 to N (One for each layer of branches)
           ?" "*(N-I)                                      Display spaces to offset asterisks, which begins at N-1 spaces long and end at 0 spaces long
                     ;"*"*(1+(I-1)*2)                      Display Asterisks
                                     NEXT                  End loop
                                         ?" "*(N-1);"*"    Display trunk
\$\endgroup\$
0
\$\begingroup\$

SAS, 70 87 bytes

87 bytes. With a pop window for N input.

data;
window _ n;
display _;
do i=1to n;
s=repeat('*',i*2-2);
put@(n-i+1)s;
end;
put@n'*';
run;

70 bytes. Imperfect, need to assign to N handly.

data;
n=9;
do i=1to n;
s=repeat('*',i*2-2);
put@(n-i+1)s;
end;
put@n'*';
run;

The result is

        *
       ***
      *****
     *******
    *********
   ***********
  *************
 ***************
*****************
        *
\$\endgroup\$
2
  • \$\begingroup\$ Do you have a link to this language? Is there really no way to take input? \$\endgroup\$
    – Jo King
    Dec 7, 2022 at 6:51
  • \$\begingroup\$ @JoKing It is relatively rarely used. SAS is a language to do statistical analysis. \$\endgroup\$
    – whymath
    Dec 7, 2022 at 7:09
1 2 3
4

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.