Створіть косу Паскаля


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. Це повинно бути послідовним вибором для всіх можливих входів.

Вихід

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

Іншими словами, кожен стовпець повинен бути точно таким же широким, як число (або пара рівних чисел) у цьому стовпчику, числа в послідовних стовпцях не повинні перетинатися, а між стовпцями не повинно бути пробілів.

Ви можете або надрукувати результат в 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

Формат здається мені трохи хамелеоном.
Leaky Nun

3
@LeakyNun Я спробував цю проблему, поки він знаходився в пісочниці, і я витратив приблизно половину стільки байтів на обчислення коси, як на її друк. Мені це здається чудовим балансом для виклику мистецтва .
FryAmTheEggman

4
@LeakyNun Я сподівався, що і генерація послідовностей, і ASCII мистецтво є важливими складовими завдання, тому що більшість мов, мабуть, буде кращим на одній із цих двох, тому я подумав, що було б цікаво їх змішати. І він вводить додатковий компонент, де не очевидно, чи краще генерувати верхню / нижню та середину окремо, або генерувати всю річ, а потім розділяти розбиття.
Мартін Ендер


У Паскалі ще ніхто не написав рішення. Це мене сумує.
динаміт, що

Відповіді:


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, яку я коли-небудь бачив.
imallett


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двовимірні масиви char створюються наступним чином (використовуючи ·для представлення символу 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);}

Пояснення

C ніколи не виграє жодних призів за стислість проти мови вищого рівня, але вправа є цікавою та гарною практикою.

Макрос 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 значень стовпця 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місця його використання? Ви ніби використовуєте його лише один раз.
tomsmeding

Ви не можете використовувати 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]);

Без гольфу:

$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

Матлаб, 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.