It's almost Christmas!

14

3

Because of this, families from all over the world are building Christmas trees.

But this normal tree can get boring after a while, so let's make an ASCII tree!

Leafs are represented by # and must be arranged as shown in the example output. We have 5 balls (O) and 5 candy canes (J), which we place randomly around the tree. We also have a candle on top.

Input: none

Output:

         ^
         |
        ###
       ##O##
      #######
       #####
      ####J##
     #########
    ####O######
   #############
      ###J###
     #########
    ####O###J##
   #######O#####
  ###J########O##
 ###########J#####
        ###
        ###

Rules (if it's not in the rules, assume you can)

  • Balls and candy canes must be randomly placed on the tree and must have at least one leaf between them, not counting diagonals.

  • Each leaf must have a non-zero chance of getting a ball or a candy cane.

  • There may be leading or trailing spaces on each line, as long as the tree has the proper shape.

  • This is , so shortest code in characters wins.

Grey

Posted 2016-12-16T10:01:37.147

Reputation: 251

related – Billywob – 2016-12-16T10:04:18.767

2@Billywob it's a close one, this one has a randomised factor and a candle tho :P – Grey – 2016-12-16T10:06:08.320

1Yeah, this is most certainly more difficult imo. – Billywob – 2016-12-16T10:06:52.853

related: http://codegolf.stackexchange.com/q/15860/7209

– John Dvorak – 2016-12-16T10:37:21.433

3

“But this normal tree can get boring after a while.” Then why the old school candle and not something creative?

– manatwork – 2016-12-16T10:56:55.827

@manatwork ohwow, that's a nice deco, I was actually reffering to a physical tree – Grey – 2016-12-16T10:58:39.873

Related. – user2428118 – 2016-12-16T11:15:29.123

1

Since no one else has mentioned, I'll recommend that you post future challenges to the Sandbox where you can get meaningful feedback and tweak challenges before you post them to Main.

– AdmBorkBork – 2016-12-16T14:35:51.193

1

If you don't answers that look like this, I suggest scoring by bytes rather than characters.

– Dennis – 2016-12-16T17:13:37.507

Is it legal to usually place all of the balls? For example, if you flip a coin for every leaf to see if it gets an ornament, then every leaf has a non-zero chance of getting an ornament, but there's also a remote (but non-zero) chance that you don't place all of the ornaments. Supposing there was a 99% chance that you place them correctly, is that a fair answer? – rexroni – 2016-12-18T16:55:56.183

Should the trunk be considered leafs as well or not? – Titus – 2018-12-22T12:07:50.187

Answers

4

JavaScript (ES6), 148 bytes

Hopefully, this should comply with the 'random enough' condition.

_=>[...'887656543254321077'].map(n=>' '.repeat(n)+'#'.repeat(17-2*n)).join`
`.replace(/#/g,_=>'OJ^|#'[++i<4?i:i>133|++j%13?4:j/13&1],i=1,j=new Date)

Demo

let f =

_=>[...'887656543254321077'].map(n=>' '.repeat(n)+'#'.repeat(17-2*n)).join`
`.replace(/#/g,_=>'OJ^|#'[++i<4?i:i>133|++j%13?4:j/13&1],i=1,j=new Date)

console.log(f())

Arnauld

Posted 2016-12-16T10:01:37.147

Reputation: 111 334

I've tested and got a tree that brokes 'and must have at least one leaf (#) inbetween them, not counting diagonals' – user2216 – 2016-12-16T14:00:09.037

@user2216 Unless I somehow missed or misunderstood something, the modulo was chosen in such a way that it can't possibly happen -- except along diagonals. (There are 13 distinct patterns that you can test by replacing j=new Date with j=0 to j=12.) – Arnauld – 2016-12-16T14:10:52.530

8

CS-Script - 306 bytes

var c=new string(' ',342).ToCharArray();var r=new Random();int e=18,i,j,w;for(;i<e;i++){c[i*e+e]='\n';w=i<5?i:i<10?i-2:i<16?i-6:2;for(j=1;j++<w*2;)c[i*e+8-w+j]='#';}for(i=0;i<10;){j=37+r.Next(288);if(c[j]=='#'&c[j+1]<42&c[j-1]<42&c[j+e]<42&c[j-e]<42)c[j]=i++<5?'J':'O';}c[8]='^';c[27]='|';Console.Write(c);

Once more with formatting and comments:

// create 'char bitmap' filled with spaces
var c=new string(' ',342).ToCharArray(); 
// Random for placing ornaments
var r=new Random();
int e=18,i,j,w;
// once for each row
for(;i<e;i++)
{
    // add new lines
    c[i*e+e]='\n';
    // determine width of tree for this row
    w=i<5?i:i<10?i-2:i<16?i-6:2;
    for(j=1;j++<w*2;)
        // add leaves
        c[i*e+8-w+j]='#';
}
for(i=0;i<10;)
{
    // select random location
    j=37+r.Next(288); 
    if( // check we have a leaf
        c[j]=='#' &
        // check surrounding to be leaf/space/new-line
        c[j+1]<42 & c[j-1]<42 & c[j+e]<42 & c[j-e]<42)
        // add ornament if location is valid
        c[j]=i++<5?'J':'O';
}
// light candle
c[8]='^';
c[27]='|';
// print
Console.Write(c);

It's basically C#, but using CS-Script allows me to skip all the boiler-plate.

Try it here!

Notes:

This currently outputs another line of white spaces below the tree to make sure the that 'checking for existing ornaments below' does not throw an IndexOutOfBoundsException. Other solutions would be:

  • Checking if it is the last line before checking below (adds a few more character)
  • Not adding ornaments to the 'stem' of the tree (Same byte count, but seems to me to be against rules)

I'll leave it to the OP if this should be changed.

Lastly, this is my first golf, so any feedback is appreciated. ;)

amulware

Posted 2016-12-16T10:01:37.147

Reputation: 181

Nice solution. It think you might need to include using System; in your byte count though, as you can't use Random or Console without it. http://meta.codegolf.stackexchange.com/questions/10081/byte-count-for-imports-or-other-things-not-needed-for-definition-but-for-exec/10848#10848 Sorry to add 13 bytes :(

– Erresen – 2016-12-23T10:41:32.653

@Erresen: Thanks for the link! As far as I can tell, it only talks about imports necessary for execution though, and for cs-script using System; is not needed (it automatically imports common namespaces). But maybe I'm splitting hairs. ¯_(ツ)_/¯ – amulware – 2016-12-24T13:40:29.427

who knows! I only started playing the other day myself. Didn't know about cs script before seeing your answer. Really useful for avoiding some C# disadvantages in golfing. Whatever the answer is, I don't think a c# script's gonna win any time soon. – Erresen – 2016-12-24T18:08:58.083

That much is certain, yeah. :D – amulware – 2016-12-24T22:23:06.730

If you compile to a function, if possible in CS-Script, you could reduce the byte count i.e. _=>{var c=... return c;} – TheLethalCoder – 2018-12-19T10:57:52.140

4

TSQL, 556 532 494 476 bytes

This script needs to be executed on the master database

Golfed:

DECLARE @ varchar(max)='',@h INT=0,@w INT=0WHILE @h<18SELECT
@+=space(9-@w)+REPLICATE(char(IIF(@h<2,94+30*@h,35)),@w*2+1)+space(9-@w)+CHAR(10),@h+=1,@w+=CHOOSE(@h,0,1,1,1,-1,1,1,1,1,-2,1,1,1,1,1,-8,0)WHILE
@h>7WITH C as(SELECT*,substring(@,number,1)v,number/20r,number%20c
FROM spt_values WHERE type='P'and number<358)SELECT @=stuff(@,number,1,CHAR(74+@h%2*5)),@h-=1FROM
c d WHERE v='#'and not exists(SELECT*FROM c WHERE abs(d.c-c)+abs(d.r-r)<2and'A'<v)ORDER BY newid()PRINT @

Ungolfed:

DECLARE @ varchar(max)='',@h INT=0,@w INT=0

WHILE @h<18
  SELECT @+=
    space(9-@w)+REPLICATE(char(IIF(@h<2,94+30*@h,35)),@w*2+1)
      +space(9-@w)+CHAR(10),
    @h+=1,
    @w+=CHOOSE(@h,0,1,1,1,-1,1,1,1,1,-2,1,1,1,1,1,-8,0)

WHILE @h>7
  WITH C as
  (
    SELECT*,substring(@,number,1)v,number/20r,number%20c
    FROM spt_values
    WHERE type='P'and number<358
  )
  SELECT @=stuff(@,number,1,CHAR(74+@h%2*5)),@h-=1
  FROM c d
  WHERE v='#'and not exists(SELECT*FROM c WHERE abs(d.c-c)+abs(d.r-r)<2and'A'<v)
  ORDER BY newid()

PRINT @

Try it out

t-clausen.dk

Posted 2016-12-16T10:01:37.147

Reputation: 2 874

1

JavaScript, 204 bytes

f=(s='^|1232345634567811'.replace(/./g,x=>(y=x|0,' '.repeat(8-y)+(y?'#'.repeat(y*2+1):x)+`
`)),o=5,j=5,r=(Math.random()*56|0)*4,k)=>j?f(s.replace(/###/g,(_,i)=>i-r?_:k=o?'#O#':'#J#'),k?o-!!o:o,k?j-!o:j):s

console.log(f());
.as-console-wrapper{max-height:100%!important;top:0}

Washington Guedes

Posted 2016-12-16T10:01:37.147

Reputation: 549

1why are you counting \n as 1 byte? – Daniel Shillcock – 2016-12-19T10:28:06.923

Not anymore, sorry – Washington Guedes – 2016-12-19T10:58:26.923

1

Python 3 - 450 427 bytes

I know 450 is too much for python. But, but.....

from random import randint as r
t=lambda o,g:(o*g).center(19,' ')+';';s,z='','#';s+=t(z,3)*2
for h,w in zip([6,5,3],[17,13,7]):
 for i in range(h):s+=t(z,w);w-=2
s+=t('|',1)+t('^',1);s=[list(i)for i in s.split(';')]
for o in'O'*5+'J'*5:
 while 1:
  h,w=r(2,15),r(1,16)
  m=s[h]
  C,m[w]=m[w],o
  P=s[h-1][w]+s[h+1][w]+m[w-1]+m[w+1]
  if not('O'in P or'J'in P)and C!=' ':break
  m[w]=C
print (*[''.join(i)+'\n'for i in s][::-1])

If the for i in'O'*... is turned into a better recursive function then lots of bytes can be cut down.

Try it here

Edit:

Saved 2 bytes by using ; as delimiter and several bytes by taking newline byte count as 1 byte.

Gurupad Mamadapur

Posted 2016-12-16T10:01:37.147

Reputation: 1 791

1

PHP, 200 bytes

might be shorter with a more sophisticated approach; but I´m in a hurry.

for(;$c="^|2343456745678922"[$i++];)$s.=str_pad(+$c?str_pad("",2*$c-1,"#"):$c,17," ",2)."
";for(;$n++<10;)$s[$p=rand(0,288)]!="#"|($s[$p-18]|$s[$p+18]|$s[$p-1]|$s[$p+1])>A?$n--:$s[$p]=OJ[$n&1];echo$s;

requires PHP 5.6 or 7.0. Run with -nr or try it online.

Titus

Posted 2016-12-16T10:01:37.147

Reputation: 13 814

0

Scala, 329 bytes

var r=scala.util.Random;var z=r.nextInt(2);def t{print(new StringBuilder({"^|234345645678922".map(x=>{val t=if(x>57)8 else(57-x);" "*t+{if(x>57)""+x else "#"}*(17-(t*2))+" "*t+" \n"})}.mkString)match{case e=>{var w=0;while(w<10){{val b=(r.nextInt(e.size/2)*2)+z;if(e.charAt(b)=='#'){e.setCharAt(b,if(w<5)'O'else'J');w+=1}}};e}})}

Minimal

Posted 2016-12-16T10:01:37.147

Reputation: 131