Skip to content

Instantly share code, notes, and snippets.

@asm0dey
Last active November 3, 2015 20:36
Show Gist options
  • Save asm0dey/01cbb2a2730cac30d686 to your computer and use it in GitHub Desktop.
Save asm0dey/01cbb2a2730cac30d686 to your computer and use it in GitHub Desktop.
Chess problem solution in Haskell
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