Tell me more ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

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 min val of 3, and a max val 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 whitespace 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 SO!

share|improve this question
2  
I believe the J version is the winner and should be chosen as the answer. – tzot Apr 1 '10 at 19:16

migrated from stackoverflow.com Dec 10 '11 at 22:16

63 Answers

1 2 3
up vote 57 down vote accepted

Language: Perl, Char count: 50 (1 relevant spaces)

perl: one line version:

print$"x($a-$_),'*'x($_*2+1),$/for 0..($a=pop)-1,0

and now with more whitesapce:

print $"  x ( $a - $_ ),             #"# Syntax Highlight Hacking Comment
      '*' x ( $_ * 2  + 1),
      $/
for 0 .. ( $a = pop ) - 1, 0;

$ perl tree.pl 3
   *
  ***
 *****
   *
$ perl tree.pl 11
           *
          ***
         *****
        *******
       *********
      ***********
     *************
    ***************
   *****************
  *******************
 *********************
           *
$

Expanded Explanation for Non-Perl Users.

# print $Default_List_Seperator ( a space )  
#     repeated ( $a - $currentloopiterationvalue ) times,
print $" x ( $a - $_ ), 
#"# print '*' repeated( $currentloopiteration * 2 + 1 ) times. 
  '*' x ( $_ * 2  + 1),
# print $Default_input_record_seperator ( a newline )
  $/
# repeat the above code, in a loop, 
#   iterating values 0 to ( n - 1) , and then doing 0 again
for 0 .. ( $a = pop ) - 1, 0;
# prior to loop iteration, set n to the first item popped off the default list, 
#   which in this context is the parameters passed on the command line.
share|improve this answer
20  
Holy crap... perl truly is unreadable. – zenazn Dec 25 '08 at 17:20
6  
@zenazn, also, it should be noticed that most golfing is BAD code in any language. If this were a competition for the cleanest code, we could win that too. – Kent Fredric Dec 25 '08 at 17:23
5  
@zenazn: proof, you can see us collaborating and improving each others code above, this proves WE can read EACH OTHERS code perfectly fine. – Kent Fredric Dec 25 '08 at 17:28
1  
PS: Thanks for the explanation for non-Perl programmers. It's still pretty unreadable, but at least it makes sense. I guess you get used to it after a while. – zenazn Dec 25 '08 at 18:11
2  
@RobH: J is the child of APL. In some senses, it's more unreadable because it doesn't use APL's character set with a special symbol for every operation -- it overloads ASCII characters with multiple meanings, instead. stackoverflow.com/questions/392788/1088931#1088931 – ephemient Jul 6 '09 at 20:01
show 21 more comments

Language: Brainfuck, Char count: 240

              ,
             >++
            +++++
           +[-<---
          --->],[>+
         +++++++[-<-
        ----->]<<[->+
       +++++++++<]>>]<
      [->+>+>>>>>>>+<<<
     <<<<<<]>>>>++++++++
    [-<++++>]>++++++[-<++
   +++++>]+>>>++[-<+++++>]
  <<<<<<[-[>.<-]<[-<+>>+<]<
 [->+<]>>>>>[-<.>>+<]>[-<+>]
>.<<++<<<-<->]>>>>>>>-[-<<<<<
           <.>>>
           >>>]<
           <<<<.

Not yet done. It works, but only with single-digit numbers.

EDIT: Done! Works for interpreters using 0 as EOF. See NOTEs in commented source for those with -1.

EDIT again: I should note that because Brainfuck lacks a standard method for reading command line arguments, I used stdin (standard input) instead. ASCII, of course.

EDIT a third time: Oh dear, it seems I stripped . (output) characters when condensing the code. Fixed...

Here's the basic memory management of the main loop. I'm sure it can be heavily optimized to reduce the character count by 30 or so.

  1. Temporary
  2. Copy of counter
  3. Counter (counts to 0)
  4. Space character (decimal 32)
  5. Asterisk character (decimal 42)
  6. Number of asterisks on current line (1 + 2*counter)
  7. Temporary
  8. New line character
  9. Temporary?
  10. Total number of lines (i.e. input value; stored until the very end, when printing the trunk)

Condensed version:

,>++++++++[-<------>],[>++++++++[-<------>]<<[->++++++++++<]>>]<[->+>+>>>>>>>+<<<<<<<<<]>>>>++++++++[-<++++>]>++++++[-<+++++++>]+>>>++[-<+++++>]<<<<<<[-[>.<-]<[-<+>>+<]<[->+<]>>>>>[-<.>>+<]>[-<+>]>.<<++<<<-<->]>>>>>>>-[-<<<<<<.>>>>>>]<<<<<.

And the pretty version:

ASCII to number
,>
++++++++[-<------>]  = 48 ('0')

Second digit (may be NULL)
,
NOTE:   Add plus sign here if your interpreter uses negative one for EOF
[ NOTE: Then add minus sign here
 >++++++++[-<------>]
 <<[->++++++++++<]>>  Add first digit by tens
]

Duplicate number
<[->+>+>>>>>>>+<<<<<<<<<]>>

Space char
>>++++++++[-<++++>]

Asterisk char
>++++++[-<+++++++>]

Star count
+

New line char
>>>++[-<+++++>]<<<

<<<

Main loop
[
Print leading spaces
-[>.<-]

Undo delete
<[-<+>>+<]
<[->+<]
>>

Print stars
>>>[-<.>>+<]

Add stars and print new line
>[-<+>]
>.<
<++

<<<

-<->
End main loop
]

Print the trunk
>>>>>>>
-[-<<<<<<.>>>>>>]
<<<<<.

Merry Christmas =)
share|improve this answer
2  
+1 Excellent work!! – CMS Jan 1 '09 at 21:18
show 2 more comments

J

24 characters.

(,{.)(}:@|."1,.])[\'*'$~

   (,{.)(}:@|."1,.])[\'*'$~5
    *    
   ***   
  *****  
 ******* 
*********
    *    

Explanation:

'*'$~5
*****

[\'*'$~5
*    
**   
***  
**** 
*****

Then }:@|."1 reverses each row and strips off the last column, and ,. staples it to ].

Then ,{. pastes the first column onto the bottom.

Previous entries:

29 characters, no spaces at all.

   ((\:i.@#),}.)"1$&'*'"0>:0,~i.3
  *
 ***
*****
  *
   ((\:i.@#),}.)"1$&'*'"0>:0,~i.11
          *
         ***
        *****
       *******
      *********
     ***********
    *************
   ***************
  *****************
 *******************
*********************
          *

   NB. count from 1 to n, then 1 again
   >:0,~i.3
1 2 3 1
   NB. replicate '*' x times each
   $&'*'"0>:0,~i.3
*
**
***
*
   NB. reverse each row
   (\:i.@#)"1$&'*'"0>:0,~i.3
  *
 **
***
  *
   NB. strip off leading column
   }."1$&'*'"0>:0,~i.3

*
**

   NB. paste together
   ((\:i.@#),}.)"1$&'*'"0>:0,~i.3
  *
 ***
*****
  *
share|improve this answer
3  
What, do you guys use some sort of J documentation library to understandable-ize the code? :) – RCIX Nov 20 '09 at 1:14
show 1 more comment

Language: Python (through shell), Char count: 64 (2 significant spaces)

python -c "
n=w=$1
s=1
while w:
    print' '*w+'*'*s
    s+=2
    w-=1
print' '*n+'*'"

$ sh ax6 11
           *
          ***
         *****
        *******
       *********
      ***********
     *************
    ***************
   *****************
  *******************
 *********************
           *
share|improve this answer
5  
what I like most about this solution is that python makes it really hard to write obscure code, it's one of the most readable solutions – Georg Schölly Dec 26 '08 at 0:46
3  
This is how I did it before. The spirit of this question is to have fun, and in addition there was no specification of using only one language :) See the brainfuck answer, for example; no arguments. – tzot Dec 26 '08 at 20:56
show 1 more comment

Language: Windows Batch Script (shocking!)

@echo off
echo Enable delayed environment variable expansion with CMD.EXE /V

rem Branches
for /l %%k in (1,1,%1) do (
set /a A=%1 - %%k
set /a B=2 * %%k - 1
set AA=
for /l %%i in (1,1,!A!) do set "AA=!AA! "
set BB=
for /l %%i in (1,1,!B!) do set BB=*!BB!
echo !AA!!BB!
)

rem Trunk
set /a A=%1 - 1
set AA=
for /l %%i in (1,1,!A!) do set "AA=!AA! "
echo !AA!*
share|improve this answer
1  
Delayed variable expansion can be enabled using the setlocal enabledelayedexpansion command. – Helen Jul 30 '09 at 17:49
show 3 more comments

Language: Ruby, Char count: 64

n=ARGV[0].to_i
((1..n).to_a+[1]).each{|i|puts' '*(n-i)+'*'*(2*i-1)}

n=$*[0].to_i
((1..n).to_a<<1).each{|i|puts' '*(n-i)+'*'*(2*i-1)}

Merry Christmas all!

Edit: Improvements added as suggested by Joshua Swink

share|improve this answer
show 8 more comments

Language: x86 asm 16-bit, Byte count: 50

No assembly version yet? :)

	bits 16
	org 100h

	mov si, 82h
	lodsb
	aaa
	mov cx, ax
	mov dx, 1
	push cx 
	mov al, 20h
	int 29h
	loop $-2
	push dx
	mov al, 2ah
	int 29h
	dec dx
	jnz $-3
	pop dx
	mov al, 0ah
	int 29h
	inc dx
	inc dx
	pop cx
	loop $-23
	shr dx, 1
	xchg cx, dx
	mov al, 20h
	int 29h
	loop $-2
	mov al, 2ah
	int 29h
	ret

(Note: N is limited to 1 - 9 in this version)

G:\>tree 9
         *
        ***
       *****
      *******
     *********
    ***********
   *************
  ***************
 *****************
         *

Download here

share|improve this answer

Language: C#, Char count: 120

static void Main(string[] a)
{
    int h = int.Parse(a[0]);

    for (int n = 1; n < h + 2; n++)
        Console.WriteLine(n <= h ?
            new String('*', n * 2 - 1).PadLeft(h + n) :
            "*".PadLeft(h + 1));
    }
}

Just the code, without formatting (120 characters):

int h=int.Parse(a[0]);for(int n=1;n<h+2;n++)Console.WriteLine(n<=h?new String('*',n*2-1).PadLeft(h+n):"*".PadLeft(h+1));

Version with 109 characters (just the code):

for(int i=1,n=int.Parse(a[0]);i<n+2;i++)Console.WriteLine(new String('*',(i*2-1)%(n*2)).PadLeft((n+(i-1)%n)));

Result for height = 10:

          *
         ***
        *****
       *******
      *********
     ***********
    *************
   ***************
  *****************
 *******************
          *
share|improve this answer

python, "-c" trick... @61 chars (and one line)

python -c"for i in range($1)+[0]:print' '*($1-i)+'*'*(2*i+1)"
share|improve this answer
show 1 more comment

Language: dc (through shell) Char count: 83

A little bit shorter dc version:

dc -e '?d1rdsv[d32r[[rdPr1-d0<a]dsaxszsz]dsbx1-rd42rlbx2+r10Plv1-dsv0<c]dscxszsz32rlbx[*]p' <<<$1

EDIT: changed constant 10 into $1

share|improve this answer
11  
Good lord, what the hell is that? – amischiefr Aug 6 '09 at 18:34
1  
Just read man page ;-) – Hynek -Pichi- Vychodil Aug 8 '09 at 5:54

Here's a reasonably space-efficient Haskell version, at 107 characters:

main=interact$(\g->unlines$map(\a->replicate(g-a)' '++replicate(a*2-1)'*')$[1..g]++[1]).(read::[Char]->Int)

running it:

$ echo 6 | runhaskell tree.hs
     *
    ***
   *****
  *******
 *********
***********
     *

Merry Christmas, all :)

share|improve this answer

Language: dc (through shell), Char count: 119 (1 significant space)

Just for the obscurity of it :)

dc -e "$1dsnsm"'
[[ ]n]ss
[[*]n]st
[[
]n]sl
[s2s1[l2xl11-ds10<T]dsTx]sR
[lndlslRxlcdltlRxllx2+sc1-dsn0<M]sM
1sclMxlmlslRxltxllx
'

$ sh ax3 10
          *
         ***
        *****
       *******
      *********
     ***********
    *************
   ***************
  *****************
 *******************
          *
share|improve this answer
show 2 more comments

Ridiculously long C++ one:

#include <iostream>
#include <conio.h>

using namespace std;

class CTree
{
// Members
private:
    unsigned short m_Lvl;
    unsigned short m_Spc;

// Construction
public:
    CTree(unsigned short lvl)
        : m_Lvl(lvl), m_Spc(0) {}
private:
    CTree(unsigned short lvl, unsigned short spc)
        : m_Lvl(lvl), m_Spc(spc) {}

// Operations
public:
    void Print()
    {
        // Print the leaves.
        if (m_Lvl)
        {
            CTree(m_Lvl-1 , m_Spc+1).Print();
            Line();
        }

        // Print the trunk.
        if (!m_Spc)
            CTree(1 , m_Lvl ? (m_Lvl - 1) : 0).Line();
    }
private:
    void Line()
    {
        // Indent the current line.
        for (unsigned short s = m_Spc; s--; )
            cout << ' ';

        // Print the leaves.
        for (unsigned short l = m_Lvl; --l; )
            cout << '*' << '*';
        cout << '*' << endl;
    }
};

int main(int argc, char** argv)
{
    // Validate the command line.
    if ((argc != 2) || !isdigit(argv[1][0]))
    {
        cout << "Command line: tree.exe number_of_lines";
        _getch();
        exit(1);
    }

    // Validate the number of lines.
    short lvl = (short)atoi(argv[1]);
    if (lvl < 0)
    {
        cout << "Do you really think " << lvl << " lines can be printed?";
        _getch();
        exit(1);
    }
    if (lvl > 40)
    {
        cout << "Sorry, but a " << lvl << "-line tree is too big to be printed.";
        _getch();
        exit(1);
    }

    // Print the tree.
    CTree((unsigned short)lvl).Print();

    // The user must press a key before the program finishes.
    _getch();
    return 0;
}


EDIT: I must add that this program doesn't follow the specifications exactly. When the input argument is N, it prints a (N+1)-line tree.

Merry X-Mas to the SO community


EDIT: Debugged the program and corrected some nasty errors.

share|improve this answer
4  
conio.h? nooo! :) – Nazgob Dec 26 '08 at 11:49

Better C++, around 210 chars:

#include <iostream>
using namespace std;
ostream& ChristmasTree(ostream& os, int height) {
    for (int i = 1; i <= height; ++i) {
        os << string(height-i, ' ') << string(2*i-1, '*') << endl;
    }
    os << string(height-1, ' ') << '*' << endl;
    return os;
}

Minimized to 179:

#include <iostream>
using namespace std;ostream& xmas(ostream&o,int h){for(int i=1;i<=h;++i){o<<string(h-i,' ')<<string(2*i-1,'*')<<endl;}o<<string(h-1,' ')<<'*'<<endl;return o;}
share|improve this answer
show 3 more comments

Improving ΤΖΩΤΖΙΟΥ's answer. I can't comment, so here is a new post. 72 characters.

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

Using the "python -c" trick, 61 characters.

python -c "
for i in range($1)+[0]:
   print ('*'*(2*i+1)).center(2*$1)
"

I learned the center function and that "python -c" can accept more than one line code. Thanks, ΤΖΩΤΖΙΟΥ.

share|improve this answer

C# using Linq:

    using System;
    using System.Linq;
    class Program
        {
            static void Main(string[] args)
            {
                int n = int.Parse(args[0]);
                int i=0;
                Console.Write("{0}\n{1}", string.Join("\n", 
                   new int[n].Select(r => new string('*',i * 2 + 1)
                   .PadLeft(n+i++)).ToArray()),"*".PadLeft(n));
            }
       }

170 charcters.

int n=int.Parse(a[0]);int i=0;Console.Write("{0}\n{1}",string.Join("\n",Enumerable.Repeat(0,n).Select(r=>new string('*',i*2+1).PadLeft(n+i++)).ToArray()),"*".PadLeft(n));
share|improve this answer

Language: python, no tricks, 78 chars

import sys
n=int(sys.argv[1])
for i in range(n)+[0]:print' '*(n-i)+'*'*(2*i+1)
share|improve this answer

Language: Java, Char count: 219

class T{ /* 219 characters */
  public static void main(String[] v){
    int n=new Integer(v[0]);
    String o="";
    for(int r=1;r<=n;++r){
      for(int s=n-r;s-->0;)o+=' ';
      for(int s=1;s<2*r;++s)o+='*';
      o+="%n";}
    while(n-->1)o+=' ';
    System.out.printf(o+"*%n");}}

For reference, I was able to shave the previous Java solution, using recursion, down to 231 chars, from the previous minimum of 269. Though a little longer, I do like this solution because T is truly object-oriented. You could create a little forest of randomly-sized T instances. Here is the latest evolution on that tack:

class T{ /* 231 characters */
  public static void main(String[] v){new T(new Integer(v[0]));}}
  String o="";
  T(int n){
    for(int r=1;r<=n;++r){
      x(' ',n-r);x('*',2*r-1);o+="%n";}
    x(' ',n-1);
    System.out.printf(o+"*%n");
  }
  void x(char c,int x){if(x>0){o+=c;x(c,x-1);}
 }
share|improve this answer
show 1 more comment

Groovy 62B

n=args[0]as Long;[*n..1,n].any{println' '*it+'*'*(n-~n-it*2)}

_

n = args[0] as Long
[*n..1, n].any{ println ' '*it + '*'*(n - ~n - it*2) }
share|improve this answer

Language: C, Char count: 133

Improvement of the C-version.

char s[61];

l(a,b){printf("% *.*s\n",a,b,s);}

main(int i,char**a){
  int n=atoi(a[1]);memset(s,42,61);
  for(i=0;i<n;i++)l(i+n,i*2+1);l(n,1);
}

Works and even takes the tree height as an argument. Needs a compiler that tolerates K&R-style code.

I feel so dirty now.. This is code is ugly.

share|improve this answer
show 4 more comments

AWK, 86 characters on one line.

awk '{s="#";for(i=0;i<$1;i++){printf"%"$1-i"s%s\n","",s;s=s"##"}printf"%"$1"s#\n",""}'

echo "8" | awk '{s="#";for(i=0;i<$1;i++){printf"%"$1-i"s%s\n","",s;s=s"##"}printf"%"$1"s#\n",""}'
        #
       ###
      #####
     #######
    #########
   ###########
  #############
 ###############
        #

cat tree.txt
3
5

awk '{s="#";for(i=0;i<$1;i++){printf"%"$1-i"s%s\n","",s;s=s"##"}printf"%"$1"s#\n",""}' tree.txt
   #
  ###
 #####
   #
     #
    ###
   #####
  #######
 #########
     #
share|improve this answer

Language: C, Char count: 176 (2 relevant spaces)

#include <stdio.h>
#define P(x,y,z) for(x=0;x++<y-1;)printf(z);
main(int c,char **v){int i,j,n=atoi(v[1]);for(i=0;i<n;i++){P(j,n-i," ")P(j,2*i+2,"*")printf("\n");}P(i,n," ")printf("*\n");}
share|improve this answer

Language: Python, Significant char count: 90

It's ugly but it works:

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

...

$ python tree.py 13
            *
           ***
          *****
         *******
        *********
       ***********
      *************
     ***************
    *****************
   *******************
  *********************
 ***********************
*************************
            *
share|improve this answer
show 1 more comment

Since this is a CW: I don't like that code golfs are always organized in terms of "number of characters" or somesuch. Couldn't they be organized in terms of number of instructions for the compiler/interpreter (or some similar criterion)? Here is the Ruby solution again, and it's basically the same, but now for human consumption too:

SPACE = " "
ASTERISK = "*"
height_of_tree=ARGV[0].to_i
tree_lines = (1..height_of_tree).to_a
tree_lines.push 1 # trunk
tree_lines.each do | line |
   spaces_before = SPACE*(height_of_tree-line)
   asterisks = ASTERISK*(2*line-1) 
   puts spaces_before + asterisks
end
share|improve this answer
show 2 more comments

PHP, 111 chars

(The very last char should be a newline.)

<?php $n=$argv[1];for($r='str_repeat';$i<$n;$i++)echo $r(' ',$n-$i).$r('*',$i*2+1)."\n";echo $r(' ',$n).'*' ?>

Readable version:

<?php

$n = $argv[1];

for ($r = 'str_repeat'; $i < $n; $i++)
    echo $r(' ', $n - $i) . $r('*' , $i * 2 + 1) . "\n";

echo $r(' ', $n) . '*'

?>
share|improve this answer
show 5 more comments

Shell version, 134 characters:

#!/bin/sh
declare -i n=$1
s="*"
for (( i=0; i<$n; i++ )); do
    printf "%$(($n+$i))s\n" "$s"
    s+="**"
done
printf "%$(($n))s\n" "*"
share|improve this answer

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).

share|improve this answer

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!)

share|improve this answer

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)
  }
share|improve this answer

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

share|improve this answer
1 2 3

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.