110
\$\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
\$\begingroup\$

PHP (133 relevant characters):

function xmastree($h) {
    for($i=0;$i<$h;++$i)
        echo str_repeat(' ',$h-$i-1).str_repeat('*',2*$i+1)."\n";
    echo str_repeat(' ',$h-1)."*\n";
}
\$\endgroup\$
1
\$\begingroup\$

Language: Pike

101 Relevant characters

int main (int c, array a) {
    int n=(int)a[1], i,l;
    for(;i<=n; l = ++i < n ? i : 0)
        write(" " *(n-l) + "*" * (l*2+1) +"\n");
}
\$\endgroup\$
1
\$\begingroup\$

Rhino Javascript shell: 117 chars minified

t=['*'];
for(i=1;i<arguments[0];++i)
{
  s='*'+t[i-1]+'*';
  for(j in t) 
    t[j]=' '+t[j];
  t[i]=s;
}
t[i]=t[0];print(t.join('\n'));

minified:

t=['*'];for(i=1;i<arguments[0];++i){s='*'+t[i-1]+'*';for(j in t) t[j]=' '+t[j];t[i]=s;}t[i]=t[0];print(t.join('\n'));

results:

c:\>java -jar C:\appl\Java\rhino1_7R1\js.jar c:/tmp/Xtree.js 10
         *
        ***
       *****
      *******
     *********
    ***********
   *************
  ***************
 *****************
*******************
         *
\$\endgroup\$
1
\$\begingroup\$

Language: Php, Char count: 110 (3 relevant spaces)

<? function x($n,$a,$t){return $n?str_repeat(' ',$n).$a.x($n-1,"*$a"," $t"):$t;}echo x($argv[1],"\n","*\n");

A bit of php recursion to reduce the count of chars to 110.

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

FreePascal:

program xmastree;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes
  { you can add units after this };

var x,y,h:integer;

{$IFDEF WINDOWS}{$R xmastree.rc}{$ENDIF}

procedure printRow(sp,st:integer);
var i:integer;
begin
    for i := 1 to sp do begin
    write(' ');
  end;
    for x := 1 to st do begin
    write('*');
  end;
    for x := 1 to sp do begin
    write(' ');
  end;
    writeln();
end;

begin
    val(ParamStr(1),h);
  for y := 1 to h do begin
    printRow(h-y,(y-1)*2+1);
  end;
  printRow(h-1,1);
end.

Output for xmastree.exe 9

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

Language: C, Char count: 116

I realized I could improve on my original design:

main(int c,char**v){char l[99],i=0;for(c=atoi(1[v]);i<c;printf("%*s%.*s\n",c,l,i++,l))l[i]=42;printf("%*c\n",c,42);}

Different approach (119 characters):

s[99],w,i=0;p(n){printf("%*.*s\n",w+n,n*2+1,s);}main(int c,char**v){w=atoi(v[1]);for(memset(s,42,99);i<w;p(i++));p(0);}

Old version (123 characters):

main(int c,char**v){char*l=calloc(c=atoi(v[1]),2),i=0;for(;i<c;printf("%*s%.*s\n",c,l,i++,l))l[i]=42;printf("%*c\n",c,42);}

(One byte can be saved by putting char *l=... in the for loop. That makes it non-standard, however (though gcc still accepts it).)

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

VBScript, 106 characters

n = WScript.Arguments(0)
For i = 1 To n
  WScript.Echo Space(n-i+1) & String(2*i-1, "*")
Next
WScript.Echo Space(n) & "*"

Usage and output example:

> cscript christmastree.vbs 7 //nologo
       *
      ***
     *****
    *******
   *********
  ***********
 *************
       *
\$\endgroup\$
1
\$\begingroup\$

Golfscript - 27 chars

~:i,0+{.i\-(' '*\.)+'*'*n}%

~:i  # eval the command line arg, store in i  
,0+  # create a list [0..i-1] add 0 to the end  
{}%  # map this block over the list  
.    # make a copy of the list element 
i\-  # subtract the list element from i 
(    # decrease by one more  
' '* # multiply the result by ' '
\    # swap, so the list element is back on top of stack
.)+  # duplicate, add one, add the two numbers together
'*'* # multiply the result by '*'
n    # put a newline here
\$\endgroup\$
1
  • \$\begingroup\$ nice, i did mine before seeing yours, was about to refactor it to look like this \$\endgroup\$
    – Claudiu
    Jun 10, 2010 at 6:29
1
\$\begingroup\$

Q, 54

{-1(-:)[((x+(!)x),x)]$(((&)((!)(2*x))mod 2),1)#\:"*";}

example:

q){-1(-:)[((x+(!)x),x)]$(((&)((!)(2*x))mod 2),1)#\:"*";} 10
         *
        ***
       *****
      *******
     *********
    ***********
   *************
  ***************
 *****************
*******************
         *
\$\endgroup\$
1
\$\begingroup\$

This is my first experience with code golf. So advices are welcome :)

C: 170 chars:

int main(){
    int n,m=1,x;
    scanf("%d",&n);x=2*n-1;
    for(;m<x*n+n+2;m++)
        printf("%c",m==x*n|m==x*n+n+1?42:m==x*n+1?10:m>x*n?32:!(m%(2*n-1))?10:!(m%x<n-m/x)&m%x<m/x+n+1?42:32);
}
\$\endgroup\$
1
\$\begingroup\$

It's in PHP.

<center><?$t=$_GET[1]*2-$i=1;while($i<=$t){echo str_repeat('*',$i).'<br>';$i+=2;}echo'*'?><center>

Total characters(with spaces):98 Total characters(with no spaces):97 Bytes:98

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

I did not see a solution using R. The code below may not be efficient, but it seems to work (170 characters with spaces if all code placed on one line):

for(i in 1:4){ cat( paste( paste(rep(' ', (3-(i-1))), collapse=''), 
                           paste(rep('*', (2*i-1)),   collapse=''), collapse=''),  
               sep='\n'); if(i==4) cat('    *    ', sep='\n')}


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

Javascript, 89

i=4
c=t=""
while(i){o=c,j=(i--+1)*2-3
while(j--)o+="*"
t=o+"\n"+t
c+=" "}console.log(t+o)

Javascript 81

o=s=''
for(a=3;a--;){l=s+=' '
for(k=a*2+1;k--;)l+='*'
o=l+'\n'+o}console.log(o+l)
\$\endgroup\$
1
\$\begingroup\$

><>: 136 chars

This one's not going to win, but because Christmas is coming again, I thought fish needed a Christmas tree too! (pun intended)

1-:&1$>:> :1(?!v~$:> :1(?!vv
        ^-1o" "<   ^-1o"*"<>~2+$1-:0(?!v~~&ao>" "o1-v
      ^                              oa<;o"*"^!?(1: <

It can be run as follows with the standard interpreter:

./fish.py christmas.fish -v 5

... for N=5. (If the file is called christmas.fish :P) In this way, one prepopulates the stack with the value 5. This is the closest I could get to a command-line argument.

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

JavaScript, 110 characters (2 relevant spaces)

function p(l)
{
    o=''
    for(c=0; c<=n+l; c++)
      o += c < n - l ? ' ' : '*'
    print(o)
}

n = parseInt(arguments[0])

for(l = 0; l < n; l++)
  p(l)
p(0)

Ran using spidermonkey. $ smjs christmas_tree.js 4

For Javascript Console 105

function p(l){o='';for(c=0;c<=n+l;)o+=c++<n-l?' ':'*';console.log(o)}n=+prompt();for(l=0;l<n;)p(l++);p(0)
\$\endgroup\$
1
\$\begingroup\$

Scala, 73 chars

val n=args(0).toInt
(1 to n):+1 foreach(i=>println(" "*(n-i)+"*"*(2*i-1)))

run as

golf.scala 10
\$\endgroup\$
2
  • \$\begingroup\$ Wait, does that display the trunk? \$\endgroup\$ Dec 12, 2013 at 19:56
  • \$\begingroup\$ yes, :+1 would do that \$\endgroup\$
    – prashanth
    Dec 12, 2013 at 20:05
1
\$\begingroup\$

Japt, 11 bytes

õ_ç* êÃp* û

Try it online!

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

Japt -R, 11 bytes

ÇÑÄ î*Ãp* û

Try it

Ç               :Map the range [0,input)
 Ñ              :  Multiply by 2
  Ä             :  Add 1
    î*          :  Repeat * that many times
      Ã         :End map
       p*       :Push a *
          û     :Centre pad each element with spaces to the length of the longest
                :Implicitly join with newlines
\$\endgroup\$
1
\$\begingroup\$

Lua, 100 99 bytes

p,r,n=io.write,('').rep,arg[1]for i=0,n do p(r(' ',n-i+1),r('*',i*2+1),'\n')end p(r(' ',n+1),'*\n')

Try it online!

Another Lua version, a little shorter.

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

PHP, 79 bytes

while($argn)echo$r[]=str_pad("
",1+$argn--).str_pad("",++$n*2-1,"*");echo$r[0];

Run as pipe with -nR or try it online.

\$\endgroup\$
1
  • \$\begingroup\$ Save 2 bytes using variable variables: Try it online! \$\endgroup\$
    – Night2
    Oct 13, 2019 at 13:50
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\$

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\$

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

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.