Nonogramm-Linien-Brute-Force-Lösung

25

Hintergrund

Nonogram , auch bekannt als Picross oder Griddlers, ist ein Puzzle, bei dem das Ziel darin besteht, anhand der Anzahl aufeinanderfolgender farbiger Zellen in jeder Zeile zu bestimmen, ob jede Zelle im 2D-Raster farbig oder leer sein soll.

Das folgende Beispiel zeigt ein Nonogramm-Puzzle mit einer Lösung.

Das Problem ist, dass einige kommerzielle Nonogram-Spiele / mobile Apps Rätsel haben, die nicht von Hand lösbar sind (z. B. mehrere Lösungen haben oder tiefes Backtracking erfordern). Sie bieten dem Spieler jedoch auch einige Leben, bei denen ein Leben verloren geht, wenn Sie versuchen, eine Zelle zu färben, deren richtige Antwort leer ist . Jetzt ist es an der Zeit, diese fiesen "Rätsel" zu lösen!

Um die Aufgabe zu vereinfachen, stellen Sie sich nur eine Zeile mit dem Hinweis und nichts anderes vor:

3 7 | _ _ _ _ _  _ _ _ _ _  _ _ _ _ _

Das [3,7]sind die Hinweise, und die Zeilenlänge beträgt 15 Zellen. Da es mehrere mögliche Lösungen gibt, müssen wir einige Leben riskieren, um diese Linie vollständig zu lösen (dh alle farbigen Zellen bestimmen).

Herausforderung

Bestimmen Sie anhand einer Linie mit Hinweisen (einer Liste positiver Ganzzahlen) und der Linienlänge die maximale Anzahl an Leben, die Sie verlieren werden, vorausgesetzt, Sie erzwingen die Linie mit optimaler Strategie.

Beachten Sie, dass Sie immer farbige Zellen erraten . In tatsächlichen Spielen hat das Erraten leerer Zellen (richtig oder falsch) keine Auswirkung auf Ihr Leben, sodass Sie das Rätsel nicht auf diese Weise "lösen" können.

Sie können auch davon ausgehen, dass die Eingabe immer eine gültige Nonogram-Zeile darstellt, sodass Sie sich nicht um etwas kümmern müssen [6], 5.

Erläuterung

Schauen wir uns zunächst einige einfachere Beispiele an.

[1,2], 5

Für diese Zeile gibt es genau drei Möglichkeiten ( Oist eine farbige Zelle, .ist eine leere):

O . O O .
O . . O O
. O . O O

Wenn wir versuchen, Zelle 0 einzufärben (0-basierter Index von links), geschieht Folgendes:

  • Die Zelle ist richtig gefärbt. Jetzt haben wir zwei Möglichkeiten, und wir können zwischen Zelle 2 und Zelle 4 wählen, um die Linie vollständig zu lösen. In beiden Fällen verlieren wir im schlimmsten Fall ein Leben.
  • Die Zelle ist leer und wir verlieren ein Leben. In diesem Fall haben wir bereits die einzigartige Lösung für diese Linie identifiziert, sodass wir mit 1 verlorenen Leben fertig sind.

Daher [1,2], 5lautet die Antwort für 1.

[5], 10

Binäre Suche? Nee.

Die naheliegendste erste Wahl ist 4 oder 5, was eine Möglichkeit aufzeigt, wenn sie leer ist (bei einem Preis von 1 Leben). Nehmen wir an, wir haben zuerst 4 gewählt. Wenn Zelle 4 tatsächlich farbig ist, verlängern wir sie nach links, dh versuchen Sie 3, 2, 1 und 0, bis ein Leben verloren geht (oder Zelle 0 farbig ist, geben wir am Ende überhaupt keine Leben aus). Wenn ein Leben verloren geht, können wir die Lösung eindeutig bestimmen, z. B. wenn wir so etwas sehen:

_ _ X O O _ _ _ _ _

Dann wissen wir bereits, dass die Antwort lautet:

. . . O O O O O . .

Daher [5], 10lautet die Antwort für auch 1.

[3,7], 15

Beginnen Sie mit Zelle 11, die, wenn sie leer ist, sofort die folgende Lösung anzeigt.

O O O . O O O O O O O X . . .

Dann versuchen Sie es mit 12, was, wenn leer, zwei Möglichkeiten ergibt, die auf Kosten von 1 zusätzlichen Leben gelöst werden können.

O O O . . O O O O O O O X . .
. O O O . O O O O O O O X . .

Versuchen Sie nun 2. Wenn leer, ergeben sich drei Möglichkeiten, die ähnlich wie im [1,2], 5Beispiel gelöst werden können .

. . X O O O . O O O O O O O .
. . X O O O . . O O O O O O O
. . X . O O O . O O O O O O O

Wenn Sie das Risiko auf diese Weise weiter minimieren, können Sie jede Lösung mit max. 2 Leben verbracht.

Testfälle

[1,2] 5 => 1
[2] 5 => 2
[1] 5 => 4
[] 5 => 0
[5] 10 => 1
[2,1,5] 10 => 0
[2,4] 10 => 2
[6] 15 => 2
[5] 15 => 2
[4] 15 => 3
[3,7] 15 => 2
[3,4] 15 => 3
[2,2,4] 15 => 4
[1,1,1,1,1,1,1] 15 => 2

[2,1,1,3,1] 15 => 3
[1,1,1,2,1] 15 => 5

In den letzten beiden Fällen durchläuft die optimale Strategie nicht die minimalen Lücken, sondern geht einfach von links nach rechts (oder von rechts nach links). Vielen Dank an @crashoz für den Hinweis.

Regeln

Es gelten die Standardregeln für . Die kürzeste gültige Übermittlung in Bytes gewinnt.

Kopfgeld

Wenn jemand einen Algorithmus für die Polynomzeit (mit dem Beweis der Korrektheit) findet, werde ich eine solche Lösung mit +100 Kopfgeld belohnen.

Bubbler
quelle
Wofür ist die Ausgabe gedacht [6], 5?
Undichte Nonne
Wenn Sie raten, müssen Sie raten, dass die Zelle schwarz ist, oder können Sie schwarz oder weiß raten?
Feersum
@LeakyNun Es ist eine ungültige Zeile. Sie können davon ausgehen, dass die Eingabe immer eine gültige Nonogram-Zeile ist.
Bubbler
@feersum Sie raten immer farbige Zellen. In tatsächlichen Spielen hat das Erraten einer leeren Zelle (richtig oder falsch) keine Auswirkung auf Ihr Leben, sodass Sie kein Feedback erhalten können.
Bubbler
Fantastische Herausforderung
Enrico Borba

Antworten:

19

Ruby , 85 Bytes

f=->l,n,s=n-l.sum-l.size+1{*a,b=l;b&&s>0?(a[0]?1+f[a,n-b-2,s-1]:(n.to_f/b).ceil-1):0}

Probieren Sie es online!

Erläuterung

l=[l1,l2,...,lx]xn

lx
nlx
nlx1+f(l,nlx)
1+f(l~,nlx2) , wol~ istl ohne den letzten Anhaltspunkt.

f(l,n)={0,if 1xli+x1nnlx1if x=11+max{f(l,nlx)f(l~,nlx2),otherwise

Hier ist ein Beispiel _unbekannt, Xist ein bekannter Raum, Oist eine bekannte farbige Zelle und List Leben verloren

[2,2,4] 15                  _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
(1) -> [2,2,4] 11           _ _ _ _ _ _ _ _ _ _ _ L X X X
    (1) -> [2,2,4] 7        _ _ _ _ _ _ _ L X X X L X X X
        0                   X X X L X X X L X X X L X X X
    (2) -> [2,2] 5          _ _ _ _ _ X O O O O L L X X X
        0                   O O X O O X O O O O L L X X X 
(2) -> [2,2] 9              _ _ _ _ _ _ _ _ _ X O O O O L
    (1) -> [2,2] 7          _ _ _ _ _ _ _ L X X O O O O L
        (1) -> [2,2] 5      _ _ _ _ _ L X L X X O O O O L
            0               O O X O O L X L X X O O O O L
        (2) -> [2] 3        _ _ _ X O O L L X X O O O O L
            1               O O L X O O L L X X O O O O L               
    (2) -> [2] 5            _ _ _ _ _ X O O L X O O O O L
        2                   O O L L X X O O L X O O O O L

O(2n)

h

h(l,n)=n1xlix+1

h

h

h(l,nlx)=nlx1xlix+1=(n1xlix+1)lx=h(l,n)lx

h(l~,nlx2)=nlx21x1li(x1)+1=(n1xlix+1)1=h(l,n)1

h(l,n)={0,if 1xli+x1nnlx,if x=1max{h(l,nlx)+lxh(l~,nlx2)+1,otherwise

h

[h(l,nlx)+lx][h(l~,nlx2)+1]=nlxn1xlix+1+lx[nlx21x1li(x1)+1+1]=2

[h(l,nlx)+lx][h(l~,nlx2)+1]=2[h(l,nlx)+lx][h(l~,nlx2)+1]<0[h(l,nlx)+lx]<[h(l~,nlx2)+1]

h(l,n)={0,if 1xli+x1nnlx,if x=1h(l~,nlx2)+1otherwise

hfh

f(l,n)={0,if 1xli+x1nnlx1if x=11+f(l~,nlx2),otherwise

nO(n)

crashoz
quelle
2
Willkommen bei PPCG, unglaublicher erster Beitrag!
Cole
1
@cole Es ist nicht ihr erster Beitrag, aber es ist mit Sicherheit unglaublich! Sehr kluger Ansatz +1
Mr. Xcoder
1
Gute Arbeit. Ich werde das Kopfgeld 2 Tage später vergeben, wenn bis dahin niemand einen schwerwiegenden logischen Fehler findet.
Bubbler
2

Python, 303 289 Bytes

Das erste Golfspiel seit langer Zeit, daher kann es zu viel Fettüberschuss kommen. (Danke, Jo King, für das Auffinden von 14 Bytes.)

Die Funktion f generiert alle möglichen Anordnungen (allerdings immer mit einem Leerzeichen als erstem Zeichen, aber das ist in Ordnung, solange wir die Länge um 1 erhöhen, bevor wir sie aufrufen). Funktion g wählt die Position mit der geringsten Anzahl von Leerzeichen und Rekursionen aus. Funktion h fügt sie zusammen.

f=lambda l,n:["."*i+"X"*l[0]+c for i in range(1,n-l[0]+1)for c in f(l[1:],n-i-l[0])]if l else["."*n]
def g(q,n):O,X=min([[[p[:i]+p[i+1:]for p in q if p[i]==u]for u in".X"]for i in range(n)],key=lambda x:len(x[0]));return(len(q)>1)*1and max(1+g(O,n-1),g(X,n-1))
h=lambda l,n:g(f(l,n+1),n+1)

Die Beispiele laufen alle gut:

>>> h([3,7],15)
2
>>> h([3,4],15)
3
>>> h([1,1,1,2,1],15)
6
Uri Granta
quelle
1
Dürfen Sie zurück Falsezu 0? Wenn ja, können Sie ändern , (len(q)>1)*1andzu len(q)>1and. Wenn Sie nicht zurückkehren Falsezu 0, dann das tun, aber ändern g(f(l,n+1),n+1)zu 1*g(f(l,n+1),n+1)und es wird immer noch speichert eine Byte
Zachary
1
Noch besser: in dem Fall Falseist nicht erlaubt für 0, statt Wechsel g(f(l,n+1),n+1)zu 1*g(f(l,n+1),n+1), ändern Sie ihn auf+g(f(l,n+1),n+1)
Zachary
2
Außerdem müssen Sie die Anzahl der h=Bytes nicht zählen
Zacharý
1
288 Bytes .
Jonathan Frech