-- http://p...content-available-to-author-only...h.net/test/read.cgi/tech/1226229627/317
import Control.Applicative
import Data.Monoid
import Data.Array (Array,array,assocs,(//),(!))
import Data
.Maybe (isJust
) import Data.List (find,sortBy,transpose,(\\))
import Data
.Ord (comparing
) import Debug.Trace
type Block
= (Sum
Int, [Loc
])
ans = [1..6]
locations :: [Loc]
locations = (,) <$> ans <*> ans
blocks :: [Block]
blocks = [
(Sum 3, [(1,1),(1,2)])
, (Sum 4, [(2,1)])
, (Sum 13, [(3,1),(3,2),(3,3)])
, (Sum 5, [(4,1),(5,1)])
, (Sum 8, [(6,1),(6,2)])
, (Sum 7, [(2,2),(2,3)])
, (Sum 1, [(4,2)])
, (Sum 7, [(5,2),(5,3)])
, (Sum 11, [(1,3),(1,4)])
, (Sum 7, [(4,3),(4,4)])
, (Sum 6, [(6,3)])
, (Sum 6, [(2,4),(3,4)])
, (Sum 6, [(5,4),(6,4)])
, (Sum 9, [(1,5),(2,5)])
, (Sum 6, [(3,5),(4,5)])
, (Sum 4, [(5,5)])
, (Sum 3, [(6,5),(6,6)])
, (Sum 4, [(1,6)])
, (Sum 5, [(2,6),(3,6)])
, (Sum 11, [(4,6),(5,6)])
]
main = case solve new_mesh of
Nothing
-> print "can't solve it." where new_mesh = array((1,1),(6,6)) [(l, Nothing) | l <- locations]
solve
:: Mesh
-> Maybe Mesh
solve m
| completed m = Just m
| otherwise = find completed
[s
| Just s
<- spread
] where
completed
= (all $ isJust
. snd) . assocs
emp_locs = [l | (l, Nothing) <- assocs m]
easy
_to
_head
= sortBy
. comparing
$ length . snd filling
= easy
_to
_head
$ zip emp
_locs
$ map (candidates m
) emp
_locs
spread = spread' -- `debugMesh` m
spread' = map solve
[m
// [(loc
, Just x
)] | (loc
, xs
) <- filling
, x
<- xs
]
candidates
:: Mesh
-> Loc
-> [Int]candidates m loc@(x,y) = let
block
= [b
| b
@(_, ls
) <- blocks
, loc `
elem` ls
] block
_avails
= concat $ map (blockCandidates m
) block
row_constraint = fixedVals m $ (,) <$> [x] <*> ans
col_constraint = fixedVals m $ (,) <$> ans <*> [y]
ret = block_avails \\ (row_constraint ++ col_constraint)
in ret -- `debug` (loc,block_avails,"row",row_constraint,"col",col_constraint,ret)
blockCandidates
:: Mesh
-> Block
-> [Int]blockCandidates m (Sum s, ls) = let
rest
_sum
= s
- (sum $ fixedVals m ls
) ret
= concat $ filter (\ xs
-> sum xs
== rest
_sum
) $ combinations rest
_num ans
in ret -- `debug` ((Sum s,ls),"fixed",fixedVals m ls,"rest_num",rest_num,"rest_sum",rest_sum,ret)
fixedVals
:: Mesh
-> [Loc
] -> [Int]fixedVals m ls = [ n | Just n <- [m ! l | l <- ls]]
combinations
:: Int -> [a
] -> [[a
]]combinations 0 _ = [[]]
combinations _ [] = []
combinations n xs@(y:ys)
| n < 0 = []
[] -> []
[_] -> [xs]
_ -> [y:c | c <- combinations (n-1) ys] ++ combinations n ys
splitEvery
:: Int -> [a
] -> [[a
]]splitEvery _ [] = []
splitEvery n list
= first :
(splitEvery n rest
) where (first
,rest
) = splitAt n list
showMesh
:: Mesh
-> [[String]]showMesh m
= transpose
$ splitEvery
6 [maybe " " show x
| (_, x
) <- assocs m
]
debugMesh :: a -> Mesh -> a
debugMesh f m
= foldr traceShow
(trace
"----" f
) $ showMesh m
debug
:: Show a
=> c
-> a
-> c
LS0gaHR0cDovL3AuLi5jb250ZW50LWF2YWlsYWJsZS10by1hdXRob3Itb25seS4uLmgubmV0L3Rlc3QvcmVhZC5jZ2kvdGVjaC8xMjI2MjI5NjI3LzMxNwppbXBvcnQgQ29udHJvbC5BcHBsaWNhdGl2ZQppbXBvcnQgRGF0YS5Nb25vaWQKaW1wb3J0IERhdGEuQXJyYXkgKEFycmF5LGFycmF5LGFzc29jcywoLy8pLCghKSkKaW1wb3J0IERhdGEuTWF5YmUgKGlzSnVzdCkKaW1wb3J0IERhdGEuTGlzdCAoZmluZCxzb3J0QnksdHJhbnNwb3NlLChcXCkpCmltcG9ydCBEYXRhLk9yZCAoY29tcGFyaW5nKQppbXBvcnQgRGVidWcuVHJhY2UKCnR5cGUgTG9jID0gKEludCwgSW50KQp0eXBlIE1lc2ggPSBBcnJheSBMb2MgKE1heWJlIEludCkKdHlwZSBCbG9jayA9IChTdW0gSW50LCBbTG9jXSkKCmFucyA6OiBbSW50XQphbnMgPSBbMS4uNl0KCmxvY2F0aW9ucyA6OiBbTG9jXQpsb2NhdGlvbnMgPSAoLCkgPCQ+IGFucyA8Kj4gYW5zCgpibG9ja3MgOjogW0Jsb2NrXQpibG9ja3MgPSBbCiAgICAoU3VtICAzLCBbKDEsMSksKDEsMildKQogICwgKFN1bSAgNCwgWygyLDEpXSkKICAsIChTdW0gMTMsIFsoMywxKSwoMywyKSwoMywzKV0pCiAgLCAoU3VtICA1LCBbKDQsMSksKDUsMSldKQogICwgKFN1bSAgOCwgWyg2LDEpLCg2LDIpXSkKICAsIChTdW0gIDcsIFsoMiwyKSwoMiwzKV0pCiAgLCAoU3VtICAxLCBbKDQsMildKQogICwgKFN1bSAgNywgWyg1LDIpLCg1LDMpXSkKICAsIChTdW0gMTEsIFsoMSwzKSwoMSw0KV0pCiAgLCAoU3VtICA3LCBbKDQsMyksKDQsNCldKQogICwgKFN1bSAgNiwgWyg2LDMpXSkKICAsIChTdW0gIDYsIFsoMiw0KSwoMyw0KV0pCiAgLCAoU3VtICA2LCBbKDUsNCksKDYsNCldKQogICwgKFN1bSAgOSwgWygxLDUpLCgyLDUpXSkKICAsIChTdW0gIDYsIFsoMyw1KSwoNCw1KV0pCiAgLCAoU3VtICA0LCBbKDUsNSldKQogICwgKFN1bSAgMywgWyg2LDUpLCg2LDYpXSkKICAsIChTdW0gIDQsIFsoMSw2KV0pCiAgLCAoU3VtICA1LCBbKDIsNiksKDMsNildKQogICwgKFN1bSAxMSwgWyg0LDYpLCg1LDYpXSkKICBdCm1haW4gOjogSU8gKCkKbWFpbiA9IGNhc2Ugc29sdmUgbmV3X21lc2ggb2YKICAgIE5vdGhpbmcgLT4gcHJpbnQgImNhbid0IHNvbHZlIGl0LiIKICAgIEp1c3QgbSAtPiBtYXBNXyBwcmludCAkIHNob3dNZXNoIG0KICB3aGVyZSBuZXdfbWVzaCA9IGFycmF5KCgxLDEpLCg2LDYpKSBbKGwsIE5vdGhpbmcpIHwgbCA8LSBsb2NhdGlvbnNdCgpzb2x2ZSA6OiBNZXNoIC0+IE1heWJlIE1lc2gKc29sdmUgbQogIHwgY29tcGxldGVkIG0gPSBKdXN0IG0KICB8IG90aGVyd2lzZSA9IGZpbmQgY29tcGxldGVkIFtzIHwgSnVzdCBzIDwtIHNwcmVhZF0KICB3aGVyZQogICAgY29tcGxldGVkID0gKGFsbCAkIGlzSnVzdCAuIHNuZCkgLiBhc3NvY3MKICAgIGVtcF9sb2NzID0gW2wgfCAobCwgTm90aGluZykgPC0gYXNzb2NzIG1dCiAgICBlYXN5X3RvX2hlYWQgPSBzb3J0QnkgLiBjb21wYXJpbmcgJCBsZW5ndGggLiBzbmQKICAgIGZpbGxpbmcgPSBlYXN5X3RvX2hlYWQgJCB6aXAgZW1wX2xvY3MgJCBtYXAgKGNhbmRpZGF0ZXMgbSkgZW1wX2xvY3MKICAgIHNwcmVhZCA9IHNwcmVhZCcgLS0gYGRlYnVnTWVzaGAgbSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgIHNwcmVhZCcgPSBtYXAgc29sdmUgW20gLy8gWyhsb2MsIEp1c3QgeCldIHwgKGxvYywgeHMpIDwtIGZpbGxpbmcsIHggPC0geHNdCgpjYW5kaWRhdGVzIDo6IE1lc2ggLT4gTG9jIC0+IFtJbnRdCmNhbmRpZGF0ZXMgbSBsb2NAKHgseSkgPSBsZXQKICAgIGJsb2NrID0gW2IgfCBiQChfLCBscykgPC0gYmxvY2tzLCBsb2MgYGVsZW1gIGxzXQogICAgYmxvY2tfYXZhaWxzID0gY29uY2F0ICQgbWFwIChibG9ja0NhbmRpZGF0ZXMgbSkgYmxvY2sKICAgIHJvd19jb25zdHJhaW50ID0gZml4ZWRWYWxzIG0gJCAoLCkgPCQ+IFt4XSA8Kj4gYW5zCiAgICBjb2xfY29uc3RyYWludCA9IGZpeGVkVmFscyBtICQgKCwpIDwkPiBhbnMgPCo+IFt5XQogICAgcmV0ID0gYmxvY2tfYXZhaWxzIFxcIChyb3dfY29uc3RyYWludCArKyBjb2xfY29uc3RyYWludCkKICBpbiByZXQgLS0gYGRlYnVnYCAobG9jLGJsb2NrX2F2YWlscywicm93Iixyb3dfY29uc3RyYWludCwiY29sIixjb2xfY29uc3RyYWludCxyZXQpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKCmJsb2NrQ2FuZGlkYXRlcyA6OiBNZXNoIC0+IEJsb2NrIC0+IFtJbnRdCmJsb2NrQ2FuZGlkYXRlcyBtIChTdW0gcywgbHMpID0gbGV0CiAgICByZXN0X251bSA9IGxlbmd0aCBscyAtIChsZW5ndGggJCBmaXhlZFZhbHMgbSBscykKICAgIHJlc3Rfc3VtID0gcyAtIChzdW0gJCBmaXhlZFZhbHMgbSBscykKICAgIHJldCA9IGNvbmNhdCAkIGZpbHRlciAoXCB4cyAtPiBzdW0geHMgPT0gcmVzdF9zdW0pICQgY29tYmluYXRpb25zIHJlc3RfbnVtIGFucwogIGluIHJldCAtLSBgZGVidWdgICgoU3VtIHMsbHMpLCJmaXhlZCIsZml4ZWRWYWxzIG0gbHMsInJlc3RfbnVtIixyZXN0X251bSwicmVzdF9zdW0iLHJlc3Rfc3VtLHJldCkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAoKZml4ZWRWYWxzIDo6IE1lc2ggLT4gW0xvY10gLT4gW0ludF0KZml4ZWRWYWxzIG0gbHMgPSBbIG4gfCBKdXN0IG4gPC0gW20gISBsIHwgbCA8LSBsc11dCgpjb21iaW5hdGlvbnMgOjogSW50IC0+IFthXSAtPiBbW2FdXQpjb21iaW5hdGlvbnMgMCBfID0gW1tdXQpjb21iaW5hdGlvbnMgXyBbXSA9IFtdCmNvbWJpbmF0aW9ucyBuIHhzQCh5OnlzKQogIHwgbiA8IDAgPSBbXQogIHwgb3RoZXJ3aXNlID0gY2FzZSBkcm9wIChuLTEpIHhzIG9mCiAgICBbXSAtPiBbXQogICAgW19dIC0+IFt4c10KICAgIF8gLT4gW3k6YyB8IGMgPC0gY29tYmluYXRpb25zIChuLTEpIHlzXSArKyBjb21iaW5hdGlvbnMgbiB5cwoKc3BsaXRFdmVyeSA6OiBJbnQgLT4gW2FdIC0+IFtbYV1dCnNwbGl0RXZlcnkgXyBbXSA9IFtdCnNwbGl0RXZlcnkgbiBsaXN0ID0gZmlyc3QgOiAoc3BsaXRFdmVyeSBuIHJlc3QpICB3aGVyZSAoZmlyc3QscmVzdCkgPSBzcGxpdEF0IG4gbGlzdAoKc2hvd01lc2ggOjogTWVzaCAtPiBbW1N0cmluZ11dCnNob3dNZXNoIG0gPSB0cmFuc3Bvc2UgJCBzcGxpdEV2ZXJ5IDYgW21heWJlICIgIiBzaG93IHggfCAoXywgeCkgPC0gYXNzb2NzIG1dCgpkZWJ1Z01lc2ggOjogYSAtPiBNZXNoIC0+IGEKZGVidWdNZXNoIGYgbSA9IGZvbGRyIHRyYWNlU2hvdyAodHJhY2UgIi0tLS0iIGYpICQgc2hvd01lc2ggbQoKZGVidWcgOjogU2hvdyBhID0+IGMgLT4gYSAtPiBjCmRlYnVnID0gZmxpcCB0cmFjZVNob3c=