画一个沙漏


32

再次受到编程101任务的启发,这是另一个挑战。

输入:

  • 一个正整数n >= 3。(必须是奇怪的)

输出:

  • n星号行,其中第一行有n星号,每条新行都比前一行少两个星号。直到打1星号。从那里开始,每个新行都比之前的行多两个星号,直到回到n星号为止。空格或类似空格之类的东西必须用于对齐星号,以使其看起来真的像沙漏。

一般规则:

  • 尾随换行符是允许的,但不必使用。
  • 缩进是必须的。
  • 这是代码高尔夫球,因此最短答案以字节为单位。
  • 由于该课程是用C ++讲授的,所以我很想看到C ++的解决方案。

测试案例(n = 5):

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

进行了相应的编辑,谢谢:-)
Sickboy '16


3
@Oliver考虑到OP 编写了 “绘制星号三角形”,因此我不确定将这个挑战称为重复是公平的。不过,这绝对是相关的。
Sherlock16年

19
由于此处并非所有人都了解整个上下文,因此OP最初发布了“绘制星号三角形”,并将此挑战作为附加挑战进行了编辑。我们告诉他们删除该部分并使它成为不同的挑战(他们做到了)。这个挑战不是重复的。OP正在做许多高级用户,甚至推荐了一些mod。
DJMcMayhem

2
@JDL:不,你为什么呢?啊,现在我明白了方形的意思了... :-D
Sickboy

Answers:


20

木炭,6个字节

G↘←↗N*

死了很简单。绘制聚ģ上的*,与从输入侧采取长度Ñ棕土,其中该侧面下去,右,水平向左,和上-右:

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

然后自动完成轮廓并填充。

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

在线尝试!


哈哈,真是傻瓜!
CT14.IT

6
这种语言非常有趣!从现在开始,我将非常仔细地观察:p。
阿德南

以前没看过这种语言...看起来很有趣!我想知道如果以某种方式将它与果冻结合会得到什么……
硕果累累

12

Python 2,57字节

N=n=input()
exec"print('*'*max(n,2-n)).center(N);n-=2;"*n

完整的程序。一行一行,打印正确数量的星号居中。

递归函数较长(67个字节):

f=lambda n,p='':p+n*'*'+'\n'+(1%n*' 'and f(n-2,p+' ')+p+n*'*'+'\n')

要么

f=lambda n,p='':1/n*(p+'*\n')or f(n-2,p+' ').join([p+n*'*'+'\n']*2)

我想建议试图取代maxabs,但我得到的是abs(n-1)+1,因为除了需要括号这更糟糕的是
njzk2

@ njzk2您可以通过执行以下操作来剪掉括号'*'*-~abs(n-1),但是它的长度与相同'*'*max(n,2-n)
xnor

def f(n,s=''):r=s+'*'*n+'\n';return 1/n*r or r+f(n-2,s+' ')+r61个字节,但是还要更长。即使有领先的换行符,def f(n,s='\n'):r=s+'*'*n;return 1/n*r or r+f(n-2,s+' ')+r仍然是58个字节...
丹尼斯

+1教给我有关center。直到现在都不知道存在。
DLosc

11

V,12个字节

Àé*hòl3Äjxx>

在线尝试!

我喜欢这样的挑战,因为我要炫耀V的2D本质的优势。说明。首先,我们需要创建一个由n个星号组成的字符串。因此,我们这样做:

À           " Arg1 times:
 é          " Insert the following single character:
  *         " '*'

附带说明,这直接等同@ai*<esc>于vim,并且寄存器@a已预先初始化为“ arg1”。这使数字输入更加方便。

然后,使用来向右移动字符h。这是有趣的部分:

ò           " Until an error is thrown:
 l          "   Move one character to the right. This will throw an error on anyline with only one asterisk in it
  3Ä        "   Make 3 copies of this line
    j       "   Move down one line
     xx     "   Delete two characters
       >    "   Indent this line once.

现在从技术上讲,这最后一部分是

òl3Äjxx>>ò

因为indent命令实际上是>>。V方便地假定不完整的命令适用于当前行,并且还隐式填充第二个ò字符以进行循环。


10

C ++元模板,186个字节

使用我的C答案中的显式公式,元模板正在竞争!

template<int N,int X=N*N+N-1>struct H{enum{I=X/(N+1)-N/2,J=X%(N+1)-N/2-1};S s{(J==-N/2-1?'\n':((I>=J&I>=-J)|(I<=J&I<=-J)?'*':' '))+H<N,X-1>().s};};template<int N>struct H<N,-1>{S s="";};

取消高尔夫:

using S=std::string;

template <int N, int X=N*N+N-1>
struct H{
 enum{I=X/(N+1)-N/2,J=X%(N+1)-N/2-1};
 S s{(J==-N/2-1 ? '\n' : ( (I>=J&I>=-J)|(I<=J&I<=-J) ?'*':' '))+H<N,X-1>().s};
};

template <int N> struct H<N,-1> {S s="";}; 

用法:

std::cout << H<5>().s;

不竞争

只是为了好玩:

//T: Tuple of chars
template <char C, char...Tail> struct T { S r=S(1,C)+T<Tail...>().r; };

//specialization for single char
template <char C> struct T<C> { S r=S(1,C); };

//M: Repeated char
template <int N, char C> struct M { S r=S(N,C); };

//U: concatenates T and M
template <class Head, class...Tail> struct U { S r=Head().r+U<Tail...>().r; };

//specialization for Tail=M
template <int N, char C> struct U<M<N,C>> { S r{M<N,C>().r}; };

//specialization for Tail=T
template <char...C> struct U<T<C...>> { S r=T<C...>().r; };

//finally the Hourglass
template <int N, int I=0> struct H {
 S s=U<
       M<I,' '>,
       M<N,'*'>,
       T<'\n'>
      >().r;
 S r{s + H<N-2,I+1>().r + s};
};

//specialization for recursion end
template <int I> struct H<1,I> {
 S r=U<
       M<I,' '>,
       T<'*','\n'>
      >().r;
};

用法:

std::cout << H<5>().r;

2
+1击败C ++中最
耗时的

7

PowerShell v2 +,54个字节

param($n)$n..1+2..$n|?{$_%2}|%{" "*(($n-$_)/2)+"*"*$_}

接受输入$n(保证是一个奇数整数),用$n..1和构造两个范围2..$n并将它们连接在一起,然后用来Where-Object仅选择奇数|?{$_%2}。这些被送入一个循环。每次迭代,我们都构造适当数量的空格,并用适当数量的星号将其字符串连接。这些字符串留在管道上,并Write-Output在程序完成时通过隐式插入在它们之间输出换行符。

例子

PS C:\Tools\Scripts\golfing> 3,5,7|%{.\draw-an-hourglass.ps1 $_;""}
***
 *
***

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

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

7

Python,78个字节

所以只有缩进:

f=lambda n,i=0:n>1and' '*i+'*'*n+'\n'+f(n-2,i+1)+' '*i+'*'*n+'\n'or' '*i+'*\n'

用法:

print f(5)

6

C,114个 109字节

i,j;k(n){for(i=-n/2;i<=n/2;++i)for(j=-n/2;j<=n/2+1;++j)putchar(j==n/2+1?10:(i>=j&i>=-j)|(i<=j&i<=-j)?42:32);}

松散:

i,j;
k(n){
 for(i=-n/2;i<=n/2;++i)
  for(j=-n/2;j<=n/2+1;++j)
   putchar(j==n/2+1?10:(i>=j&i>=-j)|(i<=j&i<=-j)?42:32);
}

先前的递归解决方案:

p(a,c){while(a--)putchar(c);}
f(n,i){p(i,32);p(n,42);p(1,10);}
g(n,i){if(n>1)f(n,i),g(n-2,i+1);f(n,i);}
h(n){g(n,0);}

5

JavaScript(ES6),66个字节

f=(n,s="*".repeat(n))=>n>1?s+`
`+f(n-2).replace(/^/gm," ")+`
`+s:s

这里的想法是从前一个沙漏生成每个沙漏:在每行的开头添加一个空格,并在n星号前面和后面加上星号。


4

05AB1E21 20 19 17字节

借助carusocomputing,节省了2个字节

;ƒ'*¹N·-×Nð×ì})û»

在线尝试!

说明

;ƒ                   # for N in [0 ... floor(input/2)+1]
  '*                 # push an asterisk
    ¹N·-×            # repeat the asterisk input-N*2 times
         Nð×ì        # prepend N spaces
             }       # end loop
              )      # wrap stack in a list
               û     # palendromize
                »    # join with newlines

Ir"*"×.pRû-走了这么远,当我意识到自己离我有多远时,脸部紧握,看到你已经回答了,现在就开始使用此示例尝试以这种语言学习迭代。谢谢!
魔术章鱼缸

4
我实际上可以提供一次帮助:;ƒ'*¹N·-×Nð×ì})û»使用新的palindromize命令。-2个字节。
魔术章鱼缸

@carusocomputing:谢谢!我不知道palendromize命令(我没有刷新文档)。很有用。之前已经需要几次了:)
Emigna

9字节,即使是旧版也是如此。虽然我敢肯定的建宏ÅÉ.c可能是还没有提供当时您发布此。:)
Kevin Cruijssen

4

MATL,12字节

Q2/Zv&<~42*c

在线尝试!

说明

这利用了最近添加的 对称范围函数。

Q     % Input n implicitly. Add 1
      % STACK: 6
2/    % Divide by 2
      % STACK: 3
Zv    % Symmetric range
      % STACK: [1 2 3 2 1]
&<~   % Matrix of all pairwise "greater than or or equal to" comparisons
      % STACK: [1 1 1 1 1
                0 1 1 1 0
                0 0 1 0 0
                0 1 1 1 0
                1 1 1 1 1]
42*   % Multiply by 42 (ASCII code of '*')
      % STACK: [42 42 42 42 42
                 0 42 42 42  0
                 0  0 42  0  0
                 0 42 42 42  0
                42 42 42 42 42]
c     % Convert to char. Implicitly display, with char 0 shown as space
      % STACK: ['*****'
                ' *** '
                '  *  '
                ' *** '
                '*****']

真好!这是一个很酷的功能。这是唯一接近我的V答案的答案,所以现在我开始着迷于删除一个或两个字节。:D
DJMcMayhem

@DJMcMayhem嘿,我认为我无法减少此字节的字节数
Luis Mendo

Yeah, I don't think I can either. There'll probably be a 4-byte Jelly answer in a couple minutes anyway, hahaha...
DJMcMayhem

4

PHP, 95 bytes

for($c=str_pad,$m=$n=$argv[1];$n<=$m;$n+=$d=$d>0||$n<2?2:-2)echo$c($c('',$n,'*'),$m,' ',2)."
";

Instead of storing the rows in an array and then outputting everything, the for loop goes down until 1, and then goes back up to the original number.


3

C++11, 93 bytes

#include<string>
using S=std::string;S f(int n,int i=0){S s=S(i,32)+S(n,42)+'\n';return n>1?s+f(n-2,i+1)+s:s;}

Slightly ungolfed:

std::string f(int n,int i=0){
 auto s=std::string(i,' ') + std::string(n,'*') + '\n';
 return n>1 ? s+f(n-2,i+1)+s : s;
}

Usage:

std::cout << f(5);

Nice! one byte can be saved by assuming ASCII and replacing '\n' with 10 :)
Quentin


3

R, 77 bytes

M=matrix(" ",n<-scan(),n);for(i in 1:n)M[i:(n-i+1),i]="*";cat(M,sep="",fill=n)

Creates a character matrix, which it then prints out via cat, with fill=n making sure the lines align properly. Note that elements are stored in a matrix column-first (i.e the first two elements are M[1,1] and M[2,1], not M[1,2].)


3

Java 7, 170 165 164 bytes

Thanks to @Hypino for saving 5 bytes.
Thanks to Kevin for saving 1 byte.

String c(int n,int x){String s,c,t=c=s=" ";int i=0;for(;i++<n;s+="*");for(i=x;i-->=0;c+=" ");for(i=x;i-->0;t+=" ");return(n=n-2)>=0?s+"\n"+c+c(n,++x)+"\n"+t+s:"*";} 

You can save 2 bytes by removing s= from s=s+"\n"and 2 more bytes by changing return(n=--n-1) to return(n=n-2) for a total of 4 bytes.
Hypino

Hi. You can golf two parts: String s="",c="",t=""; to String s,c,t=s=c=""; (-2 bytes), and return(n=n-2)>=0?s+"\n"+c+c(n,++x)+ to return n-1>0?s+"\n"+c+c(n-2,++x)+ (-2 bytes again)
Kevin Cruijssen

But @KevinCruijssen pattern not as expected after changing n=n-2->n-1>0 because n should be used in other argument of a function.
Numberknot

@Numberknot I know, but I also changed n to n-2 at that part. return(n=n-2)>=0 ... n being changed to return n-1>0 ... n-2 is still shorter. PS: You've thanked me for saving bytes, but haven't changed your code in your edit. ;)
Kevin Cruijssen

@Numberknot Umm.. you still forgot my second tip. Anyway, here is a shorter variant: String c(int n,int x){String s,c=s="";int i=0;for(;i++<n;s+="*");for(i=x;i-->0;c+=" ");return n>1?s+"\n "+c+c(n-2,x+1)+"\n"+c+s:"*";} without the t (ideone test - 133 bytes)
Kevin Cruijssen

3

PHP - 95 bytes

$c=2;for($i=$a=$argv[1];$i<=$a;$i-=$c*=$i<2?-1:1)echo str_pad(str_repeat("*",$i),$a," ",2)."
";

Saved a byte by using an actual new line instead of an "\r"


2

Pyth, 22 bytes

j+J.e+*dk*b\*_:1hQ2_PJ

A program that takes input of an integer on STDIN and prints the result.

Try it online

How it works

j+J.e+*dk*b\*_:1hQ2_PJ  Program. Input: Q
              :1hQ2     Range from 1 to Q+1 in steps of 2. Yields [1, 3, 5, ..., Q]
             _          Reverse
   .e                   Enumnerated map with b as elements and k as indices:
      *dk                 k spaces
         *b\*             b asterisks
     +                    Concatenate the spaces and asterisks
  J                     Store in J
                    PJ  All of J except the last element
                   _    Reverse
 +                      Concatenate J and its modified reverse
j                       Join on newlines
                        Implicitly print

2

C, 195 191 Bytes

Should golf down a bit smaller

x,y,i;f(n){for(i=0;i<n;i+=2,puts("")){for(y=n-i;y<n;y+=2,putchar(32));for(x=i;x++<n;putchar(42));}for(i=n-2;~i;i-=2,puts("")){for(y=n-i+2;y<n;y+=2,putchar(32));for(x=i-1;x++<n;putchar(42));}}

We can test it here on ideone


2

C, 79 bytes

h(m,n,k){for(n=m++,k=n*m;--k;putchar(k%m?abs(k%m-m/2)>abs(k/m-n/2)?32:42:10));}

It splits the countdown variable k into row and column indices. If the column index is 0 (last char in a row), it outputs a newline character (10). Then it adjusts the row and column indices to be around the center asterisk. Then, abs(x) < abs(y) is a short condition for outputting a space.


2

Ruby, 55 54 bytes

f=->n,s=0{puts a=' '*s+?**n;(f[n-2,s+1];puts a)if n>1}

?**n works; you don't need the space there.
Value Ink

2

Java 7, 156 bytes

Fairly simple. Keeps track of lines with n, stars with j, spaces with s, and direction with d. I really just wanted a non-recursive Java answer on the board, but it doesn't hurt that it's also a bit shorter :)

String f(int n){String o="";int j=n,s=0,i,d=0;for(;n-->0;o+="\n"){for(i=0;i++<s;)o+=" ";for(i=0;i++<j;)o+="*";d+=j<2?1:0;j+=d<1?-2:2;s+=d<1?1:-1;}return o;}

With line breaks:

String f(int n){
    String o="";
    int j=n,s=0,i,d=0;
    for(;n-->0;o+="\n"){
        for(i=0;i++<s;)
            o+=" ";
        for(i=0;i++<j;)
            o+="*";
        d+=j<2?1:0;
        j+=d<1?-2:2;
        s+=d<1?1:-1;
    }
    return o;
}

2

APL, 19 bytes

' *'[1+∘.≤⍨(⊢⌊⌽)⍳⎕]

Test:

      ' *'[1+∘.≤⍨(⊢⌊⌽)⍳⎕]
⎕:
      5
*****
 *** 
  *  
 *** 
*****

Explanation:

                 ⎕   ⍝ read number  
                ⍳    ⍝ 1..N
           ( ⌊ )     ⍝ at each position, minimum of
            ⊢        ⍝ 1..N
              ⌽      ⍝ and N..1 (this gives 1..N/2..1)
       ∘.≤⍨          ⍝ outer product with ≤
     1+              ⍝ add 1 to each value
' *'[             ]  ⍝ 1→space, 2→asterisk

Just remove 1+ and use an APL that has ⎕IO←0.
Adám

2

Haskell, 84 bytes

f n|l<-div n 2,k<-[-l..l]=putStr$unlines[[" *"!!(fromEnum$abs x<=abs y)|x<-k]|y<-k]

Nice solution! But I'm pretty sure you don't need the putStr and you can get rid of the fromEnum like this.
ბიმო



2

PHP, 104 88 bytes

for(;$i++<$argn;$a.='**',$i++>1?$o=$s.$o:1)$o.=$s=str_pad("*$a",$argn,' ',2)."
";echo$o;

Try it online!

This doesn't beat the lowest scores for PHP on this challenge, but it's just too crazy for me to throw away.

Okay, so I've golfed now it to be the (not for long) lowest score for PHP on this challenge, but it doesn't change the fact that it's still crazy.

$ echo 7|php -nF hour.php
*******
 *****
  ***
   *
  ***
 *****
*******

83? also huh, php has barewords too, although it's not useful here
ASCII-only

@ASCII-only rats! Looks like I've got some more work to do! lol
640KB



@ASCII-only yep, nicely done! That's for sure the right approach!
640KB


1

PHP, 191 bytes

$b=[];for($i=$a=$argv[1]+1;$i>0;$i--){$i--;if($i<=1){$c=str_pad("*",$a," ",2)."\n";break;}$b[]=str_pad(str_repeat("*",$i),$a," ",2)."\n";}echo implode("",$b).$c.implode("",array_reverse($b));

Run like php -f golf_hourglass.php 15

# php -f golf_hourglass.php 15
***************
 *************
  ***********
   *********
    *******
     *****
      ***
       *
      ***
     *****
    *******
   *********
  ***********
 *************
***************

The idea behind it is to create the top half (the part before the single *), then just echo the top part twice, but the second time in reverse order.


I think this is a better start for this task for(;$i<$a=$argv[1];$i+=2){$t=str_pad(str_pad("",$i+1,"*"),$a," ",2)."\n";$i?$s.=$t:$r=$t;}echo strrev($s)."\n".$r.$s;
Jörg Hülsermann

for(;$i<$a=$argv[1];$i++){$t=str_pad(str_pad("",$i+1+$i%2,"*"),$a," ",2)."\n";$i%2?$s.=$t:$s=$t.$s;}echo$s; this is better
Jörg Hülsermann

Replace implode() with join() to save 6 bytes.
Alex Howansky

Replace \n with an actual new line to save a byte.
Alex Howansky

1

Pyke, 22 19 bytes

F-ed*ih\**+)2%'X_OX

Try it here!

F          )        -    for i in range(input)
 -                  -        Q-i
  e                 -       floor(^/2)
   d*               -      ^*" "
          +         -     ^+V
     ih             -       i+1
       \**          -      ^*"*"
            2%      -   ^[::2]
              'X_   - splat(^),
                       reversed(^)
                 OX - splat(^[:-1])

1

C, 117 bytes

void p(c,n){while(n--)putchar(c);}void h(n){for(int i=n;i>=-n;i-=i==1?4:2){p(32,(n-abs(i))/2);p(42,abs(i));p(10,1);}}

Ungolfed

void printNum(c, n) {
  while (n--)
    putchar(c);
}

void hourGlass(n) {
  for (int i = n; i >= -n; i-=i==1?4:2) {
    printNum(32, (n - abs(i)) / 2);
    printNum(42, abs(i));
    printNum(10, 1);
  }
}
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.