User:DanBron/Game of Nim: Difference between revisions

m
nowiki to make the page disappear from task space without changing the contents too much
(→‎{{header|J}}: improve J entry by 1 point)
m (nowiki to make the page disappear from task space without changing the contents too much)
 
(10 intermediate revisions by 6 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>
 
The task is to implement the core algorithm of the [[wp:Game of Nim|Game of Nim]]. But there's a twist.
Line 37 ⟶ 39:
'''Example''':<lang j> nim 4 7 2 2 1
0 2 2 2 0</lang>
'''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