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

3
\$\begingroup\$

C# - Recursion

using System;

class A
{
    static string f(int n, int r)
    {
        return "\n".PadLeft(2 * r, '*').PadLeft(n + r) 
            + (r < n ? f(n, ++r) : "*".PadLeft(n));
    }

    static void Main(string[] a)
    {
        Console.WriteLine(f(int.Parse(a[0]), 1));
    }
}

177 chars (not as short the other C# method posted, but a different way of doing it).

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

c: 151 116 115

Just giving it a whirl

i,j,a;main(c,v)int**v;{for(a=atoi(v[1]);i<a;i+=puts(""))for(j=0;j<a+i;)putchar(++j<a-i?32:42);printf("%*s",a,"*");}

Readable code:

i, j, a; 
main(c, v) int **v; {
    for (a = atoi(v[1]); i < a; i += puts(""))
        for(j = 0; j < a + i;)
            putchar(++j < a - i ? 32 : 42);
    printf("%*s", a, "*");
}

Try it online!

Code History:

main(int c, char **v){
    int i, j, a = atoi(v[1]);
    for (i = 1; i <= a; i++) {
        for (j = 0; j < a + i - 1; j++)
            putchar((j >= a - i) ? '*' : ' ');
        putchar('\n');
    }
    printf("%*s*\n", a - 1, "");
}
\$\endgroup\$
4
  • 1
    \$\begingroup\$ Welcome to Code Golf! This is good for a first submission; however, I see some easy improvements you can make by simply removing unnecessary spaces and newlines. Also, can you provide a link to test this? It's missing #include<stdio.h> and I'm getting segfaults: link \$\endgroup\$
    – hyper-neutrino
    Nov 8, 2019 at 15:12
  • 1
    \$\begingroup\$ I think you're getting segfaults because you provided the number as an input rather than an argument link You also don't have to include the #include the compiler will yell at you but it will work. I left in the spaces because the challenge said to count characters ignoring whitespace and it makes it more readable \$\endgroup\$ Nov 8, 2019 at 18:48
  • 2
    \$\begingroup\$ Oh okay. That makes sense, sorry not a C user :P Thanks for the explanation. And yeah, my bad, I forgot about that part of this challenge (haven't visited it in a while). \$\endgroup\$
    – hyper-neutrino
    Nov 8, 2019 at 19:12
  • \$\begingroup\$ You can save another byte with ++j<a-i \$\endgroup\$
    – Jo King
    Nov 13, 2019 at 1:33
3
\$\begingroup\$

Poetic, 547 bytes

the triangle trees
a december i loved
o,i placed a fun christmasy thing
i know i am hoping on a santa,a gift,cookie plates,or bag o dolls
i know i am choosing my toy to expect of him,Mr.Claus
i say,Mr,i think i may ask nicely
we are nice people,we are
o,under the tree i go crazy as i glance at the a-b-c puzzle we got
a thing on Xmas i am happy to be toying with
o,i found it!for a moment,i shouted thanks
a gift i am having as we enjoy a holiday feast
and now i sleep
oh,here i am,silent as i could
i quickly awaken
i then go to locate a present

Try it online!

Translated from a version by Daniel Cristofani, but optimized specifically for program length in Poetic (more groups of > than <, more groups of + than -, etc).

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

05AB1E, 9 bytes

LĆ'*×j€û»

Try it online or verify all Christmas trees in the range [3, 30].

€û» can alternatively be ».º for the same byte-count: try it online.

9 bytes alternative:

·ÅÉĆ'*×.c

Try it online or verify all Christmas trees in the range [3, 30].

Explanation:

L          # Create a list in the range [1, (implicit) input]
           #  i.e. 3 → [1,2,3]
 Ć         # Enclose; appending its own head
           #  → [1,2,3,1]
  '*×     '# For each value, repeat the "*" that many times as string
           #  → ["*","**","***","*"]
     j     # Prepend spaces to make all items of a length equal to the (implicit) input
           #  → ["  *"," **","***","  *"]
      €û   # Palindromize each string
           #  → ["  *  "," *** ","*****","  *  "]
        »  # Join the list by newlines
           #  → "  *  \n *** \n*****\n  *  "
           # (after which it is output implicitly as result)

·          # Double the (implicit) input-integer
           #  i.e. 3 → 6
 ÅÉ        # Pop and push a list of all odd numbers <= this integer
           #  → [1,3,5]
   Ć       # Enclose; appending its own head
           #  → [1,3,5,1]
    '*×   '# For each value, repeat the "*" that many times as string
           #  → ["*","***","*****","*"]
       .c  # Centralize it by adding leading spaces (which implicitly joins by newlines)
           #  → "  *\n ***\n*****\n  *"
           # (after which it is output implicitly as result)
\$\endgroup\$
3
\$\begingroup\$

K (oK), 33 29 bytes

{(x+1)#(-x+!x)$(1+2*!x)#'"*"}

-4 thanks to streetser!

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ 29 bytes - {(x+1)#(-x+!x)$(1+2*!x)#'"*"} \$\endgroup\$
    – mkst
    May 9, 2020 at 21:16
  • \$\begingroup\$ @streetster, thanks. updated \$\endgroup\$
    – scrawl
    May 18, 2020 at 11:51
  • \$\begingroup\$ Can drop another byte by forgoing the $ pad: {" *"(x+1)#(|!x)(&,)'1+2*!x} \$\endgroup\$
    – coltim
    Dec 8, 2020 at 19:21
3
\$\begingroup\$

Charcoal, 9 bytes

G↗↘←N*M↓*

Try it online!

Verbose

Polygon(:UpRight, :DownRight, :Left, InputNumber(), "*")
Move(:Down)
Print("*")

Try it online!

\$\endgroup\$
3
  • 2
    \$\begingroup\$ 8 bytes \$\endgroup\$
    – Neil
    Apr 13, 2020 at 18:00
  • \$\begingroup\$ Why is this non-competing? \$\endgroup\$ Sep 23, 2020 at 14:42
  • \$\begingroup\$ this was before the rule change to allow languages made after the question; feel free to edit it \$\endgroup\$
    – ASCII-only
    Sep 24, 2020 at 15:47
3
\$\begingroup\$

><>, 67 bytes

1:{:v :,2+1{1p461<
v!?:<-1o*84
\~$
>:?!v67*o1-
+:}}\0?;~ao1-::?!v{2

Try it online!

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

Scala 3, char count 132 124

@main def t(n:Int)={def p(i:Int,j:Int):Unit={println(" "*i+"*"*j);if(i==0)println(" "*(j/2)+"*");else p(i-1,j+2);};p(n-1,1)}

Readable version

@main def t(n:Int) = 
  def p(i:Int, j:Int):Unit = 
    println(" " * i + "*" * j)
    if (i == 0) println(" " * (j / 2) + "*")
    else p(i - 1, j + 2)
  p(n - 1, 1)

Results

scala xmastree.scala 3
  *
 ***
*****
  *

scala xmastree.scala 5
    *
   ***
  *****
 *******
*********
    *

\$\endgroup\$
3
  • 3
    \$\begingroup\$ Welcome to Code Golf, and nice first answer! Can you shorten your code by removing the spaces/indentation? \$\endgroup\$ Dec 1, 2022 at 18:08
  • \$\begingroup\$ Welcome to Code Golf, and nice answer! \$\endgroup\$ Dec 1, 2022 at 19:25
  • \$\begingroup\$ In general we score answers in bytes, not characters. In this case the value seems to be the same. \$\endgroup\$
    – mousetail
    Dec 2, 2022 at 10:23
2
\$\begingroup\$

Language: Erlang, Char count: 183 (2 relevant spaces)

Here is an Erlang version, ~181chars:

-module (x).
-export ([t/1]).

t(N) ->
	t(N,0).
t(0,N) ->
	io:format("~s~s~n",[string:copies(" ",N),"*"]);
t(H,S) ->
	io:format("~s~s~n",[string:copies(" ",H),string:copies("*",(S*2)+1)]),
	t(H-1,S+1).

(btw, happy Christmas to everyone!)

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

Language: Scala, Char count: 128 (1 relevant space)

My Scala version. I'm glad I have found the * operator for strings (String implicitly promoted to RichString).

  def tree(n:Int) {
    def vals(n:Int,k:Int) = ((1 to n) map { i => (k - i, (i * 2) - 1) }).toList
    for(j <- vals(n,n) ::: vals(1,n)) 
      println(" " * j._1 + "*" * j._2)
  }
\$\endgroup\$
2
\$\begingroup\$

Language: Nemerle+Nextem, Char count: 129 (1 relevant space)

Nemerle with Nextem:

type s=string;
module t {
    public Main(a : array[s]) : void {
    	def t = int.Parse(a[0]);
    	def x(i) { print s(' ',t-i) + s('*',i*2+1) }
    	$[0..t].Iter(x);
    	x(0)
    }
}

Char count: 128

Edit: Made it take an arg Edit2: Imperative now

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

Here's how I would do it in Python, very straightforward, only 103 characters:

import sys
n=int(sys.argv[1])
for i in range(n): print ('*'*(2*i+1)).center(2*n)
print '*'.center(2*n)
\$\endgroup\$
2
\$\begingroup\$

Language: C, Char count: 433 (1 relevant space)

C version. Not short, not pretty, but it works.

#include <stdio.h>

void printLevel(int level, int width)
{
    int i;
    int count = level + (level - 1);
    int spaces = width - count;
    int lowerBound = spaces / 2;
    int upperBound = width - lowerBound;
    for (i = 0; i < width; i++) {
        if (i >= lowerBound && i < upperBound) {
            printf("*");
        } else {
            printf(" ");
        }
    }
    printf("\n");
}

void makeTree(int level)
{
    int i;
    int width = level * 2 - 1;
    for (i = 1; i <= level; i++) {
        printLevel(i, width);
    }
    printLevel(1, width);
}

int main(int argc, char **argv)
{
    int level = atoi(argv[1]);
    makeTree(level);
}
\$\endgroup\$
2
\$\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\$
2
\$\begingroup\$

Common Lisp, 117 essential characters:

(defun x (n)
  (dotimes (v n)
    (format t "~v:@<~v{*~}~>~%"
            (1- (* 2 n))
            (1+ (* 2 v))
            '(())))
  (format t "~v:@<*~>~%" (1-(* 2 n)))

Are there any format gurus out there who know a better way to get repeating arbitrary characters?

\$\endgroup\$
2
\$\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\$
2
\$\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\$
2
\$\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\$
2
\$\begingroup\$

Windows Batch File

Windows batch files have poor support for string operations: they can concatename, extract and replace strings, but generation of arbitrary-length strings according to a certain pattern AFAIK can only be done via loops. This is how Zach Scrivena's solution works.

However, one can notice that the N+1-th tree line can be generated from the N-th line by cutting one leading space off and adding two traling asterisks, which pretty much simplifies the task. Also, the tree truck repeats the tree top so we can re-use that string to get rid of a few extra loops. So, here's my batch file that uses these two tricks (165 characters):

@echo off
setlocal enableextensions enabledelayedexpansion
set s=
for /l %%i in (1,1,%1)do set s= !s!
set t=!s!*
for /l %%i in (1,1,%1)do echo !t!&set t=!t:~1!**
echo %s%*

Assuming that echo is already off and command extensions and delayed variable expansion are on, we can drop the first two lines and shorten the code down to 108 characters.

Usage:

> xmastree.bat 7 & pause
       * 
      *** 
     ***** 
    ******* 
   ********* 
  *********** 
 ************* 
       *
\$\endgroup\$
2
\$\begingroup\$

Haskell - 105 95 characters - 3 Relevant spaces

Improved on the other Haskell solution (https://codegolf.stackexchange.com/a/4267/7353) by 2 12 strokes.

  • Updated take x$cycle "*" into replicate x '*'
  • Removed unnecessary brackets

Updated version:

r=replicate;main=(\x->mapM_ putStrLn[r(x-l)' '++r(l+l-1)'*'|l<-[1..x]++[1]])=<<(readLn::IO Int)

Previous version:

c=cycle;main=(\x->mapM_ putStrLn[(take(x-l)$c" ")++(take(l+l-1)$c"*")|l<-[1..x]++[1]])=<<(readLn::IO Int)

Readable (updated) version:

main=(\ size->
          mapM_
               putStrLn
               [replicate (size - count) ' ' ++ replicate (count + count - 1) '*' | count <- [1..size] ++ [1]]
     ) =<< ( readLn :: IO Int )

Haskell is such an elegant language.

\$\endgroup\$
2
\$\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\$
2
\$\begingroup\$

K 33

q)k)f:{{(|:'x),'1_'x}x$(1+(!x),0)#'"*"}
q)f 4
"   *   "
"  ***  "
" ***** "
"*******"
"   *   "
\$\endgroup\$
2
\$\begingroup\$

Python - 104 / 94 characters

Alright, so I have two solutions here. One of them is, I guess, a bit "trickier", placing all of the code on one line, while the other solution is actually shorter.

import sys
c=int(sys.argv[1])
for i in range(c+2):print" "*(c-1)+"*"if i==c+1 else" "*(c-i)+"*"*(2*i-1)

That's the 104-char version. Who said python is always readable? It doesn't use any "tricks" though, which is a plus, I guess? If we split the if/else statement onto a seperate line like so:

import sys
c=int(sys.argv[1])
for i in range(c+1):print" "*(c-i)+"*"*(2*i-1)
print" "*(c-1)+"*"

...this is much neater and is actually a few characters shorter.

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

JavaScript (ES6), 58 bytes

f=(n,s=`*
`,l)=>n?(k=' '.repeat(--n)+s)+f(n,'**'+s,l||k):l

Demo

f=(n,s=`*
`,l)=>n?(k=' '.repeat(--n)+s)+f(n,'**'+s,l||k):l

console.log(f(7))

\$\endgroup\$
2
\$\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\$
2
\$\begingroup\$

Python 2 - 62 Bytes:

i,x=input()*2,1
exec"print('*'*(x%i)).center(i);x+=2;"*(i/2+1)

Multiplying the input by two saves a byte because of the need for extra brackets.
There may be a way to further golf the operations.

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

Python 2, 56 bytes

i=n=input()
exec"i=~-i%n;print' '*i+'*'*(n*2-i+~i);"*-~n

Try it online!

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

Perl 6, 39 bytes

{say " "x$^a-$_,\*x$_*2-1 for 1...$a,1}

Try it online!

It's one of those questions, where it's easier to just print the lines in the code block.

Explanation:

{say " "x$^a-$_,\*x$_*2-1 for 1...$a,1}
{                                     }   # Anonymous code block
                          for 1...$a,1    # Loop over 1 to n and 1 again
 say                                      # Print
     " "x$^a-$_                           # Leading spaces
               ,\*x$_*2-1                 # And then the amount of asterisks
\$\endgroup\$
2
\$\begingroup\$

05AB1E (legacy), 16 10 bytes

L·<'**Ć.c»

Try it online!

Explanation:

L·<'**Ć.c»
L          : Create a range [1..input]
 ·<        : 2n-1 every element
   '**     : Multiply every element with "*"
      Ć    : Append the first element to the end
       .c  : Centralize elements
         » : Print out with newlines

Previous solution:

µ¾·>'**¼})Ć.c»

Try it online!

Explanation:

µ¾·>'**I¾-ú¼})Ć»
 ¾·>'**I¾-ú      : Create the row with padding and push to stack
           ¼     : Increment the counter
µ           }    : Loop until the counter reaches the input
             )   : Enclose stack to a list
              Ć  : Append the head to the end
               » : Print out the stack with newlines
\$\endgroup\$
1
  • 2
    \$\begingroup\$ No need to mark as noncompeting \$\endgroup\$
    – ASCII-only
    Dec 23, 2018 at 4:21
2
\$\begingroup\$

Bash: 126120

As there is no purpose, there is one:

for((z=$1-1;z;z--)){ printf -v s "%$((($1-z)*2-1))s" ""
printf "%$((2*$1-z))s\n" "${s// /*}";};printf "%$((1+$1))s\n" \*

This could be written:

#!/bin/bash
               #
              for\
            ((z=$1-
          1;z;z--));do
        printf -v s "%$((
     ($1-z)*2-1))s" "" #fil
   printf "%$((2*$1-z))s\n" \
 "${s// /*}";done;printf "%$((1
          +$1))s\n"\
              \*
              ##

In use:

set -- 12
for((z=$1-1;z;z--)){ printf -v s "%$((($1-z)*2-1))s" ""
printf "%$((2*$1-z))s\n" "${s// /*}";};printf "%$((1+$1))s\n" \*
            *
           ***
          *****
         *******
        *********
       ***********
      *************
     ***************
    *****************
   *******************
  *********************
            *

Or into the script:

./chrismas.sh 6
      *
     ***
    *****
   *******
  *********
      *
\$\endgroup\$
3

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.