16
3
Your goal is to write a perfect player for the game of Wythoff's Nim.
Rules of Wythoff's Nim
Wythoff's Nim is a deterministic two-player game played with two piles of identical counters. Players alternate turns, in which they do one of these:
- Remove one or more counters from the first pile
- Remove one or more counters from the second pile
- Remove an equal number of counters (one or more), from both the first pile and the second pile.
Of course, piles can't go negative, but they can to 0. Whichever player removes the last counter overall wins the game.
For the more geometrically-minded, here is an equivalent formulation of the game that you can play on this applet. A single queen starts on some square of a quarter-infinite chessboard whose corner is in the bottom-left. Players alternate moving the queen, which moves like a chess queen but restricted to three directions:
- Down
- Left
- Diagonally down and left
Whoever moves the queen to the corner wins.
Associating the queen's coordinates (with corner (0,0)
) to the sizes of the respective piles, it's easy to see both games are the same.
Perfect play
(You can skip this if familiar with the notions of perfect play and winning moves.)
Since Wythoff's Nim is a finite and deterministic game, it has a notion of perfect play. A perfect player is a strategy that will always win from a theoretically won position, meaning a position in which there exists a strategy that guarantees a win.
To be a winning strategy, it suffices to move to always move to a theoretical winning position for the player who just moved, and thus the player not going next. The first of these winning positions (also called cold positions) are (0,0), (1,2), (2,1), (3,5), (5,3)
. See the Wikipedia article for an explanation of an algorithm to find a winning strategy for Wythoff's Nim, as well as a formula to generate win positions.
Program requirements
Write a program or function takes a position as input and outputs a winning move in the form of the position after that move. Fewest bytes wins.
If no winning move exists, i.e., the position is a theoretical loss, your program should indicate so and forfeit.
Your program must run within a reasonable amount of time. So, an exponential recursive game tree search will not suffice. If you want to precompute and hard-code a strategy, that's fine.
Input
A pair (i,j)
of non-negative numbers representing pile sizes, each at most 99
. This can be two numbers, a tuple, a list, or whatever container you prefer.
Output
Print or output the position after your move, again as two numbers or a container thereof. This must be a legal move to a winning position. If there's multiple such moves, any one is fine, but only one.
If there's no winning move, you must indicate this in the output. Any output like False
, None
, 0, or (-1,-1)
will do, as long as it's not a legal position, and is the same for every losing input.
Example runs
f(5,0) = (0,0)
f(2,2) = (1,2) # Or (2,1) or (0,0)
f(1,2) = False
f(13,9) = (13,8) # Or (10,6)
f(10,6) = False
f(5,10) = (5,3)
f(25,30) = (8,13)
2+1, partly because I like the idea of a quarter of infinity. – Level River St – 2014-11-28T09:57:01.410
define "reasonable amount of time". Is several seconds for (100,50) a reasonable amount of time? – John Dvorak – 2014-11-28T11:35:26.823
Oh. Wait. the input is bounded by... 30??? That's a bit low, isn't it? – John Dvorak – 2014-11-28T11:46:41.997
@JanDvorak You're right, it might allow cheap shortcuts. Changed to 99 -- I think that suffices? Apologies for editing specs after posting. – xnor – 2014-11-28T11:51:08.437
@PeterTaylor Thanks, fixed. – xnor – 2014-11-28T11:51:47.030
@JanDvorak Several seconds is fine. – xnor – 2014-11-28T11:54:19.157
Can I print all of the winning moves? i.e.
f(2,2) -> [(1,2),(2,1),(0,0)]
– FryAmTheEggman – 2014-11-28T18:09:26.387@FryAmTheEggman Nope, just one. – xnor – 2014-11-28T22:08:04.473