Built with Alectryon, running Coq+SerAPI v8.13.0+0.13.0. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus. On Mac, use instead of Ctrl.
Notation "[ rel _ _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ : _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ & _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ & _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ | _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "[ rel _ _ in _ ]" was already used in scope fun_scope. [notation-overridden,parsing]
Notation "_ + _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ - _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ <= _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ < _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ >= _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ > _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ <= _ <= _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ < _ <= _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ <= _ < _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ < _ < _" was already used in scope nat_scope. [notation-overridden,parsing]
Notation "_ * _" was already used in scope nat_scope. [notation-overridden,parsing]
From hanoi Require Import extra gdist ghanoi ghanoi3. Set Implicit Arguments. Unset Strict Implicit. Unset Printing Implicit Defensive. Section Hanoi3. (*****************************************************************************) (* The pegs are the three elements of 'I_3 *) (*****************************************************************************) Implicit Type p : peg 3. Local Notation "c1 `-->_r c2" := (rmove c1 c2) (format "c1 `-->_r c2", at level 60). Local Notation "c1 `-->*_r c2" := (connect rmove c1 c2) (format "c1 `-->*_r c2", at level 60). (******************************************************************************) (* Function that builds a path from peg to peg *) (******************************************************************************) Fixpoint ppeg {n : nat} p1 p2 := if n isn't n1.+1 return seq (configuration 3 n) then [::] else let p3 := `p[p1, p2] in [seq ↑[i]_p1 | i <- ppeg p1 p3] ++ [seq ↑[i]_p2 | i <- `c[p3] :: ppeg p3 p2].
n:nat
p1, p2:peg 3

size (ppeg p1 p2 : seq (configuration 3 n)) = (2 ^ n).-1
2
5
IH:forall p1 p2, size (ppeg p1 p2) = (2 ^ n).-1
6

size ([seq ↑[i]_p1 | i <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2]) = (2 ^ n.+1).-1
c
(2 ^ n).-1 + (2 ^ n).-1.+1 = (2 ^ n + 2 ^ n).-1
by rewrite -(prednK (_ : 0 < 2 ^ n)) // expn_gt0. Qed.
56
c:configuration 3 n
cs:=ppeg p1 p2 : seq (configuration 3 n):seq (configuration 3 n)

last c cs = `c[p2]
14
561718
HH:irreflexive (rrel (n:=3))

19
1f
p2:peg 3
c:configuration 3 0

c = `c[p2]
1f5
IH:forall p1 p2 (c : configuration 3 n), last c (ppeg p1 p2) = `c[p2]
6
c:configuration 3 n.+1
last c ([seq ↑[i]_p1 | i <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2]) = `c[p2]
29
2c
by rewrite last_cat /= last_map IH perfect_liftr. Qed.
5618

p1 != p2 -> path rmove `c[p1] cs
31
56181f

34
1f5
IH:forall p1 p2, p1 != p2 -> path rmove `c[p1] (ppeg p1 p2)
6
p1Dp2:p1 != p2

path rmove `c[p1] ([seq ↑[i]_p1 | i <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2])
1f53e63f
p3:=`p[p1, p2]:peg 3

path rmove `c[p1] ([seq ↑[i]_p1 | i <- ppeg p1 p3] ++ ↑[`c[p3]]_p2 :: [seq ↑[i]_p2 | i <- ppeg p3 p2])
1f53e63f45
p1Dp3:p1 != p3

46
1f53e63f454b
p3Dp2:p3 != p2

46
4f
[&& path (move (rrel (n:=3))) `c[p1] (ppeg p1 p3), last `c[p1] [seq ↑[i]_p1 | i <- ppeg p1 p3] `-->_r ↑[`c[p3]]_p2 & path (move (rrel (n:=3))) `c[p3] (ppeg p3 p2)]
4f
last `c[p1] [seq ↑[i]_p1 | i <- ppeg p1 p3] `-->_r ↑[`c[p3]]_p2
4f
↑[`c[p3]]_p1 `-->_r ↑[`c[p3]]_p2
by apply: move_liftr_perfect; rewrite // eq_sym opegDr. Qed. (* We can go from any perfect configuration to a perfect configuration *)
4
`c[p1 , n] `-->*_r `c[p2]
5e
563f

`c[p1] `-->*_r `c[p2]
65
`c[p2] = last `c[p1] (ppeg p1 p2)
by rewrite last_ppeg. Qed. (* The proof is done by inspecting the moves that the last disk is doing in cs*) (* We use a double induction : *) (* The first induction is used when the path has duplicates *) (* The second induction is on n and to bound recursive call *)
56
cs:seq (configuration 3 n)

p1 != p2 -> path rmove `c[p1] cs -> last `c[p1] cs = `c[p2] -> (2 ^ n).-1 <= size cs ?= iff (cs == ppeg p1 p2)
6c
566f
irrH:irreflexive (rrel (n:=3))
symH:symmetric (rrel (n:=3))

70
(* The first induction is used when the path has duplicates (1 case) *)
7677
m:nat
IHm:forall (n : nat) p1 p2 (cs : seq (configuration 3 n)), size cs < m -> p1 != p2 -> path rmove `c[p1] cs -> last `c[p1] cs = `c[p2] -> (2 ^ n).-1 <= size cs ?= iff (cs == ppeg p1 p2)
566f
sLm:size cs < m.+1

70
76777c7d5
IH:forall p1 p2 (cs : seq (configuration 3 n)), size cs < m.+1 -> p1 != p2 -> path rmove `c[p1] cs -> last `c[p1] cs = `c[p2] -> (2 ^ n).-1 <= size cs ?= iff (cs == ppeg p1 p2)
6
cs:seq (configuration 3 n.+1)
7e3f

path rmove `c[p1] cs -> last `c[p1] cs = `c[p2] -> (2 ^ n.+1).-1 <= size cs ?= iff (cs == [seq ↑[i]_p1 | i <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2])
82
size ([seq ↑[i]_p1 | i <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2]) = (2 ^ n.+1).-1 -> path rmove `c[p1] cs -> last `c[p1] cs = `c[p2] -> (2 ^ n.+1).-1 <= size cs ?= iff (cs == [seq ↑[i]_p1 | i <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2])
(* Is there a move of the last first disk *)
82
let c' := ↓[`c[p1]] in let cs' := [seq ↓[i] | i <- cs] in let p := `c[p1] ldisk in cs = [seq ↑[i]_p | i <- cs'] -> path (move (rrel (n:=3))) c' cs' -> size ([seq ↑[i0]_p1 | i0 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i0]_p2 | i0 <- ppeg `p[p1, p2] p2]) = (2 ^ n.+1).-1 -> true -> last `c[p1] cs = `c[p2] -> (2 ^ n.+1).-1 <= size cs ?= iff (cs == [seq ↑[i0]_p1 | i0 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i0]_p2 | i0 <- ppeg `p[p1, p2] p2])
82
forall (cs1 : seq (configuration 3 n)) (cs2 : seq (configuration 3 n.+1)), let p3 := `c[p1] ldisk in forall p4, let p5 := `p[p3, p4] in let c1 := ↓[`c[p1]] in let c2 := ↑[`c[p5]]_p4 in p3 != p4 -> rrel p3 p4 -> last c1 cs1 = `c[p5] -> cs = [seq ↑[i1]_p3 | i1 <- cs1] ++ c2 :: cs2 -> path (move (rrel (n:=3))) c1 cs1 -> path (move (rrel (n:=3))) c2 cs2 -> size ([seq ↑[i3]_p1 | i3 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i3]_p2 | i3 <- ppeg `p[p1, p2] p2]) = (2 ^ n.+1).-1 -> true -> last `c[p1] cs = `c[p2] -> (2 ^ n.+1).-1 <= size cs ?= iff (cs == [seq ↑[i3]_p1 | i3 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [ seq ↑[i3]_p2 | i3 <- ppeg `p[p1, p2] p2])
(* No move : impossible since p1 != p2 *)
76777c7d58363f

`c[p1] ldisk == `c[p2] ldisk -> (2 ^ n.+1).-1 <= 0 ?= iff ([::] == [seq ↑[i]_p1 | i <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2])
76777c7d58363f
a:configuration 3 n.+1
84
sLm:(size cs).+1 < m.+1
a :: cs = ↑[↓[a]]_(`c[p1] ldisk) :: [seq ↑[i]_(`c[p1] ldisk) | i <- [seq ↓[i] | i <- cs]] -> move (rrel (n:=3)) ↓[`c[p1]] ↓[a] && path (move (rrel (n:=3))) ↓[a] [seq ↓[i] | i <- cs] -> size ([seq ↑[i0]_p1 | i0 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i0]_p2 | i0 <- ppeg `p[p1, p2] p2]) = (2 ^ n.+1).-1 -> true -> last a cs = `c[p2] -> (2 ^ n.+1).-1 <= (size cs).+1 ?= iff (a :: cs == [seq ↑[i0]_p1 | i0 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [ seq ↑[i0]_p2 | i0 <- ppeg `p[p1, p2] p2])
8f
98
a :: cs = ↑[↓[a]]_(`c[p1] ldisk) :: [seq ↑[i]_(`c[p1] ldisk) | i <- [seq ↓[i] | i <- cs]] -> move (rrel (n:=3)) ↓[`c[p1]] ↓[a] && path (move (rrel (n:=3))) ↓[a] [seq ↓[i] | i <- cs] -> size ([seq ↑[i0]_p1 | i0 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i0]_p2 | i0 <- ppeg `p[p1, p2] p2]) = (2 ^ n.+1).-1 -> true -> last a cs = `c[p2] -> (2 ^ n.+1).-1 <= (size cs).+1 ?= iff (a :: cs == [seq ↑[i0]_p1 | i0 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i0]_p2 | i0 <- ppeg `p[p1, p2] p2])
8e
76777c7d58363f99849a
acsE:a :: cs = ↑[↓[a]]_p1 :: [seq ↑[i]_p1 | i <- [seq ↓[i] | i <- cs]]
lacsE:last a cs = `c[p2]

(2 ^ n.+1).-1 <= (size cs).+1 ?= iff (a :: cs == [seq ↑[i]_p1 | i <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2])
8e
a3
last a cs \in a :: cs -> (2 ^ n.+1).-1 <= (size cs).+1 ?= iff (a :: cs == [seq ↑[i]_p1 | i <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2])
8e
a3
`c[p2] ldisk == ↑[↓[a]]_p1 ldisk -> (2 ^ n.+1).-1 <= (size cs).+1 ?= iff (↑[↓[a]]_p1 :: [seq ↑[i]_p1 | i <- [seq ↓[i] | i <- cs]] == [seq ↑[i]_p1 | i <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2])
a3
`c[p2] \in [seq ↑[i]_p1 | i <- [seq ↓[i] | i <- cs]] -> (2 ^ n.+1).-1 <= (size cs).+1 ?= iff (↑[↓[a]]_p1 :: [ seq ↑[i]_p1 | i <- [ seq ↓[i] | i <- cs]] == [seq ↑[i]_p1 | i <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [ seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2])
8f
a3
`c[p2] \in [seq ↑[i]_p1 | i <- [seq ↓[i] | i <- cs]] -> (2 ^ n.+1).-1 <= (size cs).+1 ?= iff (↑[↓[a]]_p1 :: [seq ↑[i]_p1 | i <- [seq ↓[i] | i <- cs]] == [seq ↑[i]_p1 | i <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2])
8e
76777c7d58363f99849aa4a5
c:finfun_eqType (ordinal_finType n) (ordinal_eqType 3)

`c[p2] ldisk == ↑[c]_p1 ldisk -> (2 ^ n.+1).-1 <= (size cs).+1 ?= iff (↑[↓[a]]_p1 :: [seq ↑[i]_p1 | i <- [seq ↓[i] | i <- cs]] == [seq ↑[i]_p1 | i <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2])
8e
82
forall (cs1 : seq (configuration 3 n)) (cs2 : seq (configuration 3 n.+1)), let p3 := `c[p1] ldisk in forall p4, let p5 := `p[p3, p4] in let c1 := ↓[`c[p1]] in let c2 := ↑[`c[p5]]_p4 in p3 != p4 -> rrel p3 p4 -> last c1 cs1 = `c[p5] -> cs = [seq ↑[i1]_p3 | i1 <- cs1] ++ c2 :: cs2 -> path (move (rrel (n:=3))) c1 cs1 -> path (move (rrel (n:=3))) c2 cs2 -> size ([seq ↑[i3]_p1 | i3 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i3]_p2 | i3 <- ppeg `p[p1, p2] p2]) = (2 ^ n.+1).-1 -> true -> last `c[p1] cs = `c[p2] -> (2 ^ n.+1).-1 <= size cs ?= iff (cs == [seq ↑[i3]_p1 | i3 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i3]_p2 | i3 <- ppeg `p[p1, p2] p2])
(* There is a move from p1 to p3 *)
76777c7d5836847e3f
cs1:seq (configuration 3 n)
cs2:seq (configuration 3 n.+1)
p3:peg 3
4b

last `c[p1] cs1 = `c[`p[p1, p3]] -> cs = [seq ↑[i]_p1 | i <- cs1] ++ ↑[`c[`p[p1, p3]]]_p3 :: cs2 -> path (move (rrel (n:=3))) `c[p1] cs1 -> path (move (rrel (n:=3))) ↑[`c[`p[p1, p3]]]_p3 cs2 -> size ([seq ↑[i1]_p1 | i1 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i1]_p2 | i1 <- ppeg `p[p1, p2] p2]) = (2 ^ n.+1).-1 -> true -> last `c[p1] cs = `c[p2] -> (2 ^ n.+1).-1 <= size cs ?= iff (cs == [seq ↑[i1]_p1 | i1 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i1]_p2 | i1 <- ppeg `p[p1, p2] p2])
76777c7d5836847e3fc4c5c64b
p1cs1Lp1p3:last `c[p1] cs1 = `c[`p[p1, p3]]
csE:cs = [seq ↑[i]_p1 | i <- cs1] ++ ↑[`c[`p[p1, p3]]]_p3 :: cs2
p1Pcs1:path (move (rrel (n:=3))) `c[p1] cs1

path (move (rrel (n:=3))) ↑[`c[`p[p1, p3]]]_p3 cs2 -> size ([seq ↑[i0]_p1 | i0 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i0]_p2 | i0 <- ppeg `p[p1, p2] p2]) = (2 ^ n.+1).-1 -> true -> last `c[p1] cs = `c[p2] -> (2 ^ n.+1).-1 <= size cs ?= iff (cs == [seq ↑[i0]_p1 | i0 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i0]_p2 | i0 <- ppeg `p[p1, p2] p2])
cb
size cs1 < m.+1
76777c7d5836847e3fc4c5c64bcccdce
Scs1:size cs1 < m.+1
path (move (rrel (n:=3))) ↑[`c[`p[p1, p3]]]_p3 cs2 -> size ([seq ↑[i0]_p1 | i0 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i0]_p2 | i0 <- ppeg `p[p1, p2] p2]) = (2 ^ n.+1).-1 -> true -> last `c[p1] cs = `c[p2] -> (2 ^ n.+1).-1 <= size cs ?= iff (cs == [seq ↑[i0]_p1 | i0 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [ seq ↑[i0]_p2 | i0 <- ppeg `p[p1, p2] p2])
d6
cf
76777c7d5836847e3fc4c5c64bcccdced7
p1Dp1p3:p1 != `p[p1, p3]

cf
(* After the first move, last disk is on p3, the other disk is `p[p1, p3] *)
76777c7d5836847e3fc4c5c64bcccdced7e0
HL1:(2 ^ n).-1 <= size cs1 ?= iff (cs1 == ppeg p1 `p[p1, p3])

cf
e4
(2 ^ n.+1).-1 = (2 ^ n).-1 + (2 ^ n).-1.+1
76777c7d5836847e3fc4c5c64bcccdced7e0e5
n2E:(2 ^ n.+1).-1 = (2 ^ n).-1 + (2 ^ n).-1.+1
d8
ec
cf
(* Is there another move *)
ec
cs2 = [seq ↑[i]_(↑[`c[`p[p1, p3]]]_p3 ldisk) | i <- [seq ↓[i] | i <- cs2]] -> path (move (rrel (n:=3))) ↓[↑[`c[`p[p1, p3]]]_p3] [seq ↓[i] | i <- cs2] -> true -> size ([seq ↑[i1]_p1 | i1 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i1]_p2 | i1 <- ppeg `p[p1, p2] p2]) = (2 ^ n.+1).-1 -> true -> last `c[p1] cs = `c[p2] -> (2 ^ n.+1).-1 <= size cs ?= iff (cs == [seq ↑[i1]_p1 | i1 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i1]_p2 | i1 <- ppeg `p[p1, p2] p2])
ec
forall (cs1 : seq (configuration 3 n)) (cs3 : seq (configuration 3 n.+1)) p4, ↑[`c[`p[p1, p3]]]_p3 ldisk != p4 -> rrel (↑[`c[`p[p1, p3]]]_p3 ldisk) p4 -> last ↓[↑[`c[`p[p1, p3]]]_p3] cs1 = `c[`p[↑[`c[`p[p1, p3]]]_p3 ldisk, p4]] -> cs2 = [seq ↑[i1]_(↑[`c[`p[p1, p3]]]_p3 ldisk) | i1 <- cs1] ++ ↑[`c[`p[↑[`c[`p[p1, p3]]]_p3 ldisk, p4]]]_p4 :: cs3 -> path (move (rrel (n:=3))) ↓[↑[`c[`p[p1, p3]]]_p3] cs1 -> path (move (rrel (n:=3))) ↑[`c[`p[↑[`c[`p[p1, p3]]]_p3 ldisk, p4]]]_p4 cs3 -> true -> size ([seq ↑[i4]_p1 | i4 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i4]_p2 | i4 <- ppeg `p[p1, p2] p2]) = (2 ^ n.+1).-1 -> true -> last `c[p1] cs = `c[p2] -> (2 ^ n.+1).-1 <= size cs ?= iff (cs == [seq ↑[i4]_p1 | i4 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [ seq ↑[i4]_p2 | i4 <- ppeg `p[p1, p2] p2])
(* there is no move so p3 = p2 and simple induction should make it *)
ec
cs2 = [seq ↑[i]_p3 | i <- [seq ↓[i] | i <- cs2]] -> path (move (rrel (n:=3))) `c[`p[p1, p3]] [seq ↓[i] | i <- cs2] -> true -> size ([seq ↑[i1]_p1 | i1 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i1]_p2 | i1 <- ppeg `p[p1, p2] p2]) = (2 ^ n.+1).-1 -> true -> last `c[p1] cs = `c[p2] -> (2 ^ n.+1).-1 <= size cs ?= iff (cs == [seq ↑[i1]_p1 | i1 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i1]_p2 | i1 <- ppeg `p[p1, p2] p2])
f5
76777c7d5836847e3fc4c5c64bcccdced7e0e5ed
cs2E:cs2 = [seq ↑[i]_p3 | i <- [seq ↓[i] | i <- cs2]]
p1p3Pcs2:path (move (rrel (n:=3))) `c[`p[p1, p3]] [seq ↓[i] | i <- cs2]
sH:size ([seq ↑[i]_p1 | i <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2]) = (2 ^ n.+1).-1
p1csLp2:last `c[p1] cs = `c[p2]

(2 ^ n.+1).-1 <= size cs ?= iff (cs == [seq ↑[i]_p1 | i <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2])
f5
ff
p3 = p2
76777c7d5836847e3fc4c5c64bcccdced7e0e5ed100101102103
p3E:p3 = p2
(2 ^ n.+1).-1 <= size cs ?= iff (cs == [seq ↑[i]_p1 | i <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [ seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2])
f6
76777c7d5836847e3fc4c5c64bcccdced7e0e5ed100101102

↑[last `c[`p[p1, p3]] [seq ↓[i] | i <- cs2]]_p3 = `c[p2] -> p3 = p2
109
10b
104
f5
76777c7d5836847e3fc4c5c64bced7e0ed10210310c
p1cs1Lp1p3:last `c[p1] cs1 = `c[`p[p1, p2]]
csE:cs = [seq ↑[i]_p1 | i <- cs1] ++ ↑[`c[`p[p1, p2]]]_p2 :: cs2
HL1:(2 ^ n).-1 <= size cs1 ?= iff (cs1 == ppeg p1 `p[p1, p2])
cs2E:cs2 = [seq ↑[i]_p2 | i <- [seq ↓[i] | i <- cs2]]
p1p3Pcs2:path (move (rrel (n:=3))) `c[`p[p1, p2]] [seq ↓[i] | i <- cs2]

104
f5
119
size [seq ↓[i] | i <- cs2] < m.+1
76777c7d5836847e3fc4c5c64bced7e0ed10210310c11a11b11c11d11e
Scs2:size [seq ↓[i] | i <- cs2] < m.+1
10d
f6
76777c7d5836843fc4c5c64bced7e0ed10210310c11a11b11c11d11e

size [seq ↓[i] | i <- cs2] < (size cs).+1
123
125
104
f5
125
last `c[`p[p1, p2]] [seq ↓[i] | i <- cs2] = `c[p2]
76777c7d5836847e3fc4c5c64bced7e0ed10210310c11a11b11c11d11e126
p1p2Lcs2:last `c[`p[p1, p2]] [seq ↓[i] | i <- cs2] = `c[p2]
10d
f6
125
↓[last ↑[`c[`p[p1, p2]]]_p2 cs2] = `c[p2]
133
135
104
f5
76777c7d5836847e3fc4c5c64bced7e0ed10210310c11a11b11c11d11e126136
HL2:(2 ^ n).-1 <= size [seq ↓[i] | i <- cs2] ?= iff ([seq ↓[i] | i <- cs2] == ppeg `p[p1, p2] p2)

104
f5
76777c7d5836847e3fc4c5c64bced7e0ed10210310c11a11b11d11e126136142
HL1:(2 ^ n).-1 = size cs1

(2 ^ n.+1).-1 <= size cs ?= iff (cs == [seq ↑[i]_p1 | i <- cs1] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2])
76777c7d5836847e3fc4c5c64bced7e0ed10210310c11a11b11d11e126136142
HL1:(2 ^ n).-1 < size cs1
10d
f6
76777c7d5836847e3fc4c5c64bced7e0ed10210310c11a11b11d11e126136147
HL2:(2 ^ n).-1 = size [seq ↓[i] | i <- cs2]

(2 ^ n.+1).-1 <= size cs ?= iff (cs == [seq ↑[i]_p1 | i <- cs1] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- [seq ↓[i] | i <- cs2]])
76777c7d5836847e3fc4c5c64bced7e0ed10210310c11a11b11d11e126136147
HL2:(2 ^ n).-1 < size [seq ↓[i] | i <- cs2]
(2 ^ n.+1).-1 <= size cs ?= iff (cs == [seq ↑[i]_p1 | i <- cs1] ++ ↑[`c[`p[p1, p2]]]_p2 :: [ seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2])
14af6
76777c7d5836847e3fc4c5c64bced7e0ed10210310c11a11b11d11e126136147
HL2:(2 ^ n).-1 = size cs2

152
153
15b
(2 ^ n).-1 + (2 ^ n).-1.+1 <= (2 ^ n).-1 + (2 ^ n).-1.+1 ?= iff true
153
155
148
149
155
(2 ^ n.+1).-1 == size ([seq ↑[i]_p1 | i <- cs1] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2])
155
(2 ^ n.+1).-1 < size cs
14af6
155
16a
149
76777c7d5836847e3fc4c5c64bced7e0ed10210310c11a11b11d11e126136147
HL2:(2 ^ n).-1 < size cs2

(2 ^ n.+1).-1 < size cs1 + (size cs2).+1
149
14b
104
f5
14b
16a
f5
76777c7d5836847e3fc4c5c64bced7e0ed10210310c11a11b11d11e12613614c
HL2:(2 ^ n).-1 <= size cs2 ?= iff ([seq ↓[i] | i <- cs2] == ppeg `p[p1, p2] p2)

173
f5
ec
forall (cs1 : seq (configuration 3 n)) (cs3 : seq (configuration 3 n.+1)) p4, ↑[`c[`p[p1, p3]]]_p3 ldisk != p4 -> rrel (↑[`c[`p[p1, p3]]]_p3 ldisk) p4 -> last ↓[↑[`c[`p[p1, p3]]]_p3] cs1 = `c[`p[↑[`c[`p[p1, p3]]]_p3 ldisk, p4]] -> cs2 = [seq ↑[i1]_(↑[`c[`p[p1, p3]]]_p3 ldisk) | i1 <- cs1] ++ ↑[`c[`p[↑[`c[`p[p1, p3]]]_p3 ldisk, p4]]]_p4 :: cs3 -> path (move (rrel (n:=3))) ↓[↑[`c[`p[p1, p3]]]_p3] cs1 -> path (move (rrel (n:=3))) ↑[`c[`p[↑[`c[`p[p1, p3]]]_p3 ldisk, p4]]]_p4 cs3 -> true -> size ([seq ↑[i4]_p1 | i4 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i4]_p2 | i4 <- ppeg `p[p1, p2] p2]) = (2 ^ n.+1).-1 -> true -> last `c[p1] cs = `c[p2] -> (2 ^ n.+1).-1 <= size cs ?= iff (cs == [seq ↑[i4]_p1 | i4 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i4]_p2 | i4 <- ppeg `p[p1, p2] p2])
76777c7d5836847e3fc4c5c64bcccdced7e0e5ed
cs3:seq (configuration 3 n)
cs4:seq (configuration 3 n.+1)
p4:peg 3

p3 != p4 -> rrel p3 p4 -> last `c[`p[p1, p3]] cs3 = `c[`p[p3, p4]] -> cs2 = [seq ↑[i1]_p3 | i1 <- cs3] ++ ↑[`c[`p[p3, p4]]]_p4 :: cs4 -> path rmove `c[`p[p1, p3]] cs3 -> path rmove ↑[`c[`p[p3, p4]]]_p4 cs4 -> true -> size ([seq ↑[i4]_p1 | i4 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i4]_p2 | i4 <- ppeg `p[p1, p2] p2]) = (2 ^ n.+1).-1 -> true -> last `c[p1] cs = `c[p2] -> (2 ^ n.+1).-1 <= size cs ?= iff (cs == [seq ↑[i4]_p1 | i4 <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i4]_p2 | i4 <- ppeg `p[p1, p2] p2])
76777c7d5836847e3fc4c5c64bcccdced7e0e5ed187188189
p3Dp4:p3 != p4
p1p3cs3Lp3p4:last `c[`p[p1, p3]] cs3 = `c[`p[p3, p4]]
cs2E:cs2 = [seq ↑[i]_p3 | i <- cs3] ++ ↑[`c[`p[p3, p4]]]_p4 :: cs4
p1p3Pcs3:path rmove `c[`p[p1, p3]] cs3
p3p4Pcs4:path rmove ↑[`c[`p[p3, p4]]]_p4 cs4
102103

104
(* we did two moves of the largest disk so we cannot be = *)
18e
size cs = size ([seq ↑[i]_p1 | i <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2]) -> (2 ^ n.+1).-1 == size cs
18e16a
18e
16a
(* Did we come back to p1 *)
76777c7d5836847e3fc4c5c64bcccdced7e0e5ed18718818918f190191192193102103
p4Ep1:p4 = p1

16a
76777c7d5836847e3fc4c5c64bcccdced7e0e5ed18718818918f190191192193102103
p4Dp1:p4 != p1
16a
76777c7d5836847e3fc4c5c64bcccdced7e0e5ed1871881891921021031a1
p3Dp4:p3 != p1
p1p3cs3Lp3p4:last `c[`p[p1, p3]] cs3 = `c[`p[p3, p1]]
cs2E:cs2 = [seq ↑[i]_p3 | i <- cs3] ++ ↑[`c[`p[p3, p1]]]_p1 :: cs4
p3p4Pcs4:path rmove ↑[`c[`p[p3, p1]]]_p1 cs4

16a
1a2
(* if so cs has a repetition so we can use IHm *)
76777c7d5836847e3fc4c5c64bcccdced7e0e5ed1871881891921021031a11aa1ab1ac1ad
cs':=[seq ↑[i]_p1 | i <- cs1] ++ cs4:seq (configuration 3 n.+1)

16a
1a2
1b1
size cs' < size cs
76777c7d5836847e3fc4c5c64bcccdced7e0e5ed1871881891921021031a11aa1ab1ac1ad1b2
Scs':size cs' < size cs
16a
1a3
1b1
size cs1 + size cs4 < size cs1 + (size cs3 + (size cs4).+1).+1
1b7
1b9
16a
1a2
1b9
(2 ^ n.+1).-1 <= size cs'
1a2
1b9
path rmove `c[p1] cs'
1b9
last `c[p1] cs' = `c[p2]
1a3
1b9
path rmove ↑[`c[p1]]_p1 [seq ↑[i]_p1 | i <- cs1] && path rmove (last ↑[`c[p1]]_p1 [seq ↑[i]_p1 | i <- cs1]) cs4
1ca
1b9
1cc
1a2
1b9
last (last ↑[`c[p1]]_p1 [seq ↑[i]_p1 | i <- cs1]) cs4 = `c[p2]
1a2
1b9
last ↑[`c[`p[p1, p3]]]_p1 cs4 = `c[p2]
1a2
1b9
last `c[p1] cs = `c[p2] -> last ↑[`c[`p[p1, p3]]]_p1 cs4 = `c[p2]
1a2
1a4
16a
1a4
(2 ^ n).-1 + (2 ^ n).-1 <= size cs1 + size cs3 + size cs4
1a4
(2 ^ n).-1 <= size cs3
1a4
size cs3 < m.+1
76777c7d5836847e3fc4c5c64bcccdced7e0e5ed18718818918f1901911921931021031a5
Scs3:size cs3 < m.+1
1ea
76777c7d5836843fc4c5c64bcccdced7e0e5ed18718818918f1901911921931021031a5

size cs3 < (size cs).+1
1ef
1f6
size cs3 <= size cs3 + size cs4 + (size cs1).+2
1ef
1f1
1ea
1f1
`p[p1, p3] != `p[p3, p4]
by rewrite opeg3E // eq_sym opeg3E // eq_sym p1Dp3 p4Dp1 eq_sym opegDl. Qed.
4
`d[`c[p1 , n], `c[p2]]_rmove = (2 ^ n).-1 * (p1 != p2)
204
65
`d[`c[p1], `c[p2]]_rmove = (2 ^ n).-1 * ~~ false
65
`d[`c[p1], `c[p2]]_rmove = (2 ^ n).-1
65
`d[`c[p1], `c[p2]]_rmove <= size (ppeg p1 p2) <= `d[`c[p1], `c[p2]]_rmove
65
path rmove `c[p1] (ppeg p1 p2)
65
last `c[p1] (ppeg p1 p2) = `c[p2]
65
size (ppeg p1 p2) <= `d[`c[p1], `c[p2]]_rmove
215
65
21a
21b
21f
65
21c
64
563f
cs:seq (finfun_finType (ordinal_finType n) (ordinal_finType 3))
csH:gpath rmove `c[p1] `c[p2] cs
21c
22a
21c
22a
(2 ^ n).-1 <= size cs
5622b22c

last `c[p1] cs = `c[p2]
by apply: gpath_last csH. Qed. (*****************************************************************************) (* Function that builds a path from a configuration to a peg *) (*****************************************************************************) Fixpoint rpeg {n : nat} := if n is n1.+1 return configuration 3 n -> peg 3 -> seq (configuration 3 n) then fun c p => let p1 := c ldisk in if p1 == p then [seq ↑[i]_p | i <- rpeg ↓[c] p] else let p2 := `p[p1, p] in [seq ↑[i]_p1 | i <- rpeg ↓[c] p2] ++ [seq ↑[i]_p | i <- `c[p2] :: ppeg p2 p] else fun _ _ => [::].
5
p:peg 3

rpeg `c[p] p = [::]
23a
23d5
IH:rpeg `c[p] p = [::]

(if `c[p] ldisk == p then [seq ↑[i]_p | i <- rpeg ↓[`c[p]] p] else [seq ↑[i]_(`c[p] ldisk) | i <- rpeg ↓[`c[p]] `p[`c[p] ldisk, p]] ++ ↑[`c[`p[`c[p] ldisk, p]]]_p :: [seq ↑[i]_p | i <- ppeg `p[`c[p] ldisk, p] p]) = [::]
by rewrite ffunE eqxx perfect_unliftr IH. Qed.
51723d

rpeg c p = [::] -> c = `c[p]
247
23d5
IH:forall c : configuration 3 n, rpeg c p = [::] -> c = `c[p]
2b

(if c ldisk == p then [seq ↑[i]_p | i <- rpeg ↓[c] p] else [seq ↑[i]_(c ldisk) | i <- rpeg ↓[c] `p[c ldisk, p]] ++ ↑[`c[`p[c ldisk, p]]]_p :: [seq ↑[i]_p | i <- ppeg `p[c ldisk, p] p]) = [::] -> c = `c[p]
23d52502b
H:c ldisk = p

[seq ↑[i]_p | i <- rpeg ↓[c] p] = [::] -> c = `c[p]
255
[seq ↑[i]_p | i <- rpeg ↓[c] p] = [::] -> ↑[↓[c]]_(c ldisk) = `c[p]
255
↑[`c[p]]_(c ldisk) = `c[p]
by rewrite H perfect_liftr. Qed.
4
p1 != p2 -> rpeg `c[p1 , n] p2 = ppeg p1 p2
261
5
IH:forall p1 p2, p1 != p2 -> rpeg `c[p1] p2 = ppeg p1 p2
63f

(if `c[p1] ldisk == p2 then [seq ↑[i]_p2 | i <- rpeg ↓[`c[p1]] p2] else [seq ↑[i]_(`c[p1] ldisk) | i <- rpeg ↓[`c[p1]] `p[`c[p1] ldisk, p2]] ++ ↑[`c[`p[`c[p1] ldisk, p2]]]_p2 :: [seq ↑[i]_p2 | i <- ppeg `p[`c[p1] ldisk, p2] p2]) = [seq ↑[i]_p1 | i <- ppeg p1 `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- ppeg `p[p1, p2] p2]
by rewrite ffunE perfect_unliftr (negPf p1Dp2) !IH // eq_sym opegDl. Qed.
51723d
cs:=rpeg c p:seq (configuration 3 n)

last c cs = `c[p]
26c
2523d

c = `c[p]
5
IH:forall (c : configuration 3 n) p, last c (rpeg c p) = `c[p]
2b23d
last c (if c ldisk == p then [seq ↑[i]_p | i <- rpeg ↓[c] p] else [seq ↑[i]_(c ldisk) | i <- rpeg ↓[c] `p[c ldisk, p]] ++ ↑[`c[`p[c ldisk, p]]]_p :: [seq ↑[i]_p | i <- ppeg `p[c ldisk, p] p]) = `c[p]
279
27b
527a2b23d
Ho:c ldisk = p

last c [seq ↑[i]_p | i <- rpeg ↓[c] p] = `c[p]
527a2b23d
Do:c ldisk != p
last c ([seq ↑[i]_(c ldisk) | i <- rpeg ↓[c] `p[c ldisk, p]] ++ ↑[`c[`p[c ldisk, p]]]_p :: [seq ↑[i]_p | i <- ppeg `p[c ldisk, p] p]) = `c[p]
287
289
by rewrite last_cat /= last_map last_ppeg perfect_liftr. Qed.
26e
path rmove c cs
28e
51723d26f1f

290
1f5
IH:forall (c : configuration 3 n) p, path rmove c (rpeg c p)
2b23d

path rmove c (if c ldisk == p then [seq ↑[i]_p | i <- rpeg ↓[c] p] else [seq ↑[i]_(c ldisk) | i <- rpeg ↓[c] `p[c ldisk, p]] ++ ↑[`c[`p[c ldisk, p]]]_p :: [seq ↑[i]_p | i <- ppeg `p[c ldisk, p] p])
1f529a2b23d283

path rmove c [seq ↑[i]_p | i <- rpeg ↓[c] p]
1f529a2b23d288
path rmove c ([seq ↑[i]_(c ldisk) | i <- rpeg ↓[c] `p[c ldisk, p]] ++ ↑[`c[`p[c ldisk, p]]]_p :: [seq ↑[i]_p | i <- ppeg `p[c ldisk, p] p])
2a3
2a4
1f529a2b23d288
c2:=`c[`p[c ldisk, p]]:configuration 3 n

path rmove c ([seq ↑[i]_(c ldisk) | i <- rpeg ↓[c] `p[c ldisk, p]] ++ ↑[c2]_p :: [seq ↑[i]_p | i <- ppeg `p[c ldisk, p] p])
2ab
[&& true, last c [seq ↑[i]_(c ldisk) | i <- rpeg ↓[c] `p[c ldisk, p]] `-->_r ↑[c2]_p & true]
2ab
last c [seq ↑[i]_(c ldisk) | i <- rpeg ↓[c] `p[c ldisk, p]] `-->_r ↑[c2]_p
2ab
↑[c2]_(c ldisk) `-->_r ↑[c2]_p
2ab
p != `p[c ldisk, p]
by rewrite eq_sym (opegDr _). Qed. (* We can go from any configuration to a perfect configuration *)
249
c `-->*_r `c[p]
2bf
249
`c[p] = last c (rpeg c p)
by rewrite last_rpeg. Qed. (* So we can also from a perfect configuration c to any configuration *)
249
`c[p] `-->*_r c
2c8
249
connect (move (rrel (n:=3))) c `c[p]
249
symmetric (rrel (n:=3))
249
2d2
by exact: rsym. Qed. (* Two configurations are always connected *)
5
c1, c2:configuration 3 n

c1 `-->*_r c2
2d7
by apply: connect_trans (move_connect_rpeg c1 (inord 1)) (move_connect_lpeg c2 (inord 1)). Qed. (******************************************************************************) (* Function that builds a path from a configuration to a peg *) (******************************************************************************) (*****************************************************************************) (* Computes the size of rpeg *) (*****************************************************************************) Fixpoint size_rpeg {n : nat} : (configuration _ n) -> _ -> nat := match n with | 0 => fun _ _ => 0 | n1.+1 => fun c p => let p1 := c ldisk in if p1 == p then size_rpeg ↓[c] p else let p2 := `p[p1, p] in size_rpeg ↓[c] p2 + 2 ^ n1 end.
523d17

size_rpeg c p = size (rpeg c p)
2de
5
IH:forall p (c : configuration 3 n), size_rpeg c p = size (rpeg c p)
23d2b

(if c ldisk == p then size_rpeg ↓[c] p else size_rpeg ↓[c] `p[c ldisk, p] + 2 ^ n) = size (if c ldisk == p then [seq ↑[i]_p | i <- rpeg ↓[c] p] else [seq ↑[i]_(c ldisk) | i <- rpeg ↓[c] `p[c ldisk, p]] ++ ↑[`c[`p[c ldisk, p]]]_p :: [seq ↑[i]_p | i <- ppeg `p[c ldisk, p] p])
52e723d2b
clDp:c ldisk != p

size_rpeg ↓[c] `p[c ldisk, p] + 2 ^ n = size ([seq ↑[i]_(c ldisk) | i <- rpeg ↓[c] `p[c ldisk, p]] ++ ↑[`c[`p[c ldisk, p]]]_p :: [seq ↑[i]_p | i <- ppeg `p[c ldisk, p] p])
by rewrite size_cat /= !size_map size_ppeg prednK ?expn_gt0 // IH. Qed. (* Upper bound on the size *)
249
size_rpeg c p <= (2 ^ n).-1
2f0
5
IH:forall (c : configuration 3 n) p, size_rpeg c p <= (2 ^ n).-1
2b23d

(if c ldisk == p then size_rpeg ↓[c] p else size_rpeg ↓[c] `p[c ldisk, p] + 2 ^ n) <= (2 ^ n.+1).-1
2f7
size_rpeg ↓[c] p <= (2 ^ n.+1).-1
2f7
size_rpeg ↓[c] `p[c ldisk, p] + 2 ^ n <= (2 ^ n.+1).-1
2f7
(2 ^ n).-1 <= (2 ^ n.+1).-1
2fe
52f82b23d
n1:nat

(2 ^ n.+1 == 0) = false -> n1 < 2 ^ n.+1 -> n1 <= (2 ^ n.+1).-1
2fe
2f7
300
2f7
size_rpeg ↓[c] `p[c ldisk, p] + 2 ^ n <= (2 ^ n).-1 + 2 ^ n
2f7
(2 ^ n).-1 + 2 ^ n <= (2 ^ n.+1).-1
2f7
314
2f7
(2 ^ n).-1 + 2 ^ n <= (2 ^ n + 2 ^ n).-1
by case: (2 ^ n) (expn_eq0 2 n) => [|n1]; rewrite ?addn0. Qed. (* rpeg gives the smallest path to a perfect configuration. *) (* This path is unique *)
51723d6f

path rmove c cs -> last c cs = `c[p] -> size_rpeg c p <= size cs ?= iff (cs == rpeg c p)
31d
(* As we want this statememnt to hold for any configuration c1 *) (* and not just for initial perfect configuration the proof is more *) (* intricate. We need a double induction : *) (* The first induction is used when the path has duplicates (1 case) *)
7c
IHm:forall (n : nat) (c : configuration 3 n) p (cs : seq (configuration 3 n)), size cs < m -> path rmove c cs -> last c cs = `c[p] -> size_rpeg c p <= size cs ?= iff (cs == rpeg c p)
51723d6f7e

320
(* The usual induction on the number of disks *)
7c3265
IH:forall (c : configuration 3 n) p (cs : seq (configuration 3 n)), size cs < m.+1 -> path rmove c cs -> last c cs = `c[p] -> size_rpeg c p <= size cs ?= iff (cs == rpeg c p)
c1:configuration 3 n.+1
23d84
Scs:size cs < m.+1
c1Pcs:path rmove c1 cs
lc1csEp:last c1 cs = `c[p]

(if c1 ldisk == p then size_rpeg ↓[c1] p else size_rpeg ↓[c1] `p[c1 ldisk, p] + 2 ^ n) <= size cs ?= iff (cs == (if c1 ldisk == p then [ seq ↑[i]_p | i <- rpeg ↓[c1] p] else [ seq ↑[i]_ (c1 ldisk) | i <- rpeg ↓[c1] `p[ c1 ldisk, p]] ++ ↑[`c[`p[ c1 ldisk, p]]]_p :: [ seq ↑[i]_p | i <- ppeg `p[ c1 ldisk, p] p]))
7c326532b32c23d8432d32e32f
c1nEp:c1 ldisk = p

size_rpeg ↓[c1] p <= size cs ?= iff (cs == [seq ↑[i]_p | i <- rpeg ↓[c1] p])
7c
IHm:forall (n : nat) (c : configuration 3 n) p (cs : seq (configuration 3 n)), size cs < m -> path rmove c cs -> last c cs = `c[p] -> size_rpeg c p <= size cs ?= iff (cs == rpeg c p)
5
IH:forall (c : configuration 3 n) p (cs : seq (configuration 3 n)), size cs < m.+1 -> path rmove c cs -> last c cs = `c[p] -> size_rpeg c p <= size cs ?= iff (cs == rpeg c p)
32c23d8432d32e32f
c1nDp:c1 ldisk != p
size_rpeg ↓[c1] `p[c1 ldisk, p] + 2 ^ n <= size cs ?= iff (cs == [seq ↑[i]_(c1 ldisk) | i <- rpeg ↓[c1] `p[c1 ldisk, p]] ++ ↑[`c[`p[c1 ldisk, p]]]_p :: [seq ↑[i]_p | i <- ppeg `p[c1 ldisk, p] p])
(* the largest disk is already well-placed *)
334
last c1 cs ldisk = c1 ldisk
7c33a533b32c23d8432d32e32f335
lcsnEc1n:last c1 cs ldisk = c1 ldisk
size_rpeg ↓[c1] p <= size cs ?= iff (cs == [seq ↑[i]_p | i <- rpeg ↓[c1] p])
338
7c326532b32c23d8432d32e32f335345

336
337
7c326532b32c23d8432d32e32f335345c4
c1Pcs1:path (move (rrel (n:=3))) ↓[c1] cs1
lcsElcs1:last ↓[c1] cs1 = ↓[last c1 cs]

(if cs == [seq ↑[i]_(c1 ldisk) | i <- cs1] then size cs1 == size cs else size cs1 < size cs) -> size_rpeg ↓[c1] p <= size cs ?= iff (cs == [seq ↑[i]_p | i <- rpeg ↓[c1] p])
337
34e
last ↓[c1] cs1 = `c[p]
7c33a533b32c23d8432d32e32f335345c434f350
lcs1P:last ↓[c1] cs1 = `c[p]
(if cs == [seq ↑[i]_(c1 ldisk) | i <- cs1] then size cs1 == size cs else size cs1 < size cs) -> size_rpeg ↓[c1] p <= size cs ?= iff (cs == [seq ↑[i]_p | i <- rpeg ↓[c1] p])
338
7c326532b32c23d8432d32e32f335345c434f350359

351
337
7c326532b32c23d8432d32e32f335345c434f350359
csEcs1:cs = [seq ↑[i]_(c1 ldisk) | i <- cs1]

size_rpeg ↓[c1] p <= size cs1 ?= iff (cs == [seq ↑[i]_p | i <- rpeg ↓[c1] p])
7c33a533b32c23d8432d32e32f335345c434f350359
csDcs1:cs != [seq ↑[i]_(c1 ldisk) | i <- cs1]
scs1L:size cs1 < size cs
346
338
362
size_rpeg ↓[c1] p <= size cs1 ?= iff (cs1 == rpeg ↓[c1] p)
365
7c326532c23d8432d32e32f335345c434f350359363

d3
365
7c326532b32c23d8432d32e32f335345c434f350359368369

336
337
375
size_rpeg ↓[c1] p == size [seq ↑[i]_p | i <- rpeg ↓[c1] p]
367
size_rpeg ↓[c1] p < size cs
338
375
37c
337
375
size_rpeg ↓[c1] p <= size cs1
337
7c326532c23d8432d32e32f335345c434f350359368369

d3
337
7c326532b32c23d8432d32e32f33c

size_rpeg ↓[c1] `p[c1 ldisk, p] + 2 ^ n <= size cs ?= iff (cs == [seq ↑[i]_ (c1 ldisk) | i <- rpeg ↓[c1] `p[ c1 ldisk, p]] ++ ↑[`c[`p[ c1 ldisk, p]]]_p :: [ seq ↑[i]_p | i <- ppeg `p[ c1 ldisk, p] p])
7c326532b32c23d8432d32e32f33c
f:=fun_of_fin^~ ldisk:configuration 3 n.+1 -> (fun=> peg 3) ldisk

38c
7c326532b32c23d8432d32e32f33c391
HHr:irreflexive (rrel (n:=3))

38c
7c326532b32c23d8432d32e32f33c391396
HHs:symmetric (rrel (n:=3))

38c
(* We need to move the largest disk *)
7c326532b32c23d8432d32f33c39139639b
c1':=↓[c1]:configuration 3 n
cs':=[seq ↓[i] | i <- cs]:seq (configuration 3 n)
p1:=c1 ldisk:peg 3
csE:cs = [seq ↑[i]_p1 | i <- cs']
c1'Pcs':path (move (rrel (n:=3))) c1' cs'

38c
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a0
c2:=↑[`c[p3]]_p2:configuration 3 n.+1
3f
p1Rp2:rrel p1 p2
lc1'cs1Epp3:last c1' cs1 = `c[p3]
csE:cs = [seq ↑[i]_p1 | i <- cs1] ++ c2 :: cs2
c1'Pcs1:path (move (rrel (n:=3))) c1' cs1
c2Pcs2:path (move (rrel (n:=3))) c2 cs2
33d
(* this case is impossible the largest disk has to move *)
7c326532b32c23d8432d32f39139639b3a03a13a23a33a4

c1 ldisk = p
3a5
7c326532b32c23d8432d39139639b3a03a13a23a33a4

f ↑[last ↓[c1] cs']_(c1 ldisk) = f `c[p] -> ↑[↓[c1]]_(c1 ldisk) ldisk = p
3a5
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad

38c
(* c2 is the first configuration when the largest disk has moved *)
3bb
size_rpeg ↓[c1] `p[p1, p] + 2 ^ n <= size [seq ↑[i]_p1 | i <- cs1] + size (c2 :: cs2) ?= iff ([seq ↑[i]_p1 | i <- cs1] ++ c2 :: cs2 == [seq ↑[i]_p1 | i <- rpeg ↓[c1] `p[p1, p]] ++ ↑[`c[`p[p1, p]]]_p :: [seq ↑[i]_p | i <- ppeg `p[p1, p] p])
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad
p1Dp:p1 != p

3bf
3c3
d3
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d7
size_rpeg ↓[c1] `p[p1, p] + 2 ^ n <= size [seq ↑[i]_p1 | i <- cs1] + size (c2 :: cs2) ?= iff ([seq ↑[i]_p1 | i <- cs1] ++ c2 :: cs2 == [seq ↑[i]_p1 | i <- rpeg ↓[c1] `p[p1, p]] ++ ↑[`c[`p[p1, p]]]_p :: [seq ↑[i]_p | i <- ppeg `p[p1, p] p])
7c326532b32c23d8432f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4

size cs1 < size cs
3c8
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d7

3bf
3d4
size cs2 < m.+1
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d7
Scs2:size cs2 < m.+1
3cb
7c326532b32c23d8432f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d7

size cs2 < size cs
3d9
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc

3bf
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc
p2Ep:p2 = p

3bf
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc
p2Dp:p2 != p
3cb
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea
c2':=↓[c2]:configuration 3 n

3bf
3eb
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea3f3
c2'Epp3:c2' = `c[`p[p1, p2]]

3bf
3eb
(* the first moves of largest disk of cs is the right one *)
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea3f33f8
cs2':seq (configuration 3 n)
c2'Pcs2':path (move (rrel (n:=3))) ↓[c2] cs2'
lc2'cs2'E:last ↓[c2] cs2' = ↓[last c2 cs2]
cs2'L:size cs2' <= size cs2 ?= iff (cs2 == [seq ↑[i]_ (c2 ldisk) | i <- cs2'])

3bf
3eb
3fc
size cs2' < m.+1
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea3f33f83fd3fe3ff400
Scs2':size cs2' < m.+1
3cb
3ec
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea3f33f83fd3fe3ff400408

3bf
3eb
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea3f33f83fd3fe3ff400408
IHc1:size_rpeg c1' p3 <= size cs1 ?= iff (cs1 == rpeg c1' p3)

3bf
3eb
410
last c2' cs2' = `c[p]
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea3f33f83fd3fe3ff400408411
IHc2:size_rpeg c2' p <= size cs2' ?= iff (cs2' == rpeg c2' p)
3cb
3ec
410
↓[last c2 cs2] = ↓[`c[p]]
416
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea3f33f83fd3fe3ff400408411419

3bf
3eb
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea3f33f83fd3fe3ff400408411
IHc2:size_rpeg c2' p2 <= size cs2' ?= iff (cs2' == rpeg c2' p2)

3bf
3eb
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea3f33f83fd3fe3ff408411426

(if cs2 == [seq ↑[i]_(c2 ldisk) | i <- cs2'] then size cs2' == size cs2 else size cs2' < size cs2) -> size_rpeg ↓[c1] `p[p1, p] + 2 ^ n <= size [seq ↑[i]_p1 | i <- cs1] + size (c2 :: cs2) ?= iff ([seq ↑[i]_p1 | i <- cs1] ++ c2 :: cs2 == [seq ↑[i]_p1 | i <- rpeg ↓[c1] `p[p1, p]] ++ ↑[`c[`p[p1, p]]]_p :: [seq ↑[i]_p | i <- ppeg `p[p1, p] p])
3eb
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea3f33f83fd3fe3ff408411426
cs2E:cs2 = [seq ↑[i]_(c2 ldisk) | i <- cs2']

3bf
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea3f33f83fd3fe3ff408411426
cs2D:cs2 != [seq ↑[i]_(c2 ldisk) | i <- cs2']
Lcs2:size cs2' < size cs2
3cb
3ec
(* there is only one move of the largest disk in cs *)
42f
size_rpeg ↓[c1] p3 + 2 ^ n <= size cs1 + size (c2 :: [seq ↑[i]_(c2 ldisk) | i <- cs2']) ?= iff ([seq ↑[i]_p1 | i <- cs1] ++ c2 :: [seq ↑[i]_(c2 ldisk) | i <- cs2'] == [seq ↑[i]_p1 | i <- rpeg ↓[c1] p3] ++ ↑[`c[p3]]_p2 :: [seq ↑[i]_p2 | i <- ppeg p3 p2])
431
42f
size_rpeg ↓[c1] p3 + 2 ^ n <= size (rpeg c1' p3) + size (c2 :: [seq ↑[i]_(c2 ldisk) | i <- cs2']) ?= iff ([seq ↑[i]_p1 | i <- rpeg c1' p3] ++ c2 :: [seq ↑[i]_(c2 ldisk) | i <- cs2'] == [seq ↑[i]_p1 | i <- rpeg ↓[c1] p3] ++ ↑[`c[p3]]_p2 :: [seq ↑[i]_p2 | i <- ppeg p3 p2])
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea3f33f83fd3fe3ff408411426430
Lc1:size_rpeg c1' p3 < size cs1
size_rpeg ↓[c1] p3 + 2 ^ n <= size cs1 + size (c2 :: [seq ↑[i]_(c2 ldisk) | i <- cs2']) ?= iff ([seq ↑[i]_p1 | i <- cs1] ++ c2 :: [seq ↑[i]_(c2 ldisk) | i <- cs2'] == [seq ↑[i]_p1 | i <- rpeg ↓[c1] p3] ++ ↑[`c[p3]]_p2 :: [seq ↑[i]_p2 | i <- ppeg p3 p2])
4323ec
(* the first part of cs is perfect *)
42f
size_rpeg ↓[c1] p3 + 2 ^ n <= size (rpeg c1' p3) + size (c2 :: [seq ↑[i]_(c2 ldisk) | i <- rpeg c2' p2]) ?= iff ([seq ↑[i]_p1 | i <- rpeg c1' p3] ++ c2 :: [seq ↑[i]_(c2 ldisk) | i <- rpeg c2' p2] == [seq ↑[i]_p1 | i <- rpeg ↓[c1] p3] ++ ↑[`c[p3]]_p2 :: [seq ↑[i]_p2 | i <- ppeg p3 p2])
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea3f33f83fd3fe3ff408411426430
Lc2:size_rpeg c2' p2 < size cs2'
size_rpeg ↓[c1] p3 + 2 ^ n <= size (rpeg c1' p3) + size (c2 :: [seq ↑[i]_(c2 ldisk) | i <- cs2']) ?= iff ([seq ↑[i]_p1 | i <- rpeg c1' p3] ++ c2 :: [seq ↑[i]_(c2 ldisk) | i <- cs2'] == [seq ↑[i]_p1 | i <- rpeg ↓[c1] p3] ++ ↑[`c[p3]]_p2 :: [seq ↑[i]_p2 | i <- ppeg p3 p2])
43f4323ec
(* the second part of cs is perfect, only case of equality *)
42f
size ([seq ↑[i]_p1 | i <- rpeg c1' p3] ++ c2 :: [seq ↑[i]_(c2 ldisk) | i <- rpeg c2' p2]) = size ([seq ↑[i]_p1 | i <- rpeg ↓[c1] p3] ++ ↑[`c[p3]]_p2 :: [seq ↑[i]_p2 | i <- ppeg p3 p2]) -> size_rpeg ↓[c1] p3 + 2 ^ n == size (rpeg c1' p3) + size (c2 :: [seq ↑[i]_(c2 ldisk) | i <- rpeg c2' p2])
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea3f33f83fd3fe3ff408411426430
[seq ↑[i]_p1 | i <- rpeg c1' p3] ++ c2 :: [seq ↑[i]_(c2 ldisk) | i <- rpeg c2' p2] = [seq ↑[i]_p1 | i <- rpeg ↓[c1] p3] ++ ↑[`c[p3]]_p2 :: [seq ↑[i]_p2 | i <- ppeg p3 p2]
44843f4323ec
42f
(size (rpeg c1' p3) + size (rpeg `c[`p[p1, p2]] p2)).+1 = (size (rpeg c1' p3) + size (ppeg p3 p2)).+1 -> size (rpeg ↓[c1] p3) + 2 ^ n == (size (rpeg c1' p3) + size (rpeg `c[`p[p1, p2]] p2)).+1
450
42f
453
447
42f
[seq ↑[i]_(c2 ldisk) | i <- rpeg c2' p2] = [seq ↑[i]_p2 | i <- ppeg p3 p2]
447
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea3f33f83fd3fe3ff40841142643044a

43d
43e
462
size ([seq ↑[i]_p1 | i <- rpeg c1' p3] ++ c2 :: [seq ↑[i]_(c2 ldisk) | i <- cs2']) = size ([seq ↑[i]_p1 | i <- rpeg ↓[c1] p3] ++ ↑[`c[p3]]_p2 :: [seq ↑[i]_p2 | i <- ppeg p3 p2]) -> size_rpeg ↓[c1] p3 + 2 ^ n == size (rpeg c1' p3) + size (c2 :: [seq ↑[i]_(c2 ldisk) | i <- cs2'])
449
size_rpeg ↓[c1] p3 + 2 ^ n < size (rpeg c1' p3) + size (c2 :: [seq ↑[i]_(c2 ldisk) | i <- cs2'])
43f4323ec
462
size (rpeg c1' p3) + (size cs2').+1 = size (rpeg c1' p3) + (size (ppeg p3 p2)).+1 -> size (rpeg ↓[c1] p3) + 2 ^ n == size (rpeg c1' p3) + (size cs2').+1
467
462
469
43e
462
2 ^ n <= size cs2'
43e
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea3f33f83fd3fe3ff408411426430
Lc2:(2 ^ n).-1 < size cs2'

474
43e
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea3f33f83fd3fe3ff408411426430441

439
431
47d
size ([seq ↑[i]_p1 | i <- cs1] ++ c2 :: [seq ↑[i]_(c2 ldisk) | i <- cs2']) = size ([seq ↑[i]_p1 | i <- rpeg ↓[c1] p3] ++ ↑[`c[p3]]_p2 :: [seq ↑[i]_p2 | i <- ppeg p3 p2]) -> size_rpeg ↓[c1] p3 + 2 ^ n == size cs1 + size (c2 :: [seq ↑[i]_(c2 ldisk) | i <- cs2'])
440
size_rpeg ↓[c1] p3 + 2 ^ n < size cs1 + size (c2 :: [seq ↑[i]_(c2 ldisk) | i <- cs2'])
4323ec
47d
size (rpeg ↓[c1] p3) + 2 ^ n == size (rpeg ↓[c1] p3) + (size (ppeg p3 p2)).+1
482
47d
484
431
47d
(2 ^ n).-1 <= size cs2'
431
47d
(2 ^ n).-1 <= size cs2' ?= iff (cs2' == ppeg `p[p1, p2] p2) -> (2 ^ n).-1 <= size cs2'
431
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea3f33f83fd3fe3ff408411426434435

3bf
3eb
497
size ([seq ↑[i]_p1 | i <- cs1] ++ c2 :: cs2) = size ([seq ↑[i]_p1 | i <- rpeg ↓[c1] `p[p1, p]] ++ ↑[`c[`p[p1, p]]]_p :: [seq ↑[i]_p | i <- ppeg `p[p1, p] p]) -> size_rpeg ↓[c1] `p[p1, p] + 2 ^ n == size [seq ↑[i]_p1 | i <- cs1] + size (c2 :: cs2)
433
size_rpeg ↓[c1] `p[p1, p] + 2 ^ n < size [seq ↑[i]_p1 | i <- cs1] + size (c2 :: cs2)
3ec
497
size cs1 + (size cs2).+1 = size (rpeg ↓[c1] `p[p1, p]) + (size (ppeg `p[p1, p] p)).+1 -> size (rpeg ↓[c1] `p[p1, p]) + 2 ^ n == size cs1 + (size cs2).+1
49c
497
49e
3eb
497
size_rpeg ↓[c1] `p[p1, p2] <= size [seq ↑[i]_p1 | i <- cs1]
433
2 ^ n <= size cs2
3ec
497
4ac
3eb
497
(2 ^ n).-1 < size cs2
3eb
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ea3f33f83fd3fe3ff408411426434

48f
3eb
4b7
size_rpeg c2' p2 <= size cs2' ?= iff (cs2' == rpeg c2' p2) -> (2 ^ n).-1 <= size cs2'
3eb
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ee

3bf
(* The largest disk jumped to an intermediate peg *)
4bf
p3 = p
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ee
p3Ep:p3 = p
3cb
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3ad3c4d73dc3ee4c7

3bf
(* cs cannot be optimal *)
4cb
49b
4c649e
4cb
4a2
4cf
4cb
49e
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c73f3
cs2':=[seq ↓[i] | i <- cs2]:seq (configuration 3 n)

let p0 := c2 ldisk in cs2 = [seq ↑[i]_p0 | i <- cs2'] -> path (move (rrel (n:=3))) c2' cs2' -> true -> size_rpeg ↓[c1] `p[p1, p] + 2 ^ n < size [seq ↑[i0]_p1 | i0 <- cs1] + size (c2 :: cs2)
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c7187188
let p2 := c2 ldisk in forall p3, let p4 := `p[p2, p3] in let c3 := ↓[c2] in let c4 := ↑[`c[p4]]_p3 in p2 != p3 -> rrel p2 p3 -> last c3 cs3 = `c[p4] -> cs2 = [seq ↑[i1]_p2 | i1 <- cs3] ++ c4 :: cs4 -> path (move (rrel (n:=3))) c3 cs3 -> path (move (rrel (n:=3))) c4 cs4 -> true -> size_rpeg ↓[c1] `p[p1, p] + 2 ^ n < size [seq ↑[i3]_p1 | i3 <- cs1] + size (c2 :: cs2)
(* this is impossible we need another move of the largest disk *)
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c73f34db
cs2E:cs2 = [seq ↑[i]_p2 | i <- cs2']
c2'Pcs2':path (move (rrel (n:=3))) c2' cs2'

true -> size_rpeg ↓[c1] `p[p1, p] + 2 ^ n < size [seq ↑[i]_p1 | i <- cs1] + (size cs2).+1
4dd
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc4c73f34db4e54e6

p2 = p
4dd
4eb
last c1 cs = `c[p] -> p2 = p
4dd
4eb
f (last c2 cs2) = f `c[p] -> p2 = p
4dd
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c7187188

4e0
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c7187188
p2':=p2:peg 3

forall p2, let p3 := `p[p2', p2] in let c3 := ↓[c2] in let c4 := ↑[`c[p3]]_p2 in p2' != p2 -> rrel p2' p2 -> last c3 cs3 = `c[p3] -> cs2 = [seq ↑[i1]_p2' | i1 <- cs3] ++ c4 :: cs4 -> path (move (rrel (n:=3))) c3 cs3 -> path (move (rrel (n:=3))) c4 cs4 -> true -> size_rpeg ↓[c1] `p[p1, p] + 2 ^ n < size [seq ↑[i3]_p1 | i3 <- cs1] + size (c2 :: cs2)
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c7187188189

p2 != p4 -> rrel p2 p4 -> last ↓[c2] cs3 = `c[`p[p2, p4]] -> cs2 = [seq ↑[i1]_p2 | i1 <- cs3] ++ ↑[`c[`p[p2, p4]]]_p4 :: cs4 -> path (move (rrel (n:=3))) ↓[c2] cs3 -> path (move (rrel (n:=3))) ↑[`c[`p[p2, p4]]]_p4 cs4 -> true -> size_rpeg ↓[c1] `p[p1, p] + 2 ^ n < size [seq ↑[i3]_p1 | i3 <- cs1] + size (c2 :: cs2)
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c7187188189
p5:=`p[p2, p4]:peg 3
3f3

p2 != p4 -> rrel p2 p4 -> last c2' cs3 = `c[p5] -> cs2 = [seq ↑[i1]_p2 | i1 <- cs3] ++ ↑[`c[p5]]_p4 :: cs4 -> path (move (rrel (n:=3))) c2' cs3 -> path (move (rrel (n:=3))) ↑[`c[p5]]_p4 cs4 -> true -> size_rpeg ↓[c1] `p[p1, p] + 2 ^ n < size [seq ↑[i3]_p1 | i3 <- cs1] + size (c2 :: cs2)
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f3
p2Dp4:p2 != p4
p2Rp4:rrel p2 p4
c2'cs5Epp5:last c2' cs3 = `c[p5]
cs2E:cs2 = [seq ↑[i]_p2 | i <- cs3] ++ ↑[`c[p5]]_p4 :: cs4
c2'Pcs3:path (move (rrel (n:=3))) c2' cs3
pp5p4Pcs4:path (move (rrel (n:=3))) ↑[`c[p5]]_p4 cs4

49e
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f510511512513
p5Ep3:p5 = p3

size_rpeg ↓[c1] `p[p1, p] + 2 ^ n < size [seq ↑[i]_p1 | i <- cs1] + (size cs2).+1
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f510511512513
p5Dp3:p5 != p3
49e
(* the path has a duplicate use the induction hypothesis *)
517
p4 = p1
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f5105115125135181a1
519
51b
50d
(p5 != p1) && (p2 != p5) -> p4 = p1
522
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f5105115125135181a1

519
51a
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f5105115125135181a1
cs5:=[seq ↑[i]_p1 | i <- cs1] ++ cs4:seq (configuration 3 n.+1)

519
51a
530
size cs5 < size cs
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f5105115125135181a1531
scs5Lscs:size cs5 < size cs
519
51b
530
1be
536
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f5105115125135181a1531539

519
51a
540
path rmove c1 cs5
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f5105115125135181a1531539
c1Mcs5:path rmove c1 cs5
519
51b
540
path (move (rrel (n:=3))) ↓[c1] cs1 && path rmove (last ↑[↓[c1]]_(c1 ldisk) [seq ↑[i]_p1 | i <- cs1]) cs4
545
540
true && path rmove (last ↑[↓[c1]]_(c1 ldisk) [seq ↑[i]_p1 | i <- cs1]) cs4
545
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f5105115125135181a1531539548

519
51a
554
last c1 cs5 = `c[p]
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f5105115125135181a1531539548
lc1cs5E:last c1 cs5 = `c[p]
519
51b
554
last ↑[`c[p3]]_(c1 ldisk) cs4 = `c[p]
559
554
last ↑[`c[p3]]_p1 cs4 = last ↑[`c[p5]]_p4 cs4
559
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f5105115125135181a153153954855c

519
51a
568
size cs5 < size [seq ↑[i]_p1 | i <- cs1] + (size cs2).+1
55b
size_rpeg ↓[c1] `p[p1, p] + 2 ^ n < (size cs5).+1
51b
568
56f
51a
568
size_rpeg ↓[c1] `p[p1, p] + 2 ^ n <= size cs5
51a
568
size cs5 < m
55b
(forall (c : configuration 3 n.+1) p, path rmove c cs5 -> last c cs5 = `c[p] -> size_rpeg c p <= size cs5 ?= iff (cs5 == rpeg c p)) -> size_rpeg ↓[c1] `p[p1, p] + 2 ^ n <= size cs5
51b
568
(size cs5).+1 < m.+1
57b
568
57d
51a
568
(if c1 ldisk == p then size_rpeg ↓[c1] p else size_rpeg ↓[c1] `p[c1 ldisk, p] + 2 ^ n) <= size cs5 ?= iff (cs5 == (if c1 ldisk == p then [ seq ↑[i]_p | i <- rpeg ↓[c1] p] else [ seq ↑[i]_ (c1 ldisk) | i <- rpeg ↓[c1] `p[ c1 ldisk, p]] ++ ↑[`c[`p[ c1 ldisk, p]]]_p :: [ seq ↑[i]_p | i <- ppeg `p[ c1 ldisk, p] p])) -> size_rpeg ↓[c1] `p[p1, p] + 2 ^ n <= size cs5
51a
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d

49e
(* now we just need to use the induction principle on the two subpath *)
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d
cs4':seq (configuration 3 n)
pp5p4Pcs4':path (move (rrel (n:=3))) ↓[↑[`c[p5]]_p4] cs4'
lpp5p4cs4'Elpp5p4cs4:last ↓[↑[`c[p5]]_p4] cs4' = ↓[last ↑[`c[p5]]_p4 cs4]
scs4'L:size cs4' <= size cs4 ?= iff (cs4 == [seq ↑[i]_ (↑[`c[p5]]_p4 ldisk) | i <- cs4'])

49e
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d591594
lpp5p4cs4'Elpp5p4cs4:last `c[p5] cs4' = ↓[last ↑[`c[p5]]_p4 cs4]
pp5p4Pcs4':path (move (rrel (n:=3))) `c[p5] cs4'

49e
598
1ee
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159459959a1f2
49e
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73ee4c71871881895083f350e50f51051151251351d59159459959a

size cs3 < size cs2
59e
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159459959a1f2

49e
5a9
size cs4 < m.+1
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159459959a1f2
Scs4:size cs4 < m.+1
49e
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73ee4c71871881895083f350e50f51051151251351d59159459959a1f2

size cs4 < size cs2
5ae
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159459959a1f25b1

49e
5ba
size cs4' < m.+1
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159459959a1f25b1
Scs4':size cs4' < m.+1
49e
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159459959a1f25b15c2

49e
5c6
size_rpeg ↓[c1] `p[p1, p] + 2 ^ n < size cs1 + (size cs3 + (size cs4).+1).+1
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159459959a1f25b15c2
IHc1:size_rpeg c2' p5 <= size cs3 ?= iff (cs3 == rpeg c2' p5)

5ca
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159459959a1f25b15c25cf
c2'E:c2' = `c[p3]

5ca
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159459959a1f25b15c25d4
IHc1:size (ppeg p3 p5) <= size cs3 ?= iff (cs3 == ppeg p3 p5)

5ca
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159459959a1f25b15c25d4
IHc1:(2 ^ n).-1 <= size cs3 ?= iff (cs3 == ppeg p3 p5)

5ca
5dd
p5 != p
7c33a533b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159459959a1f25b15c25d45de
p6Dp:p5 != p
5ca
7c326532b32c23d8432d32f33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159459959a1f25b15c25d45de5e6

5ca
7c326532b32c23d8432d33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159459959a1f25b15c25d45de5e6

last c1 ([seq ↑[i]_p1 | i <- cs1] ++ c2 :: [seq ↑[i]_p2 | i <- cs3] ++ ↑[`c[p5]]_p4 :: cs4) = `c[p] -> size_rpeg ↓[c1] `p[p1, p] + 2 ^ n < size cs1 + (size cs3 + (size cs4).+1).+1
7c326532b32c23d8432d33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159459959a1f25b15c25d45de5e6
lpp5p4cs4Epp:last ↑[`c[p5]]_p4 cs4 = `c[p]

5ca
5f3
last `c[p5] cs4' = `c[p]
7c33a533b32c23d8432d33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159459959a1f25b15c25d45de5e65f4
lpp5cs4'Epp:last `c[p5] cs4' = `c[p]
5ca
7c326532b32c23d8432d33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159459959a1f25b15c25d45de5e65f45fc

5ca
7c326532b32c23d8432d33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159459959a1f25b15c25d45de5e65f45fc
IHc2:size_rpeg `c[p5] p <= size cs4' ?= iff (cs4' == rpeg `c[p5] p)

5ca
7c326532b32c23d8432d33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159459959a1f25b15c25d45de5e65f45fc
IHc2:(2 ^ n).-1 <= size cs4' ?= iff (cs4' == ppeg p5 p)

5ca
609
size_rpeg ↓[c1] `p[p1, p] + (2 ^ n).-1.+1 < size cs1 + (size cs3 + (size cs4).+1).+1
609
size_rpeg ↓[c1] `p[p1, p] + (2 ^ n).-1 <= size cs1 + (size cs3 + size cs4)
609
size_rpeg ↓[c1] `p[p1, p] + (2 ^ n).-1 <= size cs3 + size cs4
609
size_rpeg ↓[c1] `p[p1, p] <= size cs3
7c33a533b32c23d8432d33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159459959a1f25b15c25d45de5e65f45fc60a
(2 ^ n).-1 <= size cs4
609
61e
7c326532b32c23d8432d33c39139639bc4c53a224453a03a83f3a93aa3ab3ac3c4d73dc3ee4c71871881895083f350e50f51051151251351d59159959a1f25b15c25d45de5e65f45fc60a

(2 ^ n).-1 <= size cs4'
by rewrite IHc2. Qed.
5
c1:configuration 3 n
23d

`d[c1, `c[p]]_rmove = size_rpeg c1 p
628
62a
`d[c1, `c[p]]_rmove <= size (rpeg c1 p) <= `d[c1, `c[p]]_rmove
62a
path rmove c1 (rpeg c1 p)
62a
last c1 (rpeg c1 p) = `c[p]
62a
true && (size (rpeg c1 p) <= `d[c1, `c[p]]_rmove)
633
62a
638
639
63d
62a
63a
62a
c1 `-->*_r `c[p]
562b23d
p1:seq (finfun_finType (ordinal_finType n) (ordinal_finType 3))
p1H:gpath rmove c1 `c[p] p1
63a
64a
63a
64a
size_rpeg c1 p <= size p1
64a
last c1 p1 = `c[p]
by apply: gpath_last p1H. Qed.
249
`d[c, `c[p]]_rmove <= (2 ^ n).-1
659
by rewrite gdist_size_rpeg; apply: size_rpeg_up. Qed. (******************************************************************************) (* Function that builds a path from a peg to a configuration *) (******************************************************************************) Definition lpeg n p (c : _ _ n) := rev (belast c (rpeg c p)).
23c
lpeg p `c[p , n] = [::]
65e
by rewrite /lpeg rpeg_perfect. Qed.
249
lpeg p c = [::] -> c = `c[p]
663
249
(rpeg c p = [::] -> c = `c[p]) -> lpeg p c = [::] -> c = `c[p]
51723d
a:configuration 3 n
l:seq (configuration 3 n)

(a :: l = [::] -> c = `c[p]) -> rev (c :: belast a l) = [::] -> c = `c[p]
by rewrite rev_cons; case: rev. Qed.
51723d
cs:=lpeg p c:seq (configuration 3 n)

path rmove `c[p] cs
673
51723d67639b

677
51723d39b

path (move (rrel (n:=3))) c (rpeg c p)
by apply: path_rpeg. Qed.
675
last `c[p] cs = c
683
67c
(let cs := rpeg c p in last c cs = `c[p]) -> last `c[p] cs = c
51723d39b62b6f

last c1 cs = `c[p] -> last `c[p] (rev (c :: belast c1 cs)) = c
by rewrite rev_cons last_rcons. Qed.
249
size_rpeg c p = size (lpeg p c)
691
by rewrite size_rev size_belast size_rpegE. Qed.
31f
path rmove `c[p] cs -> last `c[p] cs = c -> size_rpeg c p <= size cs ?= iff (cs == lpeg p c)
696
(* why this is so complicated???? *)
51723d6f
pPcs:path rmove `c[p] cs
lccsEc:last `c[p] cs = c

size_rpeg c p <= size cs ?= iff (cs == lpeg p c)
51723d6f69e69f39b

6a0
6a4
path rmove c (rev (belast `c[p] cs))
51723d6f69e69f39b
cPr:path rmove c (rev (belast `c[p] cs))
6a0
6ab
6a0
6ab
last c (rev (belast `c[p] cs)) = `c[p]
51723d6f69e69f39b6ac
lcrEp:last c (rev (belast `c[p] cs)) = `c[p]
6a0
51723d6f69e69f39b6ac
c3:configuration 3 n
c4

last (last c3 cs1) (rev (`c[p] :: belast c3 cs1)) = `c[p]
6b4
6b6
6a0
6b6
size_rpeg c p <= size (rev (belast `c[p] cs)) ?= iff (rev (belast `c[p] cs) == rpeg c p) -> size_rpeg c p <= size cs ?= iff (cs == lpeg p c)
6b6
size_rpeg c p <= size cs ?= iff (rev (belast `c[p] cs) == rpeg c p) -> size_rpeg c p <= size cs ?= iff (cs == rev (belast c (rpeg c p)))
51723d6f69e69f39b6ac6b7
u:=rev (belast `c[p] cs):seq (configuration 3 n)
v:=rpeg c p:seq (configuration 3 n)

size_rpeg c p <= size cs ?= iff (u == v) -> size_rpeg c p <= size cs ?= iff (cs == rev (belast c v))
6cc
(u == v) = (rev (c :: u) == rev (c :: v))
6cc
size_rpeg c p <= size cs ?= iff (rev (c :: u) == rev (c :: v)) -> size_rpeg c p <= size cs ?= iff (cs == rev (belast c v))
6cc
(u == v) = (rev u == rev v)
6d4
6cc
rev u = rev v -> u = v
6d4
6cc
6d6
6cc
size_rpeg c p <= size cs ?= iff (rev (c :: u) == last c v :: rev (belast c v)) -> size_rpeg c p <= size cs ?= iff (cs == rev (belast c v))
6cc
size_rpeg c p <= size cs ?= iff (cs == rev (belast c v)) && (`c[p] == last c v) -> size_rpeg c p <= size cs ?= iff (cs == rev (belast c v))
51723d6f69e69f39b6ac6b76cd6ce
Hcs:cs = rev (belast c v)

`c[p] = last c v
by rewrite last_rpeg. Qed. Fixpoint rhanoi3 {n : nat} := if n is n1.+1 return configuration 3 n -> configuration 3 n -> _ _ then fun c1 c2 => let p1 := c1 ldisk in let p2 := c2 ldisk in let c1' := ↓[c1] in let c2' := ↓[c2] in if p1 == p2 then [seq ↑[i]_p1 | i <- rhanoi3 c1' c2'] else let p := `p[p1, p2] in (* one jump *) let m1 := size_rpeg c1' p + size_rpeg c2' p in (* two jumps *) let m2 := size_rpeg c1' p2 + 2 ^ n1 + size_rpeg c2' p1 in if m1 <= m2 then [seq ↑[i]_p1 | i <- rpeg c1' p] ++ [seq ↑[i]_p2 | i <- `c[p] :: lpeg p c2'] else [seq ↑[i]_p1 | i <- rpeg c1' p2] ++ [seq ↑[i]_p | i <- `c[p2] :: ppeg p2 p1] ++ [seq ↑[i]_p2 | i <- `c[p1] :: lpeg p1 c2'] else fun _ _ => [::].
52da
cs:=rhanoi3 c1 c2:seq (configuration 3 n)

last c1 cs = c2
6f1
52da6f4396

6f5
52da396

last c1 (rhanoi3 c1 c2) = c2
3965
IH:forall c1 c2 : configuration 3 n, last c1 (rhanoi3 c1 c2) = c2
c1, c2:configuration 3 n.+1

last c1 (if c1 ldisk == c2 ldisk then [seq ↑[i]_(c1 ldisk) | i <- rhanoi3 ↓[c1] ↓[c2]] else if size_rpeg ↓[c1] `p[c1 ldisk, c2 ldisk] + size_rpeg ↓[c2] `p[c1 ldisk, c2 ldisk] <= size_rpeg ↓[c1] (c2 ldisk) + 2 ^ n + size_rpeg ↓[c2] (c1 ldisk) then [seq ↑[i]_(c1 ldisk) | i <- rpeg ↓[c1] `p[c1 ldisk, c2 ldisk]] ++ ↑[`c[`p[c1 ldisk, c2 ldisk]]]_(c2 ldisk) :: [seq ↑[i]_(c2 ldisk) | i <- lpeg `p[c1 ldisk, c2 ldisk] ↓[c2]] else [seq ↑[i]_(c1 ldisk) | i <- rpeg ↓[c1] (c2 ldisk)] ++ ↑[`c[c2 ldisk]]_(`p[c1 ldisk, c2 ldisk]) :: [seq ↑[i]_(`p[c1 ldisk, c2 ldisk]) | i <- ppeg (c2 ldisk) (c1 ldisk)] ++ ↑[`c[c1 ldisk]]_(c2 ldisk) :: [seq ↑[i]_(c2 ldisk) | i <- lpeg (c1 ldisk) ↓[c2]]) = c2
3965704705
p1:=c1 ldisk:(fun=> peg 3) ldisk
p2:=c2 ldisk:(fun=> peg 3) ldisk

last c1 (if p1 == p2 then [seq ↑[i]_p1 | i <- rhanoi3 ↓[c1] ↓[c2]] else if size_rpeg ↓[c1] `p[p1, p2] + size_rpeg ↓[c2] `p[p1, p2] <= size_rpeg ↓[c1] p2 + 2 ^ n + size_rpeg ↓[c2] p1 then [seq ↑[i]_p1 | i <- rpeg ↓[c1] `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- lpeg `p[p1, p2] ↓[c2]] else [seq ↑[i]_p1 | i <- rpeg ↓[c1] p2] ++ ↑[`c[p2]]_(`p[p1, p2]) :: [seq ↑[i]_(`p[p1, p2]) | i <- ppeg p2 p1] ++ ↑[`c[p1]]_p2 :: [seq ↑[i]_p2 | i <- lpeg p1 ↓[c2]]) = c2
396570470570b70c
c3:=↑[`c[`p[p1, p2]]]_p2:configuration 3 n.+1
c4:=↑[`c[p2]]_(`p[p1, p2]):configuration 3 n.+1
c5:=↑[`c[p1]]_p2:configuration 3 n.+1

last c1 (if p1 == p2 then [seq ↑[i]_p1 | i <- rhanoi3 ↓[c1] ↓[c2]] else if size_rpeg ↓[c1] `p[p1, p2] + size_rpeg ↓[c2] `p[p1, p2] <= size_rpeg ↓[c1] p2 + 2 ^ n + size_rpeg ↓[c2] p1 then [seq ↑[i]_p1 | i <- rpeg ↓[c1] `p[p1, p2]] ++ c3 :: [seq ↑[i]_p2 | i <- lpeg `p[p1, p2] ↓[c2]] else [seq ↑[i]_p1 | i <- rpeg ↓[c1] p2] ++ c4 :: [seq ↑[i]_(`p[p1, p2]) | i <- ppeg p2 p1] ++ c5 :: [seq ↑[i]_p2 | i <- lpeg p1 ↓[c2]]) = c2
396570470570b70c712713714
p:=`p[p1, p2]:peg 3

last c1 (if p1 == p2 then [seq ↑[i]_p1 | i <- rhanoi3 ↓[c1] ↓[c2]] else if size_rpeg ↓[c1] p + size_rpeg ↓[c2] p <= size_rpeg ↓[c1] p2 + 2 ^ n + size_rpeg ↓[c2] p1 then [seq ↑[i]_p1 | i <- rpeg ↓[c1] p] ++ c3 :: [seq ↑[i]_p2 | i <- lpeg p ↓[c2]] else [seq ↑[i]_p1 | i <- rpeg ↓[c1] p2] ++ c4 :: [seq ↑[i]_p | i <- ppeg p2 p1] ++ c5 :: [seq ↑[i]_p2 | i <- lpeg p1 ↓[c2]]) = c2
396570470570b70c71271371471a
p1Ep2:p1 = p2

last c1 [seq ↑[i]_p1 | i <- rhanoi3 ↓[c1] ↓[c2]] = c2
396570470570b70c71271371471a3f
last c1 (if size_rpeg ↓[c1] p + size_rpeg ↓[c2] p <= size_rpeg ↓[c1] p2 + 2 ^ n + size_rpeg ↓[c2] p1 then [seq ↑[i]_p1 | i <- rpeg ↓[c1] p] ++ c3 :: [seq ↑[i]_p2 | i <- lpeg p ↓[c2]] else [seq ↑[i]_p1 | i <- rpeg ↓[c1] p2] ++ c4 :: [seq ↑[i]_p | i <- ppeg p2 p1] ++ c5 :: [seq ↑[i]_p2 | i <- lpeg p1 ↓[c2]]) = c2
724
725
724
last c1 ([seq ↑[i]_p1 | i <- rpeg ↓[c1] p2] ++ c4 :: [seq ↑[i]_p | i <- ppeg p2 p1] ++ c5 :: [seq ↑[i]_p2 | i <- lpeg p1 ↓[c2]]) = c2
by rewrite last_cat /= last_cat /= last_map last_lpeg cunliftrK. Qed.
6f3
path rmove c1 cs
72e
6fa
730
6fe
path rmove c1 (rhanoi3 c1 c2)
3965
IH:forall c1 c2 : configuration 3 n, path rmove c1 (rhanoi3 c1 c2)
705

path rmove c1 (if c1 ldisk == c2 ldisk then [seq ↑[i]_(c1 ldisk) | i <- rhanoi3 ↓[c1] ↓[c2]] else if size_rpeg ↓[c1] `p[c1 ldisk, c2 ldisk] + size_rpeg ↓[c2] `p[c1 ldisk, c2 ldisk] <= size_rpeg ↓[c1] (c2 ldisk) + 2 ^ n + size_rpeg ↓[c2] (c1 ldisk) then [seq ↑[i]_(c1 ldisk) | i <- rpeg ↓[c1] `p[c1 ldisk, c2 ldisk]] ++ ↑[`c[`p[c1 ldisk, c2 ldisk]]]_(c2 ldisk) :: [seq ↑[i]_(c2 ldisk) | i <- lpeg `p[c1 ldisk, c2 ldisk] ↓[c2]] else [seq ↑[i]_(c1 ldisk) | i <- rpeg ↓[c1] (c2 ldisk)] ++ ↑[`c[c2 ldisk]]_(`p[c1 ldisk, c2 ldisk]) :: [seq ↑[i]_(`p[c1 ldisk, c2 ldisk]) | i <- ppeg (c2 ldisk) (c1 ldisk)] ++ ↑[`c[c1 ldisk]]_(c2 ldisk) :: [seq ↑[i]_(c2 ldisk) | i <- lpeg (c1 ldisk) ↓[c2]])
396573d70570b70c

path rmove c1 (if p1 == p2 then [seq ↑[i]_p1 | i <- rhanoi3 ↓[c1] ↓[c2]] else if size_rpeg ↓[c1] `p[p1, p2] + size_rpeg ↓[c2] `p[p1, p2] <= size_rpeg ↓[c1] p2 + 2 ^ n + size_rpeg ↓[c2] p1 then [seq ↑[i]_p1 | i <- rpeg ↓[c1] `p[p1, p2]] ++ ↑[`c[`p[p1, p2]]]_p2 :: [seq ↑[i]_p2 | i <- lpeg `p[p1, p2] ↓[c2]] else [seq ↑[i]_p1 | i <- rpeg ↓[c1] p2] ++ ↑[`c[p2]]_(`p[p1, p2]) :: [seq ↑[i]_(`p[p1, p2]) | i <- ppeg p2 p1] ++ ↑[`c[p1]]_p2 :: [seq ↑[i]_p2 | i <- lpeg p1 ↓[c2]])
396573d70570b70c712713714

path rmove c1 (if p1 == p2 then [seq ↑[i]_p1 | i <- rhanoi3 ↓[c1] ↓[c2]] else if size_rpeg ↓[c1] `p[p1, p2] + size_rpeg ↓[c2] `p[p1, p2] <= size_rpeg ↓[c1] p2 + 2 ^ n + size_rpeg ↓[c2] p1 then [seq ↑[i]_p1 | i <- rpeg ↓[c1] `p[p1, p2]] ++ c3 :: [seq ↑[i]_p2 | i <- lpeg `p[p1, p2] ↓[c2]] else [seq ↑[i]_p1 | i <- rpeg ↓[c1] p2] ++ c4 :: [seq ↑[i]_(`p[p1, p2]) | i <- ppeg p2 p1] ++ c5 :: [seq ↑[i]_p2 | i <- lpeg p1 ↓[c2]])
396573d70570b70c71271371471a

path rmove c1 (if p1 == p2 then [seq ↑[i]_p1 | i <- rhanoi3 ↓[c1] ↓[c2]] else if size_rpeg ↓[c1] p + size_rpeg ↓[c2] p <= size_rpeg ↓[c1] p2 + 2 ^ n + size_rpeg ↓[c2] p1 then [seq ↑[i]_p1 | i <- rpeg ↓[c1] p] ++ c3 :: [seq ↑[i]_p2 | i <- lpeg p ↓[c2]] else [seq ↑[i]_p1 | i <- rpeg ↓[c1] p2] ++ c4 :: [seq ↑[i]_p | i <- ppeg p2 p1] ++ c5 :: [seq ↑[i]_p2 | i <- lpeg p1 ↓[c2]])
396573d70570b70c71271371471a720

path rmove c1 [seq ↑[i]_p1 | i <- rhanoi3 ↓[c1] ↓[c2]]
396573d70570b70c71271371471a3f
path rmove c1 (if size_rpeg ↓[c1] p + size_rpeg ↓[c2] p <= size_rpeg ↓[c1] p2 + 2 ^ n + size_rpeg ↓[c2] p1 then [seq ↑[i]_p1 | i <- rpeg ↓[c1] p] ++ c3 :: [seq ↑[i]_p2 | i <- lpeg p ↓[c2]] else [seq ↑[i]_p1 | i <- rpeg ↓[c1] p2] ++ c4 :: [seq ↑[i]_p | i <- ppeg p2 p1] ++ c5 :: [seq ↑[i]_p2 | i <- lpeg p1 ↓[c2]])
755
756
755
path rmove c1 [seq ↑[i]_p1 | i <- rpeg ↓[c1] p]
755
last c1 [seq ↑[i]_p1 | i <- rpeg ↓[c1] p] `-->_r c3
755
path rmove c3 [seq ↑[i]_p2 | i <- lpeg p ↓[c2]]
755
path rmove c1 [seq ↑[i]_p1 | i <- rpeg ↓[c1] p2]
755
last c1 [seq ↑[i]_p1 | i <- rpeg ↓[c1] p2] `-->_r c4
755
path rmove c4 ([seq ↑[i]_p | i <- ppeg p2 p1] ++ c5 :: [seq ↑[i]_p2 | i <- lpeg p1 ↓[c2]])
75b
755
760
761763765767
76b
755
↑[`c[p]]_(c1 ldisk) `-->_r c3
76d
755
[/\ rrel (↑[`c[p]]_(c1 ldisk) ldisk) (c3 ldisk), forall d2 : ordinal_finType n.+1, ldisk != d2 -> ↑[`c[p]]_(c1 ldisk) d2 = c3 d2, on_top ldisk ↑[`c[p]]_(c1 ldisk) & on_top ldisk c3]
76d
755
rrel (↑[`c[p]]_(c1 ldisk) ldisk) (c3 ldisk)
396573d70570b70c71271371471a3f
d:ordinal_finType n.+1
dmDd:ldisk != d
↑[`c[p]]_(c1 ldisk) d = c3 d
755
on_top ldisk ↑[`c[p]]_(c1 ldisk)
755
on_top ldisk c3
761763765767
778
77d
780
781783761763765767
787
396573d70570b70c71271371471a3f77e77f
j:'I_1
jE:d = j + n

`c[c1 ldisk] j = `c[p2] j
789
755
782
783761763765767
793
396573d70570b70c71271371471a3f77e

c1 ldisk = match tsplit d with | inl j => `c[c1 ldisk] j | inr j => `c[p] j end -> ldisk <= d
795
396573d70570b70c71271371471a3f77e
j:'I_n

c1 ldisk == `c[p] j -> ldisk <= d
396573d70570b70c71271371471a3f77e78f790
c1 ldisk = `c[c1 ldisk] j -> ldisk <= d
783761763765767
7a4
7a5
795
755
784
76d
79a
p2 = match tsplit d with | inl j => `c[p2] j | inr j => `c[`p[p1, p2]] j end -> n <= d
76d
79f
p2 == `c[`p[p1, p2]] j -> n <= d
76d
755
762
763765767
7b5
755
764
765767
7ba
755
766
767
7bf
755
↑[`c[p2]]_(c1 ldisk) `-->_r c4
7c1
755
rrel (c1 ldisk) `p[p1, p2]
396573d70570b70c71271371471a3f
d2:ordinal_finType n.+1
ldisk != d2 -> match tsplit d2 with | inl j => `c[c1 ldisk] j | inr j => `c[p2] j end = match tsplit d2 with | inl j => `c[`p[p1, p2]] j | inr j => `c[p2] j end
755
on_top ldisk ↑[`c[p2]]_(c1 ldisk)
755
on_top ldisk c4
767
7c8
7cd
7cf
7d07d2767
7d6
396573d70570b70c71271371471a3f7ce78f
d2E:d2 = j + n

ldisk = d2
7d8
755
7d1
7d2767
7e1
7cd
↑[`c[p2]]_(c1 ldisk) ldisk = ↑[`c[p2]]_(c1 ldisk) d2 -> ldisk <= d2
7e3
7cd
c1 ldisk = match tsplit d2 with | inl j => `c[c1 ldisk] j | inr j => `c[p2] j end -> n <= d2
7e3
396573d70570b70c71271371471a3f7ce
k:'I_n

c1 ldisk == `c[p2] k -> n <= d2
7e3
755
7d3
7c1
7cd
c4 ldisk = c4 d2 -> ldisk <= d2
7c1
7cd
`p[p1, p2] = match tsplit d2 with | inl j => `c[`p[p1, p2]] j | inr j => `c[p2] j end -> n <= d2
7c1
7f0
`p[p1, p2] == `c[p2] k -> n <= d2
7c1
755
768
755
path rmove c4 [seq ↑[i]_p | i <- ppeg p2 p1]
755
last c4 [seq ↑[i]_p | i <- ppeg p2 p1] `-->_r c5
755
path rmove c5 [seq ↑[i]_p2 | i <- lpeg p1 ↓[c2]]
806
755
p2 != p1
809
755
80b
80c
814
755
↑[`c[p1]]_p `-->_r c5
816
755
rrel p p2
7cd
ldisk != d2 -> match tsplit d2 with | inl j => `c[p] j | inr j => `c[p1] j end = match tsplit d2 with | inl j => `c[p2] j | inr j => `c[p1] j end
755
on_top ldisk ↑[`c[p1]]_p
755
on_top ldisk c5
80c
81d
7cd
822
82382580c
829
7dc82b
755
824
82580c
830
7cd
↑[`c[p1]]_p ldisk = ↑[`c[p1]]_p d2 -> ldisk <= d2
832
7cd
p = match tsplit d2 with | inl j => `c[p] j | inr j => `c[p1] j end -> n <= d2
832
7f0
p == `c[p1] k -> n <= d2
832
755
826
816
7cd
c5 ldisk = c5 d2 -> ldisk <= d2
816
7cd
p2 = match tsplit d2 with | inl j => `c[p2] j | inr j => `c[p1] j end -> n <= d2
816
7f0
p2 == `c[p1] k -> n <= d2
816
755
80d
by rewrite path_liftr // path_lpeg. Qed.
52da6f

path rmove c1 cs -> last c1 cs = c2 -> size (rhanoi3 c1 c2) <= size cs
853
52da6f396

856
52da6f39639b

856
39639b5
IH:forall (c1 c2 : configuration 3 n) (cs : seq (configuration 3 n)), path rmove c1 cs -> last c1 cs = c2 -> size (rhanoi3 c1 c2) <= size cs
70584

path rmove c1 cs -> last c1 cs = c2 -> size (if c1 ldisk == c2 ldisk then [seq ↑[i]_(c1 ldisk) | i <- rhanoi3 ↓[c1] ↓[c2]] else if size_rpeg ↓[c1] `p[c1 ldisk, c2 ldisk] + size_rpeg ↓[c2] `p[c1 ldisk, c2 ldisk] <= size_rpeg ↓[c1] (c2 ldisk) + 2 ^ n + size_rpeg ↓[c2] (c1 ldisk) then [seq ↑[i]_(c1 ldisk) | i <- rpeg ↓[c1] `p[c1 ldisk, c2 ldisk]] ++ ↑[`c[`p[c1 ldisk, c2 ldisk]]]_(c2 ldisk) :: [seq ↑[i]_(c2 ldisk) | i <- lpeg `p[c1 ldisk, c2 ldisk] ↓[c2]] else [seq ↑[i]_(c1 ldisk) | i <- rpeg ↓[c1] (c2 ldisk)] ++ ↑[`c[c2 ldisk]]_(`p[c1 ldisk, c2 ldisk]) :: [seq ↑[i]_(`p[c1 ldisk, c2 ldisk]) | i <- ppeg (c2 ldisk) (c1 ldisk)] ++ ↑[`c[c1 ldisk]]_(c2 ldisk) :: [seq ↑[i]_(c2 ldisk) | i <- lpeg (c1 ldisk) ↓[c2]]) <= size cs
39639b586470584
p:=`p[c1 ldisk, c2 ldisk]:peg 3
70b70c

path rmove c1 cs -> last c1 cs = c2 -> size (if p1 == p2 then [seq ↑[i]_p1 | i <- rhanoi3 ↓[c1] ↓[c2]] else if size_rpeg ↓[c1] p + size_rpeg ↓[c2] p <= size_rpeg ↓[c1] p2 + 2 ^ n + size_rpeg ↓[c2] p1 then [seq ↑[i]_p1 | i <- rpeg ↓[c1] p] ++ ↑[`c[p]]_p2 :: [seq ↑[i]_p2 | i <- lpeg p ↓[c2]] else [seq ↑[i]_p1 | i <- rpeg ↓[c1] p2] ++ ↑[`c[p2]]_p :: [seq ↑[i]_p | i <- ppeg p2 p1] ++ ↑[`c[p1]]_p2 :: [seq ↑[i]_p2 | i <- lpeg p1 ↓[c2]]) <= size cs
39639b58647058486a70b70c72032e
lc1csEc2:last c1 cs = c2

size [seq ↑[i]_p1 | i <- rhanoi3 ↓[c1] ↓[c2]] <= size cs
39639b58647058486a70b70c3f32e870
size (if size_rpeg ↓[c1] p + size_rpeg ↓[c2] p <= size_rpeg ↓[c1] p2 + 2 ^ n + size_rpeg ↓[c2] p1 then [seq ↑[i]_p1 | i <- rpeg ↓[c1] p] ++ ↑[`c[p]]_p2 :: [seq ↑[i]_p2 | i <- lpeg p ↓[c2]] else [seq ↑[i]_p1 | i <- rpeg ↓[c1] p2] ++ ↑[`c[p2]]_p :: [seq ↑[i]_p | i <- ppeg p2 p1] ++ ↑[`c[p1]]_p2 :: [seq ↑[i]_p2 | i <- lpeg p1 ↓[c2]]) <= size cs
39639b58647058486a70b70c72032e870
lcsmEc1m:last c1 cs ldisk = p1

871
872
39639b58647058486a70b70c72032e87087ac434f
lc1csElcs1:last ↓[c1] cs1 = ↓[last c1 cs]

size [seq ↑[i]_p1 | i <- rhanoi3 ↓[c1] ↓[c2]] <= size cs1
872
874
875
39639b58647058486a70b70c3f32e870
u:=size_rpeg ↓[c1] p + size_rpeg ↓[c2] p:nat
v:=size_rpeg ↓[c1] p2 + 2 ^ n + size_rpeg ↓[c2] p1:nat

size (if u <= v then [seq ↑[i]_p1 | i <- rpeg ↓[c1] p] ++ ↑[`c[p]]_p2 :: [seq ↑[i]_p2 | i <- lpeg p ↓[c2]] else [seq ↑[i]_p1 | i <- rpeg ↓[c1] p2] ++ ↑[`c[p2]]_p :: [seq ↑[i]_p | i <- ppeg p2 p1] ++ ↑[`c[p1]]_p2 :: [seq ↑[i]_p2 | i <- lpeg p1 ↓[c2]]) <= size cs
887
minn u v < size cs -> size (if u <= v then [seq ↑[i]_p1 | i <- rpeg ↓[c1] p] ++ ↑[`c[p]]_p2 :: [seq ↑[i]_p2 | i <- lpeg p ↓[c2]] else [seq ↑[i]_p1 | i <- rpeg ↓[c1] p2] ++ ↑[`c[p2]]_p :: [seq ↑[i]_p | i <- ppeg p2 p1] ++ ↑[`c[p1]]_p2 :: [seq ↑[i]_p2 | i <- lpeg p1 ↓[c2]]) <= size cs
887
minn u v < size cs
39639b58647058486a70b70c3f32e870888889
H1:u <= v
Lscs:u < size cs

u < size cs
39639b58647058486a70b70c3f32e870888889
H1:v < u
Lscs:v < size cs
(size_rpeg ↓[c1] p2 + (size (ppeg p2 p1) + size_rpeg ↓[c2] p1)).+1 < size cs
890
89b
89e
88f
39639b58647058486a70b70c3f32e87088888989c

size_rpeg ↓[c1] p2 + (size (ppeg p2 p1) + size_rpeg ↓[c2] p1) < v
88f
8a5
size (ppeg p2 p1) < 2 ^ n
88f
887
891
39639b58647058486a70b70c3f32e870888889391

891
39639b586470586a70b70c3f8888893917c
IH1:forall cs : seq (configuration 3 n.+1), size cs < m -> path rmove c1 cs -> last c1 cs = c2 -> minn u v < size cs
84
Lcs:size cs < m.+1
32e870

891
39639b586470586a70b70c3f8888893917c8b6848b78703a03a1
csE:cs = [seq ↑[i]_(c1 ldisk) | i <- cs']
3a4

891
39639b586470586a70b70c3f8888893917c8b6848b7870c4c5
p1':=c1 ldisk:peg 3
c6
p4:=`p[p1', p3]:peg 3
3a0
c3:=↑[`c[p4]]_p3:configuration 3 n.+1
p1Dp3:p1' != p3
p1Rp3:rrel p1' p3
lc1'cs1Epp4:last c1' cs1 = `c[p4]
csE:cs = [seq ↑[i]_p1' | i <- cs1] ++ c3 :: cs2
3ac
c3Pcs2:path (move (rrel (n:=3))) c3 cs2
891
39639b586470586a70b70c8888893917c
IH1:forall cs : seq (configuration 3 n.+1), size cs < m -> path rmove c1 cs -> last c1 cs = c2 -> minn u v < size cs
848b78703a03a18bc3a4

p1 = p2
8bd
8cb
f (last c1 cs) = f c2 -> p1 = p2
8bd
8cb
↑[last ↓[c1] cs']_(c1 ldisk) ldisk = c2 ldisk -> p1 = p2
8bd
8bf
891
39639b586470586a70b70c3f8888893917c8b6848b7870c4c58c0c68c13a08c28c38c48c58c63ac8c7
p1'Ep1:p1' = p1

891
39639b586470586a70b70c3f8888893917c8b684870c4c58c0c68c13a08c28c38c48c58c63ac8c78dd
Lcs:size cs1 + size cs2 < m

minn u v < (size cs1 + size cs2).+1
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8c78dd8e2
lc3cs2Ec2:last c3 cs2 = c2

8e3
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8c78dd8e28e8
p3Ep2:p3 = p2

8e3
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8c78dd8e28e850
8e3
8ec
p4 = p
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8c78dd8e28e88ed
p4Ep:p4 = p
8e3
8ef
8ec
p3 != p
8f5
8f7
8e3
8ee
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8c78dd8e28e88ed8f83fd
pp4Pcs2':path (move (rrel (n:=3))) ↓[c3] cs2'
pp4cs2'E:last ↓[c3] cs2' = ↓[last c3 cs2]
scs2'Lscs2:size cs2' <= size cs2 ?= iff (cs2 == [seq ↑[i]_ (c3 ldisk) | i <- cs2'])

8e3
8ee
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8c78dd8e28e88ed8f83fd906
pp4Pcs2':path (move (rrel (n:=3))) `c[p4] cs2'
pp4cs2'E:last `c[p4] cs2' = ↓[last c3 cs2]

8e3
8ee
90a
minn u v <= size cs1 + size cs2'
8ee
90a
u <= size cs1 + size cs2'
8ee
90a
383
90a
size_rpeg ↓[c2] p <= size cs2'
8ef
90a
355
918
90a
91a
8ee
90a
last `c[p4] cs2' = ↓[c2]
8ee
8f0
8e3
8f0
4c3
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8c78dd8e28e8504c7
8e3
92d
8e3
92d
p4 = p2
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8c78dd8e28e8504c7
p4Ep2:p4 = p2
8e3
92d
p4 == p2
935
92d
(p1 != p2) && ~~ ((p1 != p2) && (p2 != p2))
92d
p1 != `p[p1, p2]
936
92d
943
935
937
8e3
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8dd8e28e8504c7938
c3':=↓[c3]:configuration 3 n
4db
p5:=c3 ldisk:peg 3
cs2E:cs2 = [seq ↑[i]_p5 | i <- cs2']
c3'Pcs2':path (move (rrel (n:=3))) c3' cs2'

8e3
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8dd8e28e8504c793818718894f
p6:peg 3
p7:=`p[p5, p6]:peg 3
94e
c4:=↑[`c[p7]]_p6:configuration 3 n.+1
p5Dp6:p5 != p6
p5p6:rrel p5 p6
c3'cs3Epp7:last c3' cs3 = `c[p7]
cs2E:cs2 = [seq ↑[i]_p5 | i <- cs3] ++ c4 :: cs4
c3'Pcs3:path (move (rrel (n:=3))) c3' cs3
c4Pcs4:path (move (rrel (n:=3))) c4 cs4
8e3
94d
f (last c3 cs2) = f c2 -> minn u v < (size cs1 + size cs2).+1
952
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8dd8e28e8504c793894e4db94f9509518ed

minn u v < (size cs1 + size [seq ↑[i]_p5 | i <- cs2']).+1
952
954
8e3
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8dd8e28e8504c793818718894f95595694e95795895995a95b95c95d
p5Ep:p5 = p

8e3
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8dd504c793818718894f95595694e95795895995a95b95c95d96e
lc6cs4Ec2:last c4 cs4 = c2
Lcs:size cs1 + (size cs3 + (size cs4).+1) < m

minn u v < (size cs1 + (size cs3 + (size cs4).+1)).+1
972
minn u v <= size cs1 + ((size cs3).+1 + size cs4)
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8dd504c793818718894f95595694e95795895995a95b95c95d96e973974
p6Ep1:p6 = p1

979
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8dd504c793818718894f95595694e95795895995a95b95c95d96e973974
p6Dp1:p6 != p1
979
97d
p7 = p2
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8dd504c793818718894f95595694e95795895995a95b95c95d96e97397497e
p7Ep2:p7 = p2
979
980
97d
p7 == p2
987
989
979
97f
989
minn u v <= size ([seq ↑[i]_p1 | i <- cs1] ++ cs4)
989
size ([seq ↑[i]_p1 | i <- cs1] ++ cs4) <= size cs1 + ((size cs3).+1 + size cs4)
980
989
size ([seq ↑[i]_p1 | i <- cs1] ++ cs4) < m
989
path rmove c1 ([seq ↑[i]_p1 | i <- cs1] ++ cs4)
989
last c1 ([seq ↑[i]_p1 | i <- cs1] ++ cs4) = c2
997980
99a
989
99f
9a0997980
9a4
989
path (move (rrel (n:=3))) ↓[c1] cs1 && path rmove (last c1 [seq ↑[i]_p1 | i <- cs1]) cs4
9a6
989
true && path rmove (last c1 [seq ↑[i]_p1 | i <- cs1]) cs4
9a6
989
9a1
996
989
last ↑[last ↓[c1] cs1]_(c1 ldisk) cs4 = c2
996
989
998
97f
981
979
981
p6 = p2
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8dd504c793818718894f95595694e95795895995a95b95c95d96e973974982
p6Ep2:p6 = p2
979
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8dd504c793818718894f95595694e95795895995a95b95c95d96e973974982
p6Dp2:p6 != p2

9c0
9c1
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8dd504c793818718894f95595694e95795995a95b95c95d96e9739749829c9

p5 == p6
9c1
9c3
979
9c3
p7 = p1
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8dd504c793818718894f95595694e95795895995a95b95c95d96e9739749829c4
p7Ep1:p7 = p1
979
9c3
p7 == p1
9d6
9d8
979
9d8
v <= size cs1 + ((size cs3).+1 + size cs4)
9d8
size_rpeg ↓[c1] p2 <= size cs1
9d8
2 ^ n + size_rpeg ↓[c2] p1 <= (size cs3).+1 + size cs4
9d8
last ↓[c1] cs1 = `c[p2]
9e9
9d8
9eb
9d8
2 ^ n <= (size cs3).+1
9d8
size_rpeg ↓[c2] p1 <= size cs4
9d8
1ea
9f7
9d8
size_rpeg ↓[c3] p1 = (2 ^ n).-1
9d8
size_rpeg ↓[c3] p1 <= size cs3
9f8
9d8
a03
9f7
9d8
last ↓[c3] cs3 = `c[p1]
9f7
9d8
9f9
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8dd504c793818718894f95595694e95795895995a95b95c95d96e9739749829c49d9591
c4'Pcs4':path (move (rrel (n:=3))) ↓[c4] cs4'
lc4'cs4'Elc4cs4:last ↓[c4] cs4' = ↓[last c4 cs4]
Lcs4':size cs4' <= size cs4

9f9
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8dd504c793818718894f95595694e95795895995a95b95c95d96e9739749829c49d9591a13a14
c4'Pcs4':path (move (rrel (n:=3))) `c[p1] cs4'

9f9
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8dd504c793818718894f95595694e95795895995a95b95c95d96e9739749829c49d9591a14a19
lc4'cs4'Elc4cs4:last `c[p1] cs4' = ↓[last c4 cs4]

9f9
39639b586470586a70b70c3f8888893917c8b684c4c58c0c68c13a08c28c38c48c58c63ac8dd504c793818718894f95595694e95795895995a95b95c95d96e9739749829c49d9591a19a1e

size_rpeg ↓[c2] p1 <= size cs4'
a22
last `c[p1] cs4' = ↓[c2]
by rewrite lc4'cs4'Elc4cs4 lc6cs4Ec2. Qed. Fixpoint size_rhanoi3 {n : nat} : _ _ n -> _ _ n -> nat := if n is n1.+1 then fun c1 c2 : configuration 3 n1.+1 => let p1 := c1 ldisk in let p2 := c2 ldisk in let c1' := ↓[c1] in let c2' := ↓[c2] in if p1 == p2 then size_rhanoi3 c1' c2' else (* one jump *) let p := `p[p1, p2] in let m1 := size_rpeg c1' p + size_rpeg c2' p in (* two jumps *) let m2 := size_rpeg c1' p2 + 2 ^ n1 + size_rpeg c2' p1 in (minn m1 m2).+1 else fun _ _ => 0. (* size computes the size *)
2d9
size_rhanoi3 c1 c2 = size (rhanoi3 c1 c2)
a29
5
IH:forall c1 c2 : configuration 3 n, size_rhanoi3 c1 c2 = size (rhanoi3 c1 c2)
705

(if c1 ldisk == c2 ldisk then size_rhanoi3 ↓[c1] ↓[c2] else (minn (size_rpeg ↓[c1] `p[c1 ldisk, c2 ldisk] + size_rpeg ↓[c2] `p[c1 ldisk, c2 ldisk]) (size_rpeg ↓[c1] (c2 ldisk) + 2 ^ n + size_rpeg ↓[c2] (c1 ldisk))).+1) = size (if c1 ldisk == c2 ldisk then [seq ↑[i]_(c1 ldisk) | i <- rhanoi3 ↓[c1] ↓[c2]] else if size_rpeg ↓[c1] `p[c1 ldisk, c2 ldisk] + size_rpeg ↓[c2] `p[c1 ldisk, c2 ldisk] <= size_rpeg ↓[c1] (c2 ldisk) + 2 ^ n + size_rpeg ↓[c2] (c1 ldisk) then [seq ↑[i]_(c1 ldisk) | i <- rpeg ↓[c1] `p[c1 ldisk, c2 ldisk]] ++ ↑[`c[`p[c1 ldisk, c2 ldisk]]]_(c2 ldisk) :: [seq ↑[i]_(c2 ldisk) | i <- lpeg `p[c1 ldisk, c2 ldisk] ↓[c2]] else [seq ↑[i]_(c1 ldisk) | i <- rpeg ↓[c1] (c2 ldisk)] ++ ↑[`c[c2 ldisk]]_(`p[c1 ldisk, c2 ldisk]) :: [seq ↑[i]_(`p[c1 ldisk, c2 ldisk]) | i <- ppeg (c2 ldisk) (c1 ldisk)] ++ ↑[`c[c1 ldisk]]_(c2 ldisk) :: [seq ↑[i]_(c2 ldisk) | i <- lpeg (c1 ldisk) ↓[c2]])
5a31705
E:c1 ldisk = c2 ldisk

size_rhanoi3 ↓[c1] ↓[c2] = size [seq ↑[i]_(c1 ldisk) | i <- rhanoi3 ↓[c1] ↓[c2]]
5a31705
NE:c1 ldisk != c2 ldisk
(minn (size_rpeg ↓[c1] `p[c1 ldisk, c2 ldisk] + size_rpeg ↓[c2] `p[c1 ldisk, c2 ldisk]) (size_rpeg ↓[c1] (c2 ldisk) + 2 ^ n + size_rpeg ↓[c2] (c1 ldisk))).+1 = size (if size_rpeg ↓[c1] `p[c1 ldisk, c2 ldisk] + size_rpeg ↓[c2] `p[c1 ldisk, c2 ldisk] <= size_rpeg ↓[c1] (c2 ldisk) + 2 ^ n + size_rpeg ↓[c2] (c1 ldisk) then [seq ↑[i]_(c1 ldisk) | i <- rpeg ↓[c1] `p[c1 ldisk, c2 ldisk]] ++ ↑[`c[`p[c1 ldisk, c2 ldisk]]]_(c2 ldisk) :: [seq ↑[i]_(c2 ldisk) | i <- lpeg `p[c1 ldisk, c2 ldisk] ↓[c2]] else [seq ↑[i]_(c1 ldisk) | i <- rpeg ↓[c1] (c2 ldisk)] ++ ↑[`c[c2 ldisk]]_(`p[c1 ldisk, c2 ldisk]) :: [seq ↑[i]_(`p[c1 ldisk, c2 ldisk]) | i <- ppeg (c2 ldisk) (c1 ldisk)] ++ ↑[`c[c1 ldisk]]_(c2 ldisk) :: [seq ↑[i]_(c2 ldisk) | i <- lpeg (c1 ldisk) ↓[c2]])
a3b
a3d
5a31705a3c86a

(minn (size_rpeg ↓[c1] p + size_rpeg ↓[c2] p) (size_rpeg ↓[c1] (c2 ldisk) + 2 ^ n + size_rpeg ↓[c2] (c1 ldisk))).+1 = size (if size_rpeg ↓[c1] p + size_rpeg ↓[c2] p <= size_rpeg ↓[c1] (c2 ldisk) + 2 ^ n + size_rpeg ↓[c2] (c1 ldisk) then [seq ↑[i]_(c1 ldisk) | i <- rpeg ↓[c1] p] ++ ↑[`c[p]]_(c2 ldisk) :: [seq ↑[i]_(c2 ldisk) | i <- lpeg p ↓[c2]] else [seq ↑[i]_(c1 ldisk) | i <- rpeg ↓[c1] (c2 ldisk)] ++ ↑[`c[c2 ldisk]]_p :: [seq ↑[i]_p | i <- ppeg (c2 ldisk) (c1 ldisk)] ++ ↑[`c[c1 ldisk]]_(c2 ldisk) :: [seq ↑[i]_(c2 ldisk) | i <- lpeg (c1 ldisk) ↓[c2]])
5a31705a3c86a
x:=size_rpeg ↓[c1] p:nat
y:=size_rpeg ↓[c2] p:nat

(minn (x + y) (size_rpeg ↓[c1] (c2 ldisk) + 2 ^ n + size_rpeg ↓[c2] (c1 ldisk))).+1 = size (if x + y <= size_rpeg ↓[c1] (c2 ldisk) + 2 ^ n + size_rpeg ↓[c2] (c1 ldisk) then [seq ↑[i]_(c1 ldisk) | i <- rpeg ↓[c1] p] ++ ↑[`c[p]]_(c2 ldisk) :: [seq ↑[i]_(c2 ldisk) | i <- lpeg p ↓[c2]] else [seq ↑[i]_(c1 ldisk) | i <- rpeg ↓[c1] (c2 ldisk)] ++ ↑[`c[c2 ldisk]]_p :: [seq ↑[i]_p | i <- ppeg (c2 ldisk) (c1 ldisk)] ++ ↑[`c[c1 ldisk]]_(c2 ldisk) :: [seq ↑[i]_(c2 ldisk) | i <- lpeg (c1 ldisk) ↓[c2]])
5a31705a3c86aa4aa4b
z:=size_rpeg ↓[c1] (c2 ldisk):nat
t:=size_rpeg ↓[c2] (c1 ldisk):nat

(minn (x + y) (z + 2 ^ n + t)).+1 = size (if x + y <= z + 2 ^ n + t then [seq ↑[i]_(c1 ldisk) | i <- rpeg ↓[c1] p] ++ ↑[`c[p]]_(c2 ldisk) :: [seq ↑[i]_(c2 ldisk) | i <- lpeg p ↓[c2]] else [seq ↑[i]_(c1 ldisk) | i <- rpeg ↓[c1] (c2 ldisk)] ++ ↑[`c[c2 ldisk]]_p :: [seq ↑[i]_p | i <- ppeg (c2 ldisk) (c1 ldisk)] ++ ↑[`c[c1 ldisk]]_(c2 ldisk) :: [seq ↑[i]_(c2 ldisk) | i <- lpeg (c1 ldisk) ↓[c2]])
a50
(minn (x + y) (z + 2 ^ n + t)).+1 = (if x + y <= z + 2 ^ n + t then size ([seq ↑[i]_(c1 ldisk) | i <- rpeg ↓[c1] p] ++ ↑[`c[p]]_(c2 ldisk) :: [seq ↑[i]_(c2 ldisk) | i <- lpeg p ↓[c2]]) else size ([seq ↑[i]_(c1 ldisk) | i <- rpeg ↓[c1] (c2 ldisk)] ++ ↑[`c[c2 ldisk]]_p :: [seq ↑[i]_p | i <- ppeg (c2 ldisk) (c1 ldisk)] ++ ↑[`c[c1 ldisk]]_(c2 ldisk) :: [seq ↑[i]_(c2 ldisk) | i <- lpeg (c1 ldisk) ↓[c2]]))
a50
(minn (x + y) (z + 2 ^ n + t)).+1 = (if x + y <= z + 2 ^ n + t then size (rpeg ↓[c1] p) + (size (lpeg p ↓[c2])).+1 else size (rpeg ↓[c1] (c2 ldisk)) + (size (ppeg (c2 ldisk) (c1 ldisk)) + (size (lpeg (c1 ldisk) ↓[c2])).+1).+1)
a50
(minn (x + y) (z + 2 ^ n + t)).+1 = (if x + y <= z + 2 ^ n + t then size_rpeg ↓[c1] p + (size_rpeg ↓[c2] p).+1 else size_rpeg ↓[c1] (c2 ldisk) + (size (ppeg (c2 ldisk) (c1 ldisk)) + (size_rpeg ↓[c2] (c1 ldisk)).+1).+1)
a50
(minn (x + y) (z + 2 ^ n + t)).+1 = (if x + y <= z + 2 ^ n + t then x + y.+1 else z + (size (ppeg (c2 ldisk) (c1 ldisk)) + t.+1).+1)
a50
(minn (x + y) (z + 2 ^ n + t)).+1 = (if x + y <= z + 2 ^ n + t then x + y.+1 else z + (2 ^ n + t).+1)
a50
(minn (x + y) (z + 2 ^ n + t)).+1 = (if x + y <= z + 2 ^ n + t then (x + y).+1 else (z + (2 ^ n + t)).+1)
a50
(if x + y < z + 2 ^ n + t then x + y else z + 2 ^ n + t).+1 = (if x + y <= z + 2 ^ n + t then (x + y).+1 else (z + 2 ^ n + t).+1)
5a31705a3c86aa4aa4ba51a52
LL1:z + 2 ^ n + t <= x + y
LL2:x + y <= z + 2 ^ n + t

(z + 2 ^ n + t).+1 = (x + y).+1
5a31705a3c86aa4aa4ba51a52
LL1:x + y < z + 2 ^ n + t
LL2:z + 2 ^ n + t < x + y
(x + y).+1 = (z + 2 ^ n + t).+1
a79
a7c
by congr (_.+1); apply/eqP; rewrite eqn_leq ltnW // ltnW. Qed.
2d9
`d[c1, c2]_rmove = size_rhanoi3 c1 c2
a81
2d9
`d[c1, c2]_rmove <= size_rhanoi3 c1 c2 <= `d[c1, c2]_rmove
2d9
738
2d96ff
2d9
size (rhanoi3 c1 c2) <= `d[c1, c2]_rmove
a8a
2d9
6ff
a8e
a92
2d9
a8f
52da64b
p1H:gpath rmove c1 c2 p1

a8f
a9c
last c1 p1 = c2
by apply: gpath_last p1H. Qed. End Hanoi3.