Генерация косы Паскаля


32

Это коса Паскаля:

 1 4  15  56   209   780    2911    10864     40545      151316      564719
1 3 11  41  153   571   2131    7953     29681     110771      413403      1542841
 1 4  15  56   209   780    2911    10864     40545      151316      564719

Я полностью выдумал это. Насколько я могу судить, у Блеза Паскаля не было косички, и если он это сделал, то, вероятно, он был сделан из волос, а не из цифр.

Это определяется так:

  1. Первый столбец имеет один 1в середине.
  2. Второй столбец имеет 1вверху и внизу.
  3. Теперь мы чередуем размещение числа в середине или двух копий числа сверху и снизу.
  4. Если число идет сверху или снизу, это будет сумма двух соседних чисел (например 56 = 15 + 41). Если немного наклонить голову, это похоже на шаг в треугольнике Паскаля.
  5. Если число идет посередине, это будет сумма всех трех соседних чисел (например 41 = 15 + 11 + 15).

Ваша задача будет напечатать (некоторую часть) эту косу.

вход

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

Вы можете выбрать, соответствует ли первый столбец (печатая только один 1в средней строке) n = 0или n = 1. Это должен быть последовательный выбор во всех возможных входах.

Выход

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

Другими словами, каждый столбец должен быть точно такой же ширины, как число (или пара равных чисел) в этом столбце, числа в последовательных столбцах не должны перекрываться, и между столбцами не должно быть пробелов.

Вы можете либо распечатать результат в STDOUT (или ближайшую альтернативу), либо, если вы напишите функцию, вы можете вернуть либо строку с тем же содержимым, либо список из трех строк (по одной для каждой строки).

Более подробная информация

Вы можете предположить, что nон не будет меньше индекса первого столбца (поэтому не меньше 0или 1зависит от вашей индексации). Вы также можете предположить, что последнее число в косе меньше 256 или самое большое число, представляемое родным целочисленным типом вашего языка, в зависимости от того, что больше . Поэтому, если ваш собственный целочисленный тип может хранить только байты, вы можете предположить, что наибольшее значение nравно 9или 10(в зависимости от того, используете ли вы 0- или 1-основанное n), и если оно может хранить 32-разрядные целые числа со знаком, nбудет самое большее 33или 34.

Применяются стандартные правила . Самый короткий код выигрывает.

OEIS

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

Тестовые случаи

В этих тестах используется 1-базовое индексирование. Каждый тестовый пример состоит из четырех строк, первая из которых является вводом, а остальные три - выходом.

1

1

---
2
 1
1
 1
---
3
 1
1 3
 1
---
5
 1 4
1 3 11
 1 4
---
10
 1 4  15  56   209
1 3 11  41  153
 1 4  15  56   209
---
15
 1 4  15  56   209   780    2911
1 3 11  41  153   571   2131    7953
 1 4  15  56   209   780    2911
---
24
 1 4  15  56   209   780    2911    10864     40545      151316      564719       2107560
1 3 11  41  153   571   2131    7953     29681     110771      413403      1542841
 1 4  15  56   209   780    2911    10864     40545      151316      564719       2107560

Формат кажется мне немного хамелеоном.
Дрянная монахиня

3
@LeakyNun Я пробовал эту задачу, пока она находилась в песочнице, и потратил на вычисление оплетки примерно половину байтов, чем на ее печать. Мне кажется, это отличный баланс для ascii-art .
FryAmTheEggman

4
@LeakyNun Я надеялся, что и генерация последовательности, и искусство ASCII являются важными компонентами задачи, потому что большинство языков, вероятно, будут лучше справляться с одним из этих двух, поэтому я подумал, что было бы интересно смешать их. И это вводит дополнительный компонент, где не очевидно, лучше ли генерировать верх / низ и середину отдельно или генерировать все это, а затем разделить пополам.
Мартин Эндер


Никто еще не написал решение на Паскале. Это меня огорчает.
Dynamitereed

Ответы:


5

Желе , 31 30 29 байт

Q;S⁹o_
3ḶḂç@⁸СIµa"Ṿ€o⁶z⁶Zµ€Z

Это монадическая ссылка; он принимает индекс столбца на основе 0 в качестве аргумента и возвращает список строк.

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

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

Q;S⁹o_                  Helper link.
                        Arguments: [k, 0, k] and [0, m, 0] (any order)

Q                       Unique; deduplicate the left argument.
 ;                      Concatenate the result with the right argument.
  S                     Take the sum of the resulting array.
   ⁹o                   Logical OR with the right argument; replaces zeroes in the
                        right argument with the sum.
     _                  Subtract; take the difference with the right argument to
                        remove its values.
                        This maps [k, 0, k], [0, m, 0] to [0, k + m, 0] and
                        [0, m, 0], [k, 0, k] to [m + 2k, 0, m + 2k].


3ḶḂç@⁸СIµa"Ṿ€o⁶z⁶Zµ€Z  Monadic link. Argument: A (array of column indices)

3Ḷ                      Yield [0, 1, 2].
  Ḃ                     Bit; yield [0, 1, 0].
        I               Increments of n; yield [].
      С                Apply...
   ç@                       the helper link with swapped arguments...
     ⁸                      n times, updating the left argument with the return
                            value, and the right argument with the previous value
                            of the left one. Collect all intermediate values of
                            the left argument in an array.
         µ         µ€   Map the chain in between over the intermediate values.
            Ṿ€          Uneval each; turn all integers into strings.
          a"            Vectorized logical AND; replace non-zero integers with
                        their string representation.
              o⁶        Logical OR with space; replace zeroes with spaces.
                z⁶      Zip with fill value space; transpose the resulting 2D
                        array after inserting spaces to make it rectangular.
                  Z     Zip; transpose the result to restore the original shape.
                     Z  Zip; transpose the resulting 3D array.

12

Pyth , 44 байта

Генерация номера заняла 20 байтов, а форматирование - 24 байта.

jsMC+Led.e.<bkC,J<s.u+B+hNyeNeNQ,1 1Qm*;l`dJ

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

jsMC+Led.e.<bkC,J<s.u+B+hNyeNeNQ,1 1Qm*;l`dJ   input as Q
                   .u          Q,1 1           repeat Q times, starting with [1,1],
                                               collecting all intermediate results,
                                               current value as N:
                                               (this will generate
                                                more than enough terms)
                       +hNyeN                  temp <- N[0] + 2*N[-1]
                     +B      eN                temp <- [temp+N[-1], temp]

now, we would have generated [[1, 1], [3, 4], [11, 15], [41, 56], ...]

jsMC+Led.e.<bkC,J<s                 Qm*;l`dJ
                  s                            flatten
                 <                  Q          first Q items
                J                              store in J
                                     m    dJ   for each item in J:
                                         `     convert to string
                                        l      length
                                      *;       repeat " " that many times

jsMC+Led.e.<bkC,
              C,     transpose, yielding:
[[1, ' '], [1, ' '], [3, ' '], [4, ' '], [11, '  '], ...]
(each element with as many spaces as its length.)
        .e            for each sub-array (index as k, sub-array as b):
          .<bk            rotate b as many times as k

[[1, ' '], [' ', 1], [3, ' '], [' ', 4], [11, '  '], ...]

jsMC+Led
    +Led              add to each sub-array on the left, the end of each sub-array
   C                  transpose
 sM                   sum of each sub-array (reduced concatenation)
j                     join by new-lines

7
Это самая большая программа Pyth, которую я когда-либо видел.
Ималлетт


7

MATL , 38 байт

1ti:"yy@oQ*+]vG:)!"@Vt~oX@o?w]&v]&hZ}y

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

Вычисление массива с (уникальными) числами занимает первые 17 байтов. Форматирование занимает оставшиеся 21 байт.

объяснение

Часть 1: генерация чисел

Это создает массив с номерами от первых и вторых строк в порядке возрастания: [1; 1; 3; 4; 11; 15; ...]. Она начинается с 1, 1. Каждое новое число итеративно получается из предыдущих двух. Из них второе умножается на 1или в 2зависимости от индекса итерации, а затем суммируется с первым для получения нового числа.

Количество итераций равно входу n. Это означает, что n+2числа генерируются. После того, как массив сгенерирован, его нужно урезать, чтобы nсохранить только первые записи.

1t      % Push 1 twice
i:      % Take input n. Generage array [1 2 ... n]
"       % For each
  yy    %   Duplicate the two most recent numbers
  @o    %   Parity of the iteration index (0 or 1)
  Q     %   Add 1: gives 1 for even iteration index, 2 for odd
  *+    %   Multiply this 1 or 2 by the most recent number in the sequence, and add
       %    to the second most recent. This produces a new number in the sequence
]       % End for each
v       % Concatenate all numbers in a vertical array
G:)     % Keep only the first n entries

Часть 2: форматировать вывод

Для каждого числа в полученном массиве это генерирует две строки: строковое представление числа и строку одинаковой длины, состоящую из повторяющегося символа 0 (символ 0 отображается как пробел в MATL). Для четных итераций эти две строки меняются местами.

Затем две строки соединяются вертикально. Таким образом, nдвумерные символьные массивы создаются следующим образом (используется ·для представления символа 0):

·
1

1
·

· 
3

4
·

·· 
11

15
··

Эти массивы затем соединяются горизонтально для получения

·1·4··15
1·3·11··

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

!       % Transpose into a horizontal array [1 1 3 4 11 15 ...]
"       % For each
  @V    %   Push current number and convert to string
  t~o   %   Duplicate, negate, convert to double: string of the same length consisting 
        %   of character 0 repeated
  X@o   %   Parity of the iteration index (1 or 0)
  ?     %   If index is odd
    w   %     Swap
  ]     %   End if
  &v    %   Concatenate the two strings vertically. Gives a 2D char array representing
        %   a "numeric column" of the output (actually several columns of characters)
]       % End for
&h      % Concatenate all 2D char arrays horizontally. Gives a 2D char array with the
        % top two rows of the output
Z}      % Split this array into its two rows
y       % Push a copy of the first row. Implicitly display

6

Haskell, 101 байт

a=1:1:t
t=3:4:zipWith((-).(4*))t a
g(i,x)=min(cycle" 9"!!i)<$>show x
f n=[zip[y..y+n]a>>=g|y<-[0..2]]

Определяет функцию f :: Int → [String].

  • Майкл Кляйн напомнил мне, что мне не нужно вызывать unlinesрезультат, экономя 7 байтов. Благодарность!

  • Я сохранил байт, заменив " 9"!!mod i 2на cycle" 9"!!i.

  • Еще три байта, написав два базовых списка вместо использования drop.

  • Моя девушка указала, что я могу сохранить еще два байта, начав 0вместо ответов 1.


3

C, 183 177 176 байтов

#define F for(i=0;i<c;i++)
int i,c,a[35],t[9];p(r){F printf("%*s",sprintf(t,"%d",a[i]),r-i&1?t:" ");putchar(10);}b(n){c=n;F a[i]=i<2?1:a[i-2]+a[i-1]*(i&1?1:2);p(0);p(1);p(0);}

объяснение

Си никогда не собирается выигрывать призы за краткость против языка более высокого уровня, но упражнение является интересной и хорошей практикой.

Макрос F сбрасывает шесть байтов за счет читабельности. Переменные объявляются глобально, чтобы избежать нескольких объявлений. Мне нужен был символьный буфер для sprintf, но поскольку K & R не справляется с проверкой типов, sprintf и printf могут интерпретировать t [9] как указатель на 36-байтовый буфер. Это сохраняет отдельную декларацию.

#define F for(i=0;i<c;i++)
int i,c,a[35],t[9];

Симпатичная функция печати, где r - номер строки. Sprintf форматирует число и вычисляет ширину столбца. Чтобы сэкономить место, мы просто вызываем это три раза, по одному для каждой строки вывода; выражение ri & 1 фильтрует то, что печатается.

p(r) {
    F
        printf("%*s", sprintf(t, "%d", a[i]), r-i&1 ? t
                                                    : " ");
    putchar(10);
}

Функция точки входа, аргумент - количество столбцов. Вычисляет массив значений столбца a [], затем вызывает функцию печати p один раз для каждой строки вывода.

b(n) {
    c=n;
    F
        a[i] = i<2 ? 1
                   : a[i-2] + a[i-1]*(i&1 ? 1
                                          : 2);
    p(0);
    p(1);
    p(0);
}

Пример вызова (не включен в ответ и количество байтов):

main(c,v) char**v;
{
    b(atoi(v[1]));
}

обновленный

Включено встроенное предложение sprintf от tomsmeding. Это уменьшило счет с 183 до 177 символов. Это также позволяет удалить фигурные скобки вокруг блока printf (sprintf ()), поскольку теперь это только один оператор, но он сохранил только один символ, поскольку ему все еще требуется пробел в качестве разделителя. Так что до 176.


Не можете ли вы указать определение, wгде оно используется? Вы, кажется, используете его только один раз.
Томсминг

Вы не можете использовать itoaвместо sprintf?
Джакомо Гарабелло

Я рассмотрел itoa, но ее нет в моей системе, и я использую возвращаемое значение sprintf, чтобы установить ширину поля.
maharvey67

2

PowerShell v2 +, 133 байта

param($n)$a=1,1;1..$n|%{$a+=$a[$_-1]+$a[$_]*($_%2+1)};$a[0..$n]|%{$z=" "*$l+$_;if($i++%2){$x+=$z}else{$y+=$z}$l="$_".Length};$x;$y;$x

44 байта для вычисления значений, 70 байтов для формулировки ASCII

Принимает ввод $nкак столбец с нулевым индексом. Устанавливает начало нашего массива последовательностей $a=1,1. Затем мы возвращаемся к $nс, 1..$n|%{...}чтобы создать массив. На каждой итерации мы объединяем сумму (два элемента назад) + (предыдущий элемент) * (нечетный или четный индекс). Это будет генерировать $a=1,1,3,4,11...до $n+2.

Итак, нам нужно нарезать $aтолько первые 0..$nэлементы и передать их через другой цикл |%{...}. На каждой итерации мы устанавливаем хелпер $zравным количеству пробелов плюс текущий элемент в виде строки. Затем мы разбиваем, объединяется ли это $x(верхний и нижний ряды) или $y(средний ряд) простым нечетным if/ else. Затем мы вычисляем количество пробелов $l, беря текущее число, его строковое и беря его .Length.

Наконец, мы помещаем $x, $yи $xснова в конвейер, и вывод неявный. Поскольку .ToString()разделителем по умолчанию для массива при печати в STDOUT является символ новой строки, мы получаем его бесплатно.

пример

PS C:\Tools\Scripts\golfing> .\pascal-braid.ps1 27
 1 4  15  56   209   780    2911    10864     40545      151316      564719       2107560       7865521        29354524
1 3 11  41  153   571   2131    7953     29681     110771      413403      1542841       5757961       21489003
 1 4  15  56   209   780    2911    10864     40545      151316      564719       2107560       7865521        29354524

0

PHP 265 байт

<?php $i=$argv[1];$i=$i?$i:1;$a=[[],[]];$s=['',''];$p='';for($j=0;$j<$i;$j++){$y=($j+1)%2;$x=floor($j/2);$v=$x?$y?2*$a[0][$x-1]+$a[1][$x-1]:$a[0][$x-1]+$a[1][$x]:1;$s[$y].=$p.$v;$a[$y][$x]=$v;$p=str_pad('',strlen($v),' ');}printf("%s\n%s\n%s\n",$s[0],$s[1],$s[0]);

Un-golfed:

$a = [[],[]];
$s = ['',''];

$p = '';

$i=$argv[1];
$i=$i?$i:1;
for($j=0; $j<$i; $j++) {
    $y = ($j+1) % 2;
    $x = floor($j/2);

    if( $x == 0 ) {
        $v = 1;
    } else {
        if( $y ) {
            $v = 2 * $a[0][$x-1] + $a[1][$x-1];
        } else {
            $v = $a[0][$x-1] + $a[1][$x];
        }
    }
    $s[$y] .= $p . $v;
    $a[$y][$x] = $v;
    $p = str_pad('', strlen($v), ' ');
}

printf("%s\n%s\n%s\n", $s[0], $s[1], $s[0]);

Python 278 байт

import sys,math;a=[[],[]];s=['',''];p='';i=int(sys.argv[1]);i=1 if i<1 else i;j=0
while j<i:y=(j+1)%2;x=int(math.floor(j/2));v=(2*a[0][x-1]+a[1][x-1] if y else a[0][x-1]+a[1][x]) if x else 1;s[y]+=p+str(v);a[y].append(v);p=' '*len(str(v));j+=1
print ("%s\n"*3)%(s[0],s[1],s[0])


0

Matlab, 223 символа, 226 байтов

function[]=p(n)
r=[1;1];e={(' 1 ')',('1 1')'}
for i=3:n;r(i)=sum((mod(i,2)+1)*r(i-1)+r(i-2));s=num2str(r(i));b=blanks(floor(log10(r(i)))+1);if mod(i,2);e{i}=[b;s;b];else e{i}=[s;b;s];end;end
reshape(sprintf('%s',e{:}),3,[])

Развернулся и прокомментировал:

function[]=p(n) 
r=[1;1];                                    % start with first two 
e={(' 1 ')',('1 1')'}                       % initialize string output as columns of blank, 1, blank and 1, blank, 1.
for i=3:n;                                  % for n=3 and up! 
    r(i)=sum((mod(i,2)+1)*r(i-1)+r(i-2));   % get the next number by 1 if even, 2 if odd times previous plus two steps back
    s=num2str(r(i));                        % define that number as a string
    b=blanks(floor(log10(r(i)))+1);         % get a number of space characters for that number of digits
    if mod(i,2);                            % for odds
        e{i}=[b;s;b];                       % spaces, number, spaces
    else                                    % for evens
        e{i}=[s;b;s];                       % number, spaces, number
    end;
end
reshape(sprintf('%s',e{:}),3,[])            % print the cell array of strings and reshape it so it's 3 lines high

0

PHP, 135 124 123 120 байт

<?while($i<$argv[1]){${s.$x=!$x}.=${v.$x}=$a=$i++<2?:$v1+$v+$x*$v;${s.!$x}.=str_repeat(' ',strlen($a));}echo"$s
$s1
$s";

Используя преимущества неявных типов и переменных переменных,
треть кода (37 байт) уходит в пробелы, 64 байта в целом используются для вывода

сломать

$i=0; $x=false; $v=$v1=1; $s=$s1='';    // unnecessary variable initializations
for($i=0;$i<$argv[1];$i++)  // $i is column number -1
{
    $x=!$x; // $x = current row: true (1) for inner, false (empty string or 0) for outer
    // calculate value
    $a=
        $i<2?               // first or second column: value 1
        :$v1+(1+$x)*$v      // inner-val + (inner row: 1+1=2, outer row: 1+0=1)*outer-val
    ;
    ${s.$x}.=${v.$x}=$a;    // replace target value, append to current row
    ${s.!$x}.=str_repeat(' ',strlen($a));    // append spaces to other row
}
// output
echo "$s\n$s1\n$s";

0

Пакетный, 250 байт

@echo off
set s=
set d=
set/ai=n=0,j=m=1
:l
set/ai+=1,j^^=3,l=m+n*j,m=n,n=l
set t=%s%%l%
for /l %%j in (0,1,9)do call set l=%%l:%%j= %%
set s=%d%%l%
set d=%t%
if not %i%==%1 goto l
if %j%==1 echo %d%
echo %s%
echo %d%
if %j%==2 echo %s%

Поскольку первая и третья строки одинаковы, нам просто нужно построить две строки. Здесь dпредставляет строку, которая заканчивается последней записью и sпредставляет строку, которая заканчивается пробелами; последние четыре строки гарантируют, что они напечатаны в соответствующем порядке. iэто просто счетчик циклов (это немного дешевле, чем обратный отсчет %1). jэто переключение между удвоением предыдущего числа перед добавлением его к текущему номеру, чтобы получить следующий номер. mи nсодержать эти цифры. lкроме того, что он используется как временный для вычисления следующего числа, он также заменяет цифры на пробелы s; sа такжеd обмениваются каждый раз через промежуточную переменную t.

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