set-cover-0.1: example/LCube.hs
{-
This puzzle is like Soma cube but with only L shaped bricks in a 5x5x5 box.
-}
module Main where
import qualified Math.SetCover.Exact as ESC
import qualified Math.SetCover.BitSet as BitSet
import qualified Math.SetCover.Bit as Bit
import Math.SetCover.Cuboid
(PackedCoords(PackedCoords), Coords, Size, forNestedCoords,
allPositions, allOrientations, packCoords, unpackCoords,
rotZ, normalForm)
import qualified Control.Concurrent.PooledIO.Independent as Pool
import qualified System.IO as IO
import Text.Printf (printf)
import Utility (hPutStrLnImmediate)
import qualified Data.Map as Map
import qualified Data.Set as Set
import Control.Applicative (pure)
import Data.Foldable (foldMap)
import Data.List (intercalate)
import Data.Word (Word64)
shape :: [PackedCoords]
shape = map PackedCoords [0,1,2,3,5]
size :: Size
size = pure 5
type Mask = Set.Set PackedCoords
type Assign = ESC.Assign Mask Mask
transformedBrickAssign :: [PackedCoords] -> [Assign]
transformedBrickAssign =
map brickAssign . concatMap (allPositions size) .
allOrientations . map (unpackCoords size)
brickAssign :: [Coords Int] -> Assign
brickAssign ts =
let xs = Set.fromList $ map (packCoords size) ts
in ESC.assign xs xs
allAssigns :: [Assign]
allAssigns = transformedBrickAssign shape
allMasks :: [Mask]
allMasks = map ESC.labeledSet allAssigns
writeMasks :: IO ()
writeMasks =
writeFile "lcube.txt" $ show allMasks
initStates :: [ESC.State Mask Mask]
initStates =
map
(\rotate ->
ESC.updateState
(brickAssign $ normalForm $
map rotate $ map (unpackCoords size) shape) $
ESC.initState allAssigns)
[id, rotZ, rotZ.rotZ.rotZ]
format :: [Mask] -> String
format v =
let cubex =
Map.unions $
zipWith (\n -> foldMap (flip Map.singleton n)) [0..] $
reverse v
in forNestedCoords
unlines (intercalate " | ") (intercalate " ")
(\c ->
maybe "." (\n -> [toEnum $ n + fromEnum 'A']) $
Map.lookup (packCoords size c) cubex)
size
printMask :: [Mask] -> IO ()
printMask = putStrLn . format
type BitMask = BitSet.Set (Bit.Sum Word64 Word64)
packMask :: Mask -> BitMask
packMask =
foldMap
(\(PackedCoords x) ->
BitSet.Set $
case divMod x 64 of
(0, k) -> Bit.bitLeft k
(1, k) -> Bit.bitRight k
_ -> error "impossible position")
main, mainState, mainBits, mainParallel, testme :: IO ()
testme = mapM_ (printMask . (:[])) allMasks
mainState = do
let sol = concatMap ESC.search initStates
mapM_ printMask sol
print $ length sol
mainBits = do
let sol = concatMap ESC.search $ map (fmap packMask) initStates
mapM_ printMask sol
print $ length sol
mainParallel =
Pool.runUnlimited $
(\f -> zipWith f [0..] initStates) $ \n initState ->
IO.withFile (printf "lcube%02d.txt" (n::Int)) IO.WriteMode $ \h ->
mapM_ (hPutStrLnImmediate h . format) $
ESC.search $ fmap packMask initState
main = mainParallel