Disegna una clessidra


32

Ancora una volta ispirato da un'attività per la programmazione 101, ecco un'altra sfida.

Ingresso:

  • Un numero intero positivo n >= 3. (deve essere strano)

Produzione:

  • nlinee di asterischi, in cui la prima linea ha nasterischi e ogni nuova linea ha due asterischi in meno rispetto alla linea precedente. Fino a quando non si colpisce 1 asterisco. Da lì ogni nuova linea ha due asterischi in più rispetto alla linea precedente fino a tornare an asterischi. Gli spazi o qualcosa di simile agli spazi devono essere utilizzati per allineare gli asterischi in modo che sembrino davvero una clessidra.

Regole generali:

  • Le nuove righe finali sono consentite ma non devono essere utilizzate.
  • il rientro è d'obbligo.
  • Questo è code-golf, quindi vince la risposta più breve in byte.
  • Poiché il corso è tenuto in C ++, non vedo l'ora di vedere soluzioni in C ++.

Caso di prova (n = 5):

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

modificato di conseguenza, grazie :-)
Sickboy,

3
Possibile duplicato di Disegna un triangolo di asterisco
Oliver Ni

3
@Oliver Considerando che OP ha scritto "Disegna un triangolo asterisco", non sono del tutto sicuro che chiamare questa sfida un duplicato sia giusto. È sicuramente correlato, però.
Sherlock9

19
Poiché non tutti qui conoscono l'intero contesto, OP inizialmente ha pubblicato il "Disegna un triangolo di asterisco" e ha modificato questa sfida come sfida aggiuntiva. Abbiamo detto loro di rimuovere quella parte e renderla una sfida diversa (cosa che hanno fatto). Questa sfida non è un duplicato. OP sta facendo ciò che molti utenti ad alta reputazione, e anche alcune mod hanno raccomandato.
DJMcMayhem

2
@JDL: No, perché dovresti? Ah, ora capisco cosa intendevi per quadrato ...
MrGreen

Risposte:


20

Carbone , 6 byte

G↘←↗N*

Semplicemente morto. Disegna un poli G su di *, con la lunghezza del lato presa da un input N umber, in cui i lati vanno verso il basso e verso destra, orizzontalmente a sinistra e verso l'alto e verso destra:

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

Quindi completare automaticamente il contorno e riempirlo.

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

Provalo online!


Hah, that's pretty bonkers!
CT14.IT

6
This language is very interesting! I'll be watching this very closely from now on :p.
Adnan

Haven't seen this language before... Looks interesting! I wonder what you'd get if you combined it with Jelly somehow...
Esolanging Fruit

12

Python 2, 57 bytes

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

A full program. Goes line by line, printing the right number of asterisks centered.

A recursive function was longer (67 bytes):

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

or

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

I wanted to suggest trying to replace the max with an abs, but all I got is abs(n-1)+1, which is worse because the addition requires parenthesis
njzk2

@njzk2 You can cut the parens by doing '*'*-~abs(n-1), but then it's the same length as '*'*max(n,2-n).
xnor

There's def f(n,s=''):r=s+'*'*n+'\n';return 1/n*r or r+f(n-2,s+' ')+r for 61 bytes, but it's still longer. Even with a leading newline, def f(n,s='\n'):r=s+'*'*n;return 1/n*r or r+f(n-2,s+' ')+r is still 58 bytes...
Dennis

+1 for teaching me about center. Never knew that existed till now.
DLosc

11

V, 12 bytes

Àé*hòl3Äjxx>

Try it online!

I like challenges like this because I get to show off the advantages of V's 2D nature. Explanation. First, we need to create a string of n asterisks. So, we do this:

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

As a side note, this is directly equivalent to @ai*<esc> in vim, and register @a is pre-initialized to "arg1". This makes numeric input much more convenient.

Then, we move on character to the right with h. Here is the fun part:

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

Now technically, this last part is

òl3Äjxx>>ò

Because the indent command is actually >>. V conveniently assumes incomplete commands apply to the current line, and also implicitly fills in the second ò character for looping.


10

C++ Metatemplates, 186 bytes

With the explicit formula from my C answer the Metatemplates are competing!

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

usage:

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

non-competing

Just for the sake of fun:

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

Usage:

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

2
+1 for beating PHP with the most long-winded part of C++
matsjoyce

7

PowerShell v2+, 54 bytes

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

Takes input $n (guaranteed to be an odd integer), constructs two ranges with $n..1 and 2..$n and concatenates them together, then uses Where-Object to select only the odd ones with |?{$_%2}. Those are fed into a loop. Each iteration, we construct the appropriate number of spaces, string-concatenated with the appropriate number of asterisks. Those strings are left on the pipeline, and output via implicit Write-Output inserts newlines between them at program completion.

Examples

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

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

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

7

Python, 78 bytes

So only with indentation:

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

Usage:

print f(5)

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

Previous recursive solution:

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 bytes

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

The idea here is to generate each hourglass from the previous: add a space at the beginning of every line, and both prepend and append n asterisks.


4

05AB1E, 21 20 19 17 bytes

Saved 2 bytes thanks to carusocomputing

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

Try it online!

Explanation

;ƒ                   # 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û - Got this far, face palmed when I realized how far off I was, saw you had answered, going to go try to learn iteration in this language now using this example. Thanks!
Magic Octopus Urn

4
I can actually help for once: ;ƒ'*¹N·-×Nð×ì})û» use the new palindromize command. -2 bytes.
Magic Octopus Urn

@carusocomputing: Thanks! I didn't know about the palendromize command (I hadn't refreshed the docs). Very useful. Have needed it several times before :)
Emigna

9 bytes, even in the legacy. Although I'm pretty sure the builtins ÅÉ and .c probably weren't available yet at the time you posted this. :)
Kevin Cruijssen

4

MATL, 12 bytes

Q2/Zv&<~42*c

Try it online!

Explanation

This makes use of the recently added symmetric range function.

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

Nice! That's a cool feature. This is the only answer that came close to my V answer, so now I'm going to obsess on taking off one or two bytes. :D
DJMcMayhem

@DJMcMayhem Heh, I don't think I will be able to reduce the byte count on this one
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

Groovy, 66 Bytes

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

Try it: https://groovyconsole.appspot.com/script/5145735624392704

Explained:

((n..1)+(2..n)) - Reverse palindromize to n [n,..,1,..,n]

.each{if(it%2>0){...} - Iterate through odd elements.

println(("*"*it).center(n)) - Center n stars and print each on newline.


.each's code block could be {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));

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);
  }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.