User:DanBron/Game of Nim: Difference between revisions

m
nowiki to make the page disappear from task space without changing the contents too much
(The suitability of this task for inclusion on Rosetta Code is being discussed on the talk page.)
m (nowiki to make the page disappear from task space without changing the contents too much)
 
(8 intermediate revisions by 5 users not shown)
Line 1:
<nowiki>
{{draft task}}
'''The suitability of this task for inclusion on Rosetta Code is being discussed on the talk page. This task may disappear in future.'''<br>
'''You are welcome to join in the discussion on the [[Talk:Game of Nim|talk page]].'''<br>
Line 41:
'''Notes on execution''': Just define <tt>nim</tt> in the REPL and call it as per the example.<br/>
'''Golf score''': 23 bytes (including the assigment, i.e. naming the function; 18 bytes for the function definition).
 
=={{header|Javascript}}==
 
Translation of J:
 
<lang Javascript>function nim() {
var x=0, a=arguments, l=a.length, r=[];
for (var j=0; j<l; j++) x^=a[j];
for (var j=0; j<l; j++) r[j]= Math.max(0,a[j]-(x^a[j]));
return r;
}</lang>
 
Task example:
 
<lang Javascipt>nim(4,7,2,2,1)
[0, 2, 2, 2, 0]</lang>
 
Ugly golf variant:
 
<lang Javascript>function m(a){x=0
l=a.length
r=[]
for(j=0;j<l;j++)x^=a[j]
for(j=0;j<l;j++)r[j]=Math.max(0,a[j]-(x^a[j]))
return r}</lang>
 
Golf example:
 
<lang Javascript>m([4,7,2,2,1])
[0, 2, 2, 2, 0]</lang>
 
=={{header|MATLAB}}==
Full game implemented in standard method with two computer players
<lang MATLAB>function GameOfNim
board = [4 7 2 2 1];
fprintf('Board: [ %s]\n', sprintf('%d ', board))
turnA = true;
while sum(board)
if turnA % Player A - uses strategy, makes first possible move
nimMove = NextMoveNim(board);
movePlace = find(nimMove, 1);
if movePlace % An optimal move is possible
board(movePlace) = board(movePlace)-nimMove(movePlace);
else % No optimal move - move randomly
possMoves = find(board);
movePlace = possMoves(randi(length(possMoves)));
board(movePlace) = board(movePlace)-randi(board(movePlace));
end
fprintf('Player A: [ %s]\n', sprintf('%d ', board))
else % Player B - moves randomly
possMoves = find(board);
movePlace = possMoves(randi(length(possMoves)));
board(movePlace) = board(movePlace)-randi(board(movePlace));
fprintf('Player B: [ %s]\n', sprintf('%d ', board))
end
turnA = ~turnA;
end
end
 
function nimMove = NextMoveNim(board)
boardNimSum = CalcNimSum(board);
placeNimSums = zeros(size(board));
for k = 1:length(board)
placeNimSums(k) = CalcNimSum([board(k) boardNimSum]);
end
movePlaces = placeNimSums < board;
nimMove = zeros(size(board));
nimMove(movePlaces) = board(movePlaces)-placeNimSums(movePlaces);
end
 
function nimSum = CalcNimSum(board)
boardBinary = dec2bin(board)==49; % Shortcut to avoid using de2bi()
nimBinary = boardBinary(1, :);
for k = 2:length(board)
nimBinary = xor(nimBinary, boardBinary(k, :));
end
nimSum = bin2dec(char(nimBinary+48)); % Shortcut to avoid using bi2de()
end</lang>
{{out}}
From a first-player advantage game (non-zero initial Nim-sum)
<pre>Board: [ 4 7 2 2 1 ]
Player A: [ 4 5 2 2 1 ]
Player B: [ 3 5 2 2 1 ]
Player A: [ 3 2 2 2 1 ]
Player B: [ 3 2 2 0 1 ]
Player A: [ 1 2 2 0 1 ]
Player B: [ 1 2 2 0 0 ]
Player A: [ 0 2 2 0 0 ]
Player B: [ 0 2 0 0 0 ]
Player A: [ 0 0 0 0 0 ]</pre>
From a zero initial Nim-sum game
<pre>Board: [ 3 4 7 ]
Player A: [ 3 4 3 ]
Player B: [ 3 0 3 ]
Player A: [ 1 0 3 ]
Player B: [ 1 0 1 ]
Player A: [ 1 0 0 ]
Player B: [ 0 0 0 ]</pre>
Human-readable version of the "next move" function (with whitespace and descriptive variables)
<lang MATLAB>function nim(decBoard)
binBoard = de2bi(decBoard);
allSum = mod(sum(binBoard), 2);
for k = 1:numel(decBoard)
placeSum(k) = bi2de(binBoard(k, :)+allSum == 1);
end
moves = decBoard-placeSum;
moves(moves < 0) = 0;
disp(moves)
end</lang>
Code golf version of "next move" function (104 characters, including newlines). Requires Communications System Toolbox for de2bi() and bi2de() functions.
<lang MATLAB>function n(d)
b=de2bi(d);a=mod(sum(b),2);for k=1:numel(d)
p(k)=bi2de(b(k,:)+a==1);end
m=d-p;m(m<0)=0</lang>
No toolbox requirements (121 characters, including newlines)
<lang MATLAB>function n(d)
b=dec2bin(d)==49;a=mod(sum(b),2);for k=1:numel(d)
p(k)=bin2dec(char(b(k,:)+a==1)+48);end
m=d-p;m(m<0)=0</lang>
{{out}}
Usage
<pre>>> n([4 7 2 2 1])
 
m =
 
0 2 2 2 0
>> n([3 4 5])
 
m =
 
2 0 0</pre>
 
 
=={{header|Racket}}==
 
'''See''' [[Tic-tac-toe#Racket]] for implementation of the general game engine.
<lang racket>
#lang racket
 
(require "game.rkt"
lazy/force)
 
;;--------------------------------------------------------------------
;; The definition of the game
 
(define initial-state '(3 5 7))
 
(define (move s m) (map - s m))
 
(define (win? s) (= 1 (apply + s)))
 
(define (show-state s) (displayln (map (λ (n) (make-list n '●)) s)))
 
(define (possible-moves S)
(append-map
(λ (heap n)
(map (λ (x) (map (curry * x) heap))
(range 1 (+ 1 (min 3 n)))))
'((1 0 0) (0 1 0) (0 0 1)) S))
 
;;--------------------------------------------------------------------
;; Creating the interactive players
 
 
(define Nim% (class game%
(super-new
[draw-game? (const #f)]
[possible-moves possible-moves]
[show-state show-state])))
 
(define-partners Nim%
(first% #:win win? #:move move)
(second% #:win win? #:move move))
 
;; players
(define player-A
(new (interactive-player first%) [name "A"] [look-ahead 4]))
 
(define player-B
(new (interactive-player second%) [name "B"] [look-ahead 4]))
</lang>
 
Computer plays with the computer:
<pre>
> (!(start-game player-A player-B initial-state))
 
A makes move (0 0 2)
((● ● ●) (● ● ● ● ●) (● ● ● ● ●))
 
B makes move (1 0 0)
((● ●) (● ● ● ● ●) (● ● ● ● ●))
 
A makes move (2 0 0)
(() (● ● ● ● ●) (● ● ● ● ●))
 
B makes move (0 2 0)
(() (● ● ●) (● ● ● ● ●))
 
A makes move (0 3 0)
(() () (● ● ● ● ●))
 
B makes move (0 0 1)
(() () (● ● ● ●))
 
A makes move (0 0 3)
(() () (●))
A wins!
</pre>
 
[[Category:Handicap]]
</nowiki>
1,336

edits