Ruby, Rev B 121 ไบต์
การส่งเป็นฟังก์ชันที่ไม่ระบุชื่อลบf=
ด้วย แสดงในโปรแกรมทดสอบเพื่อแสดงการใช้งาน
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 ไบต์ที่บันทึกไว้โดยทำให้จัตุรัสกลางมีความสำคัญน้อยที่สุดแทนบิตที่สำคัญที่สุด (ลบโดย/2
แทนที่จะเป็น%256
) ที่เหลืออยู่โดยการปรับโครงสร้างองค์กรของตารางการเคลื่อนไหวที่ยอมรับได้ การจัดระเบียบเป็นศูนย์จัตุรัสว่าง / ครอบครองแทนโดยจำนวนทั้งหมดของ X ช่วยให้การทดสอบง่ายขึ้น นอกจากนี้ในตอนนี้มีเพียง 2 สตริงในอาเรย์ดังนั้น%w{string1 string2}
ไวยากรณ์จึงถูกละทิ้งเนื่องจากเป็น["string1","string2"]
ไวยากรณ์ สิ่งนี้ทำให้\7
สามารถรวมอักขระที่ไม่สามารถพิมพ์ได้ซึ่งจะทำให้สามารถเข้ารหัสได้ง่ายขึ้น: 126-t
แทนที่จะ(36-t)%120
ใช้
Ruby, Rev A 143 ไบต์
->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}
นี่คือฟังก์ชั่นที่ไม่ระบุชื่อ รูปแบบอินพุต / เอาต์พุตเปิดทิ้งไว้ดังนั้นฉันจึงไปหาเลขฐานสองขนาด 9 บิต บิตของ 512 หมายถึงศูนย์กลางโดยที่บิตที่เหลือหมุนวนรอบมัน (บิตของ 1 ถือเป็นมุม)
มีอินพุตที่เป็นไปได้มากกว่าเอาต์พุตที่ยอมรับได้ดังนั้นอัลกอริทึมคือลองทุกการเคลื่อนไหวและค้นหาอินพุตที่เหมาะกับรูปแบบเอาต์พุตที่ยอมรับได้ รูปแบบเอาต์พุตที่ยอมรับได้สำหรับ X แต่ละจำนวนนั้นเป็นฮาร์ดโค้ด
ข้อมูลเกี่ยวกับจัตุรัสกลางถูกถอดออกและส่วนที่เหลืออีก 8 บิตจะถูกคูณด้วย 257 เพื่อทำซ้ำ รูปแบบนี้จะหมุนผ่านรูปแบบที่ยอมรับได้โดยการเลื่อนระดับสิทธิ์
การวนซ้ำไม่ออกเมื่อพบรูปแบบดังนั้นรูปแบบที่ส่งคืนจะเป็นรูปแบบที่ยอมรับได้ล่าสุด ด้วยเหตุนี้รูปแบบที่นิยม (ซึ่งมีการตั้งค่า) มาในภายหลังในรายการ
ด้วยกลยุทธ์ 'Knights move' มันมีความสำคัญเล็กน้อยไม่ว่าจะเป็นรูปแบบการหมุน 45 องศาหรือไม่ รุ่น ungolfed เป็นไปตามกลยุทธ์การย้ายของอัศวินและดังนั้นจึงไม่จำเป็นต้องแยกแยะความแตกต่างระหว่างมุมของสี่เหลี่ยมกับมุมของสี่เหลี่ยมจัตุรัส
อย่างไรก็ตามฉันพบว่านี่ไม่ใช่กลยุทธ์ที่ดีที่สุดเสมอเนื่องจากมีเคล็ดลับต่อไปนี้ หากฝ่ายตรงข้ามของคุณไปก่อนและใช้ศูนย์เขาควรจะชนะ แต่ในการย้ายครั้งที่สองของเขาเขาทำให้เกิดข้อผิดพลาดในการอนุญาตให้คุณสร้าง 2x2 ตารางคุณควรจะใช้มันเพราะสิ่งนี้ช่วยให้คุณบังคับให้เขาสร้างสามแถว นี่คือการดำเนินการในรุ่น golfed จำเป็นต้องมีรหัสพิเศษเล็กน้อยในอินสแตนซ์นี้เพื่อแยกความแตกต่างระหว่าง X สามตัวที่มุมหนึ่ง (บังคับให้คู่ต่อสู้แพ้) และ 3 X ตามขอบหนึ่ง (การฆ่าตัวตายทันที)
Ungolfed ในโปรแกรมทดสอบ
เวอร์ชันที่ไม่ดีขึ้นตามตรรกะที่แสดงในคำถาม
ในรุ่นแข็งแรงเล่นกอล์ฟตารางมีการแก้ไขเล็กน้อยเพื่อที่จะใช้ลักษณะการทำงานที่แตกต่างกันเล็กน้อยสำหรับกรณีที่[[0],[1,17],[9],[37,7,51,85],[45],[47,119]]
r=3
จากนั้นจะถูกบีบอัดเป็น ASCII ที่พิมพ์ได้ (ต้องการการถอดรหัส(t-36)%120
) ต้องใช้ตรรกะเพิ่มเล็กน้อยเพื่อแยกความแตกต่างระหว่างสาม X ในมุมและสาม X ตามขอบในกรณีของรายการตาราง 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}
ผลลัพธ์ของโปรแกรมทดสอบ
สิ่งนี้จะเกิดขึ้นเมื่อคอมพิวเตอร์เล่นเอง
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
การวิเคราะห์การเล่นเกมครั้งแรก
นี่เป็นเรื่องง่ายและเป็นเส้นตรง
เมื่อเล่นก่อนสี่เหลี่ยมกลางจะเป็นสี่เหลี่ยมจัตุรัสแรกที่ถูกครอบครองเสมอ
r = 0
... binary representation 0
.X.
...
r = 2
X.. binary representation 1001=9
.XX
...
r = 4
X.. binary representation 101101=45
.XX
XX.
มีทางเดียวเท่านั้น (ขึ้นอยู่กับความสมมาตร) ที่มี X ห้าตัวรวมถึงจตุรัสกลางบนกระดานโดยที่เกมไม่จบ มี X ในช่องกลางตรงกลางแต่ละเส้นทแยงมุม (ที่ 90 องศาซึ่งกันและกัน) และอีกอันหนึ่งสำหรับแต่ละแนวนอน / แนวตั้งศูนย์กลาง (ที่ 90 องศาต่อกัน) เนื่องจากขอบทั้งหมดไม่สามารถครอบครองด้านบนได้เท่านั้น การจัดการที่เป็นไปได้ ผู้เล่นคนอื่นจะต้องแพ้ในการย้ายครั้งต่อไป
การวิเคราะห์การเล่นเกมที่สอง
การเล่นแตกต่างกันมากขึ้นอยู่กับว่าผู้เล่นคนอื่นเลือกจัตุรัสกลาง
r = 1
สแควร์กลางครอบครอง
.X. X.. binary representation 1
.X. .X.
... ...
จัตุรัสกลางฟรี
X.. .X. binary representation 10001=17
... ...
..X .X.
r = 3
Middle Square ครอบครองถ้าผู้เล่นคนอื่นเล่นติดกับ X สุดท้ายของคุณการเล่นเป็นอัศวินย้ายไปด้านล่างได้รับการสนับสนุนในรุ่น ungolfed
XX. .XX binary representation 1011=11
.X. XX. or mirror image 1101=13
X.. ...
อย่างไรก็ตามข้างต้นไม่ได้เป็นการเคลื่อนไหวที่ดีที่สุดและไม่ได้รับการสนับสนุนในเวอร์ชั่น golfed การย้ายที่ดีที่สุดมีดังนี้บังคับให้ชนะในเทิร์นถัดไป:
XX. binary representation 111=7. XXX
XX. Only to be used where j is odd. .X.
... Even j would look like image to right. ...
จัตุรัสกลางถูกครอบครองหากผู้เล่นคนอื่นเล่นที่ 90 หรือ 135 องศาจนถึง X สุดท้ายของคุณ (เล่นเป็นอัศวินย้ายไป)
X.X .X. binary representation 100101=37
.X. .XX
.X. X..
จัตุรัสกลางฟรี
X.X .X. XX. binary representations:
... X.X ... 1010101=85 (first two)
X.X .X. .XX and 110011=51 (last one)
r = 5
สแควร์กลางครอบครอง ด้วยเหตุผลที่กล่าวข้างต้นใน r = 4 มีการเคลื่อนไหวที่เป็นไปได้สี่อย่างซึ่งทั้งหมดจะเสีย รองรับเพียงหนึ่งเท่านั้น: 101111 = 47
จัตุรัสกลางฟรี มีบอร์ดเดียวที่เป็นไปได้จนถึงสมมาตรดังนี้ ผู้เล่นคนอื่นต้องแพ้ในการเคลื่อนที่ครั้งต่อไปดังนั้นจึงไม่จำเป็นต้องสนับสนุน r> 5
XX. binary representation 1110111=119
X.X
.XX