Lass uns Verstecken spielen!


12

Der Benutzer versteckt sich und der Computer versucht, sie zu finden.

Zunächst nimmt das Programm eine Eingabe für die Größe des Rasters vor. Wie 5x5, 10x10, 15x15 usw. Das Gitter wird nicht immer ein perfektes Quadrat sein.

Das Gitter ist wie ein Schachbrett:

_______________________________
|     |     |     |     |     |
| A1  |     |     |     |     | A
|_____|_____|_____|_____|_____|
|     |     |     |     |     |
|     | B2  |     |     |     | B
|_____|_____|_____|_____|_____|
|     |     |     |     |     |
|     |     | C3  |     |     | C
|_____|_____|_____|_____|_____|
|     |     |     |     |     |
|     |     |     | D4  |     | D
|_____|_____|_____|_____|_____|
|     |     |     |     |     |
|     |     |     |     | E5  | E
|_____|_____|_____|_____|_____|
   1     2     3     4     5

Jetzt wählt der Benutzer ein Quadrat aus, z. B. B2(ohne es dem Computer mitzuteilen).

Der Computer beginnt, Quadrate zu erraten. Wenn es das richtige Quadrat auswählt, antwortet der Benutzer mit y. Wenn nicht, geben sie die Richtung ein, in die sich ihr Plättchen befindet (N, NE, E, SE, S, SW, W).

Also, wenn der Benutzer auswählt B2und der Computer errät C3, würde der Benutzer Eingaben machen NW.

Hier ist ein Beispiel für die Ausgänge und Eingänge:

Grid?
5x5

C3?
NW

C2?
N

B2?
y

Wertung:

Dies wird etwas anders gewertet als eine normale Herausforderung.

Der Gewinner ist das Programm, das (im Durchschnitt) die geringste Anzahl von Raten benötigt, um das richtige Quadrat zu erraten. Die Testfälle, die gemittelt werden sollen, sind alle möglichen Quadrate in einem 5x5 und dann in einem 10x10.

Es muss jedoch auch mit jedem Rastermuster mit bis zu 26 Zeilen (dh 5x8, 6x2, 20x5 usw.) funktionieren.

Bitte geben Sie eine Möglichkeit zum Testen an, z. B. eine JSFiddle.

Und im Falle eines Unentschieden gewinnt das kürzeste Programm.


1
Wenn ich mich verstecke A1und der Computer schätzt B9, ist die richtige Antwort NWoder W?
Greg Martin

@ GregMartin Es wäre NW .... N, W, S, E müssen alle gerade sein, während etwas in einer anderen Zeile / Spalte NW, NE, SW, SE sein muss
JKonowitz

Gibt es Flexibilität im spezifischen Format der Eingabe und Ausgabe? Wenn es mehr als 26 Zeilen gibt, wie heißen sie?
Greg Martin

@ GregMartin Sie können mit der Ausgabe flexibel sein, aber versuchen, es einfach zu halten. Es muss nicht exakt gleich sein, sollte aber einen ähnlichen Stil haben. Sie müssen nichts über 26 erklären, das werde ich bearbeiten.
JKonowitz

Ich weiß nicht, was "ähnlicher Stil" bedeutet. Können wir Eingaben als geordnetes Ganzzahlpaar (Zeile #, Spalte #) annehmen? (PS: Diese Art von Fragen sind Gründe, warum das Vorab-Posten von Herausforderungen in der Sandbox eine großartige Idee ist.)
Greg Martin

Antworten:


3

Python 3.6 , 466 398 392 Bytes, Minimax

x, y = 1, 1
w, h = [int(x) for x in input('Grid?\n').split('x')]


def split_factor(a, b):
    N = b-y
    W = a-x
    S = h+~N
    E = w+~W
    return max(1, N, W, S, E, N*W, S*W, S*E, N*E)


def move(a, b):
    *Z, = zip([a, x, a, a+1, x, x, a+1, a+1],
              [y, b, b+1, b, y, b+1, b+1, y],
              [1, a-x, 1, w+x+~a, a-x, a-x, w+x+~a, w+x+~a],
              [b-y, 1, h+y+~b, 1, b-y, h+y+~b, h+y+~b, b-y])
    return Z[['N', 'W', 'S', 'E', 'NW', 'SW', 'SE', 'NE'].index(d)]

d = ''
while d != 'y':
    print()
    splits = {(a, b): split_factor(a, b) for a in range(x, x+w) for b in range(y, y+h)}
    a, b = min(splits, key=splits.get)
    d = input(f'{a}{"ABCDEFGHIJKLMNOPQRSTUVWXYZ"[b]}?\n')
    x, y, w, h = move(a, b)

Die Ein- und Ausgabe sollte in der im Beispiel gezeigten Form erfolgen. Dies findet das Quadrat mit dem minimalen "Aufteilungsfaktor" - das ist der größte verbleibende Bereich, der sich aus der Antwort des Spielers ergeben kann (dh NW, E, y usw.) - und errät dies. Ja, das ist immer die Mitte des verbleibenden Bereichs in diesem Spiel, aber diese Technik zur Minimierung des Worst-Case wird allgemeiner in ähnlichen Spielen mit unterschiedlichen Regeln funktionieren.

Unlesbare Version:

x=y=d=1
w,h=map(int,input('Grid?\n').split('x'))
while d!='y':print();s={(a,b):max(b-y,h+y+~b)*max(w+x+~a,a-x)for a in range(x,x+w)for b in range(y,y+h)};a,b=min(s,key=s.get);d=input(f'{a}{chr(64+b)}?\n');*z,=zip([a+1,x,a+1,x,a,a,a+1,x],[b+1,b+1,y,y,b+1,y,b,b],[w+x+~a,a-x,w+x+~a,a-x,1,1,w+x+~a,a-x],[h+y+~b,h+y+~b,b-y,b-y,h+y+~b,b-y,1,1]);x,y,w,h=z[~'WENS'.find(d)or-'NWNESWSE'.find(d)//2-5]

2

Mathematica, optimales Verhalten in Testfällen, 260 Bytes

For[a=f=1;{c,h}=Input@Grid;z=Characters;t=<|Thread[z@#->#2]|>&;r="";v=Floor[+##/2]&;b:=a~v~c;g:=f~v~h,r!="y",r=Input[g Alphabet[][[b]]];{{a,c},{f,h}}={t["NSu",{{a,b-1},{b+1,c},{b,b}}]@#,t["uWX",{{g,g},{f,g-1},{g+1,h}}]@#2}&@@Sort[z@r/.{c_}:>{c,"u"}/."E"->"X"]]

Dieses Programm kann getestet werden, indem Sie den obigen Code ausschneiden und in die Wolfram Cloud einfügen . (Testen Sie es jedoch schnell: Ich glaube, es gibt eine zeitliche Begrenzung für jeden Programmlauf.) Die Vermutungen 2 cdes Programms sehen wie folgt aus C2, ansonsten wird es gemäß der obigen Spezifikation ausgeführt. Das Gitter muss als geordnetes Ganzzahlpaar eingegeben werden {26,100}, und die Antworten auf die Vermutungen des Programms müssen als Zeichenfolgen eingegeben werden, z. B. "NE"oder "y".

Das Programm verfolgt die kleinste und größte Zeilennummer und Spaltennummer, die mit den bisherigen Eingaben übereinstimmt, und schätzt immer den Mittelpunkt des Teilgitters der Möglichkeiten (Rundung NW). Das Programm ist deterministisch, so dass es einfach ist, die Anzahl der erforderlichen Vermutungen im Durchschnitt über ein festes Raster zu berechnen. In einem 10x10-Raster erfordert das Programm 1 Vermutung für ein einzelnes Quadrat, 2 Vermutungen für acht Quadrate, 3 Vermutungen für 64 Quadrate und 4 Vermutungen für die verbleibenden 27 Quadrate mit einem Durchschnitt von 3,17. und dies ist das theoretische Minimum, wenn man bedenkt, wie viele Folgen von 1, 2 usw. zu korrekten Vermutungen führen können. In der Tat sollte das Programm aus ähnlichen Gründen das theoretische Minimum in einem Raster beliebiger Größe erreichen. (In einem 5x5-Raster beträgt die durchschnittliche Anzahl von Vermutungen 2,6.)

Eine kleine Erklärung des Codes, obwohl es ziemlich einfach ist, abgesehen von der Golffreundlichkeit. (Ich habe die Reihenfolge einiger Initialisierungsanweisungen für Expository-Zwecke vertauscht - keine Auswirkung auf die Byteanzahl.)

1  For[a = f = 1; z = Characters; t = <|Thread[z@# -> #2]|> &;
2      v = Floor[+##/2] &; b := a~v~c; g := f~v~h;
3      r = ""; {c, h} = Input@Grid, 
4    r != "y", 
5    r = Input[g Alphabet[][[b]]];
6      {{a, c}, {f, h}} = {t["NSu", {{a, b - 1}, {b + 1, c}, {b, b}}]@#, 
7        t["uWX", {{g, g}, {f, g - 1}, {g + 1, h}}]@#2} & @@ 
8        Sort[z@r /. {c_} :> {c, "u"} /. "E" -> "X"]
   ]

Die Zeilen 1-3 initialisieren die ForSchleife, die eigentlich nur eine Whileverschleierte Schleife ist, also zwei Bytes weniger. Die möglichen Reihennummern- und Spaltennummernbereiche werden zu jedem Zeitpunkt in gespeichert {{a, c}, {f, h}}, und die zentrierte Schätzung in diesem Teilgitter wird durch die {b, g}in Zeile 2 definierten Funktionen berechnet . Zeile 3 initialisiert die maximale Reihe cund die maximale Spalte haus Benutzereingaben und initialisiert auch rdie schleifengetestete Variable und die nachfolgenden Benutzereingaben.

Während der Test in Zeile 4 erfüllt ist, wird Zeile 5 vom Benutzer eingegeben, wobei die Eingabeaufforderung aus der aktuellen Schätzung stammt {b, g}( Alphabet[][[b]]]konvertiert die Zeilennummer in einen Buchstaben). Dann aktualisieren die Zeilen 6-8 das Teilgitter der Möglichkeiten (und damit implizit die nächste Vermutung). Beispielsweise wird t["NSu", {{a, b - 1}, {b + 1, c}, {b, b}}](in der Definition von tZeile 1) auf erweitert

<| "N" -> {a, b - 1}, "S" -> {b + 1, c}, "u" -> {b, b}|>

Hier können Sie sehen, wie die Min-Row- und Max-Row-Nummern gemäß der letzten Eingabe des Benutzers aktualisiert werden. Zeile 8 konvertiert jede mögliche Eingabe in ein geordnetes Zeichenpaar des Formulars { "N" | "S" | "u", "u" | "W" | "X"}. Hier "u"steht für eine richtige Zeile oder Spalte, und "X"steht für Osten (nur um Sortgut arbeiten zu können). Wenn der Benutzer schließlich eingibt "y", geben diese Zeilen einen Fehler aus, aber dann schlägt der Schleifentest fehl und der Fehler wird nie weitergegeben (das Programm hält einfach trotzdem an).


0

Batch, Teilen und Erobern

@echo off
set z = ABCDEFGHIJKLMNOPQRSTUVWXYZ
set /p g = Grid?
set /a w = 0, n = 0, e = %g :x= + 1, s = % + 1
:l
set /a x = (w + e) / 2, y = (n + s) / 2
call set c = %%z :~%y%,1%%
set /p g = %c %%x%?
if %g :w=.% == %g % set /a w = x
if %g :n=.% == %g % set /a n = y
if %g :e=.% == %g % set /a e = x
if %g :s=.% == %g % set /a s = y
if %g :y=.% == %g % goto l

Erstellt den Begrenzungsrahmen für den Bereich, der noch durchsucht werden muss. Die nächste Vermutung ist immer die Mitte der Box. Für die Kompasspunkte, die nicht in der Antwort enthalten sind, wird das Kästchen in diese Richtung verkleinert. Zum Beispiel werden für eine Antwort von Nder linken, rechten und unteren Seite des Kästchens das erratene Quadrat festgelegt.

Bei 369 Bytes erwarte ich nicht, jemanden zu schlagen, also habe ich die Leerzeichen für die Lesbarkeit belassen.


Nun, Divide-and-Conquer ist im Allgemeinen für große Testfälle nützlich, aber nicht für kleine Fälle. Gibt es bessere Algorithmen?
Matthew Roh

@SIGSEGV Nicht sicher, was du meinst; Greg und Bens Antworten basieren ebenfalls auf der Box-Mitte-Methode.
Neil

Wir brauchen noch einen besseren Algorithmus.
Matthew Roh

@SIGSEGV Die Center-of-Box-Methode ist optimal. Es gibt keinen besseren Algorithmus.
TheNumberOne
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.