(This article was originally published at Xi'an's Og » R, and syndicated at StatsBlogs.)
I learned something in R today thanks to Le Monde mathematical puzzle:
A two-player game consists in A picking a number n between 1 and 10 and B and A successively choosing and applying one of three transforms to the current value of n
- n=n+1,
- n=3n,
- n=4n,
starting with B, until n is larger than 999. Which value(s) of n should A pick if both players act optimally?
Indeed, I first tested the following R code
sole=function(n){
if (n>999){ return(TRUE)
}else{
return((!sole(3*n))&(!sole(4*n))&(!sole(n+1)))
}}
which did not work because of too many calls to sole:
>sole(1) Error: evaluation nested too deeply: infinite recursion / options(expressions=)?
So I included a memory in the calls to sole so that good and bad entries of n were saved for later calls:
visit=rep(-1,1000) #not yet visited
sole=function(n){
if (n>999){ return(TRUE)
}else{
if (visit[n]>-1){ return(visit[n]==1)
}else{
visit[n]<<-((!sole(3*n))&(!sole(4*n))&
(!sole(n+1)))
return(visit[n]==1)
}}}
Trying frontal attack
>sole(1) Error: evaluation nested too deeply: infinite recursion / options(expressions=)?
did not work, but one single intermediary was sufficient:
> sole(500) [1] FALSE > for (i in 1:10) + print(sole(i)) [1] FALSE [1] FALSE [1] FALSE [1] TRUE [1] FALSE [1] TRUE [1] FALSE [1] FALSE [1] FALSE [1] FALSE
which means that the only winning starters for A are n=4,6. If one wants the winning moves on top, a second counter can be introduced:
visit=best=rep(-1,1000)
sole=function(n){
if (n>999){ return(TRUE)
}else{
if (visit[n]>-1){ return(visit[n]==1)
}else{
visit[n]<<-((!sole(3*n))&(!sole(4*n))&
(!sole(n+1)))
if (visit[n]==0) best[n]<<-max(
3*n*(sole(3*n)),
4*n*(sole(4*n)),
(n+1)*(sole(n+1)))
return(visit[n]==1)
}}}
From which we can deduce the next values chosen by A or B as
> best[1:10] [1] 4 6 4 -1 6 -1 28 32 36 40
(where -1 means no winning choice is possible).
Now, what is the R trick I learned from this toy problem? Simply the use of the double allocation symbol that allows to change global variables within functions. As visit and best in the latest function. (The function assign would have worked too.)
Filed under: Kids, R, Statistics, University life Tagged: assign(), global variable, Le Monde, local variable, mathematical puzzle
Please comment on the article here: Xi'an's Og » R
