/-- `andThen f g` is the chain "do `f`, then do `g` to the result". Later you will meet itwritten `g ∘ f`, read "`g` after `f`". -/def andThen {α : Type} (f g : α → α) : α → α := fun x => g (f x)
never_agreetheoremProved here from basic factspropext, Quot.sound
never_agreeLean 4Proved here from basic factsFormally verified
/-- So the two orders **never** give the same result, whatever number you start with. -/theorem never_agree (n : Nat) : andThen addFive double n ≠ andThen double addFive n := by rw [add_then_double] omega
adding_commutestheoremProved here from basic factspropext, Quot.sound
adding_commutesLean 4Proved here from basic factsFormally verified
/-- But some actions can be done in either order: "add `a`, then add `b`" is the same action as"add `b`, then add `a`", for every starting number. -/theorem adding_commutes (a b : Nat) : andThen (· + a) (· + b) = andThen (· + b) (· + a) := by funext n show n + a + b = n + b + a omega
multiplying_commutestheoremApplies a library theorempropext, Quot.sound
multiplying_commutesLean 4Applies a library theoremFormally verified
/-- Likewise "multiply by `a`, then by `b`" is the same as "multiply by `b`, then by `a`". Thisapplies core Lean's `Nat.mul_right_comm`. -/theorem multiplying_commutes (a b : Nat) : andThen (· * a) (· * b) = andThen (· * b) (· * a) := by funext n exact Nat.mul_right_comm n a b
/-- `Undoes u f` says that the action `u` undoes the action `f`: doing `f` and then `u` putsevery thing back exactly as it was. -/def Undoes {α : Type} (u f : α → α) : Prop := ∀ x, u (f x) = x
socks_and_shoestheoremProved here from basic factsNo axioms
socks_and_shoesLean 4Proved here from basic factsFormally verified
/-- **The socks-and-shoes rule.** If `uf` undoes `f` and `ug` undoes `g`, then the chain"`f`, then `g`" is undone by "`ug`, then `uf`" — undo the **last** action first. After `f` and`g`, undoing `g` takes us back to just after `f`; then undoing `f` takes us back to thestart. -/theorem socks_and_shoes {α : Type} {f g uf ug : α → α} (hf : Undoes uf f) (hg : Undoes ug g) : Undoes (andThen ug uf) (andThen f g) := by intro x unfold andThen rw [hg (f x), hf x]
undo_addFive_then_doubletheoremProved here from basic factspropext, Quot.sound
undo_addFive_then_doubleLean 4Proved here from basic factsFormally verified
/-- "Add 5, then double" is undone by "halve, then subtract 5" — the undoing actions in reverseorder. This is the socks-and-shoes rule applied to the two facts above. -/theorem undo_addFive_then_double : Undoes (andThen halve subFive) (andThen addFive double) := socks_and_shoes subFive_undoes_addFive halve_undoes_double
wrong_order_failstheoremProved here from basic factsNo axioms
wrong_order_failsLean 4Proved here from basic factsFormally verified
/-- Undoing in the original order does **not** work: "subtract 5, then halve" does not undo"add 5, then double". From 3 the chain reaches 16, and 16 − 5 = 11 is odd, so halving cannotgive back 3. -/theorem wrong_order_fails : ¬ Undoes (andThen subFive halve) (andThen addFive double) := by intro h have h3 := h 3 revert h3 decide
four_quarter_turnstheoremProved here from basic factsNo axioms
four_quarter_turnsLean 4Proved here from basic factsFormally verified
/-- Four quarter turns, one after another, have the same effect as doing nothing: a fullturn. There are only four directions to check. -/theorem four_quarter_turns (d : Dir) : quarterTurn (quarterTurn (quarterTurn (quarterTurn d))) = d := by cases d <;> rfl
three_more_turns_undotheoremProved here from basic factsNo axioms
three_more_turns_undoLean 4Proved here from basic factsFormally verified
/-- So a quarter turn is undone by **three more** quarter turns. -/theorem three_more_turns_undo : Undoes (andThen quarterTurn (andThen quarterTurn quarterTurn)) quarterTurn := by intro d cases d <;> rfl
/-- A quarter turn clockwise about the corner `(0, 0)`, acting on a point `(x, y)` of the grid(with `y` going up): it sends `(x, y)` to `(y, −x)`, so "up" `(0, 1)` goes to "right"`(1, 0)`. -/def turnPoint (p : Int × Int) : Int × Int := (p.2, -p.1)
/-- Flipping a tile over, left to right: the mirror image in the up–down line through`(0, 0)`. -/def flipPoint (p : Int × Int) : Int × Int := (-p.1, p.2)
/-- An L-shaped tile, as the grid points it covers: a bar from `(0, 0)` up to `(0, 2)` and afoot out to `(1, 0)`. -/def lShape : List (Int × Int) := [(0, 2), (0, 1), (0, 0), (1, 0)]
turn_flip_differtheoremProved here from basic factspropext, Classical.choice, Quot.sound
turn_flip_differLean 4Proved here from basic factsFormally verified
/-- **Turning and flipping do not commute.** "Turn, then flip" moves the L so that it coversthe point `(−1, 0)`; "flip, then turn" leaves that point empty. So the two chains put thetile in different positions. -/theorem turn_flip_differ : ((-1, 0) : Int × Int) ∈ lShape.map (andThen turnPoint flipPoint) ∧ ((-1, 0) : Int × Int) ∉ lShape.map (andThen flipPoint turnPoint) := by decide
four_turns_pointstheoremProved here from basic factspropext
four_turns_pointsLean 4Proved here from basic factsFormally verified
/-- Four quarter turns move every point of the grid back to where it started:`(x, y) → (y, −x) → (−x, −y) → (−y, x) → (x, y)`. -/theorem four_turns_points (p : Int × Int) : turnPoint (turnPoint (turnPoint (turnPoint p))) = p := by obtain ⟨x, y⟩ := p simp [turnPoint]
/-- A step that can be undone: an action `act`, an action `back`, and a guarantee that `back`undoes `act`. -/structure Step (α : Type) where act : α → α back : α → α back_act : ∀ x, back (act x) = x
/-- Undo a chain of steps: undo all the *later* steps first, and the first step last. -/def undoSteps {α : Type} : List (Step α) → α → α | [], x => x | s :: ss, x => s.back (undoSteps ss x)
undo_runtheoremProved here from basic factsNo axioms
undo_runLean 4Proved here from basic factsFormally verified
/-- **Undoing in reverse order works for chains of any length.** Proved by working through thechain: undoing the rest of the chain takes us back to just after the first step, and undoingthe first step takes us back to the start. -/theorem undo_run {α : Type} (ss : List (Step α)) (x : α) : undoSteps ss (runSteps ss x) = x := by induction ss generalizing x with | nil => rfl | cons s ss ih => simp only [runSteps, undoSteps] rw [ih, s.back_act]
there_and_backtheoremProved here from basic factspropext, Quot.sound
there_and_backLean 4Proved here from basic factsFormally verified
/-- There and back again: the chain add 5, double, add 5 takes 3 to 21, and undoing it inreverse order (subtract 5, halve, subtract 5) brings 21 back to 3. -/theorem there_and_back : runSteps [addFiveStep, doubleStep, addFiveStep] 3 = 21 ∧ undoSteps [addFiveStep, doubleStep, addFiveStep] 21 = 3 := by decide
/-- Show that four quarter turns do nothing.Hint: there are only four directions. `cases d <;> rfl` checks each one. -/theorem four_quarter_turns (d : Dir) : quarterTurn (quarterTurn (quarterTurn (quarterTurn d))) = d := by sorry
Show the compiled solution
four_quarter_turnsLean 4Proved here from basic factsFormally verified
/-- Four quarter turns, one after another, have the same effect as doing nothing: a fullturn. There are only four directions to check. -/theorem four_quarter_turns (d : Dir) : quarterTurn (quarterTurn (quarterTurn (quarterTurn d))) = d := by cases d <;> rfl
/-- Prove the socks-and-shoes rule.Hint: after `intro x` and `unfold andThen`, the goal is `uf (ug (g (f x))) = x`. Rewrite with`hg (f x)` (taking off the shoes) and then with `hf x` (taking off the socks). -/theorem socks_and_shoes {α : Type} {f g uf ug : α → α} (hf : Undoes uf f) (hg : Undoes ug g) : Undoes (andThen ug uf) (andThen f g) := by sorry
Show the compiled solution
socks_and_shoesLean 4Proved here from basic factsFormally verified
/-- **The socks-and-shoes rule.** If `uf` undoes `f` and `ug` undoes `g`, then the chain"`f`, then `g`" is undone by "`ug`, then `uf`" — undo the **last** action first. After `f` and`g`, undoing `g` takes us back to just after `f`; then undoing `f` takes us back to thestart. -/theorem socks_and_shoes {α : Type} {f g uf ug : α → α} (hf : Undoes uf f) (hg : Undoes ug g) : Undoes (andThen ug uf) (andThen f g) := by intro x unfold andThen rw [hg (f x), hf x]