Mam problem z kombinatoryką, który chciałbym postawić na OEIS - problem polega na tym, że nie mam wystarczającej liczby terminów. To wyzwanie kodowe ma pomóc mi w obliczeniu większej liczby terminów, a zwycięzcą zostanie użytkownik, który prześle największą liczbę terminów.
Problem
Załóżmy, że dam ci trójkątny zestaw żarówek o długości boku :
o
o o
o o o
o o o o
o o o o o
o o o o o o
1 2 ... n
Zamierzam włączyć trzy żarówki, które tworzą „pionowy” trójkąt równoboczny, jak w poniższym przykładzie:
o
o x
o o o
o o o o
o x o o x
o o o o o o
Zanim zapalę światła, Twoim zadaniem jest usunięcie jak największej liczby żarówek z tablicy - bez utraty możliwości wywnioskowania trójkąta włączonych żarówek. Dla jasności, jeśli żarówka została usunięta, nie świeci się, gdy jej położenie jest włączone.
Na przykład, jeśli usuniesz następujące żarówki (oznaczone przez .
), zobaczysz tylko następujące dwa światła włączające się (oznaczone przez x
), co wystarczy jednoznacznie wydedukować trzecią (nieoświetloną) pozycję:
. .
. o . x
. . o . . o
o o o . => o o o .
o o o o . o x o o . <- the third unlit position
o . . . o o o . . . o o
Niech a(n)
będzie maksymalną liczbą żarówek, które można usunąć bez wprowadzania dwuznaczności.
Przykład
Za pomocą naiwnego algorytmu sprawdziłem wartości do trójkąta o długości boku 7, jak pokazano poniżej:
.
. . o
. . o o . o
. . . . . o . o o .
. . . . o o o o o . o o . o .
. . . . o o o o . o o o o o . o . o . o o
. . . o o . o o o o . . o o o . . . o o o . o . o o o
a(2) = 3 a(3) = 4 a(4) = 5 a(5) = 7 a(6) = 9 a(7) = 11
Punktacja
Zgłoszenie obliczające sekwencję [a(2), a(3), ..., a(n)]
dla największej liczby n wygrywa. Jeśli dwa zgłoszenia mają identyczne sekwencje, wygrywa ten, który został wcześniej opublikowany.
Chociaż nie jest to konieczne do przesłania, byłoby pouczające, jeśli opublikujesz konstrukcję wynikowych tablic triangluarowych, jak w powyższym przykładzie.
źródło
Odpowiedzi:
Python 3 ,
n=8
Wykorzystuje solver CP-SAT Google OR-Tools .
Po uruchomieniu przez ~ 30 sekund wyświetla następujące informacje:
Nie zdarzyło mi się nawet próbować czekać,n6 n=9
bo prawdopodobnie zajmie to wiele godzin (liczba ograniczeń rośniea(9)=15
n=8
Jak to działa
Tak więc pytanie może zostać przeformułowane jako problem SAT, z jednym ograniczeniem dla każdej pary trójkątów.
PS: Chciałbym bardzo podać przykład
n=8
, ale mam problemy z solverem SAT, który najwyraźniej chce zachować rozwiązania dla siebie.źródło
Uzyskiwanie rozwiązań z programu @ Delfad0r
Rozszerzyłem program @ Delfad0r o rozwiązania wyjściowe. Daje również wyniki pośrednie, więc otrzymujesz dane wyjściowe w następujący sposób:
Obliczenia trwały kilka godzin.
Jeśli niecierpliwisz się i naciskasz
Ctrl-C
po znalezieniu prawdopodobnie nieoptymalnego rozwiązania, program wyświetli to rozwiązanie. Nie trzeba więc długo czekać na to:Oto rozszerzony program:
źródło
Python 3
Opierając się silnie na odpowiedzi Delfad0r , przeważnie podąża tą samą progresją logiczną, sprawdzając pary trójkątów i sprawdzając poprawność konfiguracji, jeśli nie zawiera ona żadnych par trójkątów, które nie sprawdzą tej weryfikacji. Ponieważ nie korzystałem z żadnych bibliotek oprócz itertools i kopiowania, mam pełną kontrolę nad zapisywaniem przykładów napotkanych w całym programie.
Problem w tym, że nie jest zbyt wydajny. Działa naprawdę szybko
n=5
, ale zaczyna znacznie zwalniać po tym punkcie. Wn=6
biegu zajmuje około minuty i jest znacznie wolniejszyn=7
. Wyobrażam sobie, że istnieje wiele poprawek wydajności, które można wprowadzić za pomocą tego programu, ale jest to szybko opracowany wstępny szkic dobrego rozwiązania o wiele większej elastyczności, aby sprawdzić wewnętrzne funkcjonowanie tej metody. Z czasem będę stopniowo nad tym pracował.źródło