cryptol/examples/funstuff/marble.cry
2015-04-20 10:00:25 -07:00

109 lines
3.8 KiB
Plaintext

/*
* Copyright (c) 2013-2015 Galois, Inc.
* Distributed under the terms of the BSD3 license (see LICENSE file)
*/
// The classic "marble jumping" puzzle
// see: http://en.wikipedia.org/wiki/Peg_solitaire
// this is the "European" variation
type Board = [7][7]Bit
all : {n} (fin n) => [n] -> Bit
all xs = xs == ~zero
popCount : {a,b} (fin a, b >= 1, b == (width a)) => [a] -> [b]
popCount bs = ic ! 0 where
ic = [0] # [ if elt then prev + 1 else prev | elt <- bs | prev <- ic]
posns : Board
posns = [[False,False,True,True,True,False,False],
[False,True,True,True,True,True,False],
[True,True,True,True,True,True,True],
[True,True,True,True,True,True,True],
[True,True,True,True,True,True,True],
[False,True,True,True,True,True,False],
[False,False,True,True,True,False,False]]
start : Board
start = [[False,False,True,True,True,False,False],
[False,True,True,True,True,True,False],
[True,True,True,True,True,True,True],
[True,True,True,False,True,True,True],
[True,True,True,True,True,True,True],
[False,True,True,True,True,True,False],
[False,False,True,True,True,False,False]]
// testing positions
first : Board
first = [[False,False,True,True,True,False,False],
[False,True,True,True,True,True,False],
[True,True,True,True,True,True,True],
[True,True,True,True,False,False,True],
[True,True,True,True,True,True,True],
[False,True,True,True,True,True,False],
[False,False,True,True,True,False,False]]
second : Board
second = [[False,False,True,True,True,False,False],
[False,True,True,True,True,True,False],
[True,True,True,True,True,True,True],
[True,True,True,True,True,False,True],
[True,True,True,True,False,True,True],
[False,True,True,True,False,True,False],
[False,False,True,True,True,False,False]]
goal : Board
goal = [[False,False,False,False,False,False,False],
[False,False,False,True,False,False,False],
[False,False,False,False,False,False,False],
[False,False,False,False,False,False,False],
[False,False,False,False,False,False,False],
[False,False,False,False,False,False,False],
[False,False,False,False,False,False,False]]
validBoard : Board -> Bit
validBoard b = join (b && ~posns) == zero
validRowJump : Board -> Board -> Bit
validRowJump a a' = validBoard a
&& validBoard a'
&& validRowMove (differentRow a a')
differentRow : Board -> Board -> ([7], [7])
differentRow a a' = rows ! 0
where rows = [(0b0000000,0b0000000)]
# [ if row != row' then (row,row') else old
| row <- a
| row' <- a'
| old <- rows ]
validRowMove : ([7], [7]) -> Bit
validRowMove (r, r') = (xors == 0b0000111 ||
xors == 0b0001110 ||
xors == 0b0011100 ||
xors == 0b0111000 ||
xors == 0b1110000)
&& (
rxors == 0b0000011 ||
rxors == 0b0000110 ||
rxors == 0b0001100 ||
rxors == 0b0011000 ||
rxors == 0b0110000 ||
rxors == 0b1100000)
where xors = r ^ r'
rxors = r && rxors
validColJump : Board -> Board -> Bit
validColJump a a' = validRowJump (transpose a) (transpose a')
validMove : Board -> Board -> Bit
validMove a a' = validRowJump a a' || validColJump a a'
validMoveSequence : {n} (fin n, n >= 1) => [n] Board -> Bit
validMoveSequence moves = all [validMove a b | a <- moves | b <- drop`{1} moves]
solutionInNmoves : {n} (fin n) => [n] Board -> Bit
property solutionInNmoves ms = validMoveSequence ([start] # ms # [second])