Чередующийся шаблон


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)
  • Вам разрешено выводить список / массив строк для каждой строки или двумерную матрицу символов вместо печати их в STDOUT.

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

  • Это , поэтому выигрывает самый короткий ответ в байтах.
    Не позволяйте языкам кода-гольфа отговаривать вас от публикации ответов на языках, не относящихся к кодексу. Попробуйте найти как можно более короткий ответ для «любого» языка программирования.
  • К вашему ответу применяются стандартные правила , поэтому вы можете использовать STDIN / STDOUT, функции / метод с правильными параметрами и типом возврата, полные программы. Ваш звонок.
  • По умолчанию лазейки запрещены.
  • Если возможно, добавьте ссылку с тестом для вашего кода.
  • Кроме того, добавление объяснения для вашего ответа настоятельно рекомендуется.

Контрольные примеры (сначала n=1через n=10)

*

*#
#*

*##
#**
*##

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

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

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

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

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

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

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

« Вы можете использовать любые два различных символа вместо * и #. » - Должны ли они быть напечатаны? Можем ли мы использовать NUL и SOH (коды ASCII 0 и 1)?
нгл

@ngn Извините, только для печати символов. Уточню в описании задачи.
Кевин Круйссен

Ответы:


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'


Из любопытства. Сколько байт будет просто выводить матрицу 0 и 1 без пробелов? Я предполагаю, что ⎕a[...}преобразование их в Aи Bбез пробелов короче, чем сохранение их как0 и 1без пробелов, учитывая, что вы использовали это, но просто любопытно, есть ли большая разница в байтах, если вы оставляете их как 0и 1.
Кевин Круйссен

1
@KevinCruijssen Насколько я могу играть в гольф, это будет одинаковой длины - или ⎕d[... ]или ⊃¨⍕¨... В последнем выражении ⍕¨"формат каждого" - он превращает каждое число во вложенный символ вектора , поэтому нам нужно "сначала каждый "( ⊃¨) чтобы получить только символ msgstr скаляры (и, следовательно, нет пробелов при печати).
НГН

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?

Полная программа, принимающая целое число, которое печатает выходные данные, как определено в OP, используя 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

Похоже, это именно мой алгоритм, но другая реализация, которая выводит 0 вместо 1 и наоборот.
Эрик Outgolfer

Да, фактически то же самое ... и я не обновил свой пост, чтобы показать исправление, которое я сделал.
Джонатан Аллан


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

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

Ungolfed:

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

Ungolfed:

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
Я не очень хорошо знаю Lua, но, кажется, вы можете сохранить пять байтов: (n+1)/2to -~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делает в ваших предложениях? Это определенно работает, но я не понимаю почему.
Лазурные высоты

1
@AzureHeights Конечно. ~является унарным побитовым оператором отрицания. Что важно для Codegolfing, однако, это то ~iже самое значение, что и -i-1. Поэтому мы можем использовать -~iвместо i+1и ~-iвместо i-1. Это полезно в двух случаях, которые я мог бы использовать в вашем ответе: избавиться от круглых скобок, поскольку -и ~иметь приоритет оператора над другими математическими операциями, поэтому (n+1)/2может быть так -~n/2. И другая полезная часть - избавиться от пробелов в некоторых случаях, как я сделал с or-~n-i.
Кевин Круйссен

1
Вот два соответствующих совета, если вы хотите прочитать немного больше об этом: Использовать унарный ~для x+1иx-1 и Использовать унарный ~для a-b-1иa+b+1 . Все общие советы, а также советы по конкретным языкам ( в данном случае советы по игре в гольф на Lua ) могут быть интересными для чтения. :)
Кевин Круйссен




3

C (gcc) , 118 108 байтов

Этот не выиграет, но это другой подход (или, по крайней мере, я так думаю!) Вместо того, чтобы манипулировать строками, я использую тот факт, что 10Икс-1 над [1 ..N]знак равно{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, reverse ( |:- нам нужно, :чтобы заставить |быть унарным) соответствующий элемент j раз ( n f/ xприменяется f nраз x). По сути, переверните все остальные строки.

"*#" использовать матричные элементы в качестве индексов в строке "*#"

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.