-- Frap/Exercises/IndProp.lean

namespace Hidden

inductive List (α : Type u) where
  | nil  : List α
  | cons : α → List α → List α

namespace List

def reverse {α : Type u} (as : List α) : List α :=
  match as with
  | nil        => nil
  | cons a as' => reverse as' ++ cons a nil

inductive Palindrome {α : Type} : List α → Prop where
  | nil : Palindrome nil
  | single (x : α) : Palindrome (cons x nil)
  | sandwich (x : α) (xs : List α)
      : Palindrome xs → Palindrome (cons x xs ++ cons x nil)

namespace Palindrome

-- Repository definitions used:
content: ...

-- Repository lemmas used:
content: theorem List.getElem_append_left{α : Type u_1} {l₁ l₂ : List α} {i : Nat} (hn : i < l₁.length) :\n(l₁ ++ l₂)[i] = l₁[i]

-- Local definitions used:
content: inductive List (α : Type u) where
  | nil  : List α
  | cons : α → List α → List α

content: def reverse {α : Type u} (as : List α) : List α :=
  match as with
  | nil        => nil
  | cons a as' => reverse as' ++ cons a nil

content: inductive Palindrome {α : Type} : List α → Prop where
  | nil : Palindrome nil
  | single (x : α) : Palindrome (cons x nil)
  | sandwich (x : α) (xs : List α)
      : Palindrome xs → Palindrome (cons x xs ++ cons x nil)

-- Local lemmas used:
content: theorem nil_append (as : List α) : nil ++ as = as

content: theorem cons_append (a : α) (as bs : List α)
        : (cons a as) ++ bs = cons a (as ++ bs)

content: theorem append_nil (as : List α) : as ++ nil = as

content: theorem append_assoc (as bs cs : List α)
        : (as ++ bs) ++ cs = as ++ (bs ++ cs)

content: theorem reverse_append {α : Type u} (as bs : List α)
    : reverse (as ++ bs) = reverse bs ++ reverse as

-- Target theorem and proof:
theorem Palindrome_rev {α : Type} (l : List α)
    : Palindrome l → l = reverse l
:= by
  intro lPal
  induction lPal with
  | nil => rfl
  | single x => rfl
  | sandwich x xs xsPal xsRev =>
    rw [reverse_append, reverse, reverse, nil_append, reverse, ←xsRev]
    rw [cons_append, ←append_assoc, cons_append, nil_append, cons_append]