Намалюйте пісочний годинник


32

Знову натхненний завданням програмування 101 ось ще одне завдання.

Вхід:

  • Позитивне ціле число n >= 3. (має бути непарним)

Вихід:

  • nрядки зірочок, де перший рядок має nзірочки, і кожен новий рядок має дві зірочки менше, ніж рядок раніше. Поки не потрапив 1 зірочку. Звідти кожен новий рядок має дві зірочки більше, ніж рядок до повернення до nзірочок. Проміжки або щось подібне до пробілів доводиться використовувати для вирівнювання зірочок, щоб воно справді було схоже на пісочний годинник.

Загальні правила:

  • Додаткові нові рядки дозволені, але їх не потрібно використовувати.
  • відступ - обов’язковий.
  • Це код-гольф, тому найкоротша відповідь у байтах виграє.
  • Оскільки курс викладається на мові C ++, я хочу бачити рішення в C ++.

Тестовий випадок (n = 5):

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

відредаговано відповідно, дякую :-)
Sickboy


3
@Oliver З огляду на те, що OP написав "Накресли трикутник зірочки", я не зовсім впевнений, що називати цей виклик дублікатом справедливо. Це, безумовно, пов'язане.
Шерлок9,

19
Оскільки тут не всі знають повний контекст, ОП спочатку розмістила "Намалюйте трикутник зірочки" і відредагувала цей виклик як додатковий виклик. Ми сказали їм зняти цю частину і зробити це іншим завданням (що вони зробили). Цей виклик не є дублікатом. ОП робить те, що рекомендують багато користувачів з високою репутацією, і навіть кілька модників.
DJMcMayhem

2
@JDL: Ні, навіщо це робити? Ах, тепер я розумію, що ви мали на увазі під квадратом ... :-D
Sickboy

Відповіді:


20

Вугілля деревне , 6 байт

G↘←↗N*

Мертвий простий. Намалюйте полі G на *, довжина сторони взята від вхідного N umber, де сторони йдуть вниз-вправо, горизонтально вліво та вгору-вправо:

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

Потім автозаповнюють контур і заповнюють його.

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

Спробуйте в Інтернеті!


Га, це гарненькі бонкери!
CT14.IT

6
Ця мова дуже цікава! Я буду спостерігати за цим дуже уважно віднині: с.
Аднан

Я раніше не бачив цієї мови ... Виглядає цікаво! Цікаво, що ти отримаєш, якби ти якось поєднав його з Jelly ...
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+' ')+r61 байт, але він ще довший. Навіть у ведучому новому рядку 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>

Спробуйте в Інтернеті!

Мені подобаються подібні завдання, тому що я можу показати свої переваги 2-ї природи V. Пояснення. Спочатку нам потрібно створити рядок з n зірочок. Отже, ми робимо це:

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

Як бічна примітка, це прямо еквівалентно @ai*<esc>in 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>>ò

Тому що насправді команда відступу є >>. V зручно припускає, що неповні команди застосовуються до поточного рядка, а також неявно заповнюють другий òсимвол для циклічного циклу.


10

Мета + шаблони C ++, 186 байт

Маючи явну формулу з моєї відповіді на С, метатемплати змагаються!

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

Безголівки:

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 з найбільш
довговітковою

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

Пітон, 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);}

неозорений:

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 байти.
Magic Octopus Urn

@carusocomputing: Дякую! Я не знав про команду palendromize (я не оновив документи). Дуже корисний. Потрібні були кілька разів раніше :)
Емінья

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-байтного желе за пару хвилин у будь-якому випадку, ха-ха ...
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="";( -2 байти ), а return(n=n-2)>=0?s+"\n"+c+c(n,++x)+до return n-1>0?s+"\n"+c+c(n-2,++x)+( -2 байти знову)
Кевін Круїссен

Але шаблон @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 Umm .. ти все ж забув мою другу пораду. У будь-якому випадку, тут є коротший варіант: 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)."
";

Збережено байт, використовуючи фактично новий рядок замість an "\r"


2

Піт, 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

С, 195 191 байт

Якщо гольф вниз трохи менше

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

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

Хаскелл, 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 тільки так, прекрасно зроблено! Це точно точно правильний підхід!
640 Кб

1

Гроовий, 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 [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);}}

Безумовно

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.