십자가, 필요 없음


10

모두 박하 사탕 발가락 이 해결 된 게임 이라는 것을 알고 있습니다. 그러나 Misère 버전의 only-X는 흥미로운 대안을 제공합니다.

이 버전의 게임에서 두 선수 모두 X를 보드에 놓고 3 연승을 피하려고합니다. 이에 대한 자세한 내용을 보려면 Numberphile 에이 개념에 대한 멋진 비디오가 있습니다.

Misère Crosses 보드가 주어지면 최적의 움직임을하십시오.

보드는 각각 3 자씩 3 줄이며, X또는 입니다. 그러므로:

X X
X  
 XX

유효한 보드입니다. 입력과 출력이 동일한 형식을 사용하는 한, 편리한 형식으로 이것을 취할 수 있습니다. 형식에는 다음이 포함됩니다 (단, 이에 한하지 않음). 여러 줄 문자열 (선택적인 후행 줄 바꿈 포함); X또는 ; 문자의 2D 배열 각 위치가 재생되었는지 여부를 나타내는 1D 평면화 된 부울 값 배열.

최적의 이동은 가능한 한 오랫동안 최적으로 계속 플레이하거나 손실을 연장함으로써 이길 수있는 보장이며 다음 규칙에 의해 정의됩니다.

  • 연속으로 3 개를 만들지 마십시오.
  • 먼저 가면 중간에서 연주하십시오.
  • 점유 된 공간이 중간 인 경우 나머지 공간에서 연주하십시오.
  • 중간 정사각형이 점유되지 않고 외부 정사각형이 있으면 상대의 마지막 경기 반대편에 경기하십시오.
  • 중간 정사각형이 점유되어 있고 외부 정사각형이있는 경우, 잃지 않는 이전 기사에서 "기사 이동"(한 번 이상)을하십시오.
  • 잃지 않는 곳에 남은 사각형이 없으면 남은 사각형 중 하나를 사용하십시오.

[참고 : 이것은 한 경우에 최적아닌 것으로 판명 되었지만 어쨌든이 알고리즘을 사용해야합니다.]

이전의 모든 움직임이 최적이라고 가정 할 수 있습니다. 따라서 첫 번째 예제 보드는 유효한 입력이 아닙니다. 상대방의 움직임은 최적 일 수도 있고 아닐 수도 있습니다.

게임이 종료 된 경우 (즉, 연속 3 개가 만들어진 경우) 동작은 정의되지 않습니다.

이것이 이므로 바이트 단위의 최단 답변이 승리합니다!

최적의 이동 만 사용하는 가능한 경로는 다음과 같습니다.

[   ]  [   ]  [X  ]  [X  ]  [X  ]  [X  ]  [XX ]
[   ]->[ X ]->[ X ]->[ XX]->[ XX]->[ XX]->[ XX]
[   ]  [   ]  [   ]  [   ]  [ X ]  [XX ]  [XX ]

최적이 아닌 동작을 사용하여 상대방이 입력 할 수있는 입력은 다음과 같습니다.
(이 목록의 왼쪽 보드 만 유효한 입력입니다.)

[X  ]  [X  ]
[   ]->[   ]
[   ]  [  X]

[XX ]  [XX ]
[   ]->[   ]
[  X]  [ XX]

[XX ]  [XX ]
[X  ]->[X X]
[ XX]  [ XX]


입력 및 출력 형식은 무엇입니까? 보드를 배열 또는 문자열로 간주한다고 가정합니까? 그러나 이것은 마지막 이동에 대한 정보를 제공하지 않으므로 다음 질문입니다.
Level River St

1
"적의 마지막 플레이와 반대되는 플레이"전략은 상대의 이동 이력에 대한 지식 또는 이전에이 전략을 따랐다 고 가정합니다 .XX\nX..\nX... 예를 들어 보드를 상속받지 않았습니다 . 이와 같은 보드 상속을 고려해야합니까?
Level River St

@LevelRiverSt 쓰여진대로 "이전의 모든 동작이 최적이라고 가정 할 수 있습니다"라고 보드가 유효하지 않게 입력 될 수 있습니다. 원하는 형식으로 입력 할 수 있지만 예제와 같은 여러 줄 문자열에는 "default"가 있습니다. 이동 논리가 중요 할 때 누군가가 문자열을 구문 분석하지 않도록 제한하고 싶지 않습니다. 도전.
CAD97

답변:


3

루비, 레브 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.

루비, 레브 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 정사각형을 만들 수 없다는 오류를 범합니다. 이것은 골프 버전으로 구현됩니다. 이 경우에는 코너에있는 3 개의 X (상대방을 잃게 함)와 한 쪽 가장자리에있는 3 개의 X (즉시 자살)를 구분하기 위해 약간의 추가 코드가 필요합니다.

테스트 프로그램에서 언 골프

ungolfed 버전은 질문에 표현 된 논리를 따릅니다.

골프 버전에서는 테이블이 약간 다르게 수정되어 [[0],[1,17],[9],[37,7,51,85],[45],[47,119]]사건에 대해 약간 다른 동작을 구현합니다 r=3. 그런 다음 인쇄 가능한 ASCII로 압축됩니다 (디코딩 필요 (t-36)%120). 표 항목 7의 경우 모서리에있는 3 개의 X와 모서리에있는 3 개의 X를 구별하려면 추가 비트가 필요합니다.&&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.

게임이 끝나지 않고 보드의 중간 정사각형을 포함하여 5 개의 X를 갖는 한 가지 방법 (최대 대칭까지)이 있습니다. 중간 정사각형에는 X가 있으며, 대각선 1 개 (각각 90도)와 가로 / 세로 중심선 (90도)이 있습니다. 배열 가능. 다른 플레이어는 다음 이동에서 잃어야합니다.

게임 분석 두 번째 게임

다른 플레이어가 중간 정사각형을 선택하는지에 따라 플레이는 상당히 다릅니다.

r = 1

점령 된 중간 광장

.X. X..  binary representation 1 
.X. .X.
... ...

중간 광장 무료

X.. .X. binary representation 10001=17
... ...
..X .X.

r = 3

다른 플레이어가 마지막 X 근처에서 플레이하는 경우 중간 정사각형 점령되지 않은 버전에서 다음과 같이 기사의 이동을 재생하는 것이 지원됩니다.

XX. .XX binary representation 1011=11 
.X. XX. or mirror image 1101=13
X.. ...

그러나 위의 방법은 최선의 방법이 아니며 골프 버전에서는 지원되지 않습니다. 가장 좋은 움직임은 다음과 같습니다. 다음 턴에 승리합니다.

XX. binary representation 111=7.           XXX
XX. Only to be used where j is odd.        .X.
... Even j would look like image to right. ...

다른 플레이어가 마지막 X에 90도 또는 135도를 재생하면 중앙 광장이 점령됩니다 (나이트 이동 거리).

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

이것은 놀라운 답변입니다! 나는 모든 사례를 최적의 모에 확인했다고 생각했지만 하나를 놓친 것 같습니다. 그러나 사양은 단순성을 위해 동일하게 유지됩니다. (정말 놀라운 일입니다.이 일을 해주셔서 감사합니다.이 설명은 매우 훌륭합니다! 사람들이 이렇게 놀라운 일을 할 수 있도록 I / O를 잃어 버렸습니다.)
CAD97

1
고마워, 그것은 흥미로운 도전이었다. 나는 지금 그것보다 꽤 골프를 쳤다.
Level River St
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.