@@ -0,0 +1,248 @@
1+module Solver
2+
3+import Decidable.Equality
4+import Control.Monad.State
5+import Debug.Trace
6+
7+%default total
8+
9+Cell : Nat -> Type
10+Cell n = Maybe (Fin n)
11+
12+data Board : Nat -> Type where
13+ MkBoard : {n : Nat} -> Vect (Vect (Cell n) n) n -> Board n
14+
15+emptyBoard : Board n
16+emptyBoard {n=n} = MkBoard (replicate n (replicate n Nothing))
17+
18+showElt : Cell n -> String
19+showElt Nothing = "."
20+showElt (Just x) = show (1 + (the Int (cast x)))
21+
22+showRow : Vect (Cell n) n -> String
23+showRow xs = unwords (toList (map showElt xs))
24+
25+unlines : Vect String n -> String
26+unlines Nil = ""
27+unlines (l::Nil) = l
28+unlines (l::ls) = pack (foldl addLine (unpack l) (map unpack ls))
29+ where
30+ addLine : List Char -> List Char -> List Char
31+ addLine w s = w ++ ('\n' :: s)
32+
33+instance Show (Board n) where
34+ show (MkBoard rs) = unlines (map showRow rs)
35+
36+updateAt : Fin n -> Vect a n -> (a -> a) -> Vect a n
37+updateAt fO (x::xs) f = f x :: xs
38+updateAt (fS i) (x::xs) f = x :: updateAt i xs f
39+
40+setCell : Board n -> (Fin n, Fin n) -> Fin n -> Board n
41+setCell (MkBoard b) (x, y) value = MkBoard (updateAt y b (\row => updateAt x row (const (Just value))))
42+
43+getCell : Board n -> (Fin n, Fin n) -> Cell n
44+getCell (MkBoard b) (x, y) = index x (index y b)
45+
46+data Any : (P : a -> Type) -> Vect a n -> Type where
47+ Here : {P : a -> Type} -> {xs : Vect a n} -> P x -> Any P (x :: xs)
48+ There : {P : a -> Type} -> {xs : Vect a n} -> Any P xs -> Any P (x :: xs)
49+
50+anyNilAbsurd : {P : a -> Type} -> Any P Nil -> _|_
51+anyNilAbsurd Here impossible
52+anyNilAbsurd There impossible
53+
54+anyElim : {xs : Vect a n} -> {P : a -> Type} -> (Any P xs -> b) -> (P x -> b) -> Any P (x :: xs) -> b
55+anyElim _ f (Here p) = f p
56+anyElim f _ (There p) = f p
57+
58+any : {P : a -> Type} -> ((x : a) -> Dec (P x)) -> (xs : Vect a n) -> Dec (Any P xs)
59+any _ Nil = No anyNilAbsurd
60+any p (x::xs) with (p x)
61+ | Yes prf = Yes (Here prf)
62+ | No prf =
63+ case any p xs of
64+ Yes prf' => Yes (There prf')
65+ No prf' => No (anyElim prf' prf)
66+
67+Not : Type -> Type
68+Not a = a -> _|_
69+
70+data All : (P : a -> Type) -> Vect a n -> Type where
71+ Nil : {P : a -> Type} -> All P Nil
72+ (::) : {P : a -> Type} -> {xs : Vect a n} -> P x -> All P xs -> All P (x :: xs)
73+
74+negAnyAll : {P : a -> Type} -> {xs : Vect a n} -> Not (Any P xs) -> All (\x => Not (P x)) xs
75+negAnyAll {xs=Nil} _ = Nil
76+negAnyAll {xs=(x::xs)} f = (\x => f (Here x)) :: negAnyAll (\x => f (There x))
77+
78+notAllHere : {P : a -> Type} -> {xs : Vect a n} -> (P x -> _|_) -> All P (x :: xs) -> _|_
79+notAllHere _ Nil impossible
80+notAllHere np (p :: _) = np p
81+
82+notAllThere : {P : a -> Type} -> {xs : Vect a n} -> (All P xs -> _|_) -> All P (x :: xs) -> _|_
83+notAllThere _ Nil impossible
84+notAllThere np (_ :: ps) = np ps
85+
86+all : {P : a -> Type} -> ((x : a) -> Dec (P x)) -> (xs : Vect a n) -> Dec (All P xs)
87+all _ Nil = Yes Nil
88+all d (x::xs) with (d x)
89+ | No prf = No (notAllHere prf)
90+ | Yes prf =
91+ case all d xs of
92+ Yes prf' => Yes (prf :: prf')
93+ No prf' => No (notAllThere prf')
94+
95+getRow : Fin n -> Board n -> Vect (Cell n) n
96+getRow i (MkBoard b) = index i b
97+
98+getCol : Fin n -> Board n -> Vect (Cell n) n
99+getCol i (MkBoard b) = helper i b
100+ where
101+ helper : Fin n -> Vect (Vect a n) m -> Vect a m
102+ helper _ Nil = Nil
103+ helper i (xs::xss) = index i xs :: helper i xss
104+
105+LegalNeighbors : Cell n -> Cell n -> Type
106+LegalNeighbors (Just x) (Just y) = Not (x = y)
107+LegalNeighbors _ _ = ()
108+
109+legalNeighbors : (x : Cell n) -> (y : Cell n) -> Dec (LegalNeighbors x y)
110+legalNeighbors (Just x) (Just y) with (decEq x y)
111+ | Yes prf = No (\pf => pf prf)
112+ | No prf = Yes prf
113+legalNeighbors Nothing (Just _) = Yes ()
114+legalNeighbors (Just _) Nothing = Yes ()
115+legalNeighbors Nothing Nothing = Yes ()
116+
117+rowSafe : (b : Board n) -> (r : Fin n) -> (val : Fin n) -> Dec (All (LegalNeighbors (Just val)) (getRow r b))
118+rowSafe b r v = all (legalNeighbors (Just v)) (getRow r b)
119+
120+colSafe : (b : Board n) -> (r : Fin n) -> (val : Fin n) -> Dec (All (LegalNeighbors (Just val)) (getCol r b))
121+colSafe b r v = all (legalNeighbors (Just v)) (getCol r b)
122+
123+Empty : Cell n -> Type
124+Empty {n=n} x = (the (Cell n) Nothing) = x
125+
126+empty : (cell : Cell n) -> Dec (Empty cell)
127+empty Nothing = Yes refl
128+empty (Just _) = No nothingNotJust
129+
130+-- Predicate for legal cell assignments
131+LegalVal : Board n -> (Fin n, Fin n) -> Fin n -> Type
132+LegalVal b (x, y) val = (Empty (getCell b (x, y)), All (LegalNeighbors (Just val)) (getCol x b), All (LegalNeighbors (Just val)) (getRow y b))
133+
134+legalVal : (b : Board n) -> (coord : (Fin n, Fin n)) -> (val : Fin n) -> Dec (LegalVal b coord val)
135+legalVal b (x, y) v =
136+ case rowSafe b y v of
137+ No prf => No (\(_, _, rf) => prf rf)
138+ Yes prf =>
139+ case colSafe b x v of
140+ No prf' => No (\(_, cf, _) => prf' cf)
141+ Yes prf' =>
142+ case empty (getCell b (x, y)) of
143+ No prf'' => No (\(ef, _, _) => prf'' ef)
144+ Yes prf'' => Yes (prf'', prf', prf)
145+
146+
147+Filled : Cell n -> Type
148+--Filled {n=n} x = Not (Empty x) -- TODO: Find out why this doesn't work
149+Filled {n=n} = (\x => Not (Empty x))
150+--Filled {n=n} x = the (Maybe (Fin n)) Nothing = x -> _|_
151+--Filled {n=n} = \x => the (Maybe (Fin n)) Nothing = x -> _|_
152+
153+filled : (cell : Cell n) -> Dec (Filled cell)
154+filled Nothing = No (\f => f refl)
155+filled (Just _) = Yes nothingNotJust
156+
157+FullBoard : Board n -> Type
158+FullBoard (MkBoard b) = All (All Filled) b
159+
160+fullBoard : (b : Board n) -> Dec (FullBoard b)
161+fullBoard (MkBoard b) = all (all filled) b
162+
163+fins : Vect (Fin n) n
164+fins {n=O} = Nil
165+fins {n=(S m)} = last :: map weaken fins
166+
167+data LegalBoard : Board n -> Type where
168+ Base : LegalBoard (emptyBoard {n})
169+ Step : {b : Board n} -> {coords : (Fin n, Fin n)} -> {v : Fin n} -> LegalVal b coords v -> LegalBoard b -> LegalBoard (setCell b coords v)
170+
171+CompleteBoard : Board n -> Type
172+CompleteBoard b = (LegalBoard b, FullBoard b)
173+
174+indexStep : {i : Fin n} -> {xs : Vect a n} -> {x : a} -> index i xs = index (fS i) (x::xs)
175+indexStep = refl
176+
177+find : {P : a -> Type} -> ((x : a) -> Dec (P x)) -> (xs : Vect a n)
178+ -> Either (All (\x => Not (P x)) xs) (y : a ** (P y, (i : Fin n ** y = index i xs)))
179+find _ Nil = Left Nil
180+find d (x::xs) with (d x)
181+ | Yes prf = Right (x ** (prf, (fO ** refl)))
182+ | No prf =
183+ case find d xs of
184+ Right (y ** (prf', (i ** prf''))) =>
185+ Right (y ** (prf', (fS i ** replace (indexStep {x=x}) prf'')))
186+ Left prf' => Left (prf::prf')
187+
188+findEmptyInRow : (xs : Vect (Cell n) n) -> Either (All Filled xs) (i : Fin n ** Empty (index i xs))
189+findEmptyInRow xs =
190+ case find {P=Empty} empty xs of
191+ Right (_ ** (pempty, (i ** pidx))) => Right (i ** trans pempty pidx)
192+ Left p => Left p
193+
194+emptyCell : (b : Board n) -> Either (FullBoard b) (c : (Fin n, Fin n) ** Empty (getCell b c))
195+emptyCell (MkBoard rs) =
196+ case helper rs of
197+ Left p => Left p
198+ Right (ri ** (ci ** pf)) => Right ((ci, ri) ** pf)
199+ where
200+ helper : (rs : Vect (Vect (Cell n) n) m)
201+ -> Either (All (All Filled) rs) (r : Fin m ** (c : Fin n ** Empty (index c (index r rs))))
202+ helper Nil = Left Nil
203+ helper (r::rs) =
204+ case findEmptyInRow r of
205+ Right (ci ** pf) => Right (fO ** (ci ** pf))
206+ Left prf =>
207+ case helper rs of
208+ Left prf' => Left (prf::prf')
209+ Right (ri ** (ci ** pf)) => Right (fS ri ** (ci ** pf))
210+
211+
212+tryValue : {b : Board (S n)} -> LegalBoard b -> (c : (Fin (S n), Fin (S n))) -> Empty (getCell b c) -> (v : Fin (S n))
213+ -> Either (Not (LegalVal b c v)) (b' : Board (S n) ** LegalBoard b')
214+tryValue {b=b} l c _ v =
215+ case legalVal b c v of
216+ No prf => Left prf
217+ Yes prf => Right (_ ** Step prf l)
218+
219+nullBoardFull : (b : Board O) -> FullBoard b
220+nullBoardFull (MkBoard Nil) = Nil
221+
222+-- TODO: Prove complete by induction on illegal values wrt. some base state, e.g. every value is illegal for 123\21_\312
223+fillBoard : (b : Board n) -> LegalBoard b -> Maybe (b' : Board n ** CompleteBoard b')
224+fillBoard {n=O} b l = Just (b ** (l, nullBoardFull b))
225+fillBoard {n=(S n)} b l with (emptyCell b)
226+ | Left full = Just (b ** (l, full))
227+ | Right (coords ** p) = recurse last
228+ where
229+ %assert_total
230+ tryAll : (v : Fin (S n)) -> (Fin (S n), Maybe (b' : Board (S n) ** LegalBoard b'))
231+ tryAll v = --trace ("Trying " ++ show (the Int (cast v))) $
232+ case tryValue l coords p v of
233+ Right success => (v, Just success)
234+ Left _ => -- TODO: Prove unsolvable
235+ case v of
236+ fS k => tryAll (weaken k)
237+ fO => (v, Nothing)
238+
239+ %assert_total
240+ recurse : Fin (S n) -> Maybe (b' : Board (S n) ** CompleteBoard b')
241+ recurse start =
242+ case tryAll start of
243+ (_, Nothing) => Nothing
244+ (fO, Just (b' ** l')) => fillBoard b' l'
245+ (fS next, Just (b' ** l')) =>
246+ case fillBoard b' l' of
247+ Just solution => Just solution
248+ Nothing => recurse (weaken next)