Czas podjąć niebezpieczną misję pokonania brytyjskiego wywiadu. Celem tego wyzwania jest napisanie najkrótszego kodu, który rozwiąże Nonogram.
Co to jest nonogram?
Zasady są proste. Masz siatkę kwadratów, które muszą być wypełnione na czarno lub pozostawione puste. Obok każdego rzędu siatki są wymienione długości serii czarnych kwadratów w tym rzędzie. Nad każdą kolumną są wymienione długości serii czarnych kwadratów w tej kolumnie. Twoim celem jest znalezienie wszystkich czarnych kwadratów. W tym typie puzzli liczby są formą dyskretnej tomografii, która mierzy, ile nieprzerwanych linii wypełnionych kwadratów znajduje się w danym wierszu lub kolumnie. Na przykład wskazówka „4 8 3” oznacza, że istnieją zestawy czterech, ośmiu i trzech wypełnionych kwadratów, w tej kolejności, z co najmniej jednym pustym kwadratem między kolejnymi grupami. [ 1 ] [ 2 ]
Rozwiązaniem powyższego Nonogramu byłoby:
Szczegóły dotyczące wdrożenia
Możesz wybrać reprezentowanie Nonograma w dowolny sposób i brać go jako dane wejściowe w dowolny sposób, który uznasz za odpowiedni dla twojego języka. To samo dotyczy wyników. Celem tego wyzwania jest dosłownie wykonanie pracy; jeśli możesz rozwiązać nonogram za pomocą danych wyjściowych programu, jest to poprawne. Jednym zastrzeżeniem jest to, że nie możesz użyć solvera online :)
Ten problem jest bardzo trudny algorytmicznie (np. Kompletny), ponieważ nie ma całkowicie skutecznego rozwiązania i jako taki, nie zostaniesz ukarany za to, że nie jesteś w stanie rozwiązać większych, chociaż twoja odpowiedź będzie silnie wynagrodzona, jeśli jest w stanie obsługiwać duże skrzynki (patrz bonus). Jako punkt odniesienia moje rozwiązanie działa w przybliżeniu na 25 x 25 w ciągu 5-10 sekund. Aby zapewnić elastyczność między różnymi językami, wystarczające są rozwiązania, które zajmują mniej niż 5 minut dla nonogramu 25x25.
Możesz założyć układankę w zawsze kwadratowym nonogramie NxN.
Możesz użyć tego internetowego łamigłówki nonogramowej do przetestowania swoich rozwiązań.
Punktacja
Oczywiście możesz swobodnie używać dowolnego języka, a ponieważ jest to kod do golfa, wpisy zostaną posortowane w kolejności: accuracy -> length of code -> speed.
jednak nie zniechęcaj się kodami języków golfowych, odpowiedzi we wszystkich językach, które pokazują próby gry w golfa w ciekawy sposób zostaną ocenione!
Premia
I rzeczywiście dowiedział się o Nonograms z kryptograficznego kartki świąteczne wydany przez brytyjskiego wywiadu tutaj . Pierwsza część była w zasadzie ogromnym Nonogramem 25x25. Jeśli twoje rozwiązanie jest w stanie rozwiązać ten problem, otrzymasz odznaczenia :)
Aby ułatwić Ci życie w zakresie wprowadzania danych, przedstawiłem sposób, w jaki przedstawiłem dane dla tej konkretnej układanki do bezpłatnego użytku. Pierwsze 25 wierszy to wskazówki wierszy, następnie linia separatora „-”, następnie 25 linii wskazówek col, następnie linia separatora „#”, a następnie reprezentacja siatki z wypełnionymi kwadratowymi wskazówkami.
7 3 1 1 7
1 1 2 2 1 1
1 3 1 3 1 1 3 1
1 3 1 1 6 1 3 1
1 3 1 5 2 1 3 1
1 1 2 1 1
7 1 1 1 1 1 7
3 3
1 2 3 1 1 3 1 1 2
1 1 3 2 1 1
4 1 4 2 1 2
1 1 1 1 1 4 1 3
2 1 1 1 2 5
3 2 2 6 3 1
1 9 1 1 2 1
2 1 2 2 3 1
3 1 1 1 1 5 1
1 2 2 5
7 1 2 1 1 1 3
1 1 2 1 2 2 1
1 3 1 4 5 1
1 3 1 3 10 2
1 3 1 1 6 6
1 1 2 1 1 2
7 2 1 2 5
-
7 2 1 1 7
1 1 2 2 1 1
1 3 1 3 1 3 1 3 1
1 3 1 1 5 1 3 1
1 3 1 1 4 1 3 1
1 1 1 2 1 1
7 1 1 1 1 1 7
1 1 3
2 1 2 1 8 2 1
2 2 1 2 1 1 1 2
1 7 3 2 1
1 2 3 1 1 1 1 1
4 1 1 2 6
3 3 1 1 1 3 1
1 2 5 2 2
2 2 1 1 1 1 1 2 1
1 3 3 2 1 8 1
6 2 1
7 1 4 1 1 3
1 1 1 1 4
1 3 1 3 7 1
1 3 1 1 1 2 1 1 4
1 3 1 4 3 3
1 1 2 2 2 6 1
7 1 3 2 1 1
#
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
A oto nieco inna wersja dla twojej wygody; krotka oddzielona przecinkami (wiersz, kolumna), gdzie każdy element jest listą list.
([[7, 3, 1, 1, 7],
[1, 1, 2, 2, 1, 1],
[1, 3, 1, 3, 1, 1, 3, 1],
[1, 3, 1, 1, 6, 1, 3, 1],
[1, 3, 1, 5, 2, 1, 3, 1],
[1, 1, 2, 1, 1],
[7, 1, 1, 1, 1, 1, 7],
[3, 3],
[1, 2, 3, 1, 1, 3, 1, 1, 2],
[1, 1, 3, 2, 1, 1],
[4, 1, 4, 2, 1, 2],
[1, 1, 1, 1, 1, 4, 1, 3],
[2, 1, 1, 1, 2, 5],
[3, 2, 2, 6, 3, 1],
[1, 9, 1, 1, 2, 1],
[2, 1, 2, 2, 3, 1],
[3, 1, 1, 1, 1, 5, 1],
[1, 2, 2, 5],
[7, 1, 2, 1, 1, 1, 3],
[1, 1, 2, 1, 2, 2, 1],
[1, 3, 1, 4, 5, 1],
[1, 3, 1, 3, 10, 2],
[1, 3, 1, 1, 6, 6],
[1, 1, 2, 1, 1, 2],
[7, 2, 1, 2, 5]],
[[7, 2, 1, 1, 7],
[1, 1, 2, 2, 1, 1],
[1, 3, 1, 3, 1, 3, 1, 3, 1],
[1, 3, 1, 1, 5, 1, 3, 1],
[1, 3, 1, 1, 4, 1, 3, 1],
[1, 1, 1, 2, 1, 1],
[7, 1, 1, 1, 1, 1, 7],
[1, 1, 3],
[2, 1, 2, 1, 8, 2, 1],
[2, 2, 1, 2, 1, 1, 1, 2],
[1, 7, 3, 2, 1],
[1, 2, 3, 1, 1, 1, 1, 1],
[4, 1, 1, 2, 6],
[3, 3, 1, 1, 1, 3, 1],
[1, 2, 5, 2, 2],
[2, 2, 1, 1, 1, 1, 1, 2, 1],
[1, 3, 3, 2, 1, 8, 1],
[6, 2, 1],
[7, 1, 4, 1, 1, 3],
[1, 1, 1, 1, 4],
[1, 3, 1, 3, 7, 1],
[1, 3, 1, 1, 1, 2, 1, 1, 4],
[1, 3, 1, 4, 3, 3],
[1, 1, 2, 2, 2, 6, 1],
[7, 1, 3, 2, 1, 1]])
źródło
s=[].fill([].fill(0,0,25),0,25);s[3][3]=s[3][4]=s3[3][12]=s3[3][13]=s3[3][21]=s[8][6]=s[8][7]=s[8][10]=s[8][14]=s[8][15]=s[8][18]=s[16][6]=s[16][11]=s[16][16]=s[16][20]=s[21][3]=s[21][4]=s[21][9]=s[21][10]=s[21][15]=s[21][20]=s[21][21]=1;
Odpowiedzi:
Brachylog ,
7069 bajtówPobiera to listę dwóch list (najpierw wskaźniki wierszy, a następnie kolumny). Każdy wskaźnik sam w sobie jest listą (dla pozycji jak
[3,1]
w jednym rzędzie).Ta wersja zajmuje około 3 minut, aby rozwiązać przykładowe wyzwanie 5 na 5.
Znacznie bardziej wydajna wersja, 91 bajtów
Wypróbuj online!
Ten nie jest całkowitą brutalną siłą: jedyną różnicą jest to, że nakłada ograniczenia na wartości komórek, tak że liczba 1s w każdym rzędzie i kolumnie odpowiada liczbom podanym jako wskaźniki na wejściu. Jedyną częścią siły brutalnej jest wówczas znalezienie jednej siatki z tymi ograniczeniami, dla których „bloki” 1s odpowiadają temu, co podano jako wskazanie.
To trwa około 0,05 sekundy na przykładzie wyzwania 5 na 5. Jest to wciąż zbyt wolne w przypadku premii, ponieważ nie mam pojęcia, jak wyrazić bloki zer oddzielone jednym lub więcej zerami w kategoriach ograniczeń.
Wyjaśnienie
Wyjaśnię poniżej wersję 93 bajtów. Jedyną różnicą między nimi jest wywołanie predykatu 3, które nie istnieje w wersji 70-bajtowej, i numeracja predykatów (ponieważ jest jeden mniej).
Główny predykat:
Predykat 1: Wymusza, aby wiersze miały określoną długość, a każda komórka ma wartość 0 lub 1.
Predykat 2: Ogranicz zmienną do wartości 0 lub 1
Predykat 3: Suma 1s na liście musi być równa sumie wskaźników (np. Jeśli wskaźnikiem jest [3: 1], wówczas lista musi mieć sumę 4)
Predykat 4: Sprawdź, czy bloki 1s pasują do wskaźnika
Predykat 5: Prawda dla bloków 1s, w przeciwnym razie fałsz
źródło
Haskell,
242 230 201 199 177 163 160 149131 bajtówWreszcie poniżej 200 bajtów, kredyt @Bergi. Ogromne podziękowania dla @nimi za pomoc prawie o połowę mniejszą.
Łał. Prawie w połowie wielkości teraz, częściowo przeze mnie, ale głównie przez @nimi.
Magiczną funkcją jest
(#)
. Znajduje wszystkie rozwiązania danego nonogramu.Jest to w stanie rozwiązać wszystkie przypadki, ale może być bardzo wolne, ponieważ chodzi o jego złożoność
O(2^(len a * len b))
. Szybki test porównawczy ujawnił 86 GB przydzielonych dla nonogramu 5x5.Ciekawostka: działa na wszystkie nonogramy, nie tylko kwadratowe.
Jak to działa:
a#b
: Biorąc pod uwagę listy liczb całkowitych reprezentujących liczbę kwadratów, generuj wszystkie siatki (map(chunk$length b).mapM id$a>>b>>[[0,1]]
) i filtruj wyniki, aby zachować tylko te prawidłowe.g
: Biorąc pod uwagę potencjalny nonogram, sumuje biegi 1 w poziomie.źródło
m(chunk$l b)
ireplicate(l$a>>b)
import Data.Lists
wystarczy, ponieważ ponownie eksportuje zarównoData.List
iData.List.Split
.Pyth,
917271 bajtówProgram, który pobiera listę postaci, w
[size, [horizontal clues], [vertical clues]]
której każda wskazówka jest listą liczb całkowitych (puste wskazówki są pustą listą[]
), i drukuje każde rozwiązanie, oddzielone znakiem nowej linii, w postaci siatki binarnej, w której1
jest zacieniowany i nie0
jest zacieniowany .To brutalna siła, więc z grubsza
O(2^n^2)
. Zaczyna się zajmować dużo czasu dla większych łamigłówek, ale rozwiąże każdy rozmiar arbitrary, mając wystarczającą ilość czasu.Wypróbuj online
Jak to działa
Program generuje każdy możliwy układ, biorąc powtarzalny iloczyn kartezjański o
[0, 1]
długości równejsize^2
. Jest to następnie dzielone na części, dając listę dla każdej linii poziomej. Każda linia jest kodowana na całej długości, filtrowana przez obecność1
i spłaszczana, pozostawiając wskazówkę dla tej linii. Jest to następnie porównywane z danymi wejściowymi. Powyższy proces powtarza się dla transpozycji fragmentów, sprawdzając linie pionowe. W przypadku trafienia każdy fragment jest konkatenowany, a konkatenowane fragmenty są łączone na znakach nowej linii i domyślnie drukowane, z końcowym znakiem nowego wiersza.Dzięki @ Pietu1998 za kilka wskazówek
źródło
=ZhZ
jest równy=hZ
iFN
równyV
.JavaScript (ES6),
401386333 bajtówTo wczesna próba. Nie jest to zbyt wydajne, ale byłem ciekawy przetestowania rozwiązania przy użyciu wyrażeń regularnych na binarnej reprezentacji wierszy i kolumn.
Na przykład przetłumaczy wskazówkę
[3,1]
na następujące wyrażenie regularne:W tej chwili ta wersja nie uwzględnia kwadratowych wskazówek. Prawdopodobnie dodam to później.
Kod
Wynik
Rozwiązanie jest wyświetlane w formacie binarnym. Jak na przykład:
Test
Jest to prosty test na przykładowej siatce.
źródło
Haskell, 109 bajtów
Oświadczenie: pochodzi z odpowiedzi @ ThreeFx . Pomogłem mu odrzucić odpowiedź, ale wydaje się, że stracił zainteresowanie dołączeniem moich ostatnich znacznych ulepszeń, więc opublikowałem je jako nową odpowiedź.
Przykład użycia:
[[2],[3],[3],[3,1],[1]] # [[2],[3],[4],[2],[2]]
->[[" ## "," ### ","### ","### #"," #"]]
.Brutalna siła. Wypróbuj wszystkie kombinacje
i
#
, podziel int części#
, policz długości i porównaj z danymi wejściowymi.źródło
PHP,
751833 (720)753724726710691680682 bajtówBardzo chciałem zbudować specjalną sekwencję i spróbować jeszcze raz mojego kartezjańskiego generatora;
ale zrezygnował z kartezjan na rzecz wycofania się, aby szybciej rozwiązać dużą zagadkę.
$r
do wierszy, podpowiedzi$c
do kolumn i$s
podpowiedzi kwadratowych.invalid argument supplied for foreach
jeśli nie znajdzie rozwiązania.\n
i usuń pozostałe dwa podziały wiersza.opis
1) z podpowiedzi wierszy
wygeneruj możliwe wiersze, które spełniają podpowiedzi kwadratowe
i zapamiętaj ich liczby dla każdego indeksu wiersza.
2) cofnij się nad kombinacjami wierszy:
jeśli kombinacja spełnia podpowiedzi kolumny, szukaj głębiej lub zwróć udaną kombinację, w przeciwnym razie
spróbuj następnej możliwości dla tego wiersza
3) rozwiązanie drukowania
Ostatni golf miał poważny wpływ na wyniki;
ale usunąłem zadania profilowania dla końcowych testów porównawczych.
Wymień
$n=$n*($f=($p[$y][$i[$y]]>>$x&1)==$v)+$k=$f?:($v=!$v)||$n==$h[$z++];
się
if(($p[$y][$i[$y]]>>$x&1)-$v){$k=($v=!$v)||$n==$h[$z++];$n=1;}else$n++;
cofnąć ostatni krok w golfa.
przykłady
Dla małego przykładu (od
17 do 21około12876,75,3 ms), użyjdla świątecznej układanki:
5037,845,5 wokoło 36 sekundumieść dane z pytania w pliku
christmas.nonogram
i użyj tego kodu, aby zaimportować:awaria
źródło
$d
musi być w odpowiedniej kolejnościforeach