Нарисуй песочные часы


32

Снова вдохновленный задачей для программирования 101, вот еще одна проблема.

Входные данные:

  • Целое положительное число n >= 3. (должно быть странно)

Выход:

  • nлинии звездочек, где в первой строке есть nзвездочки, а в каждой новой строке на две звездочки меньше, чем в предыдущей строке. До удара 1 звездочка. Оттуда каждая новая строка имеет на две звездочки больше, чем строка до возвращения к nзвездочкам. Для выравнивания звездочек необходимо использовать пробелы или что-то вроде пробелов, чтобы они действительно выглядели как песочные часы.

Основные правила:

  • Конечные переводы строк разрешены, но не должны использоваться.
  • отступ является обязательным.
  • Это код-гольф, поэтому выигрывает самый короткий ответ в байтах.
  • Поскольку курс преподается на C ++, мне не терпится увидеть решения на C ++.

Тестовый пример (n = 5):

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

отредактировал соответственно, спасибо :-)
Sickboy


3
@Oliver Учитывая, что OP написал «Нарисуйте треугольник звездочки», я не совсем уверен, что называть этот вызов дубликатом справедливо. Это определенно связано, хотя.
Шерлок9

19
Поскольку не все здесь знают полный контекст, OP первоначально опубликовал «Нарисуйте треугольник звездочки» и отредактировал этот вызов как дополнительный вызов. Мы сказали им убрать эту часть и сделать ее другой задачей (что они и сделали). Эта задача не является дубликатом. OP делает то, что рекомендовали многие высокопрофессионалы, и даже несколько модов.
DJMcMayhem

2
@JDL: Нет, с чего бы ты? Ах, теперь я понимаю, что вы имели в виду под квадратом ... :-D
Sickboy

Ответы:


20

Древесный уголь , 6 байт

G↘←↗N*

Смертельно просто. Draw поли G на из *, с длиной стороны , взятой из входного N умбры, где стороны идут вниз и вправо, влево по горизонтали, а также вверх и вправо:

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

Затем автозаполните контур и заполните его.

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

Попробуйте онлайн!


Ха, это просто помешательство!
CT14.IT

6
Этот язык очень интересный! С этого момента я буду внимательно следить за этим: с.
Аднан

Не видел этот язык раньше ... Выглядит интересно! Интересно, что бы вы получили, если бы вы как-то совместили это с желе ...
Esolanging Fruit

12

Python 2, 57 байт

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

Полная программа. Идет построчно, печатая нужное количество звездочек по центру.

Рекурсивная функция была длиннее (67 байт):

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

или

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

Я хотел бы предложить , пытаясь заменить maxс abs, но все , что я получил это abs(n-1)+1, что еще хуже , потому что добавление требует скобки
njzk2

@ njzk2 Вы можете вырезать паренсы '*'*-~abs(n-1), но тогда они имеют ту же длину, что и '*'*max(n,2-n).
xnor

Там def f(n,s=''):r=s+'*'*n+'\n';return 1/n*r or r+f(n-2,s+' ')+rна 61 байт, но все еще длиннее. Даже с лидирующим символом новой строки def f(n,s='\n'):r=s+'*'*n;return 1/n*r or r+f(n-2,s+' ')+rвсе равно остается 58 байт ...
Деннис

+1 для обучения меня о center. Никогда не знал, что существовало до сих пор.
DLosc

11

V , 12 байт

Àé*hòl3Äjxx>

Попробуйте онлайн!

Мне нравятся такие вызовы, потому что я могу продемонстрировать преимущества 2D-характера V. Объяснение. Для начала нам нужно создать строку из n звездочек. Итак, мы делаем это:

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

В качестве примечания, это прямо эквивалентно @ai*<esc>vim, а регистр @aпредварительно инициализирован как «arg1». Это делает числовой ввод намного более удобным.

Затем мы перемещаемся на символ справа с h. Вот самое интересное:

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

Технически, эта последняя часть

òl3Äjxx>>ò

Потому что команда indent на самом деле >>. V удобно предполагает, что к текущей строке применяются неполные команды, а также неявно заполняет второй òсимвол для цикла.


10

Метаданные C ++, 186 байт

С явной формулой из моего ответа C, Metatemplates конкурируют!

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

использование:

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

не конкурирующих

Просто для удовольствия

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

Использование:

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

2
+1 для победы над PHP с самой скучной частью C ++
matsjoyce

7

PowerShell v2 +, 54 байта

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

Принимает входной сигнал $n(гарантированно будет нечетное целое число), конструирует два диапазона с $n..1и 2..$nи сцепляет их вместе, а затем использует Where-Objectдля выбора только нечетные с |?{$_%2}. Те питаются в петле. На каждой итерации мы строим соответствующее количество пробелов, соединенных строкой с соответствующим количеством звездочек. Эти строки остаются в конвейере и выводятся через неявные Write-Outputвставки между ними строк при завершении программы.

Примеры

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

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

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

7

Python, 78 байт

Так что только с отступом:

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

Использование:

print f(5)

6

C 114 109 байт

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

Предыдущее рекурсивное решение:

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 байт

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

Идея состоит в том, чтобы сгенерировать каждый песочные часы из предыдущего: добавить пробел в начале каждой строки, а также добавить и добавить nзвездочки.


4

05AB1E , 21 20 19 17 байт

Экономия 2 байта благодаря carusocomputing

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

Попробуйте онлайн!

объяснение

;ƒ                   # 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û- Дошло так далеко, лицо было ладонями, когда я понял, насколько далеко я был, увидел, что вы ответили, собираюсь попытаться выучить итерацию на этом языке сейчас, используя этот пример. Благодарность!
Волшебная Урна Осьминога

4
На самом деле я могу помочь на этот раз: ;ƒ'*¹N·-×Nð×ì})û»используйте новую команду palindromize. -2 байта.
Волшебная Урна Осьминога

@carusocomputing: Спасибо! Я не знал о команде palendromize (я не обновлял документы). Очень полезный. Нужно было несколько раз, прежде чем :)
Emigna

9 байт даже в наследство. Хотя я довольно уверен , что внутренние команды ÅÉи , .cвероятно , не были доступны еще в то время , вы отправили это. :)
Кевин Круйссен

4

MATL , 12 байт

Q2/Zv&<~42*c

Попробуйте онлайн!

объяснение

Это использует недавно добавленную функцию симметричного диапазона .

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

Ницца! Это классная особенность. Это единственный ответ, который был близок к моему V-ответу, так что теперь я собираюсь одержать верх над одним или двумя байтами. : D
DJMcMayhem

@DJMcMayhem Хех, я не думаю, что смогу уменьшить количество байтов на этом
Луис Мендо

Да, я тоже не могу. Вероятно, в любом случае через 4 минуты будет 4-байтовый ответ Jelly, хахаха ...
DJMcMayhem

4

PHP, 95 байт

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

Вместо того, чтобы хранить строки в массиве и затем выводить все, цикл for уменьшается до 1, а затем возвращается к исходному числу.


3

C ++ 11, 93 байта

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

Слегка разгульный

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

Использование:

std::cout << f(5);

Ницца! один байт можно сохранить, приняв ASCII и заменив '\n'на 10:)
Квентин

3

MATL , 20 байтов

XyY>t1X!*t2X!+ZS42*c

Попробуйте онлайн!


Вы можете сохранить несколько байтов с помощью недавно введенной функции симметричного диапазона: Q2 / Zv & <~ 42 * c
Луис Мендо

@ LuisMendo Это круто! Так как это совершенно другой подход, я дам вам его.
DJMcMayhem

Хорошо, я выложу это!
Луис Мендо

3

R 77 байт

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

Создает матрицу символов, через которую она затем распечатывает cat, с fill=nобеспечением правильного выравнивания линий. Обратите внимание, что элементы хранятся в матрице столбец-первый (т. Е. Первые два элемента M[1,1]и M[2,1], а не M[1,2].)


3

Java 7, 170 165 164 байта

Спасибо @Hypino за сохранение 5 байтов.
Спасибо Кевину за сохранение 1 байта.

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

Вы можете сэкономить 2 байта, удалив s=из них s=s+"\n"и еще 2 байта, изменив return(n=--n-1)значение return(n=n-2)на 4 байта.
Hypino

Здравствуй. Вы можете String s="",c="",t="";String s,c,t=s=c="";return(n=n-2)>=0?s+"\n"+c+c(n,++x)+return n-1>0?s+"\n"+c+c(n-2,++x)+
сыграть в

Но шаблон @KevinCruijssen отличается от ожидаемого после изменения n=n-2->, n-1>0потому что n следует использовать в другом аргументе функции.
Numberknot

@Numberknot Я знаю, но я изменился nк n-2в этой части. return(n=n-2)>=0 ... nбыть измененным на return n-1>0 ... n-2все еще короче. PS: Вы поблагодарили меня за сохранение байтов, но не изменили свой код при редактировании. ;)
Кевин Круйссен

@Numberknot Хмм .. ты все еще забыл мой второй совет. Во всяком случае, вот более короткий вариант: 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:"*";}без t( тест идеона - 133 байта )
Кевин Круйссен

3

PHP - 95 байт

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

Сохраненный байт, используя новую строку вместо "\r"


2

Pyth, 22 байта

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

Программа, которая принимает ввод целого числа в STDIN и печатает результат.

Попробуйте онлайн

Как это работает

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

Гольф должен быть немного меньше

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

Мы можем проверить это здесь на Ideone


2

C, 79 байтов

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

Он разбивает переменную обратного отсчета kна индексы строк и столбцов. Если индекс столбца равен 0 (последний символ в строке), он выводит символ новой строки (10). Затем он корректирует индексы строк и столбцов так, чтобы они находились вокруг центральной звездочки. Тогда abs(x) < abs(y)это короткое условие для вывода пробела.


2

Рубин, 55 54 байта

f=->n,s=0{puts a=' '*s+?**n;(f[n-2,s+1];puts a)if n>1}

?**nработает; вам не нужно место там.
Value Ink

2

Java 7, 156 байт

Довольно просто. Отслеживает линии с n, звезды с j, пробелы с sи направление с d. Я действительно просто хотел нерекурсивный ответ Java на доске, но это не повредит, что он также немного короче :)

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

С переносами строк:

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 байт

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

Тест:

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

Объяснение:

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

Просто удалите 1+и используйте APL, который имеет ⎕IO←0.
Адам

2

Haskell, 84 байта

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

Отличное решение! Но я уверен, что вам не нужноputStr , и вы можете избавиться от , fromEnumкак это .
ბიმო



2

PHP ,104 88 байт

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

Попробуйте онлайн!

Это не побеждает самые низкие оценки для PHP в этом соревновании, но я просто схожу с ума, чтобы отбросить.

Итак, теперь я играю в гольф, чтобы быть (недолго) самым низким показателем для PHP в этом соревновании, но это не меняет того факта, что он все еще сумасшедший.

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

83? да, у php тоже есть голые слова, хотя здесь это бесполезно
только ASCII

@ ASCII-только крысы! Похоже, у меня есть еще работа! LOL
640KB



@ ASCII-только да, красиво сделано! Это точно правильный подход!
640KB

1

Groovy, 66 байт

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

Попробуйте это: https://groovyconsole.appspot.com/script/5145735624392704

Разъяснение:

((n..1)+(2..n)) - обратный палиндромиз [n,..,1,..,n]

.each{if(it%2>0){...} - Перебирать нечетные элементы.

println(("*"*it).center(n)) - Центрировать n звездочек и напечатать каждую на новой строке.


.eachКодовый блок может быть {it%2&&println(("*"*it).center(n))}.
Манатворк

1

PHP, 191 байт

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

Беги как php -f golf_hourglass.php 15

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

Идея заключается в том, чтобы создать верхнюю половину (часть перед синглом *), а затем просто повторить верхнюю часть дважды, но второй раз в обратном порядке.


Я думаю, что это лучшее начало для этой задачи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;
Йорг Хюльсерманн

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;это лучше
Йорг Хюльсерманн

Замените implode () на join (), чтобы сохранить 6 байтов.
Алекс Ховански

Замените \nфактической новой строкой, чтобы сохранить байт.
Алекс Ховански


1

C 117 байт

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);
  }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.