Last active
November 3, 2015 20:36
-
-
Save asm0dey/01cbb2a2730cac30d686 to your computer and use it in GitHub Desktop.
Chess problem solution in Haskell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Lib | |
( someFunc | |
) where | |
import Data.Maybe | |
import Data.Either | |
import Data.Foldable | |
import Data.Sequence | |
import Data.Set | |
data Piece = King | Queen | Knight | Rook | Bishop | |
deriving (Show, Eq, Ord) | |
data Cell = Cell { piece :: Maybe Piece | |
, x :: Int | |
, y :: Int | |
} deriving (Show, Eq, Ord) | |
type Board = Seq Cell | |
union :: Set Board -> [Set Board] -> Set Board | |
union currentSet toAdd | |
| Data.Foldable.length toAdd == 0 = currentSet | |
| otherwise = Lib.union (Data.Set.union (head toAdd) currentSet) (tail toAdd) | |
generateBoard :: Int -> Int -> Seq Cell | |
generateBoard x y = Data.Sequence.fromList [ Cell { piece = Nothing, x=xs, y=ys} | xs <- [1..x], ys <- [1..y]] | |
tryPlacePieceOnCell :: Piece -> Cell -> Board -> Maybe Board | |
tryPlacePieceOnCell piece cell board | |
| piece == Queen && Data.Sequence.length onQueenWay == 0 = Just updateBoard | |
| piece == King && Data.Sequence.length onKingWay == 0 = Just updateBoard | |
| piece == Knight && Data.Sequence.length onKnightWay == 0 = Just updateBoard | |
| piece == Rook && Data.Sequence.length onRookWay == 0 = Just updateBoard | |
| piece == Bishop && Data.Sequence.length onBishopWay == 0 = Just updateBoard | |
| otherwise = Nothing | |
where cellToUpdate = fromJust $ elemIndexL cell board | |
updateBoard = Data.Sequence.update cellToUpdate cell{piece=Just piece} board | |
nonEmpty = Data.Sequence.filter nonEmptyPredicate board | |
horizWay cell1 = x cell1 == x cell | |
vertWay cell1 = y cell1 == y cell | |
xDistance cell1 = abs (x cell - x cell1) | |
yDistance cell1 = abs (y cell - y cell1) | |
diagWay cell1 = xDistance cell1 == yDistance cell1 | |
checkQueen cell1 = horizWay cell1 || vertWay cell1 || diagWay cell1 | |
checkKing cell1 = xDistance cell1 <=1 && yDistance cell1 <= 1 | |
checkRook cell1 = horizWay cell1 || vertWay cell1 | |
checkBishop cell1 = diagWay cell1 | |
checkKnight cell1 = (xDistance cell1, yDistance cell1) == (1,2) || (xDistance cell1, yDistance cell1) == (2,1) | |
onQueenWay = Data.Sequence.filter checkQueen nonEmpty | |
onKingWay = Data.Sequence.filter checkKing nonEmpty | |
onBishopWay = Data.Sequence.filter checkBishop nonEmpty | |
onRookWay = Data.Sequence.filter checkRook nonEmpty | |
onKnightWay = Data.Sequence.filter checkKnight nonEmpty | |
nonEmptyPredicate :: Cell -> Bool | |
nonEmptyPredicate cellToCheck = (piece cellToCheck) /= Nothing | |
findSuitableCombinations :: Board -> Seq Piece -> Set Board -> Set Board | |
findSuitableCombinations board pieces currentResults | |
| Data.Foldable.length pieces == 0 = Data.Set.insert board currentResults | |
| otherwise = Data.Set.union currentResults $ Data.Set.union currentResults $ unions [findSuitableCombinations board others currentResults | board <- filterPossibilities ] | |
where splitPieces = Data.Sequence.splitAt 1 pieces | |
piece = Data.Sequence.index (fst splitPieces) 0 | |
others = snd splitPieces | |
checkPossibility index cell = tryPlacePieceOnCell piece cell board | |
filterPossibilities = Data.Foldable.toList $ Data.Sequence.mapWithIndex toValue $ Data.Sequence.filter Data.Maybe.isJust $ Data.Sequence.mapWithIndex checkPossibility board | |
toValue :: Int -> Maybe a -> a | |
toValue int val = fromJust val | |
someFunc = do | |
let hSize = 6 | |
let vSize = 6 | |
let board = generateBoard hSize vSize | |
let pieces = Data.Sequence.fromList $ Prelude.replicate 6 Rook | |
let boards = Data.Foldable.length $ findSuitableCombinations board pieces Data.Set.empty | |
putStrLn . show $ boards |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment