Ruby, Rev B 121 bayt
Gönderme, eksi f=. Kullanımı göstermek için test programında gösterilmiştir.
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}
Merkez kareyi en önemli bit yerine en küçük anlamlı bit yaparak ( /2yerine kaldırmak %256) 2 bayt tasarruf etti. Toplam X sayısı yerine merkez kare serbest / dolu olarak organize etmek daha basit bir test yapılmasını sağlar. Ayrıca, dizide sadece 2 dize vardır, böylece %w{string1 string2}sözdizimi sözdizimi lehine terk edilir ["string1","string2"]. Bu, yazdırılamayan bir karakterin \7eklenmesini sağlar ve bu da daha basit bir kodlamanın kullanılmasını sağlar: 126-tyerine (36-t)%120.
Ruby, Rev A 143 bayt
->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}
Bu anonim bir işlevdir. Giriş / çıkış formatı açık bırakıldı, bu yüzden 9-bit ikili sayı için gittim. 512 biti merkezi temsil eder, kalan bitler etrafına döner (1 biti bir köşe olarak kabul edilir).
Kabul edilebilir çıkışlardan çok daha fazla giriş vardır, bu nedenle algoritma tüm hareketleri denemek ve kabul edilebilir bir çıkış modeline uyan bir giriş bulmaktır. Her bir X sayısı için kabul edilebilir çıktı modelleri sabit kodlanmıştır.
Merkez kareyle ilgili bilgiler çıkarılır ve kalan 8 bit, kopyaları çoğaltmak için 257 ile çarpılır. Bu kalıp daha sonra hak değiştirerek kabul edilebilir kalıpların ötesine döndürülür.
Bir örüntü bulunduğunda döngüden çıkılmaz, bu nedenle döndürülen örüntü LAST kabul edilebilir örüntü olur. Bu nedenle, tercih edilen modeller (bir tercihin olduğu yerlerde) listenin ilerleyen kısımlarında gelir.
'Şövalyeler hareketi' stratejisi göz önüne alındığında, bir desenin 45 derece döndürülüp döndürülmemesi çok az önemlidir. Çözümsüz versiyon şövalyelerin hareket stratejisini takip eder ve bu nedenle köşe kareleri ve kenar kareleri arasında ayrım yapmak zorunda değildir: yine de arka arkaya üçten kaçınılmalıdır.
Ancak, aşağıdaki hile olduğu için bunun her zaman en iyi strateji olmadığını buldum. Rakibiniz önce giderse ve merkezi alırsa kazanmalıdır. Ancak ikinci hamlesinde, 2x2 kare yapmanıza izin verme hatasını yapar, çünkü onu arka arkaya üç yapmaya zorlamanıza izin verir. Bu, golf versiyonunda uygulanır. Bir köşedeki üç X'i (rakibi kaybetmeye zorlamak) ve bir kenar boyunca 3 X'i (hemen intihar) ayırt etmek için bu örnekte biraz ekstra kod gereklidir.
Test programında yönlendirilmemiş
Çözülmemiş versiyon, soruda ifade edilen mantığı takip eder.
Golf edilmiş versiyonda tablo, [[0],[1,17],[9],[37,7,51,85],[45],[47,119]]durum için biraz farklı davranışları uygulamak üzere biraz değiştirilmiştir r=3. Daha sonra yazdırılabilir ASCII'ye sıkıştırılır (kod çözme gerektirir (t-36)%120). Tablo girişi 7 durumunda bir köşedeki üç X ile bir kenar boyunca üç X arasında ayrım yapmak için ek bir mantık gerekir:&&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}
Test programının çıktısı
Bilgisayar kendini oynattığında olan budur.
C: \ Kullanıcılar \ steve> ruby tictac.rb
0
256
000
010
000
C: \ Kullanıcılar \ steve> ruby tictac.rb
256
384
010
010
000
C: \ Kullanıcılar \ steve> ruby tictac.rb
384
400
010
010
100
C: \ Kullanıcılar \ steve> ruby tictac.rb
400
404
010
010
101
C: \ Kullanıcılar \ steve> ruby tictac.rb
404
436
010
110
101
C: \ Kullanıcılar \ steve> ruby tictac.rb
436
444
010
110
111
İLK OYUN ANALİZİ
Bu aslında çok basit ve doğrusal.
İlk oynarken, orta kare daima işgal edilen ilk kare olacaktır.
r = 0
... binary representation 0
.X.
...
r = 2
X.. binary representation 1001=9
.XX
...
r = 4
X.. binary representation 101101=45
.XX
XX.
Oyun bitmeden tahtadaki orta kareyi içeren beş X'e sahip olmanın tek bir yolu (simetriye kadar) vardır. Orta karede X, her biri çapraz (biri 90 derece) ve yatay / dikey her biri (90 derece birbirine). Bir kenarın tamamı işgal edilemediğinden, düzenleme mümkündür. Diğer oyuncu bir sonraki hamlede kaybetmelidir.
İKİNCİ OYNANAN OYUN ANALİZİ
Oyun diğer oyuncunun orta kareyi seçmesine bağlı olarak oldukça farklıdır.
r = 1
orta meydan işgal edildi
.X. X.. binary representation 1
.X. .X.
... ...
orta kare ücretsiz
X.. .X. binary representation 10001=17
... ...
..X .X.
r = 3
Diğer oyuncu son X'inize bitişik oynarsa, ortadaki kare işgal edilir.
XX. .XX binary representation 1011=11
.X. XX. or mirror image 1101=13
X.. ...
Ancak, yukarıdaki en iyi hareket değildir ve golf versiyonunda desteklenmez. En iyi hamle aşağıdaki gibi bir sonraki turda kazanmayı zorlar:
XX. binary representation 111=7. XXX
XX. Only to be used where j is odd. .X.
... Even j would look like image to right. ...
Diğer oyuncu son X'inize 90 veya 135 derece oynarsa orta şövalye işgal edilir (şövalyenin hamlesini oynayın.)
X.X .X. binary representation 100101=37
.X. .XX
.X. X..
Orta kare serbest
X.X .X. XX. binary representations:
... X.X ... 1010101=85 (first two)
X.X .X. .XX and 110011=51 (last one)
r = 5
orta kare işgal etti. Yukarıda r = 4'te belirtilen nedenlerden dolayı, hepsi kaybedilen dört olası hareket vardır. sadece bir tanesi desteklenir: 101111 = 47.
orta kare ücretsiz. Aşağıdaki gibi simetriye kadar sadece bir olası kart vardır. Diğer oyuncu bir sonraki hamlede kaybetmelidir, bu yüzden r> 5'i desteklemeye gerek yoktur.
XX. binary representation 1110111=119
X.X
.XX