Ромб Паскаля

20

Ромб Паскаля (который на самом деле является треугольником) получается путем добавления в шаблон:

  *
 ***
  x

вместо того

* *
 x

Это означает, что каждая ячейка является суммой трех ячеек в строке непосредственно над ней и одной ячейки в ряду 2 над ней. Точно так же, как треугольник Паскаля, в нулевом ряду есть один, 1который генерирует треугольник.

Вот первая пара строк ромба Паскаля

      1
    1 1 1
  1 2 4 2 1
1 3 8 9 8 3 1

задача

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

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

OEIS A059317

Мастер пшеницы
источник
4
Как и в случае с треугольником Паскаля, четность ромба создает красивые и фрактальные узоры .
Мартин Эндер
Вы должны стремиться к тому, чтобы размер файла вашего исходного кода был как можно меньшим, что если я добавлю свой код в качестве аргумента командной строки? : P
Эрик Outgolfer
Пошёл гуглить на ярлыки и, по-видимому, arxiv.org/abs/1504.04404 говорит, что вычисление результата напрямую непригодно для кода гольф.
JollyJoker

Ответы:

12

Haskell , 59 55 байт

Ромб Паскаля? Больше похоже на ромб Хаскелла! я прав?

4 байта сохранены благодаря Эрджану Йохансену

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

1!1=1
n!k=sum[(n-2)!(k-2)+sum(map((n-1)!)[k-2..k])|n>1]

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

объяснение

Это немного устарело с последним гольфом

Вместо расчета

  *
 ***
  x

Мы рассчитываем

*
***
  x

Это наклоняет весь наш треугольник, чтобы стать

1
1 1 1
1 2 4 2 1
1 3 8 9 8 3 1

Это выстраивает в ряд все наши строки, упрощая индексацию n-го элемента любого столбца. Затем мы определяем наши базовые случаи.

Нулевой ряд все нули, так

0!_=0

Есть один 1в позиции, 1,1поэтому мы определяем, что

1!1=1

И мы определяем оставшуюся часть первого ряда также нулями

1!_=0

Затем мы определяем общий случай рекурсивно, используя шаблон, описанный выше:

n!k=(n-2)!(k-2)+(sum$map((n-1)!)[k-2..k])
Мастер пшеницы
источник
Обыграй меня! Это также намного чище, чем у меня.
Джулиан Вольф
@JulianWolf К сожалению об этом, когда я разместил это, казалось, что никто, кроме Йорга, не делал проблему. Я все еще хотел бы увидеть ваше решение.
Пшеничный волшебник
1
Вы можете сохранить четыре байта с помощью n!k=sum[(n-2)!(k-2)+sum(map((n-1)!)[k-2..k])|n>1].
Орджан Йохансен
10

Паскаль , 122 байта

Ну, это ромб Паскаля .

37 байтов сохранено благодаря @manatwork

function f(n,k:integer):integer;begin f:=1-Ord((k<0)or(k>n*2));if n>0then f:=f(n-1,k-2)+f(n-1,k-1)+f(n-1,k)+f(n-2,k-2)end;

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

Уриэль
источник
Скобки вокруг всего ifсостояния бессмысленны. (1-го числа ifвы сохраняете 2 символа, а 2-го ifсимвола 1, не оставляя пробела между thenключевым словом и предыдущей цифрой.) О, и переменная r совершенно не нужна.
Манатворк
Странное животное, которое Паскаль на Идоне. Никогда прежде не видел строк с двойными кавычками в любом варианте Паскаля. Еще одна вещь , которую вы можете удалить: ;до function«с end.
Манатворк
@manatwork да, теперь, когда вы упомянули об этом, все другие онлайн-редакторы жаловались на это
Уриэль
@ Manatwork Я не уверен, что понял. разве это не удлинит код >= <=? Мне все еще нужно сохранитьif n=0
Уриэль
Извините @Uriel, у меня больше нет этой версии. В настоящее время я нахожусь наfunction f(n,k:integer):integer;begin f:=1-Ord((k<0)or(k>n*2));if n>0then f:=f(n-1,k-2)+f(n-1,k-1)+f(n-1,k)+f(n-2,k-2)end;
manatwork
7

PHP , 86 байт

рекурсивным способом только функция строки и столбца 0-проиндексированы

function f($r,$c){return$r|$c?$r<0?0:f($r-=1,$c)+f($r,$c-1)+f($r,$c-=2)+f($r-1,$c):1;}

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

PHP , 114 байт

рекурсивный способ полной строки программы и столбца 0-Indexed

<?=f(...$_GET);function f($r,$c){return$r|$c?$r<0|$c<0|$c>2*$r?0:f($r-=1,$c)+f($r,$c-1)+f($r,$c-=2)+f($r-1,$c):1;}

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

PHP , 129 байт

строка и столбец 0-проиндексированы

for(;$r<=$argv[1];$l=$t[+$r++])for($c=~0;$c++<$r*2;)$t[+$r][$c]=$r|$c?$t[$r-2][$c-2]+$l[$c]+$l[$c-1]+$l[$c-2]:1;echo$l[$argv[2]];

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

Йорг Хюльсерманн
источник
и +1 за фактическое улучшение :)
Уриэль
3

MATL , 22 20 19 байтов

Ti:"2Y6Y+FT_Y)]!i_)

Оба входа основаны на 0.

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

объяснение

Позвольте rи cобозначить два входа, указав 0 и строки и столбца соответственно.

Каждая новая строка в ромбе Паскаля может быть построена из матрицы, содержащей предыдущие две строки, путем свертки с ядром [1 1 1; 0 1 0]и сохранения двух последних строк результата. Это делается rраз, начиная с матрицы 1.

Оказывается, короче использовать ядро [0 1 0; 1 1 1; 0 1 0], которое является предопределенным литералом. Это создает дополнительную строку, которая будет отброшена.

Рассмотрим, к примеру r = 3, чтобы были 3итерации.

  1. Начиная с

    1
    

    свертка [0 1 0; 1 1 1; 0 1 0]дает

    0 1 0
    1 1 1
    0 1 0
    

    Сохранение двух последних строк (в данном случае всей матрицы) и их замена дает

    0 1 0
    1 1 1
    
  2. Свертывание выше [0 1 0; 1 1 1; 0 1 0]дает

    0 0 1 0 0
    0 1 1 1 0
    1 2 4 2 1
    0 1 1 1 0
    

    Матрица, образованная из двух последних замененных строк:

    0 1 1 1 0
    1 2 4 2 1
    

    Это содержит новую строку внизу, а предыдущий расширен нулями.

  3. Свертка снова дает

    0 0 1 1 1 0 0
    0 1 2 3 2 1 0
    1 3 8 9 8 3 1
    0 1 2 4 2 1 0
    

    Взяв последние два ряда поменялись местами дает

    0 1 2 4 2 1 0
    1 3 8 9 8 3 1
    

После того как rитерации выполнены, выходные данные содержатся в последней строке окончательной матрицы. Например, для c = 2(на основе 0) результат будет 8. Вместо индексации последней строки и нужного столбца можно использовать трюк, который использует симметрию каждой строки: конечная матрица транспонируется

0 1
1 3
2 8
4 9
2 8
1 3
0 1

и его -c-й элемент взят. При этом используется линейное индексирование, то есть матрица индексируется одним индексом в порядке старших столбцов . Поскольку индексирование является модульным , 0-entry - это правый нижний угол (значение 1), а -2-я запись - на два шага выше (значение 8).

T       % Push true
i       % Input row number
:"      % Do the following that many times
  2Y6   %   Push predefined literal [0 1 0; 1 1 1; 0 1 0]
  Y+    %   2D convolution, increasing size
  FT_   %   Push [0 -1]
  Y)    %   Matrix with rows 0 (last) and -1 (second-last), in that order
]       % End
!       % Transpose
i       % Input: colun number
_       % Negate
)       % Entry with that index. Implicitly display
Луис Мендо
источник
2

Haskell , 74 байта

0#0=1
n#m|m<=2*n&&m>=0=sum[(n-a)#(m-b)|(a,b)<-zip[2,1,1,1]$2:[0..2]]
n#m=0

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

Позвоните n # m, где nстрока и mстолбец.

Юлианский волк
источник
m<=2*n&&m>=0может быть просто n>0.
Орджан Йохансен
2

Mathematica, 56 байт

If[#<1,Boole[##==0],Sum[#0[#-i,#2-j],{i,2},{j,2i-2,2}]]&

Чистая функция, принимающая два целочисленных аргумента (первый ряд, второй столбец) и возвращающая целое число. Работает и для отрицательных целочисленных аргументов, возвращая 0. Довольно простая рекурсивная структура: If[#<1,Boole[##==0],...]определяет поведение в базовом случае для 0-й строки (и выше), а также Sum[#0[#-i,#2-j],{i,2},{j,2i-2,2}]реализует рекурсивное определение.

Грег Мартин
источник
1

JavaScript (ES6), 68 байт

f=(y,x)=>x<0|x>y+y?0:x>0&x<y+y?f(--y,x)+f(y,--x)+f(y,--x)+f(--y,x):1
Нил
источник
1

Mathematica, 53 байта

D[1/(1-x(1+y+y^2(1+x))),{x,#},{y,#2}]/#!/#2!/.x|y->0&

Использование производящей функции.

alephalpha
источник
0

Python 3 , 82 84 байта

Это рекурсивная реализация с 1-индексированными строками и столбцами. (С технической точки зрения необходимо получить f=перед, кто-то, дайте мне знать, если я должен изменить его на 84 байта. Все еще новый и не уверен на 100% в правилах.)

При этом используется рекурсивная формула, найденная на странице OEIS , но со kсмещенной влево для правильного выравнивания. По совпадению, sum(f(n-1,k-i)for i in(0,1,2))такой же размер как f(n-1,k)+f(n-1,k-1)+f(n-1,k-2). Вся функция - это and orтрюк Питона , где первое условие проверяет, находится ли k внутри треугольника, а не на границе, и в этом случае используется рекурсивная формула. Если это не так, orвозвращается часть после , которая проверяет, kнаходится ли она (1, 2*n-1), то есть на границе, возвращая Trueи False. k+1in(2,2*n)на один байт короче k in(1,2*n-1). Оборачивая это в скобках и помещая +перед ними, преобразуется в целое число, что и нужно.

f=lambda n,k:2*n-1>k>1and sum(f(n-1,k-i)for i in(0,1,2))+f(n-2,k-2)or+(k+1in(2,2*n))

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

С МакЭвой
источник
Рекурсивные функции нужны f=.
Пшеничный волшебник
Хотя я лично не согласен с этим в соответствии с этим несколько утонувшим мета-консенсусом, вы можете выводить его, Trueа не 1потому, что он ведет себя как 1Python. Это позволяет вам удалить +(...)в конце. Я понимаю, что если вы не хотите этого делать, потому что это сделает вывод немного странным, это вариант.
Пшеничный волшебник
@WheatWizard Вау, это очень интересно. Спасибо за чаевые.
С
0

Java (OpenJDK 8) , 87 байт

int f(int r,int c){return c<0|2*r<c?0:0<c&c<2*r?f(--r,c)+f(r,--c)+f(r,--c)+f(--r,c):1;}

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

Сначала я был доволен итеративным методом с 160 байтами ... Хммм ... давайте просто забудем об этом, хорошо?

Оливье Грегуар
источник
0

Python 3 , 75 байт

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

p=lambda r,c:(r<0 or((c==0)|p(r-1,c-2)+p(r-1,c)+p(r-1,c-1)+p(r-2,c-2))+1)-1

Вот (немного) более читаемая версия с функцией печати:

p = lambda r,c:(r<0 or ((c==0) | p(r-1,c-2)+p(r-1,c)+p(r-1,c-1)+p(r-2,c-2))+1)-1

def pp(r):
    ml = len(str(p(r,r)))+1
    for i in range(0, r):
            a=" "*ml*(r-i)
            for j in range(0,i*2 + 1):
                    a+=str(p(i,j))+(" "*(ml-len(str(p(i,j)))))
            print(a)
Эрик Канам
источник