Draw an hourglass

32

4

Again inspired by a task for Programming 101 here's another challenge.

Input:

  • A positive integer n >= 3. (has to be odd)

Output:

  • n lines of asterisks, where the first line has n asterisks and every new line has two asterisks less than the line before. Until hitting 1 asterisk. From there every new line has two asterisks more than the line before until getting back to n asterisks. Spaces or something like spaces have to used to align the asterisks so that it really will look like an hourglass.

General rules:

  • Trailing newlines are allowed but do not have to be used.
  • indentation is a must.
  • This is code-golf, so shortest answer in bytes wins.
  • Since the course is taught in C++, I'm eager to see solutions in C++.

Test case (n=5):

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

Sickboy

Posted 2016-10-25T11:16:41.633

Reputation: 1 075

edited accordingly, thanks :-) – Sickboy – 2016-10-25T11:42:12.227

I don't see how this is the duplicate of "Draw an asterisk triangle". This has indentation and a down-up sequence where the triangle is only upwards. – Karl Napf – 2016-10-25T11:51:09.840

@KarlNapf: Before the last edit you had the option of printing it without indentation meaning it was just a triangle from the other question printed as in that question and once in reverse. – Emigna – 2016-10-25T11:55:09.863

@Emigna Yes i know, already answered like that. But now it isnt anymore, so it should be open again. – Karl Napf – 2016-10-25T11:57:31.467

3

Possible duplicate of Draw an asterisk triangle

– Oliver Ni – 2016-10-25T14:59:52.370

3@Oliver Considering OP wrote "Draw an asterisk triangle", I'm not entirely sure that calling this challenge a duplicate is fair. It is definitely related, though. – Sherlock9 – 2016-10-25T16:01:46.713

Can we assume the input is always >=3 and always odd? – ʰᵈˑ – 2016-10-25T16:04:01.433

19Since not everyone here knows the full context, OP originally posted the "Draw an asterisk triangle" and edited this challenge in as an additional challenge. We told them to remove that part and make it a different challenge (which they did). This challenge is not a duplicate. OP is doing what many high rep users, and even a few mods have recommended. – James – 2016-10-25T16:08:16.257

@closevoters could you remove your dupe votes? This question is no longer a duplicate of that question – Blue – 2016-10-25T19:16:09.573

Is it necessary to have enough trailing spaces to make the output square, or is "*****\n ***\n *\n *\n***" acceptable output? (With two spaces before the single asterisk, which SO edits to a single space!) – JDL – 2016-10-26T08:03:01.360

@JDL: As outlined in the rules, it has to be "square" (i.e. has to use indentation). – Sickboy – 2016-10-26T08:06:01.503

@ʰᵈˑ: yes, you don't have to check the input as this would lengthen the code unnecessarily. – Sickboy – 2016-10-26T08:07:03.587

@Sickboy I get that the stars have to align, but do we need any spaces to the right of the stars? – JDL – 2016-10-26T08:23:41.173

2@JDL: No, why would you? Ah, now I understand what you meant by square... :-D – Sickboy – 2016-10-26T08:34:38.743

Answers

20

Charcoal, 6 bytes

G↘←↗N*

Dead simple. Draw a polyGon of *, with side length taken from an input Number, where the sides go down-and-right, horizontally left, and up-and-right:

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

Then autocomplete the outline and fill it.

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

Try it online!

DLosc

Posted 2016-10-25T11:16:41.633

Reputation: 21 213

Hah, that's pretty bonkers! – CT14.IT – 2016-10-26T20:33:50.910

6This language is very interesting! I'll be watching this very closely from now on :p. – Adnan – 2016-10-26T21:24:13.317

Haven't seen this language before... Looks interesting! I wonder what you'd get if you combined it with Jelly somehow... – Esolanging Fruit – 2016-10-31T04:19:53.833

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)

xnor

Posted 2016-10-25T11:16:41.633

Reputation: 115 687

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 – 2016-10-25T21:39:52.123

@njzk2 You can cut the parens by doing '*'*-~abs(n-1), but then it's the same length as '*'*max(n,2-n). – xnor – 2016-10-25T23:02:16.357

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 – 2016-10-27T04:09:28.023

+1 for teaching me about center. Never knew that existed till now. – DLosc – 2016-10-31T04:38:37.013

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.

James

Posted 2016-10-25T11:16:41.633

Reputation: 54 537

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;

Karl Napf

Posted 2016-10-25T11:16:41.633

Reputation: 4 131

2+1 for beating PHP with the most long-winded part of C++ – matsjoyce – 2016-10-25T20:02:48.970

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

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

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

AdmBorkBork

Posted 2016-10-25T11:16:41.633

Reputation: 41 581

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)

Karl Napf

Posted 2016-10-25T11:16:41.633

Reputation: 4 131

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

Karl Napf

Posted 2016-10-25T11:16:41.633

Reputation: 4 131

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.

ETHproductions

Posted 2016-10-25T11:16:41.633

Reputation: 47 880

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

Emigna

Posted 2016-10-25T11:16:41.633

Reputation: 50 798

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 – 2016-10-25T18:01:35.427

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

@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 – 2016-10-25T18:09:28.273

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 – 2019-04-12T06:45:28.000

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

Luis Mendo

Posted 2016-10-25T11:16:41.633

Reputation: 87 464

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 – James – 2016-10-25T21:24:00.303

@DJMcMayhem Heh, I don't think I will be able to reduce the byte count on this one – Luis Mendo – 2016-10-25T21:25:46.783

Yeah, I don't think I can either. There'll probably be a 4-byte Jelly answer in a couple minutes anyway, hahaha... – James – 2016-10-25T21:27:24.997

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.

chocochaos

Posted 2016-10-25T11:16:41.633

Reputation: 547

3

PowerShell, 54 50 bytes

filter f{if($_-1){'*'*$_;($_-2)|f|%{" $_"}}'*'*$_}

Try it online!

mazzy

Posted 2016-10-25T11:16:41.633

Reputation: 4 832

3

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
*******
 *****
  ***
   *
  ***
 *****
*******

640KB

Posted 2016-10-25T11:16:41.633

Reputation: 7 149

83? also huh, php has barewords too, although it's not useful here – ASCII-only – 2019-04-12T23:15:28.867

@ASCII-only rats! Looks like I've got some more work to do! lol – 640KB – 2019-04-12T23:16:31.227

182? alternative 82 – ASCII-only – 2019-04-12T23:17:46.240

with proper flags :P sadly, this is longer – ASCII-only – 2019-04-12T23:20:43.473

@ASCII-only yep, nicely done! That's for sure the right approach! – 640KB – 2019-04-12T23:24:53.287

ouch, that didn't work :/ – ASCII-only – 2019-04-12T23:37:05.700

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

Karl Napf

Posted 2016-10-25T11:16:41.633

Reputation: 4 131

Nice! one byte can be saved by assuming ASCII and replacing '\n' with 10 :) – Quentin – 2016-10-26T14:30:08.113

3

MATL, 20 bytes

XyY>t1X!*t2X!+ZS42*c

Try it online!

James

Posted 2016-10-25T11:16:41.633

Reputation: 54 537

You can save a few bytes with the recently introduced symmetric range function: Q2/Zv&<~42*c – Luis Mendo – 2016-10-25T19:01:43.273

@LuisMendo That's cool! Since it's a completely different approach, I'll let you have it. – James – 2016-10-25T20:57:45.413

Ok, I'll post it! – Luis Mendo – 2016-10-25T21:18:46.677

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

Numberknot

Posted 2016-10-25T11:16:41.633

Reputation: 885

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 – 2016-10-25T23:04:37.137

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 – 2016-10-26T09:40:14.560

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 – 2016-10-26T10:15:53.360

@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 – 2016-10-26T11:31:43.257

@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 – 2016-10-28T09:39:23.320

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].)

JDL

Posted 2016-10-25T11:16:41.633

Reputation: 1 135

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"

CT14.IT

Posted 2016-10-25T11:16:41.633

Reputation: 231

2

C (gcc), 80 74 bytes

Thank ceilingcat for 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);}

Try it online!

l4m2

Posted 2016-10-25T11:16:41.633

Reputation: 5 985

2

Canvas, 7 bytes

⇵{*×]⤢┼

Try it here!

Explanation:

⇵{*×]⤢┼
⇵         ceiling divide by 2
 {  ]    map over [1..pop]
   *         push *
    ×        repeat by the counter
       ⤢  transpose
        ┼  quad-palindromize with 1 overlap

+1 byte with support for even numbers

dzaima

Posted 2016-10-25T11:16:41.633

Reputation: 19 048

2

J, 30 28 bytes

-2 bytes thanks to FrownyFrog!

' *'{~[:(>.|.)@(*|."1)]\@#&1

Try it online!

Galen Ivanov

Posted 2016-10-25T11:16:41.633

Reputation: 13 815

]\@#&1 is 2 shorter – FrownyFrog – 2019-04-13T16:16:07.540

@FrownyFrog Yes, of course! Thank you! – Galen Ivanov – 2019-04-13T18:13:40.053

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

TheBikingViking

Posted 2016-10-25T11:16:41.633

Reputation: 3 674

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

cleblanc

Posted 2016-10-25T11:16:41.633

Reputation: 3 360

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.

anatolyg

Posted 2016-10-25T11:16:41.633

Reputation: 10 719

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

Posted 2016-10-25T11:16:41.633

Reputation: 521

?**n works; you don't need the space there. – Value Ink – 2016-10-25T17:34:00.017

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

Geobits

Posted 2016-10-25T11:16:41.633

Reputation: 19 061

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

marinus

Posted 2016-10-25T11:16:41.633

Reputation: 30 224

Just remove 1+ and use an APL that has ⎕IO←0. – Adám – 2016-10-31T09:16:43.673

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

Posted 2016-10-25T11:16:41.633

Reputation: 4 825

Nice solution! But I'm pretty sure you don't need the putStr and you can get rid of the fromEnum like this.

– ბიმო – 2017-12-31T17:27:24.313

1

Common Lisp, 101 bytes

(dotimes(i(1+(set'x(read))))(format t"~v:@<~v{*~}~>~&"x(set'b(abs(- x(* i 2))))1)(if(= 1 b)(incf i)))

user65167

Posted 2016-10-25T11:16:41.633

Reputation:

1

Excel VBA, 68 67 Bytes

Anonymous VBE immediate window function that takes input from [A1] and outputs to the VBE immediate window

n=[Int(A1/2)]:For i=-n To n:j=abs(i):?Spc(n-j)String(2*j+1,42):Next

Taylor Scott

Posted 2016-10-25T11:16:41.633

Reputation: 6 709

1

SOGL V0.12, 12 bytes

.↔∫ **}⁰№§╬3

Try it Here!

dzaima

Posted 2016-10-25T11:16:41.633

Reputation: 19 048

1

Ruby, 66 bytes

->n{(-n..n).each{|x|x.abs>1?(puts"*"*x.abs):(puts"*"*x if x>0)}}

Probably a shorter way of doing this, but this is the most straight forward one i came up with.

Håvard Nygård

Posted 2016-10-25T11:16:41.633

Reputation: 341

1

Japt, 11 bytes

õ_î*ÃÔë ê û

Try it online

Oliver

Posted 2016-10-25T11:16:41.633

Reputation: 7 160

1

Japt -R, 11 bytes

1õU2_ç*Ãê û

Try it

                :Implicit input of integer U
1õU2            :Range [U,1] in increments of 2
    _           :Map each Z
     ç*         :  Repeat "*" Z times
       Ã        :End map
        ê       :Palindromise
          û     :Centre pad each element with spaces to the length of the longest
                :Implicitly join with newlines and output

Shaggy

Posted 2016-10-25T11:16:41.633

Reputation: 24 623

1

Python 3, 79 bytes

def f(i):[print(' '*(i//2-abs(j-i//2))+'*'*2*abs(j-i//2)+'*')for j in range(i)]

wizzwizz4

Posted 2016-10-25T11:16:41.633

Reputation: 1 895

1

Oracle SQL, 119 bytes

SQL> select lpad(' ',ceil(n/2)-x-1,' ')||rpad('*',x*2+1,'*')from(select n,abs(ceil(n/2)-rownum)x from t connect by level<=n)
  2  /

LPAD('',CEIL(N/2)-X-1,'')||RPAD('*',X*2+1,'*')
--------------------------------------------------------------------------------
*******
 *****
  ***
   *
  ***
 *****
*******

7 rows selected.

Dr Y Wit

Posted 2016-10-25T11:16:41.633

Reputation: 511

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.

ʰᵈˑ

Posted 2016-10-25T11:16:41.633

Reputation: 1 426

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 – 2016-10-25T17:09:54.020

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 – 2016-10-25T17:18:41.230

Replace implode() with join() to save 6 bytes. – Alex Howansky – 2016-10-25T17:38:33.080

Replace \n with an actual new line to save a byte. – Alex Howansky – 2016-10-25T17:39:21.447

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.

Magic Octopus Urn

Posted 2016-10-25T11:16:41.633

Reputation: 19 422

.each's code block could be {it%2&&println(("*"*it).center(n))}. – manatwork – 2016-10-26T08:35:06.243

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])

Blue

Posted 2016-10-25T11:16:41.633

Reputation: 26 661

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

Indiana Kernick

Posted 2016-10-25T11:16:41.633

Reputation: 109

1

PHP, 158 bytes

(-2 if I can omit the start tag)

<?$v=$argv[1]/2;while($c++<$v){$a="";$b=$v+.5;while(--$b)$a.=$b<$c?" ":"*";$z[]=strrev($a)."*$a";}$c=array_pop($z);$a=join($z,"
");echo"$a
$c
".strrev($a);

A similar approach to the one @hd took but uses manual concatenation instead of built-in string functions with overly long names. I wish I could call $z->pop()

ToXik-yogHurt

Posted 2016-10-25T11:16:41.633

Reputation: 311

1

Pyth, 22 bytes

VQ+*d-J/Q2aJN*\*hatQyN

Try online.

Lame attempt at explaining:

VQ+*d-J/Q2aJN*\*hatQyN   The whole thing.
VQ                       For N in [0,1,2, ... ,Q-1]; Q takes the input.
      J/Q2               Integer division Q/2, store in J
          aJN            Absolute difference between N and J
     -                   Subtract the above numbers...
   *d                    ...and repeat whitespace that many times
  +                      Concatenate that with output from the next block
                 atQyN   Absolute difference between Q-1 and 2*N
             *\*h        Repeat an asterisk the above number of times + 1

Interestingly I matched TheBikingViking's score on the same language using a different approach... O:

alleks

Posted 2016-10-25T11:16:41.633

Reputation: 61

1

Batch, 191 154 bytes

@echo off
set s=*
set l=for /l %%i in (2,1,%1)do call:
%l%s
%l%s
%l%u
%l%l
:l
echo %s%
:s
set s=%s:~1%**
exit/b
:u
echo %s%
set s= %s:~0,-2%

The u subroutine generates the top half of the hourglass by prepending a space and removing two trailing stars each time. The l subroutine generates the bottom half of the hourglass by removing a space and appending two trailing stars each time. The code falls through into the l subroutine at the end to save bytes. The second half of the l subroutine is also used to build up the initial string, although it has to be called twice as many times as the string doesn't have its spaces yet.

Edit: Saved 37 bytes by using an idea by @ConorO'Brien.

Neil

Posted 2016-10-25T11:16:41.633

Reputation: 95 035

1

Racket 177 bytes

(let p((n N)(d #t))(for((i(/(- N n)2)))(display" "))(for((i n))(display #\*))(displayln"")
(cond[(and(not d)(= n N))][(= n 1)(set! d #f)(p(+ 2 n)d)][d(p(- n 2)d)][(p(+ 2 n)d)]))

Ungolfed:

(define (f N)
  (let loop ((n N)
             (d #t))                      ; descending
    (for ((i (/(- N n)2)))
          (display " "))
    (for ((i n))
      (display #\*))
    (displayln "")
    (cond
      [(and (not d) (= n N))]             ; end
      [(= n 1) (set! d #f)
               (loop (+ 2 n) d)]
      [d (loop (- n 2) d)]
      [(loop (+ 2 n) d)]))
  )

Testing:

(f 9)

Output:

*********
 *******
  *****
   ***
    *
   ***
  *****
 *******
*********
#t

rnso

Posted 2016-10-25T11:16:41.633

Reputation: 1 635

1

Swift 3, 139 130

let c={String(repeating:$0,count:$1)};func d(_ n:Int,_ i:Int=0)->String{let b=c(" ",i)+c("*",n)+"\n";return n>1 ?b+d(n-2,i+1)+b:b}

On-line test

let c={(s,i)in(0..<i).reduce(""){(b,_)in b+s}};func d(_ n:Int,_ i:Int=0)->String{let b=c(" ",i)+c("*",n)+"\n";return n>1 ?b+d(n-2,i+1)+b:b}

Apollonian

Posted 2016-10-25T11:16:41.633

Reputation: 61

1

CJam, 26 bytes

ri:A,_W%.e<{_S*A@2*-'**N}/

Try it online!

ri:A     e# read integer, save as A
,_W%     e# make range and mirror (e.g.[0,1,2,3,4],[4,3,2,1,0])
.e<      e# take minimums (e.g.[0,1,2,1,0])
{        e# for each minimum "m"
  _S*    e#   push m spaces
  A@2*-  e#   calculate A-2m (rotates to spare m)
  '**    e#   push A-2m asterisks
  N      e#   push a newline
}/       e# end, prints stack

Linus

Posted 2016-10-25T11:16:41.633

Reputation: 1 948

1

T-SQL, 93 bytes

This will also provide an answer when an even number is used - the bottom row will be missing.

Golfed:

DECLARE @ INT=5

,@i INT=0z:PRINT SPACE(@/2-abs(@/2-@i))+REPLICATE('*',abs(@/2-@i)*2+1)SET
@i+=1IF @i<@ GOTO z

Ungolfed:

DECLARE @ INT=5

,@i INT=0
z:
PRINT SPACE(@/2-abs(@/2-@i))+REPLICATE('*',abs(@/2-@i)*2+1)
SET @i+=1
IF @i<@ GOTO z

A bit longer alternative solution without looping

USE master
DECLARE @ INT=5
SELECT top(@)SPACE(@/2-abs(@/2-number))+REPLICATE('*',abs(@/2-number)*2+1)
FROM spt_values
WHERE'P'=type

Fiddle

t-clausen.dk

Posted 2016-10-25T11:16:41.633

Reputation: 2 874

1

Actually, 34 bytes

;╗R`1&`░`'**╜kd#"{:^%d}"%f`M;pXR+i

Try it online!

Explanation:

;╗R`1&`░`'**╜kd#"{:^%d}"%f`M;pXR+i
;╗                                  store a copy of n in register 0
  R                                 range(1, n+1) ([1, n])
   `1&`░                            filter: keep only odd values
        `'**╜kd#"{:^%d}"%f`M        for each value:
         '**                          push a string containing that many asterisks
            ╜                         push n
             kd#                      list from stack, dequeue, listify (make both stack elements singleton lists)
                "{:^%d}"%             format string to center string in n-wide field
                         f            do the formatting
                            ;pXR+   duplicate list, discard the extra "*" element, reverse, and append original list (vertical mirroring)
                                 i  flatten and implicitly print

Mego

Posted 2016-10-25T11:16:41.633

Reputation: 32 998