Sekwencje Skolem
Sekwencja Skolem jest ciągiem 2n
liczb, gdzie każda liczba i
pomiędzy 1
i n
zachodzi dokładnie dwa razy, a odległość między dwoma wystąpieniami i
jest dokładnie i
kroki. Oto kilka przykładów sekwencji Skolem:
1 1
1 1 4 2 3 2 4 3
16 13 15 12 14 4 7 3 11 4 3 9 10 7 13 12 16 15 14 11 9 8 10 2 6 2 5 1 1 8 6 5
Następujące sekwencje nie są sekwencjami Skolem:
1 2 1 2 (The distance between the 1's is 2, not 1)
3 1 1 3 (The number 2 is missing)
1 1 2 1 1 2 (There are four 1's)
Cel
Napisz program, funkcję lub wyrażenie, aby policzyć liczbę wszystkich sekwencji Skolem o danej długości. Mówiąc ściślej, dane wejściowe są liczbami całkowitymi n
, a dane wyjściowe to liczba sekwencji Skolem o długości 2n
. Ta sekwencja ma wpis OEIS . Dla n = 0
, można zwrócić albo 0
albo 1
. Pierwsze kilka wartości, zaczynając od 0
, to
0, 1, 0, 0, 6, 10, 0, 0, 504, 2656, 0, 0, 455936, 3040560, 0, 0, 1400156768
Zasady i punktacja
To jest kod golfowy. Format wyjściowy jest luźny w granicach rozsądku.
0, 1, 0, 0, 6...
pytasz? Czy to fragment kodu, jeśli tak, to w jakim języku?0
? Jeśli masz zamiar przyznać, że0
jest to poprawny sygnał wejściowy, wynik powinien być1
.Odpowiedzi:
GolfScript,
4846 znakówWersja szybsza ( spróbuj online ) - działa dość szybko, np.
n=8
Zajmuje około dwóch sekund. Wybrane podejście zajmuje naprawdę niewiele postaci.Ta wersja działa również z maskami bitowymi. Buduje możliwą tablicę wyników od 1 w górę, tj. Dla
n=3
:Podczas gdy niektóre wyniki (jak 000011) mają dwie możliwe kontynuacje, inne (tj. 001100) nie mają żadnych i są usuwane z tablicy wyników.
Objaśnienie kodu:
źródło
Wyrażenie J, 47 znaków
Przykład:
Trwa około 30 sekund
y=:5
na moim komputerze.algorytm jest tak wolny, jak to tylko możliwe:
~.(i.!+:y)A.,~>:i.y
generuje każdą permutację1 2 .. y 1 2 .. y
i usuwa zduplikowane wpisy((=&{:+.2-#@])#;.2)\"1
oblicza:(...)\"1
dla każdego prefiksu każdego wiersza:#;.2
liczy elementy przed każdym wystąpieniem ostatniego elementu#@]
zlicza liczbę zliczeń (tj. liczbę wystąpień ostatniego elementu)=&{:
określa „równość” „” ostatniego elementu ”listy liczników i listy oryginalnej.+.
jest logicznym OR.=&{:+.2-#@]
czyta „albo ostatnie elementy [listy zliczeń i oryginalnej listy] są równe, lub jest tylko jeden element [na liście zliczeń] zamiast dwóch”.*/"1
mnoży (logiczne AND) przez wiersze tabeli warunków, określając, które permutacje są sekwencjami Skolema.+/
sumuje jedynki i zera razem.źródło
GolfScript (46 znaków)
To wyrażenie pobiera dane wejściowe ze stosu. Aby przekształcić go w pełny program, który pobiera dane wejściowe na standardowe wejście, dodaj
~
Jest to dość nieefektywne - większość oszczędności, które poczyniłem, grając w golfa z 56 znaków bez golfa, polegało na rozszerzeniu zakresu pętli w sposób, który nie wprowadza niepoprawnych wyników, ale oblicza straty.
Podejście polega na bitowym maskowaniu produktów kartezjańskich. Np. (Użycie binarne dla masek) dla
n=4
kodu bez golfa obliczałby xor każdego elementu w produkcie kartezjańskim[00000011 00000110 ... 11000000] x [00000101 00001010 ... 10100000] x ... x [00010001 ... 10001000]
. Dowolny wynik z 8 bitami można osiągnąć tylko za pomocą nienakładających się masek.Aby zoptymalizować rozmiar, a nie szybkość, kod gromadzi produkty cząstkowe (
S1 u S1xS2 u S1xS2xS3 ...
) i sprawia, że każdy produkt składa się z2n
elementów, a nie tylko z tych,2n-1-i
które mogą faktycznie przyczynić się do prawidłowej sekwencji.Prędkość
Gra w golfa działa
n=5
na moim komputerze za 10 sekund i przez ponad 5 minutn=6
. Oryginalna wersja bez golfa oblicza sięn=5
w niecałą sekundę in=6
około 1 minuty. Dzięki prostemu filtrowi wyników pośrednich można go obliczyćn=8
w 30 sekund. Grałem w golfa do 66 znaków (jako program - 65 znaków jako wyrażenie), jednocześnie utrzymując pętle tak ograniczone, jak to możliwe i filtrując kolizje pośrednie:źródło
GolfScript, 49 znaków
Oczekuje liczby
n
na STDIN. To jest golf golfowy - nie próbuj kodu z wartościąn
większą niż 5.źródło
Sage, 70
To jest trochę krótsze niż mój oryginał.
Jak to działa:
Biorąc pod uwagę macierz 0/1, dokładnym problemem pokrycia dla tej macierzy jest znalezienie podzestawu wierszy, który sumuje (jako liczby całkowite) do wektora wszystkich. Na przykład,
ma rozwiązanie
Moje ulubione podejście do problemów polega na rzuceniu ich na dokładny problem z okładką. Sekwencje Skolem skutecznie to ułatwiają. Dokładnie opisuję problem, w którym rozwiązania są bijection z sekwencjami długości Skolema
2n
. Na przykład wierszem problemun=6
jestgdzie 1 w pozycji
a < n
oznacza, żea
używany jest symbol . Pozostałe pozycje odpowiadają faktycznym lokalizacjom w sekwencji. Dokładna okładka odpowiada każdemu symbolowi używanemu dokładnie raz, a każda lokalizacja jest wypełniana dokładnie raz. Z konstrukcji każdy symbolk
w lokalizacji jestk
oddalony od partnera.W Sage
DLXCPP
jest implementacją „tańczących linków” - rozwiązuje dokładnie problem z okładką w wyjątkowo wdzięczny sposób. Jest to jeden z moich ulubionych algorytmów w historii, a bycie na powierzchni w Sage sprawia, że kombinatoryczne wyliczanie jest radością.źródło
len(list(...))
spowoduje zapisanie 4 znaków.len(list(...))
dla n = 16. I to całkowicie zabiłoby środowisko uruchomieniowe.