packages feed

set-cover-0.1: example/Nonogram/Base.hs

module Nonogram.Base where

import qualified Math.SetCover.Exact as ESC

import Control.Monad (liftM3)

import qualified Data.Map as Map; import Data.Map (Map)
import qualified Data.Set as Set; import Data.Set (Set)
import qualified Data.List.Match as Match
import qualified Data.Monoid.HT as Mn
import Data.Monoid (Monoid, mempty)


{- |
Identifies one row or column by its orientation and its position.
-}
data Strip = Strip Orientation Int
   deriving (Eq, Ord, Show)

{- |
A brick is a horizontal or vertical stripe of adjacent black squares
delimited by white squares.
We number them per line or column.
-}
newtype BrickId = BrickId Int
   deriving (Eq, Ord, Show)

instance Enum BrickId where
   fromEnum (BrickId n) = n
   toEnum = BrickId

data Orientation = Horizontal | Vertical
   deriving (Eq, Ord, Show)

data Color = White | Black
   deriving (Eq, Ord, Show, Enum)

type ColorMap = Map (Int,Int) Color


noAssign :: (Monoid map) => set -> ESC.Assign map set
noAssign = ESC.assign mempty

strip :: Ord item => Orientation -> Int -> [item] -> Map Strip (Set item)
strip orient line = Map.singleton (Strip orient line) . Set.fromList

class Ord item => Position item where
   position :: Int -> Color -> item

{- |
Assert that colors are consistent in slices of both orientations.
-}
assignsFromPositions ::
   (Position item) =>
   (Int -> Int -> Color -> map) ->
   [[Int]] -> [[Int]] -> [ESC.Assign map (Map Strip (Set item))]
assignsFromPositions squ rows columns =
   liftM3
      (\r c col ->
         ESC.assign (squ r c col) $
         Map.fromList
            [(Strip Horizontal r, Set.singleton (position c col)),
             (Strip Vertical c, Set.singleton (position r col))])
      (Match.take rows [0..])
      (Match.take columns [0..])
      [White, Black]


square :: Int -> Int -> Color -> Set (Int,Int)
square r c col = Mn.when (col==Black) $ Set.singleton (r,c)

squareBW :: Int -> Int -> Color -> ColorMap
squareBW r c = Map.singleton (r,c)