Vẽ một chiếc đồng hồ cát


32

Một lần nữa lấy cảm hứng từ một nhiệm vụ cho Lập trình 101 đây là một thách thức khác.

Đầu vào:

  • Một số nguyên dương n >= 3. (phải là số lẻ)

Đầu ra:

  • ncác dòng dấu sao, trong đó dòng đầu tiên có ndấu hoa thị và mỗi dòng mới có hai dấu sao nhỏ hơn dòng trước. Cho đến khi đánh 1 dấu sao. Từ đó, mỗi dòng mới có hai dấu sao nhiều hơn dòng trước cho đến khi quay lại ndấu sao. Không gian hoặc một cái gì đó giống như không gian phải được sử dụng để sắp xếp các dấu sao để nó thực sự trông giống như một chiếc đồng hồ cát.

Quy tắc chung:

  • Trailing newlines được cho phép nhưng không phải sử dụng.
  • thụt là phải.
  • Đây là môn đánh gôn, vì vậy câu trả lời ngắn nhất bằng byte thắng.
  • Vì khóa học được dạy bằng C ++, tôi rất mong muốn được thấy các giải pháp trong C ++.

Trường hợp thử nghiệm (n = 5):

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

chỉnh sửa cho phù hợp, cảm ơn :-)
Sickboy

3
Bản sao có thể có của Vẽ hình tam giác hoa thị
Oliver Ni

3
@Oliver Xem xét OP đã viết "Vẽ một tam giác hoa thị", tôi không hoàn toàn chắc chắn rằng việc gọi thử thách này là một bản sao là công bằng. Nó chắc chắn có liên quan, mặc dù.
Sherlock9

19
Vì không phải ai ở đây cũng biết toàn bộ bối cảnh, OP ban đầu đã đăng "Vẽ tam giác hoa thị" và chỉnh sửa thử thách này thành một thử thách bổ sung. Chúng tôi bảo họ loại bỏ phần đó và biến nó thành một thử thách khác (mà họ đã làm). Thử thách này không phải là một bản sao. OP đang làm những gì mà nhiều người dùng đại diện cao và thậm chí một vài mod đã khuyến nghị.
DJMcMayhem

2
@JDL: Không, tại sao bạn? À, giờ thì tôi đã hiểu ý của bạn là gì bởi hình vuông ... :-D
Sickboy

Câu trả lời:


20

Than , 6 byte

G↘←↗N*

Chết một cách đơn giản. Vẽ một poly G trên *, với độ dài cạnh được lấy từ đầu vào số N , trong đó các cạnh đi xuống và phải, theo chiều ngang trái và lên trên và phải:

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

Sau đó tự động hoàn thành các phác thảo và điền vào nó.

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

Hãy thử trực tuyến!


Hah, đó là những người hâm mộ xinh đẹp!
CT14.IT

6
Ngôn ngữ này rất thú vị! Tôi sẽ theo dõi điều này rất kỹ từ bây giờ: p.
Ad Nam

Chưa từng thấy ngôn ngữ này trước đây ... Có vẻ thú vị! Tôi tự hỏi bạn sẽ nhận được gì nếu kết hợp nó với Jelly bằng cách nào đó ...
Esolanging Fruit

12

Python 2, 57 byte

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

Một chương trình đầy đủ. Đi từng dòng, in đúng số dấu hoa thị ở giữa.

Hàm đệ quy dài hơn (67 byte):

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

hoặc là

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

Tôi muốn đề nghị cố gắng thay thế maxbằng một abs, nhưng tất cả những gì tôi nhận được là abs(n-1)+1, điều tồi tệ hơn bởi vì việc bổ sung yêu cầu dấu ngoặc đơn
njzk2

@ njzk2 Bạn có thể cắt parens bằng cách thực hiện '*'*-~abs(n-1), nhưng sau đó nó có cùng độ dài '*'*max(n,2-n).
xnor

def f(n,s=''):r=s+'*'*n+'\n';return 1/n*r or r+f(n-2,s+' ')+r61 byte, nhưng nó vẫn dài hơn. Ngay cả với một dòng mới hàng đầu, def f(n,s='\n'):r=s+'*'*n;return 1/n*r or r+f(n-2,s+' ')+rvẫn là 58 byte ...
Dennis

+1 để dạy tôi về center. Không bao giờ biết rằng tồn tại cho đến bây giờ.
DLosc

11

V , 12 byte

Àé*hòl3Äjxx>

Hãy thử trực tuyến!

Tôi thích những thử thách như thế này vì tôi có thể thể hiện những lợi thế của bản chất 2D của V. Giải trình. Đầu tiên, chúng ta cần tạo một chuỗi n dấu hoa thị. Vì vậy, chúng tôi làm điều này:

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

Là một lưu ý phụ, điều này tương đương trực tiếp với @ai*<esc>vim và đăng ký @ađược khởi tạo trước thành "arg1". Điều này làm cho đầu vào số thuận tiện hơn nhiều.

Sau đó, chúng ta di chuyển sang nhân vật bên phải với h . Đây là phần thú vị:

ò           " 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.

Về mặt kỹ thuật, phần cuối cùng này là

òl3Äjxx>>ò

Bởi vì lệnh thụt lề thực sự >>. V thuận tiện giả định các lệnh không đầy đủ áp dụng cho dòng hiện tại và cũng hoàn toàn điền vào òký tự thứ hai để lặp.


10

Siêu dữ liệu C ++, 186 byte

Với công thức rõ ràng từ câu trả lời C của tôi , MetHRsheet đang cạnh tranh!

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="";};

Ung dung:

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="";}; 

sử dụng:

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

không cạnh tranh

Chỉ để cho vui:

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

Sử dụng:

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

2
+1 để đánh bại PHP với phần dài nhất của C ++
matjoyce

7

PowerShell v2 +, 54 byte

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

Đưa đầu vào $n(đảm bảo là một số nguyên lẻ), xây dựng hai dãy với $n..12..$nvà concatenates chúng lại với nhau, sau đó sử dụng Where-Objectđể chỉ chọn những cái lẻ với |?{$_%2}. Những người được đưa vào một vòng lặp. Mỗi lần lặp, chúng tôi xây dựng số lượng không gian thích hợp, nối chuỗi với số dấu hoa thị thích hợp. Các chuỗi đó được để lại trên đường ống và đầu ra thông qua việc Write-Outputchèn các dòng mới giữa chúng khi hoàn thành chương trình.

Ví dụ

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

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

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

7

Python, 78 byte

Vì vậy, chỉ với thụt lề:

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

Sử dụng:

print f(5)

6

C, 114 109 byte

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

vô dụng:

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

Giải pháp đệ quy trước:

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 byte

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

Ý tưởng ở đây là tạo ra mỗi chiếc đồng hồ cát từ trước đó: thêm một khoảng trắng ở đầu mỗi dòng, và cả ndấu hoa thị và thêm dấu hoa thị.


4

05AB1E , 21 20 19 17 byte

Đã lưu 2 byte nhờ tính toán carusocomputing

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

Hãy thử trực tuyến!

Giải trình

;ƒ                   # 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û- Đã đi xa đến thế, mặt tái mét khi tôi nhận ra mình đã đi được bao xa, thấy bạn đã trả lời, sẽ đi thử học lặp lại bằng ngôn ngữ này bằng cách sử dụng ví dụ này. Cảm ơn!
Bạch tuộc ma thuật Urn

4
Tôi thực sự có thể giúp một lần: ;ƒ'*¹N·-×Nð×ì})û»sử dụng lệnh palindromize mới. -2 byte.
Bạch tuộc ma thuật Urn

@carusocomputing: Cảm ơn! Tôi không biết về lệnh palendromize (Tôi đã không làm mới các tài liệu). Rất hữu dụng. Đã cần nó vài lần trước đó :)
Emigna

9 byte , ngay cả trong di sản. Mặc dù tôi khá chắc chắn các nội dung ÅÉ.ccó thể chưa có sẵn tại thời điểm bạn đăng bài này. :)
Kevin Cruijssen

4

MATL , 12 byte

Q2/Zv&<~42*c

Hãy thử trực tuyến!

Giải trình

Điều này làm cho việc sử dụng hàm phạm vi đối xứng được thêm gần đây .

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: ['*****'
                ' *** '
                '  *  '
                ' *** '
                '*****']

Tốt đẹp! Đó là một tính năng thú vị. Đây là câu trả lời duy nhất gần với câu trả lời V của tôi, vì vậy bây giờ tôi sẽ bị ám ảnh về việc tháo một hoặc hai byte. : D
DJMcMayhem

@DJMcMayhem Heh, tôi không nghĩ rằng tôi sẽ có thể giảm số byte trên cái này
Luis Mendo

Vâng, tôi không nghĩ rằng tôi có thể. Có lẽ sẽ có một 4-byte Jelly câu trả lời trong một vài phút dù sao, hahaha ...
DJMcMayhem

4

PHP, 95 byte

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

Thay vì lưu trữ các hàng trong một mảng và sau đó xuất ra tất cả mọi thứ, vòng lặp for sẽ giảm xuống cho đến 1, và sau đó quay trở lại số ban đầu.


3

C ++ 11, 93 byte

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

Hơi vô dụng:

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

Sử dụng:

std::cout << f(5);

Tốt đẹp! một byte có thể được lưu bằng cách giả sử ASCII và thay thế '\n'bằng 10:)
Quentin


3

R, 77 byte

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

Tạo một ma trận ký tự, sau đó nó sẽ in ra cat, với fill=nviệc đảm bảo các đường thẳng hàng. Lưu ý rằng các phần tử được lưu trữ trong cột ma trận - trước tiên (tức là hai phần tử đầu tiên là M[1,1]M[2,1]không M[1,2].)


3

Java 7, 170 165 164 byte

Cảm ơn @Hypino đã lưu 5 byte.
Cảm ơn Kevin vì đã tiết kiệm 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:"*";} 

Bạn có thể lưu 2 byte bằng cách xóa s=từ s=s+"\n"và 2 byte nữa bằng cách thay đổi return(n=--n-1)thành return(n=n-2)tổng cộng 4 byte.
Hypino

Chào. Bạn có thể chơi golf hai phần: String s="",c="",t="";đến String s,c,t=s=c="";( -2 byte ) và return(n=n-2)>=0?s+"\n"+c+c(n,++x)+đến return n-1>0?s+"\n"+c+c(n-2,++x)+( -2 byte một lần nữa)
Kevin Cruijssen

Nhưng mẫu @KevinCruijssen không như mong đợi sau khi thay đổi n=n-2-> n-1>0vì n nên được sử dụng trong đối số khác của hàm.
Numberjack

@Numberjack Tôi biết, nhưng tôi cũng đổi nthành n-2phần đó. return(n=n-2)>=0 ... nđược thay đổi return n-1>0 ... n-2vẫn còn ngắn hơn. PS: Bạn đã cảm ơn tôi vì đã lưu byte, nhưng chưa thay đổi mã trong chỉnh sửa của bạn. ;)
Kevin Cruijssen

@Numberjack Umm .. bạn vẫn quên mẹo thứ hai của tôi. Dù sao, đây là một biến thể ngắn hơn: 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:"*";}không có t( kiểm tra ideone - 133 byte )
Kevin Cruijssen

3

PHP - 95 byte

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

Đã lưu một byte bằng cách sử dụng một dòng mới thực tế thay vì một dòng "\r"


2

Bình thường, 22 byte

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

Một chương trình lấy đầu vào của một số nguyên trên STDIN và in kết quả.

Dùng thử trực tuyến

Làm thế nào nó hoạt động

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 byte

Nên chơi golf nhỏ hơn một chút

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

Chúng tôi có thể kiểm tra nó ở đây trên ideone


2

C, 79 byte

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

Nó phân tách biến đếm ngược kthành các chỉ số hàng và cột. Nếu chỉ số cột là 0 (char cuối cùng trong một hàng), nó sẽ xuất ra một ký tự dòng mới (10). Sau đó, nó điều chỉnh các chỉ số hàng và cột ở xung quanh dấu hoa thị trung tâm. Sau đó, abs(x) < abs(y)là một điều kiện ngắn để xuất ra một không gian.


2

Ruby, 55 54 byte

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

?**ncông trinh; bạn không cần không gian ở đó.
Mực giá trị

2

Java 7, 156 byte

Khá đơn giản. Theo dõi các dòng với n, sao với j, khoảng trắng với svà hướng với d. Tôi thực sự chỉ muốn một câu trả lời Java không đệ quy trên bảng, nhưng nó không làm tổn thương rằng nó cũng ngắn hơn một chút :)

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

Với ngắt dòng:

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 byte

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

Kiểm tra:

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

Giải trình:

                 ⎕   ⍝ 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

Chỉ cần loại bỏ 1+và sử dụng một APL có ⎕IO←0.
Adám

2

Haskell, 84 byte

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);
  }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.