Rubino, Rev. B 121 byte
L'invio è la funzione anonima, meno il f=
. Indicato nel programma di test per illustrare l'uso.
f=->n{["~mK)\7","}uYwQO"][l=n%2].bytes{|t|9.times{|i|(m=n|1<<i)==n||8.times{|j|m/2*257>>j&255==126-t&&t+j%2!=119&&l=m}}}
l}
puts g=f[gets.to_i]
puts
[7,6,5,
8,0,4,
1,2,3].each{|i|print g>>i&1; puts if i/3==1}
2 byte salvati rendendo il quadratino centrale il bit meno significativo anziché il bit più significativo (rimuovi per /2
anziché %256
.) Risparmi rimanenti mediante una riorganizzazione della tabella delle mosse accettabili. L'organizzazione come quadrato centrale libero / occupato anziché per il numero totale di X consente un test più semplice. Inoltre, ora ci sono solo 2 stringhe nell'array, quindi la %w{string1 string2}
sintassi viene abbandonata a favore della ["string1","string2"]
sintassi. Ciò consente \7
di includere un carattere non stampabile , che a sua volta consente di utilizzare una codifica più semplice: 126-t
anziché (36-t)%120
.
Rubino, Rev A 143 byte
->n{l=r=("%b"%n).sum%8
%w{$ %5 - I+Wy Q S#}[r].bytes{|t|9.times{|i|(m=n|1<<i)==n||8.times{|j|m%256*257>>j&255==(t-36)%120&&t+j%2!=43&&l=m}}}
l}
Questa è una funzione anonima. Il formato di input / output è stato lasciato aperto, quindi ho scelto un numero binario a 9 bit. il bit del 512 rappresenta il centro, con i bit rimanenti che lo circondano a spirale (il bit dell'1 è considerato un angolo).
Ci sono molti più input possibili che output accettabili, quindi l'algoritmo è quello di provare tutti i movimenti e trovarne uno che si adatti a un modello di output accettabile. I modelli di output accettabili per ogni numero di X sono codificati.
Le informazioni sul quadrato centrale vengono rimosse e gli 8 bit rimanenti vengono moltiplicati per 257 per duplicarli. Questo modello viene quindi ruotato oltre i modelli accettabili spostando i diritti.
Il loop non viene chiuso quando viene trovato un pattern, quindi il pattern restituito sarà il LAST pattern accettabile trovato. Per questo motivo, i modelli preferibili (dove esiste una preferenza) vengono più avanti nell'elenco.
Data la strategia del "movimento dei cavalieri", è poco importante che un modello venga ruotato di 45 gradi o meno. La versione ungolfed segue la strategia di spostamento dei cavalieri e quindi non ha bisogno di distinguere tra quadrati d'angolo e quadrati di bordo: bisogna comunque evitarne tre di fila.
Tuttavia, ho scoperto che questa non è sempre la strategia migliore, in quanto esiste il seguente trucco. Se il tuo avversario va per primo e prende il centro, dovrebbe vincere. Ma alla sua seconda mossa fa l'errore di permetterti di fare un quadrato 2x2 che dovresti prendere, in quanto ciò ti consente di costringerlo a fare tre di fila. Questo è implementato nella versione golf. In questo caso è necessario un piccolo codice aggiuntivo per distinguere tra tre X in un angolo (forza dell'avversario per perdere) e 3 X lungo un lato (suicidio immediato).
Non registrato nel programma di test
La versione non golfata segue la logica espressa nella domanda.
Nella versione golf la tabella è leggermente modificata [[0],[1,17],[9],[37,7,51,85],[45],[47,119]]
per implementare il comportamento leggermente diverso per il caso r=3
. Viene quindi compresso in ASCII stampabile (che richiede la decodifica (t-36)%120
). È necessario un ulteriore bit di logica per distinguere tra tre X in un angolo e tre X lungo un bordo nel caso della voce di tabella 7:&&t+j%2!=43
f=->n{l=r=("%b"%n).sum%8 #convert input to text, take character checksum to count 1's(ASCII 49.)
#0 is ASCII 48, so %8 removes unwanted checksum bloat of 48 per char.
#l must be initialised here for scoping reasons.
[[0],[1,17],[9],[11,13,37,51,85],[45],[47,119]][r].each{|t| #according to r, find the list of acceptable perimeter bitmaps, and search for a solution.
9.times{|i|(m=n|1<<i)==n|| #OR 1<<i with input. if result == n, existing X overwritten, no good.
#ELSE new X is in vacant square, good. So..
8.times{|j|m%256*257>>j&255==t&&l=m}} #%256 to strip off middle square. *257 to duplicate bitmap.
#rightshift, see if pattern matches t. If so, write to l
}
l} #return l (the last acceptable solution found) as the answer.
#call function and pretty print output (not part of submission)
puts g=f[gets.to_i]
puts
[6,7,0,
5,8,1,
4,3,2].each{|i|print g>>i&1; puts if i<3}
Uscita del programma di test
Questo succede quando il computer si gioca da solo.
C: \ Users \ steve> ruby tictac.rb
0
256
000
010
000
C: \ Users \ steve> ruby tictac.rb
256
384
010
010
000
C: \ Users \ steve> ruby tictac.rb
384
400
010
010
100
C: \ Users \ steve> ruby tictac.rb
400
404
010
010
101
C: \ Users \ steve> ruby tictac.rb
404
436
010
110
101
C: \ Users \ steve> ruby tictac.rb
436
444
010
110
111
ANALISI DEL GIOCO GIOCANDO PER PRIMO
Questo è in realtà molto semplice e lineare.
Quando si gioca per primo, il quadrato centrale sarà sempre il primo quadrato occupato.
r = 0
... binary representation 0
.X.
...
r = 2
X.. binary representation 1001=9
.XX
...
r = 4
X.. binary representation 101101=45
.XX
XX.
C'è solo un modo (fino alla simmetria) per avere cinque X incluso il quadrato centrale sul tabellone senza che il gioco sia finito. C'è una X nel quadrato centrale, una su ciascuna diagonale (a 90 gradi l'una rispetto all'altra) e una su ciascuna linea centrale orizzontale / verticale (a 90 gradi l'una rispetto all'altra). Poiché un intero bordo non può essere occupato, il precedente è l'unico accordo possibile. L'altro giocatore deve perdere alla prossima mossa.
ANALISI DEL GIOCO CHE GIOCA SECONDO
Il gioco è abbastanza diverso a seconda che l'altro giocatore scelga il quadrato centrale.
r = 1
piazza centrale occupata
.X. X.. binary representation 1
.X. .X.
... ...
piazza centrale libera
X.. .X. binary representation 10001=17
... ...
..X .X.
r = 3
Quadrato centrale occupato, se un altro giocatore gioca adiacente alla tua ultima X Giocare una mossa di un cavaliere come di seguito è supportato nella versione non golfata
XX. .XX binary representation 1011=11
.X. XX. or mirror image 1101=13
X.. ...
Tuttavia, quanto sopra NON è la mossa migliore e non è supportato nella versione golf. La mossa migliore è la seguente, forzando una vittoria al turno successivo:
XX. binary representation 111=7. XXX
XX. Only to be used where j is odd. .X.
... Even j would look like image to right. ...
Quadrato centrale occupato, se un altro giocatore gioca a 90 o 135 gradi rispetto alla tua ultima X (gioca la mossa del cavaliere).
X.X .X. binary representation 100101=37
.X. .XX
.X. X..
Piazza centrale libera
X.X .X. XX. binary representations:
... X.X ... 1010101=85 (first two)
X.X .X. .XX and 110011=51 (last one)
r = 5
piazza centrale occupata. Per le ragioni sopra esposte in r = 4, ci sono quattro possibili mosse, che perdono tutte. ne è supportato solo uno: 101111 = 47.
piazza centrale libera. C'è solo una scheda possibile fino alla simmetria, come segue. L'altro giocatore deve perdere alla prossima mossa, quindi non è necessario supportare r> 5.
XX. binary representation 1110111=119
X.X
.XX