Code Golf圣诞版:如何打印出高度为N的圣诞树


89

给定一个数字N,如何N使用最少数量的代码字符打印出一棵高度高的圣诞树? N假定被限制为的最小值3和的最大值30(不需要边界和错误检查)。N作为程序或脚本的唯一命令行参数给出。

感谢所有语言,如果您看到一种已经实现的语言,并且可以将其简化,请尽可能编辑-否则请评论,并希望有人清理混乱。为了清楚起见,包括换行符和空格,但不要在字符数中包括它们。

这样生成一棵圣诞树,其“树干”仅包含居中的“ *”

N = 3:

   *
  ***
 *****
   *

N = 4:

    *
   ***
  *****
 *******
    *

N = 5:

     *
    ***
   *****
  *******
 *********
     *

N定义不包括一个主干的分支的高度。

圣诞快乐PPCG!

Answers:


46

J,24个字符

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

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

说明:

'*'$~5
*****

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

然后}:@|."1反转每一行并剥离最后一列,并将其,.装订到]

然后,{.将第一列粘贴到底部。

以前的条目

29个字符,完全没有空格。

   (((\:i。@#),}。)“ 1 $&'*'” 0>:0,〜i.3
  *
 ***
*****
  *
   ((\\ i。@#),}。)“ 1 $&'*'” 0>:0,〜i.11
          *
         ***
        *****
       *******
      *********
     ***********
    *************
   ***************
  *****************
 *******************
*********************
          *

   注意 从1到 n 计数,然后再从1计数
   >:0,〜i.3
1 2 3 1
   注意 每次复制“ *” x 
   $&'*'“ 0>:0,〜i.3
*
**
***
*
   注意 反转每一行
   (\:i。@#)“ 1 $&'*'” 0>:0,〜i.3
  *
 **
***
  *
   注意 去除前导柱
   }。“ 1 $&'*'” 0>:0,〜i.3

*
**

   注意 粘贴在一起
   ((\\ i。@#),}。)“ 1 $&'*'” 0>:0,〜i.3
  *
 ***
*****
  *

仅需增加9个字符,您便可以为该函数命名:c=:[:((\:i.@#),}.)"1[:$&'*'"0[:>:0,~i.
ephemient

11
什么,你们使用某种J文档库来使代码易于理解吗?:)

92

Brainfuck,240个字符

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

尚未完成。它有效,但仅适用于一位数字。

编辑:完成!适用于使用0作为EOF的口译员。请参阅NOTE带有注释的源中带有-1的s。

再次编辑:我应该注意,因为Brainfuck缺乏读取命令行参数的标准方法,所以我改用了stdin(标准输入)。ASCII,当然。

第三次编辑:亲爱的,似乎我.在压缩代码时剥离了(输出)字符。固定...

这是主循环的基本内存管理。我敢肯定,可以对其进行大幅优化,以减少30个左右的字符数。

  1. 临时
  2. 柜台副本
  3. 计数器(计数为0)
  4. 空格字符(十进制32)
  5. 星号字符(十进制42)
  6. 当前行上的星号数(1 + 2 *计数器)
  7. 临时
  8. 换行符
  9. 临时?
  10. 总行数(即输入值;在打印主干时一直存储到最后)

精简版:

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

和漂亮的版本:

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

1
我的大脑感到不适……

3
哦,我的上帝。
匿名

63

Perl,50个字符

(1个相关空格)

perl:一行版本:

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

现在有了更多的空白:

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

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

非Perl用户的扩展说明。

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

25
真是不可思议。

8
同样,@ zenazn也应注意,大多数打高尔夫球都是任何语言的错误代码。如果这是最干净的代码的竞争,那么我们也可以赢得胜利。
肯特·弗雷德里克

5
@zenazn:证明,您可以在上面看到我们在互相协作和改进彼此的代码,这证明我们可以很好地阅读每个其他代码。
肯特弗雷德里克

1
PS:感谢您对非Perl程序员的解释。它仍然是很难理解的,但至少有道理。我想你会在一段时间后习惯的。

2
@RobH:J是APL的孩子。从某种意义上说,它更不易读,因为它没有对每个操作都使用带有特殊符号的APL字符集-而是使具有多种含义的ASCII字符过载。 stackoverflow.com/questions/392788/1088931#1088931
短暂

26

语言:Python(通过shell),字符数:64(2个有效空间)

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

$ sh ax6 11
           *
          ***
         *****
        *******
       *********
      ***********
     *************
    ***************
   *****************
  *******************
 *********************
           *

8
我最喜欢此解决方案的地方是python很难编写晦涩难懂的代码,它是最易读的解决方案之一

您正在使用外壳程序处理参数,这与高尔夫IMO代码的精神不同。使用“ import sys”和“ n = w = int(sys.argv [1])”,并为循环体缩进1个字符,对于这个版本,我得出了89个字符。

4
这是我以前做过的。这个问题的实质是玩得开心,此外,没有规定使用一种语言:没有争论。

26

x86 asm 16位,50字节

还没有汇编版本?:)

    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

(注意:在此版本中,N限于1-9)

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

在这里下载


24

语言:Windows批处理脚本令人震惊!

@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!*

受虐狂!我喜欢

很好...您得到+1

2
可以使用以下setlocal enabledelayedexpansion命令启用延迟变量扩展。
海伦

老兄 认真吗?

无法使其工作。我第一次尝试。
Fabinout

21

Ruby,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)}

祝大家圣诞快乐!

编辑:根据约书亚·斯威克(Joshua Swink)的建议进行了改进


dang,我希望没有人尝试过红宝石。不错的工作。

这是Ruby的非常不错的一行。

我似乎太赞了吗?对不起,不是我的意图!圣诞快乐!:)

也不意味着要卑鄙,当然你是对的!圣诞快乐!

1
在1.9,你可以节省一些字符:n=$*[0].to_i;puts [*1..n,1].map{|i|" "*(n-i)+"*"*(2*i-1)}带来下来到58

14

语言:C#,字符数: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));
    }
}

仅代码,不格式化(120个字符):

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

109个字符的版本(仅代码):

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

高度= 10的结果:

          *
         ***
        *****
       *******
      *********
     ***********
    *************
   ***************
  *****************
 *******************
          *

13

语言:dc(通过外壳)字符数:83

直流版本短一点:

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

编辑:将常量10更改为$ 1


11
上帝,这到底是什么?

1
刚刚阅读了手册页;-)

12

python,“-c”技巧... @ 61个字符(一行)

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

实际上,它是57个字符,根据问题说明,仅''空格有效。

10

这是一个节省空间的Haskell版本,共有107个字符:

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

运行它:

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

圣诞快乐,所有:)


10

语言:dc(通过外壳),字符数:119(1个有效空间)

只是为了它的晦涩:)

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

$ sh ax3 10
          *
         ***
        *****
       *******
      *********
     ***********
    *************
   ***************
  *****************
 *******************
          *

嗯,认真,wtf?我不明白这

dc是反向抛光计算器。'man dc'是最明显的方法:)

6

更好的C ++,大约210个字符:

#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;
}

最小化为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;}

使用std; 任何人?

斯特拉格-当我开始时,只有几个std ::和'using namespace std;'。有很多文字。我想现在这将减少字符。

您的版本比我的版本效率低下,因为它必须创建字符串,而我的版本仅会打印所需的字符。:)
pyon

6

语言:python,没有技巧,78个字符

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

6

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

5

改善ΤζΩΤζΙΟΥ的答案。我无法发表评论,所以这是新帖子。72个字符。

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

使用“ python -c”技巧,共有61个字符。

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

我了解了中心函数,并且“ python -c”可以接受多个行代码。谢谢,谢谢。


5

使用Linq的C#:

    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个字符。

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

5

AWK,一行上有86个字符。

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
   #
  ###
 #####
   #
     #
    ###
   #####
  #######
 #########
     #

5

语言:Java,字符数: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");}}

作为参考,我能够使用递归将以前的Java解决方案(从以前的最少269个字符减少到231个字符)进行剃毛。尽管更长一点,但我还是喜欢这种解决方案,因为T它确实是面向对象的。您可以创建一个随机大小的T实例的小森林。这是该方法的最新进展:

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);}
 }

您的新角色数是251(1个相关空格)

摆脱“ public static void main”,使用静态块并使用Java 6进行编译;)
Fabinout

我知道已经快9年了(笑),但是您可以打高尔夫:class T{public static void main(String[]v){long n=new Long(v[0]),r=1,s;String o="";for(;r<=n;r++){for(s=n-r;s-->0;)o+=' ';for(;++s<2*r;)o+='*';o+="\n";}while(n-->1)o+=' ';System.out.println(o+"*");}}(199个字符/字节)
Kevin Cruijssen

5

语言:PowerShell,字符数:41(包括1个空格)

1..$args[0]+1|%{" "*(30-$_)+"*"*($_*2-1)}

5

dyalog APL为21个字符。

m,⍨⌽0 1↓m←↑'*'\¨⍨1,⍨⍳

⍳给出一个从1开始的整数向量。

1,⍨在向量的末尾添加一个。这将是树的脚。

'*'\¨⍨给出一个*字符串向量,其长度由前一个向量给定。

↑将向量转换为矩阵,并在右侧添加空格。

m←将矩阵存储在m中。

0 1↓删除零行和第一列。

s反转矩阵。

m,⍨在右侧与m连接。


m,⍨⌽0 1↓m←->(⌽,0 1↓⊢)
ngn

4

语言:C,字符数:133

C版本的改进。

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);
}

起作用,甚至以树的高度作为参数。需要可以容忍K&R风格代码的编译器。

我现在感觉很脏。这是丑陋的代码。


这与我第一次使用Java时遇到的问题相同。它不是使用命令行参数的完整程序!

哦?这是必需的吗?没问题。我会解决的。

删除所有不必要的换行符后,它是138个字符。
Can BerkGüder08年

我数了133(只是删除了所有空白并检查了文件大小)

4

R(62个字节)

我还没有看到R解决方案。如果我错过了,请纠正我。

for(i in c(1:N,1))cat(rep(" ",N-i),rep("*",2*i-1),"\n",sep="")

输出:

> N <- 3
> for(i in c(1:N,1))cat(rep(" ",N-i),rep("*",2*i-1),"\n",sep="")
  *
 ***
*****
  *
> 
> N <- 4
> for(i in c(1:N,1))cat(rep(" ",N-i),rep("*",2*i-1),"\n",sep="")
   *
  ***
 *****
*******
   *
> 
> N <- 5
> for(i in c(1:N,1))cat(rep(" ",N-i),rep("*",2*i-1),"\n",sep="")
    *
   ***
  *****
 *******
*********
    *

3

语言:C,字符数:176(2个相关空格)

#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");}

3

Shell版本,134个字符:

#!/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" "*"


3

语言:Python,有效字符数:90

很难看,但是可以用:

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
            *
           ***
          *****
         *******
        *********
       ***********
      *************
     ***************
    *****************
   *******************
  *********************
 ***********************
*************************
            *

您的字符数是98(2个有效空格,用引号引起来)

3

由于这是CW:我不喜欢代码高尔夫球总是以“字符数”之类来组织的。难道不能按照针对编译器/解释器的指令数量(或类似标准)来组织它们吗?这又是Ruby解决方案,基本上是相同的,但现在也供人类使用:

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

我同意第一句话。用这样的术语,像perl这样的语言具有一个开始的优势。应该是一些statemetns之类的。

谢谢...昨天我问了一个关于高尔夫的问题,做高尔夫的方法可能是用“令牌” ...那样,名字长度等等都不会受到影响。



2

PHP,111个字符

(最后一个字符应该是换行符。)

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

可读版本:

<?php

$n = $argv[1];

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

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

?>

您可以通过构建字符串,然后回显字符串来保存几个字符。我认为。试试看。

好主意,但我尝试过,但这只会使它更长。'$ t。=(...)'仅比'echo(...)'短一个字符,然后您还必须在最后加上'echo $ t'。

通过删除'$ i = 0;'将其缩短4个字符。for语句的第一部分。PHP假定整数上下文中使用的不存在变量已经为0!:P

通过在$中放入$ r = ..来保存字符。另外,我说换行符应该是一个字节,而不是两个字节。=]

是的,我刚刚意识到自己被误计数了一次,因为我是使用文本编辑器中的列号进行计数的。我使用linux,所以换行符是一个字节。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.