Desenhe uma ampulheta

32

Novamente inspirado por uma tarefa da Programação 101, aqui está outro desafio.

Entrada:

  • Um número inteiro positivo n >= 3. (tem que ser impar)

Saída:

  • nlinhas de asteriscos, em que a primeira linha possui nasteriscos e cada nova linha possui dois asteriscos a menos que a linha anterior. Até atingir 1 asterisco. A partir daí, toda nova linha possui dois asteriscos a mais que a linha anterior, até voltar ao nasterisco. Espaços ou algo parecido com espaços devem ser usados ​​para alinhar os asteriscos, para que realmente pareça uma ampulheta.

Regras gerais:

  • Novas linhas à direita são permitidas, mas não precisam ser usadas.
  • recuo é uma obrigação.
  • Isso é código-golfe, então a resposta mais curta em bytes vence.
  • Como o curso é ministrado em C ++, estou ansioso para ver soluções em C ++.

Caso de teste (n = 5):

*****
 ***
  *
 ***
*****
Sickboy
fonte
editadas em conformidade, graças :-)
Sickboy
3
Possível duplicata de Desenhe um triângulo de asterisco #
Oliver Ni
3
Considerando que o OP escreveu "Desenhe um triângulo de asterisco", não tenho muita certeza de que chamar esse desafio de duplicata seja justo. É definitivamente relacionado, no entanto.
Sherlock9
19
Como nem todos aqui conhecem o contexto completo, o OP publicou originalmente o "Desenhe um triângulo de asterisco" e editou esse desafio como um desafio adicional. Dissemos a eles para remover essa parte e torná-la um desafio diferente (o que eles fizeram). Este desafio não é uma duplicata. O OP está fazendo o que muitos usuários de alta reputação, e até alguns mods recomendaram.
DJMcMayhem
2
@JDL: Não, por que você faria? Ah, agora eu entendo o que você entende por quadrado ... :-D
Sickboy

Respostas:

20

Carvão , 6 bytes

G↘←↗N*

Simplesmente morto. Desenhe um G poli de *, com o comprimento lateral retirado de uma entrada N úmero, onde os lados ir para baixo e para a direita, horizontalmente para a esquerda, e para cima-e-direita:

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

Em seguida, preencha automaticamente o contorno e preencha-o.

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

Experimente online!

DLosc
fonte
Hah, isso é muito louco!
CT14.IT 26/10/16
6
Essa linguagem é muito interessante! De agora em diante, observarei isso de perto: p.
Adnan
Você nunca viu esse idioma antes ... Parece interessante! Eu me pergunto o que você conseguiria se combinasse com Jelly de alguma forma ...
Esolanging Fruit
12

Python 2, 57 bytes

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

Um programa completo. Vai linha por linha, imprimindo o número certo de asteriscos centralizados.

Uma função recursiva era mais longa (67 bytes):

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

ou

f=lambda n,p='':1/n*(p+'*\n')or f(n-2,p+' ').join([p+n*'*'+'\n']*2)
xnor
fonte
Eu queria sugerir tentar substituir o maxpor um abs, mas tudo o que tenho é o abs(n-1)+1que é pior porque a adição requer parênteses
njzk2
@ njzk2 Você pode cortar os parênteses fazendo '*'*-~abs(n-1), mas depois tem o mesmo comprimento que '*'*max(n,2-n).
xnor
def f(n,s=''):r=s+'*'*n+'\n';return 1/n*r or r+f(n-2,s+' ')+r61 bytes, mas ainda é mais longo. Mesmo com uma nova linha líder, def f(n,s='\n'):r=s+'*'*n;return 1/n*r or r+f(n-2,s+' ')+rainda há 58 bytes ...
Dennis
+1 por me ensinar sobre center. Nunca soube que existia até agora.
DLosc
11

V , 12 bytes

Àé*hòl3Äjxx>

Experimente online!

Gosto de desafios como esse, porque mostro as vantagens da natureza 2D do V. Explicação. Primeiro, precisamos criar uma sequência de n asteriscos. Então, fazemos isso:

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

Como uma observação lateral, isso é diretamente equivalente ao @ai*<esc>no vim, e o registro @aé pré-inicializado para "arg1". Isso torna a entrada numérica muito mais conveniente.

Então, passamos o personagem à direita com h. Aqui está a parte divertida:

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

Agora tecnicamente, esta última parte é

òl3Äjxx>>ò

Como o comando indent é realmente >> . V pressupõe convenientemente que comandos incompletos se aplicam à linha atual e também preenche implicitamente o segundo òcaractere para loop.

DJMcMayhem
fonte
10

Metatemplates C ++, 186 bytes

Com a fórmula explícita da minha resposta C, os Metatemplates estão competindo!

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

Ungolfed:

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

uso:

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

não concorrente

Apenas por diversão:

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

Uso:

std::cout << H<5>().r;
Karl Napf
fonte
2
+1 para vencer o PHP com a parte mais demorada do C ++ #
matsjoyce 25/10
7

PowerShell v2 +, 54 bytes

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

Leva entrada $n(garantia de ser um número inteiro ímpar), constrói dois intervalos com $n..1e 2..$ne encadeia-los juntos, em seguida, utilizaWhere-Object a seleccionar apenas os ímpares com|?{$_%2} . Aqueles são alimentados em um loop. A cada iteração, construímos o número apropriado de espaços, concatenados com o número apropriado de asteriscos. Essas seqüências são deixadas no pipeline e a saída via implícita Write-Outputinsere novas linhas entre elas na conclusão do programa.

Exemplos

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

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

*******
 *****
  ***
   *
  ***
 *****
*******
AdmBorkBork
fonte
7

Python, 78 bytes

Portanto, apenas com recuo:

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

Uso:

print f(5)
Karl Napf
fonte
6

C, 114 109 bytes

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

ungolfed:

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

Solução recursiva anterior:

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);}
Karl Napf
fonte
5

JavaScript (ES6), 66 bytes

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

A idéia aqui é gerar cada ampulheta a partir da anterior: adicione um espaço no início de cada linha e inclua nasteriscos antes e depois .

ETHproductions
fonte
4

05AB1E , 21 20 19 17 bytes

Economizou 2 bytes graças a carusocomputing

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

Experimente online!

Explicação

;ƒ                   # 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
Emigna
fonte
Ir"*"×.pRû- Cheguei tão longe, cara pálida quando percebi o quão longe eu estava, vi que você tinha respondido, indo tentar aprender a iteração neste idioma agora usando este exemplo. Obrigado!
Magic Octopus Urn
4
Na verdade, posso ajudar pela primeira vez: ;ƒ'*¹N·-×Nð×ì})û»use o novo comando palindromize. -2 bytes.
Magic Octopus Urn
@carusocomputing: Obrigado! Eu não sabia sobre o comando palendromize (não havia atualizado os documentos). Muito útil. Precisado várias vezes antes :)
Emigna
9 bytes , mesmo no legado. Embora eu tenha certeza de que os componentes internos ÅÉe .cprovavelmente ainda não estavam disponíveis no momento em que você postou isso. :)
Kevin Cruijssen
4

MATL , 12 bytes

Q2/Zv&<~42*c

Experimente online!

Explicação

Isso faz uso da função de faixa simétrica adicionada recentemente .

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: ['*****'
                ' *** '
                '  *  '
                ' *** '
                '*****']
Luis Mendo
fonte
Agradável! Esse é um recurso interessante. Esta é a única resposta que se aproximou da minha resposta V, então agora eu vou ficar obcecado em tirar um ou dois bytes. : D
DJMcMayhem
@DJMcMayhem Heh, eu não acho que eu vou ser capaz de reduzir a contagem de bytes em um presente
Luis Mendo
Sim, acho que também não posso. Provavelmente haverá uma resposta de 4 bytes da Jelly em alguns minutos, 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)."
";

Em vez de armazenar as linhas em uma matriz e depois produzir tudo, o loop for desce até 1 e depois volta ao número original.

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

Ligeiramente não destruído:

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

Uso:

std::cout << f(5);
Karl Napf
fonte
Agradável! um byte pode ser salvo, assumindo ASCII e substituindo '\n'com 10:)
Quentin
3

MATL , 20 bytes

XyY>t1X!*t2X!+ZS42*c

Experimente online!

DJMcMayhem
fonte
Você pode economizar alguns bytes com a função gama simétrica introduziu recentemente: Q2 / Zv & <~ 42 * c
Luis Mendo
@LuisMendo Isso é legal! Como é uma abordagem completamente diferente, deixarei você entender.
DJMcMayhem
Ok, eu vou postar!
Luis Mendo
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)

Cria uma matriz de caracteres, que é impressa via cat, fill=ngarantindo que as linhas estejam alinhadas corretamente. Observe que os elementos são armazenados em uma matriz primeiro (ou seja, os dois primeiros elementos são M[1,1]e M[2,1], não M[1,2]).

JDL
fonte
3

Java 7, 170 165 164 bytes

Agradecemos ao @Hypino por salvar 5 bytes.
Agradecemos a Kevin por economizar 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:"*";} 
Numberknot
fonte
Você pode salvar 2 bytes por remoção s=do s=s+"\n"e mais 2 bytes mudando return(n=--n-1)para return(n=n-2)um total de 4 bytes.
Hypino # 25/16
Oi. Você pode golfe duas partes: String s="",c="",t="";a String s,c,t=s=c="";( -2 bytes ) e return(n=n-2)>=0?s+"\n"+c+c(n,++x)+para return n-1>0?s+"\n"+c+c(n-2,++x)+( -2 bytes novamente)
Kevin Cruijssen
Mas o padrão @KevinCruijssen não é o esperado após a alteração n=n-2-> n-1>0porque n deve ser usado em outro argumento de uma função.
Numberknot
@ Numberknot eu sei, mas também mudei npara n-2nessa parte. return(n=n-2)>=0 ... nser alterado para return n-1>0 ... n-2ainda é mais curto. PS: Você me agradeceu por salvar bytes, mas não alterou seu código em sua edição. ;)
Kevin Cruijssen 26/10
@ Numberknot Umm .. você ainda esqueceu minha segunda dica. Enfim, aqui é uma variante mais curta: 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:"*";}sem a t( teste ideone - 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)."
";

Salve um byte usando uma nova linha real em vez de uma "\r"

CT14.IT
fonte
2

Pitão, 22 bytes

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

Um programa que recebe a entrada de um número inteiro em STDIN e imprime o resultado.

Experimente online

Como funciona

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
TheBikingViking
fonte
2

C, 195 191 bytes

Deveria jogar golfe um pouco menor

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

Podemos testá-lo aqui em ideone

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

Ele divide a variável de contagem regressiva kem índices de linha e coluna. Se o índice da coluna for 0 (último caractere em uma linha), ele emitirá um caractere de nova linha (10). Em seguida, ajusta os índices de linha e coluna para ficarem em torno do asterisco central. Então,abs(x) < abs(y) é uma condição curta para gerar um espaço.

anatolyg
fonte
2

Ruby, 55 54 bytes

f=->n,s=0{puts a=' '*s+?**n;(f[n-2,s+1];puts a)if n>1}
Lee W
fonte
?**ntrabalho; você não precisa do espaço lá.
Value Ink
2

Java 7, 156 bytes

Relativamente simples. Mantém o controle de linhas com n, estrelas com j, espaços com se direção com d. Eu realmente só queria uma resposta Java não recursiva no quadro, mas não faz mal que também seja um pouco mais curto :)

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

Com quebras de linha:

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;
}
Geobits
fonte
2

APL, 19 bytes

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

Teste:

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

Explicação:

                 ⎕   ⍝ 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
marinus
fonte
Basta remover 1+e usar um APL que possui ⎕IO←0.
Adám 31/10/16
2

Haskell, 84 bytes

f n|l<-div n 2,k<-[-l..l]=putStr$unlines[[" *"!!(fromEnum$abs x<=abs y)|x<-k]|y<-k]
Angs
fonte
Ótima solução! Mas eu tenho certeza que você não precisa do putStre você pode se livrar do fromEnumcomo este .
ბიმო
2

C (gcc) , 80 74 bytes

Obrigado roofcat por 6 bytes

-Du(x,k)=for(x=~n;x+=2,x<n;putchar(k))

i;j;f(n){u(i,10)u(j,i*i<j*j?32:42);}

Experimente online!

l4m2
fonte
2

PHP ,104 88 bytes

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

Experimente online!

Isso não supera as pontuações mais baixas do PHP nesse desafio, mas é muito louco para eu jogar fora.

Ok, então eu joguei agora que é a pontuação mais baixa (não por muito tempo) para o PHP nesse desafio, mas isso não muda o fato de que ainda é uma loucura.

$ echo 7|php -nF hour.php
*******
 *****
  ***
   *
  ***
 *****
*******
640KB
fonte
83? também hein, o php também tem palavras-chave, embora não seja útil aqui
ASCII-only
@ Ratos apenas ASCII! Parece que tenho mais trabalho a fazer! lol
640KB 12/04
11
82? alternativa 82
somente ASCII
@ Sim apenas ASCII, muito bem feito! Essa é com certeza a abordagem correta!
640 KB
1

Groovy, 66 bytes

{n->((n..1)+(2..n)).each{if(it%2>0){println(("*"*it).center(n))}}}

Experimente: https://groovyconsole.appspot.com/script/5145735624392704

Explicado:

((n..1)+(2..n)) - Palindromize reverso para n [n,..,1,..,n]

.each{if(it%2>0){...} - Iterar através de elementos ímpares.

println(("*"*it).center(n)) - Centralize n estrelas e imprima cada uma na nova linha.

Urna de polvo mágico
fonte
.eachO código do bloco pode ser {it%2&&println(("*"*it).center(n))}.
manatwork
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));

Corra como php -f golf_hourglass.php 15

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

A idéia por trás disso é criar a metade superior (a parte antes do single * ) e depois repetir a parte superior duas vezes, mas a segunda vez na ordem inversa.

ʰᵈˑ
fonte
Acho que este é um começo melhor para esta tarefafor(;$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;isso é melhor
Jörg Hülsermann 25/10
Substitua implode () por join () para economizar 6 bytes.
Alex Howansky
Substitua \npor uma nova linha real para salvar um byte.
Alex Howansky
1

Pyke, 22 19 bytes

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

Experimente aqui!

F          )        -    for i in range(input)
 -                  -        Q-i
  e                 -       floor(^/2)
   d*               -      ^*" "
          +         -     ^+V
     ih             -       i+1
       \**          -      ^*"*"
            2%      -   ^[::2]
              'X_   - splat(^),
                       reversed(^)
                 OX - splat(^[:-1])
Azul
fonte
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);
  }
}
Kerndog73
fonte