Narysuj klepsydrę


32

Ponownie zainspirowany zadaniem programowania 101, oto kolejne wyzwanie.

Wkład:

  • Dodatnia liczba całkowita n >= 3. (musi być nieparzysty)

Wydajność:

  • nlinie gwiazdek, gdzie pierwsza linia ma ngwiazdki, a każda nowa linia ma dwie gwiazdki mniej niż poprzednia linia. Aż do trafienia 1 gwiazdką. Stamtąd każda nowa linia ma dwie gwiazdki więcej niż linia wcześniej, aż do powrotu do ngwiazdek. Spacje lub coś w rodzaju spacji muszą zostać użyte do wyrównania gwiazdek, aby naprawdę wyglądały jak klepsydra.

Główne zasady:

  • Końcowe znaki nowej linii są dozwolone, ale nie muszą być używane.
  • wcięcie jest koniecznością.
  • To jest golf golfowy, więc wygrywa najkrótsza odpowiedź w bajtach.
  • Ponieważ kurs jest nauczany w C ++, chętnie widzę rozwiązania w C ++.

Przypadek testowy (n = 5):

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

zredagowane odpowiednio, dzięki :-)
— Sickboy


3
@Oliver Biorąc pod uwagę OP napisał „Narysuj trójkąt z gwiazdką”, nie jestem do końca pewien, czy nazwanie tego wyzwania duplikatem jest uczciwe. Jest to jednak zdecydowanie powiązane.
— Sherlock9,

19
Ponieważ nie wszyscy tutaj znają pełny kontekst, OP pierwotnie opublikował „Narysuj trójkąt z gwiazdką” i zredagował to wyzwanie jako dodatkowe wyzwanie. Powiedzieliśmy im, aby usunęli tę część i uczynili z niej inne wyzwanie (co zrobili). To wyzwanie nie jest duplikatem. OP robi to, co zalecało wielu użytkowników o wysokiej liczbie powtórzeń, a nawet kilka modów poleciło.
— DJMcMayhem

2
@JDL: Nie, dlaczego miałbyś? Ach, teraz rozumiem, co miałeś na myśli przez kwadrat ... :-D
— Sickboy

Odpowiedzi:


20

Węgiel , 6 bajtów

G↘←↗N*

Zupełnie proste. Wyciągnąć poli G o o *, o długości boku pobranej z wejścia N umbra, gdzie boki przejść dół i w prawo, w lewo, w poziomie i w górę i w prawo:

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

Następnie wypełnij kontur automatycznie i wypełnij go.

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

Wypróbuj online!


Hah, to całkiem dziwne!
— CT14.IT

6
Ten język jest bardzo interesujący! Od tego momentu będę bacznie obserwował: s.
— Adnan

Nie widziałem tego języka wcześniej ... Wygląda interesująco! Zastanawiam się, co byś otrzymał, gdybyś jakoś połączył to z galaretką ...
— Esolanging Fruit

12

Python 2, 57 bajtów

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

Pełny program. Przechodzi linia po linii, wypisując odpowiednią liczbę gwiazdek na środku.

Funkcja rekurencyjna była dłuższa (67 bajtów):

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

lub

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

Chciałem zaproponować próbuje zastąpić maxze związkiem abs, ale wszystko co mam to abs(n-1)+1, co jest gorsze, ponieważ dodatek wymaga nawiasów
— njzk2

@ njzk2 Możesz przycinać parens, robiąc to '*'*-~abs(n-1), ale wtedy ma ona taką samą długość jak '*'*max(n,2-n).
— xnor

Jest def f(n,s=''):r=s+'*'*n+'\n';return 1/n*r or r+f(n-2,s+' ')+rna 61 bajtów, ale wciąż jest dłuższy. Nawet z wiodącą nową linią def f(n,s='\n'):r=s+'*'*n;return 1/n*r or r+f(n-2,s+' ')+rwciąż ma 58 bajtów ...
— Dennis

+1 za nauczenie mnie o center. Nigdy nie wiedziałem, że istniało do tej pory.
— DLosc

11

V , 12 bajtów

Àé*hòl3Äjxx>

Wypróbuj online!

Lubię takie wyzwania, ponieważ mogę pochwalić się zaletami natury 2D 2D. Wyjaśnienie. Najpierw musimy utworzyć ciąg n gwiazdek. Robimy to:

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

Na marginesie, jest to bezpośrednio równoważne z @ai*<esc>vim, a rejestr @ajest wstępnie inicjowany na „arg1”. Dzięki temu wprowadzanie numeryczne jest znacznie wygodniejsze.

Następnie poruszamy się postacią w prawo za pomocą h. Oto część zabawy:

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

Teraz technicznie ta ostatnia część jest

òl3Äjxx>>ò

Ponieważ tak naprawdę jest polecenie wcięcia >>. V dogodnie zakłada, że ​​niekompletne polecenia dotyczą bieżącej linii, a także domyślnie wypełnia drugi òznak w celu zapętlenia.


10

C ++ Metatemplates, 186 bajtów

Z wyraźną formułą z mojej odpowiedzi C, Metatemplates konkurują!

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

Nie golfowany:

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

stosowanie:

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

niekonkurujący

Dla zabawy:

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

Stosowanie:

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

2
+1 za pokonanie PHP najdłużej
— rozwijaną

7

PowerShell v2 +, 54 bajty

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

Zajmuje wejście $n(gwarantowane być nieparzysta liczba całkowita), konstruuje dwa zakresy z $n..1a 2..$ni łączy je ze sobą, a następnie używa Where-Object, aby wybrać tylko te z nieparzystych |?{$_%2}. Te są wprowadzane do pętli. W każdej iteracji konstruujemy odpowiednią liczbę spacji, połączonych ciągiem znaków z odpowiednią liczbą gwiazdek. Te ciągi są pozostawione w potoku, a dane wyjściowe za pośrednictwem niejawnych Write-Outputwstawia między nimi nowe wiersze po zakończeniu programu.

Przykłady

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

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

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

7

Python, 78 bajtów

Tylko z wcięciem:

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

Stosowanie:

print f(5)

6

C, 114 109 bajtów

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

bez golfa:

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

Poprzednie rozwiązanie rekurencyjne:

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 bajtów

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

Chodzi o to, aby wygenerować każdą klepsydrę z poprzedniej: dodaj spację na początku każdej linii oraz dodawaj i dodawaj ngwiazdki.


4

05AB1E , 21 20 19 17 bajtów

Zaoszczędzono 2 bajty dzięki carusocomputing

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

Wypróbuj online!

Wyjaśnienie

;ƒ                   # 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û- Dotarłem tak daleko, twarz zbladła, kiedy zdałem sobie sprawę, jak daleko jestem, zobaczyłem, że odpowiedziałeś, idziesz spróbować nauczyć się iteracji w tym języku, korzystając teraz z tego przykładu. Dzięki!
— Magic Octopus Urn

4
Mogę faktycznie pomóc choć raz: ;ƒ'*¹N·-×Nð×ì})û»użyj nowego polecenia palindromize. -2 bajty.
— Magic Octopus Urn

@carusocomputing: Dzięki! Nie wiedziałem o poleceniu palendromize (nie odświeżyłem dokumentów). Bardzo przydatne. Potrzebowałem go już kilka razy :)
— Emigna

9 bajtów , nawet w starszej wersji. Chociaż jestem prawie pewien, że wbudowane ÅÉi .cprawdopodobnie nie były jeszcze dostępne w momencie, gdy to opublikowałeś. :)
— Kevin Cruijssen

4

MATL , 12 bajtów

Q2/Zv&<~42*c

Wypróbuj online!

Wyjaśnienie

Wykorzystuje to ostatnio dodaną funkcję zakresu symetrycznego .

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

Miły! To fajna funkcja. To jedyna odpowiedź, która zbliżyła się do mojej odpowiedzi V, więc teraz mam obsesję na punkcie usunięcia jednego lub dwóch bajtów. : D
— DJMcMayhem

@DJMcMayhem Heh, nie sądzę, że będę w stanie zmniejszyć liczbę bajtów w tym przypadku
— Luis Mendo

Tak, nie sądzę, żebym mógł. Prawdopodobnie za kilka minut pojawi się 4-bajtowa galaretka, hahaha ...
— DJMcMayhem

4

PHP, 95 bajtów

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

Zamiast zapisywać wiersze w tablicy, a następnie wyprowadzać wszystko, pętla for przechodzi w dół do 1, a następnie wraca do pierwotnej liczby.


3

C ++ 11, 93 bajty

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

Nieznacznie nie golfista:

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

Stosowanie:

std::cout << f(5);

Miły! jeden bajt można zapisać zakładając ASCII i zastąpienie '\n'ze 10:)
— Quentin


3

R, 77 bajtów

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

Tworzy macierz znaków, którą następnie drukuje cat, fill=nupewniając się, że linie są odpowiednio wyrównane. Zauważ, że elementy są przechowywane w macierzy jako pierwsze w kolumnie (tzn. Pierwsze dwa elementy są, M[1,1]a M[2,1]nie M[1,2]).


3

Java 7, 170 165 164 bajty

Dzięki @Hypino za oszczędność 5 bajtów.
Dzięki Kevinowi za uratowanie 1 bajtu.

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:"*";} 

Można zapisać 2 bajty, których autorem jest usunięcie s=z s=s+"\n"i 2 więcej bajtów, zmieniając return(n=--n-1)się return(n=n-2)w sumie 4 bajty.
— Hypino,

Cześć. Możesz grać w golfa w dwie części: String s="",c="",t="";do String s,c,t=s=c="";( -2 bajtów ) i return(n=n-2)>=0?s+"\n"+c+c(n,++x)+do return n-1>0?s+"\n"+c+c(n-2,++x)+( ponownie -2 bajtów )
— Kevin Cruijssen

Ale wzorzec @KevinCruijssen nie zmienia się zgodnie z oczekiwaniami po zmianie n=n-2->, n-1>0ponieważ n powinno być użyte w innym argumencie funkcji.
— Numberknot

@Numberknot wiem, ale też zmieniło nsię n-2w tej części. return(n=n-2)>=0 ... nzmiana na return n-1>0 ... n-2jest wciąż krótsza. PS: Podziękowałeś mi za zapisanie bajtów, ale nie zmieniłeś kodu w swojej edycji. ;)
— Kevin Cruijssen

@Numberknot Umm .. nadal zapomniałeś mojej drugiej wskazówki. W każdym razie, tutaj jest krótszy wariant: 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:"*";}bez t( test ideone - 133 bajty )
— Kevin Cruijssen

3

PHP - 95 bajtów

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

Zapisano bajt, używając rzeczywistej nowej linii zamiast "\r"


2

Pyth, 22 bajty

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

Program, który pobiera liczbę całkowitą na STDIN i wypisuje wynik.

Wypróbuj online

Jak to działa

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 bajtów

Powinieneś grać w golfa nieco mniej

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

Możemy to przetestować tutaj na ideone


2

C, 79 bajtów

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

Dzieli zmienną odliczania kna indeksy wierszy i kolumn. Jeśli indeks kolumny to 0 (ostatni znak z rzędu), to wypisuje znak nowej linii (10). Następnie dopasowuje indeksy wierszy i kolumn wokół środkowej gwiazdki. Zatem abs(x) < abs(y)jest krótki warunek wyprowadzenia spacji.



2

Java 7, 156 bajtów

Dość proste. Śledzi linie z n, gwiazdy z j, spacje si kierunek z d. Naprawdę chciałem po prostu nierekurencyjnej odpowiedzi Java na tablicy, ale nie szkodzi, że jest ona również nieco krótsza :)

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

Z podziałami linii:

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 bajtów

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

Test:

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

Wyjaśnienie:

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

Wystarczy usunąć 1+i użyć APL, który ma ⎕IO←0.
— Adám

2

Haskell, 84 bajty

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

Fajne rozwiązanie! Ale jestem pewien, że nie trzeba putStri można pozbyć się fromEnumjak ten .
— ბიმო



2

PHP ,104 88 bajtów

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

Wypróbuj online!

To nie bije najniższych wyników dla PHP w tym wyzwaniu, ale jest to po prostu zbyt szalone, żebym go wyrzucił.

Ok, więc grałem w golfa, aby być (nie na długo) najniższym wynikiem dla PHP w tym wyzwaniu, ale to nie zmienia faktu, że wciąż jest szalony.

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

83? także huh, php ma też słowa kluczowe, chociaż tutaj nie jest to przydatne
— tylko ASCII

@ Szczury tylko ASCII! Wygląda na to, że mam jeszcze trochę pracy! lol
— 640KB



@ Tak, tylko ASCII, ładnie zrobione! To z pewnością właściwe podejście!
— 640 KB


1

PHP, 191 bajtów

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

Biegnij jak php -f golf_hourglass.php 15

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

Chodzi o to, aby stworzyć górną połowę (część przed singlem *), a następnie po prostu powtórzyć górną część dwa razy, ale za drugim razem w odwrotnej kolejności.


Myślę, że to lepszy początek tego zadaniafor(;$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;tak jest lepiej
— Jörg Hülsermann

Zamień implode () na join (), aby zapisać 6 bajtów.
— Alex Howansky

Zastąp \nrzeczywistą nową linią, aby zapisać bajt.
— Alex Howansky

1

Pyke, 22 19 bajtów

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

Wypróbuj tutaj!

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 bajtów

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

Bez golfa

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);
  }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.