R, 86 8483 bytes
-1 byte by using !m
instead of m<1
; -1 byte by realizing I only need one long OR ||
(the first one can be a short OR |
); -1 byte by toggling B
and using subtraction instead of equality of booleans.
a=function(x,m=max(x),B=FB=T)!m|all(x-1)==B||any-B||any(sapply(1:m,function(y)!a(x-y,y-1,!B)))
Exhaustive recursive search. Takes input as a vector. Outputs TRUE
or FALSE
.
At each step, subtracts the value chosen by the player from all the values in the set x
.
Alice wins if at her turn, the updated x
includes 1
. Bob wins if at his turn, the updated x
does not include 1
. To this end, the function includes a boolean B
, worth FALSETRUE
when Alice plays and TRUEFALSE
when Bob plays, and checks all(x != 1) ==!= B
. If this condition is verified, then the player wins, else the player wins if theirthere is a move which makes the other player lose (last condition in the code, uses recursion).
The initial !m
(equivalent to m!=0
) is there to check whether at the last move, the other player played 1
even though it is a losing move.
Edit: Arnauld added an explanation to his JavaScript answer while I was typing; it seems we have similar algorithms.