Write a function that prints an n
big tree, e.g. for n=5:
*
* *
* * *
* * * *
* * * * *
| |
Here is what I came up with in C:
N,i;a(n){for(i=N=N?N:n+2;i--;printf(i?"* "+(N-n-1<i):--n?"\n":"\n%*s",N,"| |"));n&&a(n);}
// the invocation isn't part of the golf:
main(){a(5);}
PS: Code blocks currently wrap around when they are too long, I’ve already submitted a patch to make them scroll horizontally instead.
Perl - 55 characters with say:
say ' 'x($N-$_).'* 'x$_ for 1..$N;say ' 'x($N-2).'| |';
Here’s my attempt with Rust:
101 Characters:
fn a(n:usize){for i in 1..=n{println!("{:2$}{}","","* ".repeat(i),n-i);}println!("{:1$}| |","",n-2);}
(Edited to remove a few unnecessary whitespace characters)
Python - 94 chars
I tried using some alternatives, but they all ended up more verbose than:
def a(n): for i in range(0,n): print(' '*(n-i)+'* '*(i+1)+' '*(n-i-1)) print(' '*(n-1)+'| |')
The list tools in python are great, but they all use keywords, so doing anything that doesn’t directly do for and print is likely too much. You could make a list of strings for instance, and print it all out at once to save a ‘print’ but you’d end up using a for in list comprehension or a join or something, so you can’t really save any characters afaict.
I’m sure someone will find a way to beat it tho!
Just for fun I asked ChatGPT and got a Python in 65 chars:
def p(n):print('\n'.join(' '*(n-i)+'* '*i for i in range(1,n+1)))
Since I’m most familiar with JavaScript I’ll try that myself now
Poor ChatGPT, it’s always so close but so far. This doesn’t meet spec :)
It doesn’t print the bottom row of ’ | | ', and it misses the leading spaces.
Fixing it produces:
def p(n):print('\n'.join(' '*(n-i)+'* '*(i+1)+' '*(n-i-1) for i in range(0,n)));print(' '*(n-1)+'| |')
Which is 102 characters, so longer than before. Like I said, I tried the list comp route. You get rid of some stuff, but you add more unfortunately.
However, both me and ChatGPT made the mistake of printing spaces after, which tbh isn’t necessary. That can give a bit of a boost:
def p(n):print('\n'.join(' '*(n-i)+'* '*(i+1) for i in range(0,n)));print(' '*(n-1)+'| |')
Which is 90, but applying it to my og answer:
def a(n): for i in range(0,n): print(' '*(n-i)+'* '*(i+1)) print(' '*(n-1)+'| |')
Yields 82.
Putting the loop on one line saves a couple characters though:
def a(n): for i in range(0,n):print(' '*(n-i)+'* '*(i+1)) print(' '*(n-1)+'| |')
Gets it to 80
Oh I totally missed that the trunk was part of the spec, gotta fix my own answer too
Just discovered this community existed, I’ve got to make a post in my usual golfing lang:
Zsh, 70 bytes
l=() repeat $1 l=(${(l.++i.)}\* $^l' *') print -l $l ${(l.$1-1.)}'| |'
The key constructs here are
(l.ARITHMETIC EXPRESSION.)
, which left-pads, and$^l
, which expands the array like a cross product.a=(a b c); echo x$a
printsxa b c
, butecho x$^a
printsxa xb xc
.Interestingly,
print -l
was shorter than<<<
by one byte.My JavaScript solution -
82103 chars:a=n=>{for(s=‘’,i=1;i<=n;i++)s+=’ ‘.repeat(n-i)+’* ‘.repeat(i)+’\n’;console.log(s)}a=n=>{for(s='',i=0;++i<=n;)s+=' '.repeat(n-i)+'* '.repeat(i)+'\n';console.log(s+' '.repeat(n-2)+'| |')}
I’m happy I was able to beat ChatGPT, it had the same strategy but used additional for loops instead of string.repeat(), so it was 113 chars. But I suspect further improvements might be possible with array.reduce or other prototype functions I’m forgetting about.
very cool, but you forgot the trunk
Woops, can you tell my teachers were always on my case for misreading the assignment :P
I don’t know about how y’all feel about submissions in dedicated golfing languages/esolangs like this, but
Vyxal - 14 characters/SBCS bytes (22 UTF-8 bytes)
ɾ×*vṄ
| |JøĊ⁋
Vyxal is a stack-based esolang designed to do well in code-golf competitions just like this one. It’s far from the only golfing language in existence, there’s many more like 05AB1E, Jelly and Thunno 2. This one is just one I made in 2020 (yes creative naming I know, I just couldn’t think of anything better).
You can try the program online here
Explained:
ɾ×*vṄ`| |`JøĊ⁋ ɾ # Generate a list of numbers from 1 to the input. ×* # Repeat the character "*" n many times, for each n in the above list vṄ # Insert a space between each asterisk. Normally, Ṅ will join an entire list on spaces, but the v makes Ṅ apply to each item in a list. `| |`J # Append the string "| |" to that list - this is the stump of the tree øĊ # Centre each of the strings in the list, relative to the longest string in the list. This is a single built-in function (the ø indicates that it's a two-character function) ⁋ # Join the resulting list on newlines
For
input = 5
, the stack looks like so:ɾ×*vṄ`| |`JøĊ⁋ ɾ [1, 2, 3, 4, 5] ×* ["*", "**", "***", "****", "*****"] (* does the multiplication, the × is the character that pushes "*" to the stack - it was a later addition) vṄ ["*", "* *", "* * *", "* * * *", "* * * * *"] `| |`J ["*", "* *", "* * *", "* * * *", "* * * * *", "| |"] øĊ [" * ", " * * ", " * * * ", " * * * * ", "* * * * *", " | | "] ⁋ Output as in the original challenge post
As you can see, some built-ins automatically apply to each item in a list, as if you wrote
[
. ]Once again, I don’t mean to come in and ruin golf for everyone, I just want to see how such a language might be seen by the community.
JavaScript, 93 characters:
l=console.log,r='repeat',b=n=>{for(i=0;i++<n;l(' '[r](n-i)+'* '[r](i)));l(' '[r](n-2)+'| |')}
EDIT: Damn, lemmy still mangles code. Here’s a gist, and I’ll replace the text in here with images.
This doesn’t beat anyone’s char count, but here’s my try in Factor. I hope someone comes along and does it even better. 177 chars (1 line):
You prefix the number to that code to invoke.
Here it is with the slight bit of sanity afforded by line breaks and a function wrapper:
To invoke:
5 tree print
EDIT 2: it’s 176 if you replace
first2
withlast2
, as someone pointed out to me.