The game
Nim is a mathematical strategy game, where 2 players take turns taking items from distinct heaps. On your turn, you must take at least one item, and you may take as many as you want, provided that you only take from one heap. The player that takes the last item wins! This is a solved game. Before I go into the strategy, you can try playing it online here.
The Strategy
The winning strategy is explained very clearly and simply here at this link. I will explain it using a little bit more technical terms. The way to win this game, is to always take as many items as possible so that the binary-digital-sum is always 0. Consider the following board:
*
* *
* * *
* * * *
* * * * *
1 2 3 4 5
To find the binary-digital-sum of this board, you must:
Convert the number in each row to binary. So we have 001, 010, 011, 100 and 101.
Add all the numbers together, and ignore any carrying.
001 010 011 100 +101 ---- 001
You can also bitwise-xor each number, and this will achieve the same result.
Now, if the sum in this current configuration is 001, then this is not (yet) a winning board. But you can make it a winning board! If we take one item off of columns 1, 3 or 5, the sum will be 0. This is a winning board, which means that, provided you don't make a mistake, the next player to move will lose. So you must always end your turn with a winning board. Lets say you take one item off of column 5. Now the board looks like this:
* *
* * *
* * * *
* * * * *
1 2 3 4 5
As long as you don't screw up, you have a guaranteed win. There is nothing your opponent can do to stop you. Lets say he takes all of the items from column 5.
*
* *
* * *
* * * *
1 2 3 4 5
Where would you go next? Don't scroll down yet, and try to figure it out for yourself.
Right now, the sum is 100. The best move (and only winning move) would be to take everything from column 4. That would leave the board like this:
*
* *
* * *
1 2 3 4 5
and the sum like this
001
010
+011
----
000
that means that you are in a winning board! Yay!
The Challenge
You must write a program or function that, given a nim board, will return a winning move, or a falsey value if there is no winning move.
Your input:
Will be your languages native list format, where each item in the list corresponds to the number of items in a given column. For example, the input {4, 2, 1, 0, 3} corresponds to the following nim board:
* * * * * * * * * * 1, 2, 3, 4, 5
(optional) The number of rows. (For languages like C/C++ where this is not known from the list itself.)
Your output:
Can go to STDOUT or be returned from the function
Must be two numbers, 1) the column we are removing from (Remember that the columns are 0-indexed) and 2) the number of items to remove from that row. This could be a 2-item array, a string of the two numbers, etc. Keep in mind that the answer might be more than 2 digits long, so returning the string "111" is not valid because it isn't clear if this means "Remove one item from column eleven" or "Remove eleven items from column one". "1,11" or "11,1" would both be acceptable.
If there is no answer, return or print a falsy value. If your langauge can only return one type of variable (again, like C/C++), a negative number for the column, or 0 or less for the number to remove would both be acceptable falsey values.
If the column number or number to remove are too large, this is seen as an invalid output.
Sample Inputs/Outputs
[1, 2, 3, 4, 5]
---> [0, 1]
or [4, 1]
or [2, 1]
[1, 3, 5, 6]
---> [0, 1]
or [1, 1]
or [2, 1]
[1, 2, 0, 0, 5]
---> [4, 2]
[1, 2, 3]
---> ERROR
If you choose to do a function instead of full program, then you must write a full program to demonstrate the function in action. This will not count towards your full score. Also, programs are expected to run in a reasonable amount of time. I'm not planning to enter any excessively large inputs, so as long as your program isn't doing a brute force search over the entire game tree, you should be fine.
As usual, this is code-golf, so standard loop-holes apply, and answers are counted in bytes.
Leaderboard
Here is a Stack Snippet to generate both a regular leaderboard and an overview of winners by language.
To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:
# Language Name, N bytes
where N
is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:
# Ruby, <s>104</s> <s>101</s> 96 bytes
var QUESTION_ID=52356;function answersUrl(e){return"http://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),e.has_more?getAnswers():process()}})}function shouldHaveHeading(e){var a=!1,r=e.body_markdown.split("\n");try{a|=/^#/.test(e.body_markdown),a|=["-","="].indexOf(r[1][0])>-1,a&=LANGUAGE_REG.test(e.body_markdown)}catch(n){}return a}function shouldHaveScore(e){var a=!1;try{a|=SIZE_REG.test(e.body_markdown.split("\n")[0])}catch(r){}return a}function getAuthorName(e){return e.owner.display_name}function process(){answers=answers.filter(shouldHaveScore).filter(shouldHaveHeading),answers.sort(function(e,a){var r=+(e.body_markdown.split("\n")[0].match(SIZE_REG)||[1/0])[0],n=+(a.body_markdown.split("\n")[0].match(SIZE_REG)||[1/0])[0];return r-n});var e={},a=1,r=null,n=1;answers.forEach(function(s){var t=s.body_markdown.split("\n")[0],o=jQuery("#answer-template").html(),l=(t.match(NUMBER_REG)[0],(t.match(SIZE_REG)||[0])[0]),c=t.match(LANGUAGE_REG)[1],i=getAuthorName(s);l!=r&&(n=a),r=l,++a,o=o.replace("{{PLACE}}",n+".").replace("{{NAME}}",i).replace("{{LANGUAGE}}",c).replace("{{SIZE}}",l).replace("{{LINK}}",s.share_link),o=jQuery(o),jQuery("#answers").append(o),e[c]=e[c]||{lang:c,user:i,size:l,link:s.share_link}});var s=[];for(var t in e)e.hasOwnProperty(t)&&s.push(e[t]);s.sort(function(e,a){return e.lang>a.lang?1:e.lang<a.lang?-1:0});for(var o=0;o<s.length;++o){var l=jQuery("#language-template").html(),t=s[o];l=l.replace("{{LANGUAGE}}",t.lang).replace("{{NAME}}",t.user).replace("{{SIZE}}",t.size).replace("{{LINK}}",t.link),l=jQuery(l),jQuery("#languages").append(l)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",answers=[],page=1;getAnswers();var SIZE_REG=/\d+(?=[^\d&]*(?:<(?:s>[^&]*<\/s>|[^&]+>)[^\d&]*)*$)/,NUMBER_REG=/\d+/,LANGUAGE_REG=/^#*\s*([^,]+)/;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"><div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table></div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table></div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody></table><table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody></table>