-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathleap.idr
74 lines (52 loc) · 2.24 KB
/
leap.idr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
{-
We'd like to prove that:
isLeapYear year =
(mod year 4 == 0) && ((mod year 400 == 0) || not (mod year 100 == 0))
is equivalent to:
isLeapYear year = mod year 4 == 0 && mod year 100 /= 0 || mod year 400 == 0
by proving that the only case where they're not equivalent (when the year is
divisible by 400 but not by 4) is impossible. In other words, proving that if
a year is divisible by 400 then it's divisible by 4.
-}
-- Props ----------------------------------------------------------------------
leap : (year : Integer) ->
let p = mod year 4 == 0
q = mod year 100 == 0
r = mod year 400 == 0
v = mod year 100 /= 0
in
p && (r || not q) = p && v || r
pqr : {p, q, r : Bool} -> r && not p = False -> p && (r || q) = p && q || r
-- Can't do much with Integer and mod ...
axiom : {n : Integer} -> mod n 400 == 0 && not (mod n 4 == 0) = False
-- ... So let's prove an "equivalent" theorem that uses more friendly encodings
equiv : {n : Nat} -> (k ** n = 400 * k) -> (k ** n = 4 * k)
-- Proofs ---------------------------------------------------------------------
leap y = pqr axiom
equiv (k ** h) = (100 * k ** rewrite h in masoc {n = 4} {m = 100})
where
mdist : {n, m : Nat} -> (n + m) * k = (n * k) + (m * k)
masoc : {n, m : Nat} -> (n * m) * k = n * (m * k)
pasoc : {n, m, k : Nat} -> (n + m) + k = n + (m + k)
pasoc {n = 0} = Refl
pasoc {n = S n} = cong S pasoc
masoc {n = 0} = Refl
masoc {n = S n} = rewrite mdist {n = m, m = n * m} in
rewrite masoc {n, m} in Refl
mdist {n = 0} = Refl
mdist {n = S n} = rewrite pasoc {n = k, m = n * k, k = m * k} in
rewrite mdist {n, m} in Refl
noth : {a : Bool} -> not a = False -> a = True
andh : {a, b : Bool} -> a && b = False -> Either (b = False) (a = False)
orcom : {a, b : Bool} -> a || b = b || a
pqr hyp with (andh hyp)
_| Right hr = rewrite hr in orcom
_| Left hnp = rewrite noth {a = p} $ hnp in orcom
noth {a = False} _ impossible
noth {a = True} _ = Refl
andh {a = False} _ = Right Refl
andh {b = False} _ = Left Refl
orcom {a = False, b = False} = Refl
orcom {a = False, b = True} = Refl
orcom {a = True, b = False} = Refl
orcom {a = True, b = True} = Refl