Чергуючи візерунок


16

У видаленому запитанні stackoverflow хтось опублікував таке:

Напишіть програму або функцію для друку змінних шаблонів у *та #на основі заданого цілого числа n. Деякі приклади:

Вхід: n=1
Вихід:

*

Вхідний n=5
вихід:

*####
###**
***##
###**
*####

Вхід: n=8
Вихід:

*#######
######**
***#####
####****
****####
#####***
**######
#######*

Оскільки це виглядало як дуже класна проблема з кодом для гольфу, ось він.

Як будуються ці закономірності?

Перший рядок починається з одинарного *, після чого йде n-1кількість останнього #.
Потім другий рядок містить два *, із n-2кількістю провідних #.
Третій рядок починається з трьох *, а потім - n-3кількість останнього #.
тощо.

Як тільки ми досягли середини ( n/2), ми ще раз відраховуємо суму *, яку можна побачити в прикладах вище.

Зверніть увагу, що для непарних вхідних чисел перевернута пара рядків (так, перша і остання; друга і наступна до останньої; тощо) точно однакові. У n=5прикладі перший і останній рядки *####; другий і наступний останній рядки ###**.
Однак для рівних вхідних чисел перевернута пара рядків перевернута. У n=8прикладі перший і останній рядки є *#######і #######*; другий і наступний останній рядки є ######**і **######; тощо.

Правила виклику:

  • Ви можете використовувати будь-які два різних символи для друку замість *та #. Ви можете використовувати Aі B; 3і 7; <і >; Будь ласка, вкажіть у своїх відповідях, що ви використовували.
  • Ви можете припустити n, що це додатне ціле число ( >= 1)
  • Вам дозволяється виводити список / масив рядків для кожного рядка або 2D матрицю символів, замість того, щоб друкувати їх у STDOUT.

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

  • Це , тому найкоротша відповідь у байтах виграє.
    Не дозволяйте мовам з кодовим гольфом відштовхувати вас від публікації відповідей з мов, що не кодують гольф. Спробуйте придумати якомога коротшу відповідь на "будь-яку" мову програмування.
  • Стандартні правила застосовуються до вашої відповіді, тому вам дозволяється використовувати STDIN / STDOUT, функції / метод із відповідними параметрами та повним програмами типу повернення. Твій дзвінок.
  • Лазівки за замовчуванням заборонені.
  • Якщо можливо, додайте посилання з тестом для вашого коду.
  • Також настійно рекомендується додавати пояснення до своєї відповіді.

Тестові приклади (спочатку n=1до n=10)

*

*#
#*

*##
#**
*##

*###
##**
**##
###*

*####
###**
***##
###**
*####

*#####
####**
***###
###***
**####
#####*

*######
#####**
***####
###****
***####
#####**
*######

*#######
######**
***#####
####****
****####
#####***
**######
#######*

*########
#######**
***######
#####****
*****####
#####****
***######
#######**
*########

*#########
########**
***#######
######****
*****#####
#####*****
****######
#######***
**########
#########*

" Ви можете використовувати будь-які два різних символи замість * та #. " - Чи потрібно їх друкувати? Чи можемо ми використовувати NUL і SOH (коди ASCII 0 і 1)?
ngn

@ngn Вибачте, лише символи для друку. Роз'яснемо в описі виклику.
Kevin Cruijssen

Відповіді:


14

Желе , 9 байт

>þµoṚUÐeY

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

Пояснення

>þ           Create a table of (x>y) over [1…n]×[1…n]:
               [0 1 1 1 1]
               [0 0 1 1 1]
               [0 0 0 1 1]
               [0 0 0 0 1]
               [0 0 0 0 0]
  µ          Take this array, and...
   oṚ        OR it with its reverse:
               [0 1 1 1 1]
               [0 0 1 1 1]
               [0 0 0 1 1]
               [0 0 1 1 1]
               [0 1 1 1 1]
    UÐe      Apply U (reverse) to even-indexed rows.
       Y     Join by newlines.

17

Python 2 , 62 байти

lambda n:["%*s"%(i%2*2*n-n,"x"*min(i+1,n-i))for i in range(n)]

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

Використання xта простір.

Рядки обчислюються так:

"%-5s" % "x"      == "x    "
"%5s"  % "xx"     == "   xx"
"%-5s" % "xxx"    == "xxx  "
"%5s"  % "xx"     == "   xx"
"%-5s" % "x"      == "x    "

Використовуючи %*sспецифікатор для вибору між nта -n.



6

MATL, 34 31 18 байт

:t!>tPY|!"@X@oQ&P!

Спробуйте це на MATL Online

Використовує 0 для * та 1 для #. Спираючись на відповідь Желі Лінни .


Старша відповідь, 31 байт:

2/tk:wXk:Ph"X@ot~XHh@Gy-hHQ&PY"

Спробуйте це на MATL Online

Використовує 1 для * і 0 для #.

         % implicit input, say 5
2/       % divide input number by 2 [2.5]
tk       % make a copy and floor that [2.5, 2]
:        % create range 1 to the floored value [2.5, [1, 2]]
wXk      % bring out the division result and this time ceil it
         %  [[1, 2], 3]
:        % create range 1 to that [[1, 2], [1, 2, 3]]
Ph       % flip the last array and concatenate horizontally 
         %  [[1, 2, 3, 2, 1]]
"        % loop through the array
  X@o    % Is the current loop index odd? 1 for odd, 0 for even
  t~     % duplicate and logical negate that
  XH     % copy that value to clipboard H
  h      % and concatenate the values ([1 0] on odd iterations, [0 1] on even) 
  @      % push current value from array (say 2, then stack is [[0 1], 2)
  G      % push input again
  y-     % subtract current array value from input [[0 1], 2, 3]
  h      % concatenate those two [[0 1], [2, 3]]
  H      % get the stored value from clipboard H (1 for even iterations, 0 for odd) 
  Q      % increment that
  &P     % flip the array in that dimension: in even iterations, this flips
         %   across columns and hence inverts the two values. [[0 1], [3, 2]]
         %   in odd iterations, it's a no-op
  Y"     % run-length decoding - repeat the element from first array the number of times
         %  specified in the second array
         % implicit loop end, implicit output

6

APL (Dyalog Classic) , 18 байт

a[↑⊢∘⌽\(⊂>⊢⌊⌽)⍳⎕]

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

Виходи ABзамість*#

оцінений вхід n

⍳⎕ вектор 0 1 ... n-1

⊢⌊⌽min ( ) між собою ( ) та їх зворотним ( ) - див. поїзди

⊂>⊢⌊⌽де вектор у цілому ( ) менший за кожен його ⊢⌊⌽- повертають вектор булевих (0/1) векторів

⊢∘⌽\ повернути кожен інший вектор

змішати в матрицю

⎕aВеликий англійський алфавіт, 'AB...Z'

⎕a[ ]замінити 0 1на'A' 'B'


З цікавості. Скільки байтів було б просто вивести матрицю 0s і 1s без пробілів? Я припускаю, що ⎕a[...}перетворення їх на пробіли Aі Bбез них коротше, ніж зберігати їх як 0і 1без пробілів, враховуючи, що ви використовували це, але просто цікаво, якщо в байтах є велика різниця, якщо ви зберігаєте їх як 0і 1.
Кевін Круїссен

1
@KevinCruijssen Наскільки я можу гольф, він був би однакової довжини - або ⎕d[... ]або ⊃¨⍕¨... В останньому виразі ⍕¨є "форматувати кожен" - воно перетворює кожне число у вкладений векторний вектор , тому нам потрібен "спочатку кожен "( ⊃¨) отримувати лише скаляри символів (і, отже, пробілу під час друку).
ngn

5

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

≔⮌…⁰NθEθ⭆蛧⟦μλ⟧κ⌊⟦κι

Спробуйте в Інтернеті! Використання 0та 1. Посилання полягає у багатослівній версії коду і включає, §*#що переводить вихід на запитання *та #питання. Пояснення:

    N                   Input number
  …⁰                    Range from 0
 ⮌                      Reversed
≔    θ                  Assign to `q`
      Eθ                Map over reversed range
        ⭆θ              Map over reversed range and join
           §⟦μλ⟧κ       Alternate between range and reversed range column
                 ⌊⟦κι   Minimum of range and reversed range row
          ›             Greater
                        Implicitly print each row on its own line

5

Желе ,  12  15 байт

+3 виправлення n=1помилки на корпусі :(

R«Ṛ$‘r⁸ṬUÐe0YE?

Повна програма, що приймає ціле число, яке друкує вихід, як визначено в ОП, використовуючи 0і 1для, *і #відповідно.

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

Як?

R«Ṛ$‘r⁸ṬUÐe0YE? - Main Link: integer, n
R               - range -> [1,2,3,4,...,n]
   $            - last two links as a monad:
  Ṛ             -   reverse -> [n,...,4,3,2,1]
 «              -   minimum (vectorises) -> [1,2,3,4,...,4,3,2,1]
    ‘           - increment (vectorises) -> [2,3,4,5,...,5,4,3,2]
      ⁸         - chain's left argument, n
     r          - inclusive range (vectorises) -> [[2,3,...,n],[3,4,...n],[4,5,...n],[5,...n],...,[5,...n],[4,5,...n],[3,4,...n],[2,3,...,n]]
       Ṭ        - untruth (vectorises) -> [[0,1,1,...,1],[0,0,1,1,...,1],[0,0,0,1,...,1],[0,0,0,0,1,...,1],...,[0,0,0,0,1,...,1],[0,0,0,1,...,1],[0,0,1,1,...,1],[0,1,1,...,1]]
         Ðe     - apply to entries with even indices:
        U       -   upend              -> [[0,1,1,...,1],[1,1,...,1],[0,0,0,1,...,1],[1,...,1,0,0,0,0],...]
              ? - if...
             E  - ...condition: all equal? (only true when n=1, where we have [1,1])
           0    - ...then: zero
            Y   - ...else: join with newline characters
                - implicit print

Схоже, це саме мій алгоритм, але інша реалізація, яка виводить 0s замість 1s і навпаки.
Ерік Аутгольфер

Так, фактично те саме ... і я не оновлював свою публікацію, щоб показати виправлене, що я зробив.
Джонатан Аллан


4

Java 10, 145 байт

n->{var r=new char[n][n];for(int j=0,k;j<n;++j)for(k=0;k<n;)r[j][k]=k++<(j<n/2?j%2<1?j+1:n+~j:j%2>0?j:n-j)?j%2<1?'*':'#':j%2>0?'*':'#';return r;}

Весь термінал робить його трохи безладним, але він чудово працює. Я спробував вирівняти вкладений цикл та різні інші речі, але вони лише збільшили кількість байтів. Спробуйте його онлайн тут .

Безголівки:

n -> { // lambda taking an integer as output and returning a char[][]
    var r = new char[n][n]; // the output array; we make use of Java 10's var here (replace with char[][] for another 4 bytes to make this work in Java 8)
    for(int j = 0, k; j < n; ++j) // iterate over the lines
        for(k = 0; k < n; )       // iterate over the j'th line
            r[j][k] = // set the current character
                      k++ < // determine if we're in the first or second portion of the line:
                            (j < n/2 ? // for the first half of the output:
                                 j%2 < 1  // on even lines ...
                                 ? j + 1  // ... print the first symbol j+1 times ...
                                 : n + ~j // ... on odd lines, print it n-j-1 times.
                             : j%2 > 0 ?  // for the second half of the output, on odd lines ...
                                 j :      // ... print the first symbol j times ...
                                 n - j)   // ... on even lines, print it n-j times.
                      ? j%2 < 1 ? '*' : '#'  // for the first part of the line, use '*' on even lines, '#' otherwise
                      : j%2 > 0 ? '*' : '#'; // for the second part of the line, use '*' on odd lines, '#' otherwise
    return r; // return the completed array
}

Java 8 11, 179 127 байт

n->{String r="",a,b;for(int j=0;j<n;b="#".repeat(j<n/2?n+~j:j),r+=(j++%2<1?a+b:b+a)+"\n")a="*".repeat(j<n/2?j+1:n-j);return r;}

Спробуйте його в режимі он-лайн тут (у TIO ще немає Java 11, тому для цього використовується користувацький метод, який призводить до того ж кількості байтів, що і String#repeat()).

Дякуємо Кевіну Крейсейну за те, що він займався гольфу на колосальних 52 байти!

Безголівки:

n -> { // lambda taking an int argument and returning a String
    String r = "", // the output String
           a,      // temporary String containing the '*'s
           b;      // temporary String containing the '#'s
    for(int j = 0; j < n; // loop over the lines
        b = "#".repeat( // repeat the '#' character ...
            j < n/2 ? n + ~j // ... n-j-1 times in the first half of the output ...
            : j), // ... j times in the second half
        r += (j++ % 2 < 1 ? a + b : b + a) + "\n") // assemble the j'th line and append it to the output: on even lines, the '*'s go first; on odd lines, the '#'s go first
        a = "*".repeat( // repeat the '*' character ...
              j < n/2 ? j + 1 // ... j+1 times in the first half of the output ...
              : n - j); // n-j times in the second half
    return r; // return the completed output
}

3
Якщо ви перейдете на Java 11, ви можете переграти його на 127 байт, використовуючи "*".repeat(...)та "#".repeat(...)(а також повертаючи рядок замість того, щоб безпосередньо друкувати та гольфувати n-j-1в n+~j):n->{String r="",a,b;for(int j=0;j<n;b="#".repeat(j<n/2?n+~j:j),r+=(j++%2<1?a+b:b+a)+"\n")a="*".repeat(j<n/2?j+1:n-j);return r;}
Кевін Круїйссен,

Дякую, це чудова економія в байтах. Мені вдалося створити 145-байтну версію для Java 10, використовуючи вкладені петлі - не можу дочекатися виходу Java 11, цей repeat()метод дуже приємний для гольфу.
OOBalance

4

Луа ,  148  133 байт

function(n)t,a,b={},".","#"for i=1,n do r=i<n/2+1 and i or-~n-i s=a:rep(r)..b:rep(n-r)t[i]=i%2<1 and s:reverse()or s end return t end

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

-15 байт завдяки @KevinCruijssen та @JoKing.

function(n)
   t = {}; a = "."; b = "#"          -- initialize variables, output is in table
                                     -- strings are needed in variables for
                                     --   the str:rep and str:reverse syntax

   for i = 1, n do                          -- build the rows of the table
      r = i<=(n+1)/2 and i or n-i+1         -- logic used to count up then down
      str = a:rep(r)..b:rep(n-r)            -- append correct number of '.'s, fill
                                            --   in the rest with '#'s
      t[i]=i%2==0 and str:reverse() or str  -- logic used to control reversing
   end
   return t                                 -- return table
end

2
Я не дуже добре знаю Луа, але, здається, ви можете зберегти п’ять байт: (n+1)/2до -~n/2; or n-i+1до or-~n-i; i%2==0до i%2<1; і reverse() orдо reverse()or. Крім того, і ваша версія TIO, і кількість байтів містять кінцеву крапку з двокрапкою, яка, здається, не потрібна. Хороша перша відповідь, хоча. +1 від мене. І ласкаво просимо до PPCG! :)
Кевін Круїссен

2
Насправді вам не потрібен жоден з напівколонок. 133 байти, включаючи пропозиції Кевіна.
Джо Кінг,

@KevinCruijssen Дякую! Чи можу я запитати, що -~nробить у ваших пропозиціях? Це, безумовно, працює, але я не розумію, чому.
Azure Heights

1
@AzureHeights Звичайно. ~є одинарним бітовим оператором заперечення. Що важливо для кодогольфінгу, це те, що ~iмає таке ж значення, як і -i-1. Тому ми можемо використовувати -~iзамість i+1і~-i замість цього i-1. Це корисно в двох випадках, які я міг би і використовуємо в своїй відповіді: позбавлення від дужки, так -і ~у оператора пріоритет над іншими математичними операціями, тому , (n+1)/2отже , може бути -~n/2. А інша корисна частина - це позбутися пробілів у деяких випадках, як я робив or-~n-i.
Kevin Cruijssen

1
Ось дві відповідні поради, якщо ви хочете прочитати трохи більше про це: Використовуйте unary ~для x+1таx-1 та Використовуйте unry ~для a-b-1іa+b+1 . Усі загальні поради, а також мовні поради ( поради щодо гольфу в Луа в даному випадку) можуть бути цікавими для прочитання. :)
Кевін Кройсейсен




3

C (gcc) , 118 108 байт

Цей не збирається перемагати, але це інший підхід (або, принаймні, я так думаю!) Замість того, щоб робити жорсткі маніпуляції, я використовую той факт, що 10х-1 над [1.н]={9,99,999 рік,...}, яку потім можна помножити, щоб отримати відповідний візерунок; printf()тоді робиться нульове прокладка для правильного виправдання.

На жаль, у вас є intлише достатній діапазон, щоб зробити до 9 цифр (на 32-бітних платформах), тому вам потрібно перейти доlong більш великих шаблонів; мова, яка споконвічно робить арифметику MP, може бути в змозі використати це для чогось.

Дякую стельовій кішці за пропозицію.

h,j,k;p(h){h=h?10*p(--h):1;}f(i){for(j=0,h=i++;k=++j>i/2?i-j:j,j<i;printf("%0*d\n",h,~-p(k)*p(j%2*(h-k))));}

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


Доведення концепції, що це працює з арифметикою MP:

C # (компілятор Mono C #) , 187 165 байт

(143 байти + 22 байти для using System.Numerics;заголовка)

q=>{var r="";for(int j=0,h=q+1,k;j<q;r+=((BigInteger.Pow(10,k)-1)*BigInteger.Pow(10,j%2*(q-k))).ToString("D"+q)+"\n")k=++j>h/2?h-j:j;return r;}

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


1
Доказ концепції з цифрами поза максимальним цілим діапазоном (використовуючи C # та BigIntegers): Спробуйте в Інтернеті!
ErikF

3

Vim, 99 натискань клавіш

Завжди цікаво намагатися робити vim із вхідними аргументами. Це дуже неприродно, тому це не буде напрочуд коротко. Напевно, є й інші хороші підходи до цього.

Введення вважається самим собою в буфері. Регістри вважаються порожніми. Припускається, що редактор є досить високим, щоб містити результат без прокрутки (технічно цього можна уникнути ціною деяких натискань клавіш).

"nD@ni<cr><esc>MmaGddM
<c-v>'aI*<esc>qwgvjokoI*<esc>@wq@w<esc>
:set ve=all<cr>@nlh<c-v>@nkr#
:%s/ /#/g<cr>o<esc>
2Gqqdt#$p2j0@qq@q

Пояснення

 | Buffer state (odd and even case):
 | 5                    6

"nD              read input into register n
@ni<cr><esc>     add n newlines
MmaGddM<c-v>'a   visual block select center row(s)
I*<esc>          prepend a column of *
qw               record macro w
  gvjoko         expand selection up and down
  I*<esc>
  @w             recurse
q
@w<esc>          run macro w and exit visual block select

 | Buffer state:
 | *                    *
 | **                   **
 | ***                  ***
 | **                   ***
 | *                    **
 |                      *

:set ve=all<cr>  move anywhere!
@nlh<c-v>@nkr#   add last column of #s

 | Buffer state:
 | *   #                *    #
 | **  #                **   #
 | *** #                ***  #
 | **  #                ***  #
 | *   #                **   #
 |                      *    #

:%s/ /#/g<cr>      replace spaces with #

 | Buffer state:
 | *####                *#####
 | **###                **####
 | ***##                ***###
 | **###                ***###
 | *####                **####
 |                      *#####

o<esc>2G           prep and jump to line 2
qqdt#$p2j0@qq@q    (effectively) flip every other onward

 | Buffer state:
 | *####                *#####
 | ###**                ####**
 | ***##                ***###
 | ###**                ###***
 | *####                **####
 |                      #####*

І в base64, з фактичними символами (введіть inputі натисніть клавіші keysта запустіть за допомогою vim -u NONE -s keys input)

Im5EQG5pDRtNbWFHZGRNFidhSSobcXdndmpva29JKhtAd3FAdxs6c2V0IHZlPWFsbA1AbmxoFkBua3IjOiVzLyAvIy9nDW8bMkdxcWR0IyRwMmowQHFxQHE=

2

R , 75 байт

function(n)outer(1:n,1:n,function(x,y,a=x<y|x>n-y+1)+ifelse(x%%2,a,rev(a)))

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

  • Натхненний відповіддю @Lynn
  • функція отримання nв якості параметра і повернення матриці, 0/1де 0відповідає '*'і 1відповідає'#'

2

К (нг / к) , 22 байти

{"*#"i|:/'i>/:i&|i:!x}

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

{ } функція з аргументом x

!x список (0;1; ...;x-1)

i: призначити i

i&|iмінімуми ( &) iта його зворотний (| )

i>/:порівняти з більшим ніж ( >)i проти кожного елемента зі списку праворуч ( /:) - повернути булеву матрицю (список списків)

i|:/'для кожного ( ') j in i, зворотного ( |:- нам потрібно, :щоб примусити |бути одинаковою) відповідний елемент j разів ( n f/ xзастосовується f nрази наx ). Ефективно переверніть кожен інший ряд.

"*#" використовувати матричні елементи як індекси в рядку "*#"

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.