Romb Pascala


20

Romb Pascala (który w rzeczywistości jest trójkątem) uzyskuje się poprzez dodanie wzoru:

  *
 ***
  x

zamiast

* *
 x

Oznacza to, że każda komórka jest sumą trzech komórek w rzędzie bezpośrednio nad nią i jednej komórki w rzędzie 2 powyżej. Podobnie jak trójkąt Pascala, wiersz zerowy zawiera jeden 1, który generuje trójkąt.

Oto kilka pierwszych rzędów rombu Pascala

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

Zadanie

Podany numer wiersza (zaczynając od góry) i numer kolumny (zaczynając od pierwszego niezerowego elementu w tym wierszu) wyprowadza wartość w tej konkretnej komórce. Oba wejścia mogą być indeksowane 1 lub 0 (możesz miksować i dopasowywać, jeśli chcesz).

To jest więc powinieneś dążyć do jak najmniejszego rozmiaru pliku kodu źródłowego.

OEIS A059317


4
Podobnie jak w przypadku trójkąta Pascala, parzystość rombu tworzy ładne i fraktalne wzory .
Martin Ender

powinieneś dążyć do tego, aby rozmiar pliku kodu źródłowego był jak najmniejszy, a co jeśli wstawię mój kod jako argument wiersza poleceń? : P
Erik the Outgolfer,

Poszedłem do wyszukiwarki skrótów i najwyraźniej arxiv.org/abs/1504.04404 mówi, że bezpośrednie obliczenie wyniku nie jest możliwe dla golfa kodowego.
JollyJoker,

Odpowiedzi:


12

Haskell , 59 55 bajtów

Romb Pascala? Bardziej jak Hombell's Rhombus! czy mam rację?

4 bajty zapisane dzięki Ørjan Johansen

Myślałem, że spróbuję rozwiązać mój problem i poćwiczyć mój Haskell. Mamy nadzieję, że zainspiruje to więcej osób do odpowiedzi na to pytanie.

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

Wypróbuj online!

Wyjaśnienie

To jest trochę nieaktualne w najnowszym golfie

Zamiast obliczać

  *
 ***
  x

Obliczamy

*
***
  x

To skłania cały nasz trójkąt

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

To wyrównuje wszystkie nasze wiersze, ułatwiając indeksowanie n-tego elementu dowolnej kolumny. Następnie definiujemy nasze przypadki podstawowe.

Wiersz zerowy składa się z zer

0!_=0

Jest jeden 1na pozycji, 1,1więc go zdefiniujemy

1!1=1

I resztę pierwszego wiersza definiujemy również jako zera

1!_=0

Następnie definiujemy ogólny przypadek rekurencyjnie za pomocą wzoru opisanego powyżej:

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

Pokonaj mnie do tego! Jest to również o wiele czystsze niż moje.
Julian Wolf

@JulianWolf Przepraszam za to, że kiedy to opublikowałem, wyglądało na to, że nikt inny jak Jorg nie robi problemu. Nadal chciałbym zobaczyć twoje rozwiązanie.
Wheat Wizard

1
Możesz zapisać cztery bajty za pomocą n!k=sum[(n-2)!(k-2)+sum(map((n-1)!)[k-2..k])|n>1].
Ørjan Johansen

10

Pascal , 122 bajty

Cóż, to romb Pascala .

37 bajtów zapisanych dzięki @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;

Wypróbuj online!


Nawiasy wokół całego ifstanu są bezcelowe. (Na 1. ifzapisujesz 2 znaki, na 2. if1 znak, nie zostawiając spacji między thensłowem kluczowym a poprzednią cyfrą.) Och, i zmienna r jest całkowicie niepotrzebna.
manatwork

Dziwne zwierzę, które Pascal na Ideone. Nigdy wcześniej nie widziałem ciągów podwójnych cudzysłowów w żadnym wariancie Pascala. Jeszcze jedno można usunąć: the ;przed function„s end.
manatwork

@manatwork tak, teraz kiedy o tym wspomniałeś, wszyscy inni redaktorzy internetowi narzekali na to
Uriel

@manatwork Nie jestem pewien, czy zrozumiałem. czy to nie po prostu wydłuży kod o >= <=? Nadal muszę zachowaćif n=0
Uriel

Przepraszam @Uriel, nie mam już tej wersji. Obecnie jestem wfunction 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 bajtów

sposób rekurencyjny tylko wiersz funkcji i kolumna 0-indeksowane

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

Wypróbuj online!

PHP , 114 bajtów

sposób rekurencyjny pełny wiersz programu i kolumna 0-indeksowane

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

Wypróbuj online!

PHP , 129 bajtów

wiersz i kolumna 0-indeksowane

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

Wypróbuj online!


i +1 za faktyczne ulepszenie :)
Uriel


3

MATL , 22 20 19 bajtów

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

Oba wejścia są oparte na 0.

Wypróbuj online!

Wyjaśnienie

Niech ri coznacz dwa dane wejściowe, określając odpowiednio wiersz i kolumnę oparte na 0.

Każdy nowy rząd w rombu Pascala może być zbudowany z matrycy zawierającej dwa poprzednie wiersze przez splatanie z jądrem [1 1 1; 0 1 0]i utrzymanie dwóch ostatnich rzędów wyniku zamienione. Robi się to rrazy, zaczynając od matrycy 1.

Okazuje się, że użycie jądra [0 1 0; 1 1 1; 0 1 0], które jest predefiniowanym dosłownie, jest krótsze . Daje to dodatkowy rząd, który zostanie odrzucony.

Rozważmy na przykład r = 3, więc są 3iteracje.

  1. Zaczynając od

    1
    

    splot [0 1 0; 1 1 1; 0 1 0]daje

    0 1 0
    1 1 1
    0 1 0
    

    Zachowanie dwóch ostatnich wierszy (w tym przypadku całej macierzy) i ich zamiana daje

    0 1 0
    1 1 1
    
  2. Splot powyższego z [0 1 0; 1 1 1; 0 1 0]daje

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

    Macierz utworzona przez zamienione dwa ostatnie rzędy to

    0 1 1 1 0
    1 2 4 2 1
    

    Zawiera on nowy wiersz u dołu, a poprzedni przedłużony zerami.

  3. Ponowne rozmycie daje

    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
    

    Biorąc dwa ostatnie zamienione wiersze daje

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

Po zakończeniu riteracji dane wyjściowe są zawarte w ostatnim wierszu ostatniej macierzy. Na przykład dla c = 2(na podstawie 0) wynik byłby 8. Zamiast indeksować ostatni wiersz i żądaną kolumnę, można zastosować lewę, która wykorzystuje symetrię każdego rzędu: ostatnia macierz jest transponowana

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

i jego -c-ty element jest brany. Wykorzystuje to indeksowanie liniowe, to znaczy macierz jest indeksowana jednym indeksem w porządku głównym kolumny . Ponieważ indeksowanie jest modułowe , 0-wejście jest prawym dolnym rogiem (wartość 1), a -2-ty wpis to dwa kroki powyżej (wartość 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

Mathematica, 56 bajtów

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

Czysta funkcja pobierająca dwa argumenty całkowite (pierwszy wiersz, druga kolumna) i zwracająca liczbę całkowitą. Działa również w przypadku ujemnych argumentów liczb całkowitych, zwracając 0. Dość prosta struktura rekurencyjna: If[#<1,Boole[##==0],...]definiuje zachowanie przypadku podstawowego dla 0-go wiersza (i powyżej), a jednocześnie Sum[#0[#-i,#2-j],{i,2},{j,2i-2,2}]implementuje definicję rekurencyjną.



1

JavaScript (ES6), 68 bajtów

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 bajty

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

Korzystanie z funkcji generowania.


0

Python 3 , 82 84 bajtów

Jest to rekurencyjna implementacja z 1-indeksowanymi wierszami i kolumnami. (Technicznie potrzebujef= przodu, ktoś dał mi znać, czy powinienem zmienić go na 84 bajty. Nadal nowe i nie w 100% pewne zasad).

Wykorzystuje to rekurencyjną formułę znalezioną na stronie OEIS , ale z kprzesuniętą w lewo, aby poprawnie ustawić. Przypadkowo sum(f(n-1,k-i)for i in(0,1,2))ma taki sam rozmiar jak f(n-1,k)+f(n-1,k-1)+f(n-1,k-2). Cała funkcja to and orsztuczka Pythona , w której pierwszy warunek sprawdza, czy k znajduje się w trójkącie, a nie na granicy, w którym to przypadku używana jest formuła rekurencyjna. Jeśli nie orjest, zwracana jest część po , która sprawdza, czy kjest (1, 2*n-1), tj. Na granicy, zwracając Truei False. k+1in(2,2*n)jest o jeden bajt krótszy niż k in(1,2*n-1). Zawijanie tego w nawiasach i umieszczanie z +przodu konwertuje na liczbę całkowitą, co jest potrzebne.

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))

Wypróbuj online!


Funkcje rekurencyjne wymagają f=.
Wheat Wizard

Podczas gdy ja osobiście się z tym nie zgadzam zgodnie z tym nieco zakopanym meta konsensusem, możesz wypisywać Truezamiast tego, 1ponieważ zachowuje się jak 1python. To pozwala usunąć +(...)na końcu. Rozumiem, że jeśli nie chcesz tego zrobić, ponieważ spowoduje to, że wynik będzie wyglądał trochę dziwnie, jest to opcja.
Wheat Wizard

@WheatWizard Wow, to bardzo interesujące. Dzięki za wskazówkę.
C McAvoy,


0

Python 3 , 75 bajtów

Jest to rekurencyjna lambda, która przyjmuje kolumnę i wiersz jako liczby całkowite 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

Oto (nieco) bardziej czytelna wersja z funkcją drukowania:

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)
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.