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.