l3lab/ntp-mathlib huggingface dataset:
/-- Given a `s : Cycle α` such that `Nodup s`, retrieve the next element after `x ∈ s`. -/
nonrec def next : ∀ (s : Cycle α) (_hs : Nodup s) (x : α) (_hx : x ∈ s), α := fun s =>
  Quot.hrecOn (motive := fun (s : Cycle α) => ∀ (_hs : Cycle.Nodup s) (x : α) (_hx : x ∈ s), α) s
  (fun l _hn x hx => next l x hx) fun l₁ l₂ h =>
    Function.hfunext (propext h.nodup_iff) fun h₁ h₂ _he =>
      Function.hfunext rfl fun x y hxy =>
        Function.hfunext (propext (by rw [eq_of_heq hxy]; simpa [eq_of_heq hxy] using h.mem_iff))
  fun hm hm' he' => heq_of_eq
    (by rw [heq_iff_eq] at hxy; subst x; 

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s : Cycle α
l₁ l₂ : List α
h : Setoid.r l₁ l₂
h₁ : Nodup (Quot.mk Setoid.r l₁)
h₂ : Nodup (Quot.mk Setoid.r l₂)
_he : HEq h₁ h₂
y : α
hm' : y ∈ Quot.mk Setoid.r l₂
hm : y ∈ Quot.mk Setoid.r l₁
he' : HEq hm hm'
⊢ (fun l _hn x hx => List.next l x hx) l₁ h₁ y hm = (fun l _hn x hx => List.next l x hx) l₂ h₂ y hm'

Next tactic:
simpa using isRotated_next_eq h h₁ _
/-- Given a `s : Cycle α` such that `Nodup s`, retrieve the previous element before `x ∈ s`. -/
nonrec def prev : ∀ (s : Cycle α) (_hs : Nodup s) (x : α) (_hx : x ∈ s), α := fun s =>
  Quot.hrecOn (motive := fun (s : Cycle α) => ∀ (_hs : Cycle.Nodup s) (x : α) (_hx : x ∈ s), α) s
  (fun l _hn x hx => prev l x hx) fun l₁ l₂ h =>
    Function.hfunext (propext h.nodup_iff) fun h₁ h₂ _he =>
      Function.hfunext rfl fun x y hxy =>
        Function.hfunext (propext (by 

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s : Cycle α
l₁ l₂ : List α
h : Setoid.r l₁ l₂
h₁ : Nodup (Quot.mk Setoid.r l₁)
h₂ : Nodup (Quot.mk Setoid.r l₂)
_he : HEq h₁ h₂
x y : α
hxy : HEq x y
⊢ x ∈ Quot.mk Setoid.r l₁ ↔ y ∈ Quot.mk Setoid.r l₂

Next tactic:
rw [eq_of_heq hxy]
/-- Given a `s : Cycle α` such that `Nodup s`, retrieve the previous element before `x ∈ s`. -/
nonrec def prev : ∀ (s : Cycle α) (_hs : Nodup s) (x : α) (_hx : x ∈ s), α := fun s =>
  Quot.hrecOn (motive := fun (s : Cycle α) => ∀ (_hs : Cycle.Nodup s) (x : α) (_hx : x ∈ s), α) s
  (fun l _hn x hx => prev l x hx) fun l₁ l₂ h =>
    Function.hfunext (propext h.nodup_iff) fun h₁ h₂ _he =>
      Function.hfunext rfl fun x y hxy =>
        Function.hfunext (propext (by rw [eq_of_heq hxy]; 

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s : Cycle α
l₁ l₂ : List α
h : Setoid.r l₁ l₂
h₁ : Nodup (Quot.mk Setoid.r l₁)
h₂ : Nodup (Quot.mk Setoid.r l₂)
_he : HEq h₁ h₂
x y : α
hxy : HEq x y
⊢ y ∈ Quot.mk Setoid.r l₁ ↔ y ∈ Quot.mk Setoid.r l₂

Next tactic:
simpa [eq_of_heq hxy] using h.mem_iff
/-- Given a `s : Cycle α` such that `Nodup s`, retrieve the previous element before `x ∈ s`. -/
nonrec def prev : ∀ (s : Cycle α) (_hs : Nodup s) (x : α) (_hx : x ∈ s), α := fun s =>
  Quot.hrecOn (motive := fun (s : Cycle α) => ∀ (_hs : Cycle.Nodup s) (x : α) (_hx : x ∈ s), α) s
  (fun l _hn x hx => prev l x hx) fun l₁ l₂ h =>
    Function.hfunext (propext h.nodup_iff) fun h₁ h₂ _he =>
      Function.hfunext rfl fun x y hxy =>
        Function.hfunext (propext (by rw [eq_of_heq hxy]; simpa [eq_of_heq hxy] using h.mem_iff))
  fun hm hm' he' => heq_of_eq
    (by 

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s : Cycle α
l₁ l₂ : List α
h : Setoid.r l₁ l₂
h₁ : Nodup (Quot.mk Setoid.r l₁)
h₂ : Nodup (Quot.mk Setoid.r l₂)
_he : HEq h₁ h₂
x y : α
hxy : HEq x y
hm : x ∈ Quot.mk Setoid.r l₁
hm' : y ∈ Quot.mk Setoid.r l₂
he' : HEq hm hm'
⊢ (fun l _hn x hx => List.prev l x hx) l₁ h₁ x hm = (fun l _hn x hx => List.prev l x hx) l₂ h₂ y hm'

Next tactic:
rw [heq_iff_eq] at hxy
/-- Given a `s : Cycle α` such that `Nodup s`, retrieve the previous element before `x ∈ s`. -/
nonrec def prev : ∀ (s : Cycle α) (_hs : Nodup s) (x : α) (_hx : x ∈ s), α := fun s =>
  Quot.hrecOn (motive := fun (s : Cycle α) => ∀ (_hs : Cycle.Nodup s) (x : α) (_hx : x ∈ s), α) s
  (fun l _hn x hx => prev l x hx) fun l₁ l₂ h =>
    Function.hfunext (propext h.nodup_iff) fun h₁ h₂ _he =>
      Function.hfunext rfl fun x y hxy =>
        Function.hfunext (propext (by rw [eq_of_heq hxy]; simpa [eq_of_heq hxy] using h.mem_iff))
  fun hm hm' he' => heq_of_eq
    (by rw [heq_iff_eq] at hxy; 

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s : Cycle α
l₁ l₂ : List α
h : Setoid.r l₁ l₂
h₁ : Nodup (Quot.mk Setoid.r l₁)
h₂ : Nodup (Quot.mk Setoid.r l₂)
_he : HEq h₁ h₂
x y : α
hxy : x = y
hm : x ∈ Quot.mk Setoid.r l₁
hm' : y ∈ Quot.mk Setoid.r l₂
he' : HEq hm hm'
⊢ (fun l _hn x hx => List.prev l x hx) l₁ h₁ x hm = (fun l _hn x hx => List.prev l x hx) l₂ h₂ y hm'

Next tactic:
subst x
/-- Given a `s : Cycle α` such that `Nodup s`, retrieve the previous element before `x ∈ s`. -/
nonrec def prev : ∀ (s : Cycle α) (_hs : Nodup s) (x : α) (_hx : x ∈ s), α := fun s =>
  Quot.hrecOn (motive := fun (s : Cycle α) => ∀ (_hs : Cycle.Nodup s) (x : α) (_hx : x ∈ s), α) s
  (fun l _hn x hx => prev l x hx) fun l₁ l₂ h =>
    Function.hfunext (propext h.nodup_iff) fun h₁ h₂ _he =>
      Function.hfunext rfl fun x y hxy =>
        Function.hfunext (propext (by rw [eq_of_heq hxy]; simpa [eq_of_heq hxy] using h.mem_iff))
  fun hm hm' he' => heq_of_eq
    (by rw [heq_iff_eq] at hxy; subst x; 

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s : Cycle α
l₁ l₂ : List α
h : Setoid.r l₁ l₂
h₁ : Nodup (Quot.mk Setoid.r l₁)
h₂ : Nodup (Quot.mk Setoid.r l₂)
_he : HEq h₁ h₂
y : α
hm' : y ∈ Quot.mk Setoid.r l₂
hm : y ∈ Quot.mk Setoid.r l₁
he' : HEq hm hm'
⊢ (fun l _hn x hx => List.prev l x hx) l₁ h₁ y hm = (fun l _hn x hx => List.prev l x hx) l₂ h₂ y hm'

Next tactic:
simpa using isRotated_prev_eq h h₁ _
theorem next_reverse_eq_prev (s : Cycle α) (hs : Nodup s) (x : α) (hx : x ∈ s) :
    s.reverse.next (nodup_reverse_iff.mpr hs) x (mem_reverse_iff.mpr hx) = s.prev hs x hx := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s : Cycle α
hs : Nodup s
x : α
hx : x ∈ s
⊢ next (reverse s) (_ : Nodup (reverse s)) x (_ : x ∈ reverse s) = prev s hs x hx

Next tactic:
simp [← prev_reverse_eq_next]
@[simp]
theorem next_reverse_eq_prev' (s : Cycle α) (hs : Nodup s.reverse) (x : α) (hx : x ∈ s.reverse) :
    s.reverse.next hs x hx = s.prev (nodup_reverse_iff.mp hs) x (mem_reverse_iff.mp hx) := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s : Cycle α
hs : Nodup (reverse s)
x : α
hx : x ∈ reverse s
⊢ next (reverse s) hs x hx = prev s (_ : Nodup s) x (_ : x ∈ s)

Next tactic:
simp [← prev_reverse_eq_next]
@[simp]
nonrec theorem next_mem (s : Cycle α) (hs : Nodup s) (x : α) (hx : x ∈ s) : s.next hs x hx ∈ s := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s : Cycle α
hs : Nodup s
x : α
hx : x ∈ s
⊢ next s hs x hx ∈ s

Next tactic:
induction s using Quot.inductionOn
@[simp]
nonrec theorem next_mem (s : Cycle α) (hs : Nodup s) (x : α) (hx : x ∈ s) : s.next hs x hx ∈ s := by
  induction s using Quot.inductionOn
  

Proof state:
case h
α : Type u_1
inst✝ : DecidableEq α
x : α
a✝ : List α
hs : Nodup (Quot.mk Setoid.r a✝)
hx : x ∈ Quot.mk Setoid.r a✝
⊢ next (Quot.mk Setoid.r a✝) hs x hx ∈ Quot.mk Setoid.r a✝

Next tactic:
apply next_mem
@[simp]
nonrec theorem next_mem (s : Cycle α) (hs : Nodup s) (x : α) (hx : x ∈ s) : s.next hs x hx ∈ s := by
  induction s using Quot.inductionOn
  apply next_mem; 

Proof state:
case h.h
α : Type u_1
inst✝ : DecidableEq α
x : α
a✝ : List α
hs : Nodup (Quot.mk Setoid.r a✝)
hx : x ∈ Quot.mk Setoid.r a✝
⊢ x ∈ a✝

Next tactic:
assumption
theorem prev_mem (s : Cycle α) (hs : Nodup s) (x : α) (hx : x ∈ s) : s.prev hs x hx ∈ s := by
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s : Cycle α
hs : Nodup s
x : α
hx : x ∈ s
⊢ prev s hs x hx ∈ s

Next tactic:
rw [← next_reverse_eq_prev, ← mem_reverse_iff]
theorem prev_mem (s : Cycle α) (hs : Nodup s) (x : α) (hx : x ∈ s) : s.prev hs x hx ∈ s := by
  rw [← next_reverse_eq_prev, ← mem_reverse_iff]
  

Proof state:
α : Type u_1
inst✝ : DecidableEq α
s : Cycle α
hs : Nodup s
x : α
hx : x ∈ s
⊢ next (reverse s) (_ : Nodup (reverse s)) x (_ : x ∈ reverse s) ∈ reverse s

Next tactic:
apply next_mem
/-- `chain R s` means that `R` holds between adjacent elements of `s`.

`chain R ([a, b, c] : Cycle α) ↔ R a b ∧ R b c ∧ R c a` -/
nonrec def Chain (r : α → α → Prop) (c : Cycle α) : Prop :=
  Quotient.liftOn' c
    (fun l =>
      match l with
      | [] => True
      | a :: m => Chain r a (m ++ [a]))
    fun a b hab =>
    propext <| by
      

Proof state:
α : Type u_1
r : α → α → Prop
c : Cycle α
a b : List α
hab : Setoid.r a b
⊢ (fun l =>
        match l with
        | [] => True
        | a :: m => List.Chain r a (m ++ [a]))
      a ↔
    (fun l =>
        match l with
        | [] => True
        | a :: m => List.Chain r a (m ++ [a]))
      b

Next tactic:
cases' a with a l
/-- `chain R s` means that `R` holds between adjacent elements of `s`.

`chain R ([a, b, c] : Cycle α) ↔ R a b ∧ R b c ∧ R c a` -/
nonrec def Chain (r : α → α → Prop) (c : Cycle α) : Prop :=
  Quotient.liftOn' c
    (fun l =>
      match l with
      | [] => True
      | a :: m => Chain r a (m ++ [a]))
    fun a b hab =>
    propext <| by
      cases' a with a l <;> 

Proof state:
case nil
α : Type u_1
r : α → α → Prop
c : Cycle α
b : List α
hab : Setoid.r [] b
⊢ (fun l =>
        match l with
        | [] => True
        | a :: m => List.Chain r a (m ++ [a]))
      [] ↔
    (fun l =>
        match l with
        | [] => True
        | a :: m => List.Chain r a (m ++ [a]))
      b

Next tactic:
cases' b with b m
/-- `chain R s` means that `R` holds between adjacent elements of `s`.

`chain R ([a, b, c] : Cycle α) ↔ R a b ∧ R b c ∧ R c a` -/
nonrec def Chain (r : α → α → Prop) (c : Cycle α) : Prop :=
  Quotient.liftOn' c
    (fun l =>
      match l with
      | [] => True
      | a :: m => Chain r a (m ++ [a]))
    fun a b hab =>
    propext <| by
      cases' a with a l <;> 

Proof state:
case cons
α : Type u_1
r : α → α → Prop
c : Cycle α
b : List α
a : α
l : List α
hab : Setoid.r (a :: l) b
⊢ (fun l =>
        match l with
        | [] => True
        | a :: m => List.Chain r a (m ++ [a]))
      (a :: l) ↔
    (fun l =>
        match l with
        | [] => True
        | a :: m => List.Chain r a (m ++ [a]))
      b

Next tactic:
cases' b with b m
/-- `chain R s` means that `R` holds between adjacent elements of `s`.

`chain R ([a, b, c] : Cycle α) ↔ R a b ∧ R b c ∧ R c a` -/
nonrec def Chain (r : α → α → Prop) (c : Cycle α) : Prop :=
  Quotient.liftOn' c
    (fun l =>
      match l with
      | [] => True
      | a :: m => Chain r a (m ++ [a]))
    fun a b hab =>
    propext <| by
      cases' a with a l <;> cases' b with b m
      · 

Proof state:
case nil.nil
α : Type u_1
r : α → α → Prop
c : Cycle α
hab : Setoid.r [] []
⊢ (fun l =>
        match l with
        | [] => True
        | a :: m => List.Chain r a (m ++ [a]))
      [] ↔
    (fun l =>
        match l with
        | [] => True
        | a :: m => List.Chain r a (m ++ [a]))
      []

Next tactic:
rfl
/-- `chain R s` means that `R` holds between adjacent elements of `s`.

`chain R ([a, b, c] : Cycle α) ↔ R a b ∧ R b c ∧ R c a` -/
nonrec def Chain (r : α → α → Prop) (c : Cycle α) : Prop :=
  Quotient.liftOn' c
    (fun l =>
      match l with
      | [] => True
      | a :: m => Chain r a (m ++ [a]))
    fun a b hab =>
    propext <| by
      cases' a with a l <;> cases' b with b m
      · rfl
      · 

Proof state:
case nil.cons
α : Type u_1
r : α → α → Prop
c : Cycle α
b : α
m : List α
hab : Setoid.r [] (b :: m)
⊢ (fun l =>
        match l with
        | [] => True
        | a :: m => List.Chain r a (m ++ [a]))
      [] ↔
    (fun l =>
        match l with
        | [] => True
        | a :: m => List.Chain r a (m ++ [a]))
      (b :: m)

Next tactic:
have := isRotated_nil_iff'.1 hab
/-- `chain R s` means that `R` holds between adjacent elements of `s`.

`chain R ([a, b, c] : Cycle α) ↔ R a b ∧ R b c ∧ R c a` -/
nonrec def Chain (r : α → α → Prop) (c : Cycle α) : Prop :=
  Quotient.liftOn' c
    (fun l =>
      match l with
      | [] => True
      | a :: m => Chain r a (m ++ [a]))
    fun a b hab =>
    propext <| by
      cases' a with a l <;> cases' b with b m
      · rfl
      · have := isRotated_nil_iff'.1 hab
        

Proof state:
case nil.cons
α : Type u_1
r : α → α → Prop
c : Cycle α
b : α
m : List α
hab : Setoid.r [] (b :: m)
this : [] = b :: m
⊢ (fun l =>
        match l with
        | [] => True
        | a :: m => List.Chain r a (m ++ [a]))
      [] ↔
    (fun l =>
        match l with
        | [] => True
        | a :: m => List.Chain r a (m ++ [a]))
      (b :: m)

Next tactic:
contradiction
/-- `chain R s` means that `R` holds between adjacent elements of `s`.

`chain R ([a, b, c] : Cycle α) ↔ R a b ∧ R b c ∧ R c a` -/
nonrec def Chain (r : α → α → Prop) (c : Cycle α) : Prop :=
  Quotient.liftOn' c
    (fun l =>
      match l with
      | [] => True
      | a :: m => Chain r a (m ++ [a]))
    fun a b hab =>
    propext <| by
      cases' a with a l <;> cases' b with b m
      · rfl
      · have := isRotated_nil_iff'.1 hab
        contradiction
      · 

Proof state:
case cons.nil
α : Type u_1
r : α → α → Prop
c : Cycle α
a : α
l : List α
hab : Setoid.r (a :: l) []
⊢ (fun l =>
        match l with
        | [] => True
        | a :: m => List.Chain r a (m ++ [a]))
      (a :: l) ↔
    (fun l =>
        match l with
        | [] => True
        | a :: m => List.Chain r a (m ++ [a]))
      []

Next tactic:
have := isRotated_nil_iff.1 hab
/-- `chain R s` means that `R` holds between adjacent elements of `s`.

`chain R ([a, b, c] : Cycle α) ↔ R a b ∧ R b c ∧ R c a` -/
nonrec def Chain (r : α → α → Prop) (c : Cycle α) : Prop :=
  Quotient.liftOn' c
    (fun l =>
      match l with
      | [] => True
      | a :: m => Chain r a (m ++ [a]))
    fun a b hab =>
    propext <| by
      cases' a with a l <;> cases' b with b m
      · rfl
      · have := isRotated_nil_iff'.1 hab
        contradiction
      · have := isRotated_nil_iff.1 hab
        

Proof state:
case cons.nil
α : Type u_1
r : α → α → Prop
c : Cycle α
a : α
l : List α
hab : Setoid.r (a :: l) []
this : a :: l = []
⊢ (fun l =>
        match l with
        | [] => True
        | a :: m => List.Chain r a (m ++ [a]))
      (a :: l) ↔
    (fun l =>
        match l with
        | [] => True
        | a :: m => List.Chain r a (m ++ [a]))
      []

Next tactic:
contradiction
/-- `chain R s` means that `R` holds between adjacent elements of `s`.

`chain R ([a, b, c] : Cycle α) ↔ R a b ∧ R b c ∧ R c a` -/
nonrec def Chain (r : α → α → Prop) (c : Cycle α) : Prop :=
  Quotient.liftOn' c
    (fun l =>
      match l with
      | [] => True
      | a :: m => Chain r a (m ++ [a]))
    fun a b hab =>
    propext <| by
      cases' a with a l <;> cases' b with b m
      · rfl
      · have := isRotated_nil_iff'.1 hab
        contradiction
      · have := isRotated_nil_iff.1 hab
        contradiction
      · 

Proof state:
case cons.cons
α : Type u_1
r : α → α → Prop
c : Cycle α
a : α
l : List α
b : α
m : List α
hab : Setoid.r (a :: l) (b :: m)
⊢ (fun l =>
        match l with
        | [] => True
        | a :: m => List.Chain r a (m ++ [a]))
      (a :: l) ↔
    (fun l =>
        match l with
        | [] => True
        | a :: m => List.Chain r a (m ++ [a]))
      (b :: m)

Next tactic:
dsimp only
/-- `chain R s` means that `R` holds between adjacent elements of `s`.

`chain R ([a, b, c] : Cycle α) ↔ R a b ∧ R b c ∧ R c a` -/
nonrec def Chain (r : α → α → Prop) (c : Cycle α) : Prop :=
  Quotient.liftOn' c
    (fun l =>
      match l with
      | [] => True
      | a :: m => Chain r a (m ++ [a]))
    fun a b hab =>
    propext <| by
      cases' a with a l <;> cases' b with b m
      · rfl
      · have := isRotated_nil_iff'.1 hab
        contradiction
      · have := isRotated_nil_iff.1 hab
        contradiction
      · dsimp only
        

Proof state:
case cons.cons
α : Type u_1
r : α → α → Prop
c : Cycle α
a : α
l : List α
b : α
m : List α
hab : Setoid.r (a :: l) (b :: m)
⊢ List.Chain r a (l ++ [a]) ↔ List.Chain r b (m ++ [b])

Next tactic:
cases' hab with n hn
/-- `chain R s` means that `R` holds between adjacent elements of `s`.

`chain R ([a, b, c] : Cycle α) ↔ R a b ∧ R b c ∧ R c a` -/
nonrec def Chain (r : α → α → Prop) (c : Cycle α) : Prop :=
  Quotient.liftOn' c
    (fun l =>
      match l with
      | [] => True
      | a :: m => Chain r a (m ++ [a]))
    fun a b hab =>
    propext <| by
      cases' a with a l <;> cases' b with b m
      · rfl
      · have := isRotated_nil_iff'.1 hab
        contradiction
      · have := isRotated_nil_iff.1 hab
        contradiction
      · dsimp only
        cases' hab with n hn
        

Proof state:
case cons.cons.intro
α : Type u_1
r : α → α → Prop
c : Cycle α
a : α
l : List α
b : α
m : List α
n : ℕ
hn : rotate (a :: l) n = b :: m
⊢ List.Chain r a (l ++ [a]) ↔ List.Chain r b (m ++ [b])

Next tactic:
induction' n with d hd generalizing a b l m
/-- `chain R s` means that `R` holds between adjacent elements of `s`.

`chain R ([a, b, c] : Cycle α) ↔ R a b ∧ R b c ∧ R c a` -/
nonrec def Chain (r : α → α → Prop) (c : Cycle α) : Prop :=
  Quotient.liftOn' c
    (fun l =>
      match l with
      | [] => True
      | a :: m => Chain r a (m ++ [a]))
    fun a b hab =>
    propext <| by
      cases' a with a l <;> cases' b with b m
      · rfl
      · have := isRotated_nil_iff'.1 hab
        contradiction
      · have := isRotated_nil_iff.1 hab
        contradiction
      · dsimp only
        cases' hab with n hn
        induction' n with d hd generalizing a b l m
        · 

Proof state:
case cons.cons.intro.zero
α : Type u_1
r : α → α → Prop
c : Cycle α
a : α
l : List α
b : α
m : List α
hn : rotate (a :: l) Nat.zero = b :: m
⊢ List.Chain r a (l ++ [a]) ↔ List.Chain r b (m ++ [b])

Next tactic:
simp only [Nat.zero_eq, rotate_zero, cons.injEq] at hn
/-- `chain R s` means that `R` holds between adjacent elements of `s`.

`chain R ([a, b, c] : Cycle α) ↔ R a b ∧ R b c ∧ R c a` -/
nonrec def Chain (r : α → α → Prop) (c : Cycle α) : Prop :=
  Quotient.liftOn' c
    (fun l =>
      match l with
      | [] => True
      | a :: m => Chain r a (m ++ [a]))
    fun a b hab =>
    propext <| by
      cases' a with a l <;> cases' b with b m
      · rfl
      · have := isRotated_nil_iff'.1 hab
        contradiction
      · have := isRotated_nil_iff.1 hab
        contradiction
      · dsimp only
        cases' hab with n hn
        induction' n with d hd generalizing a b l m
        · simp only [Nat.zero_eq, rotate_zero, cons.injEq] at hn
          

Proof state:
case cons.cons.intro.zero
α : Type u_1
r : α → α → Prop
c : Cycle α
a : α
l : List α
b : α
m : List α
hn : a = b ∧ l = m
⊢ List.Chain r a (l ++ [a]) ↔ List.Chain r b (m ++ [b])

Next tactic:
rw [hn.1, hn.2]
/-- `chain R s` means that `R` holds between adjacent elements of `s`.

`chain R ([a, b, c] : Cycle α) ↔ R a b ∧ R b c ∧ R c a` -/
nonrec def Chain (r : α → α → Prop) (c : Cycle α) : Prop :=
  Quotient.liftOn' c
    (fun l =>
      match l with
      | [] => True
      | a :: m => Chain r a (m ++ [a]))
    fun a b hab =>
    propext <| by
      cases' a with a l <;> cases' b with b m
      · rfl
      · have := isRotated_nil_iff'.1 hab
        contradiction
      · have := isRotated_nil_iff.1 hab
        contradiction
      · dsimp only
        cases' hab with n hn
        induction' n with d hd generalizing a b l m
        · simp only [Nat.zero_eq, rotate_zero, cons.injEq] at hn
          rw [hn.1, hn.2]
        · 

Proof state:
case cons.cons.intro.succ
α : Type u_1
r : α → α → Prop
c : Cycle α
d : ℕ
hd :
  ∀ (a : α) (l : List α) (b : α) (m : List α),
    rotate (a :: l) d = b :: m → (List.Chain r a (l ++ [a]) ↔ List.Chain r b (m ++ [b]))
a : α
l : List α
b : α
m : List α
hn : rotate (a :: l) (Nat.succ d) = b :: m
⊢ List.Chain r a (l ++ [a]) ↔ List.Chain r b (m ++ [b])

Next tactic:
cases' l with c s
/-- `chain R s` means that `R` holds between adjacent elements of `s`.

`chain R ([a, b, c] : Cycle α) ↔ R a b ∧ R b c ∧ R c a` -/
nonrec def Chain (r : α → α → Prop) (c : Cycle α) : Prop :=
  Quotient.liftOn' c
    (fun l =>
      match l with
      | [] => True
      | a :: m => Chain r a (m ++ [a]))
    fun a b hab =>
    propext <| by
      cases' a with a l <;> cases' b with b m
      · rfl
      · have := isRotated_nil_iff'.1 hab
        contradiction
      · have := isRotated_nil_iff.1 hab
        contradiction
      · dsimp only
        cases' hab with n hn
        induction' n with d hd generalizing a b l m
        · simp only [Nat.zero_eq, rotate_zero, cons.injEq] at hn
          rw [hn.1, hn.2]
        · cases' l with c s
          · 

Proof state:
case cons.cons.intro.succ.nil
α : Type u_1
r : α → α → Prop
c : Cycle α
d : ℕ
hd :
  ∀ (a : α) (l : List α) (b : α) (m : List α),
    rotate (a :: l) d = b :: m → (List.Chain r a (l ++ [a]) ↔ List.Chain r b (m ++ [b]))
a b : α
m : List α
hn : rotate [a] (Nat.succ d) = b :: m
⊢ List.Chain r a ([] ++ [a]) ↔ List.Chain r b (m ++ [b])

Next tactic:
simp only [rotate_cons_succ, nil_append, rotate_singleton, cons.injEq] at hn
/-- `chain R s` means that `R` holds between adjacent elements of `s`.

`chain R ([a, b, c] : Cycle α) ↔ R a b ∧ R b c ∧ R c a` -/
nonrec def Chain (r : α → α → Prop) (c : Cycle α) : Prop :=
  Quotient.liftOn' c
    (fun l =>
      match l with
      | [] => True
      | a :: m => Chain r a (m ++ [a]))
    fun a b hab =>
    propext <| by
      cases' a with a l <;> cases' b with b m
      · rfl
      · have := isRotated_nil_iff'.1 hab
        contradiction
      · have := isRotated_nil_iff.1 hab
        contradiction
      · dsimp only
        cases' hab with n hn
        induction' n with d hd generalizing a b l m
        · simp only [Nat.zero_eq, rotate_zero, cons.injEq] at hn
          rw [hn.1, hn.2]
        · cases' l with c s
          · simp only [rotate_cons_succ, nil_append, rotate_singleton, cons.injEq] at hn
            

Proof state:
case cons.cons.intro.succ.nil
α : Type u_1
r : α → α → Prop
c : Cycle α
d : ℕ
hd :
  ∀ (a : α) (l : List α) (b : α) (m : List α),
    rotate (a :: l) d = b :: m → (List.Chain r a (l ++ [a]) ↔ List.Chain r b (m ++ [b]))
a b : α
m : List α
hn : a = b ∧ [] = m
⊢ List.Chain r a ([] ++ [a]) ↔ List.Chain r b (m ++ [b])

Next tactic:
rw [hn.1, hn.2]
/-- `chain R s` means that `R` holds between adjacent elements of `s`.

`chain R ([a, b, c] : Cycle α) ↔ R a b ∧ R b c ∧ R c a` -/
nonrec def Chain (r : α → α → Prop) (c : Cycle α) : Prop :=
  Quotient.liftOn' c
    (fun l =>
      match l with
      | [] => True
      | a :: m => Chain r a (m ++ [a]))
    fun a b hab =>
    propext <| by
      cases' a with a l <;> cases' b with b m
      · rfl
      · have := isRotated_nil_iff'.1 hab
        contradiction
      · have := isRotated_nil_iff.1 hab
        contradiction
      · dsimp only
        cases' hab with n hn
        induction' n with d hd generalizing a b l m
        · simp only [Nat.zero_eq, rotate_zero, cons.injEq] at hn
          rw [hn.1, hn.2]
        · cases' l with c s
          · simp only [rotate_cons_succ, nil_append, rotate_singleton, cons.injEq] at hn
            rw [hn.1, hn.2]
          · 

Proof state:
case cons.cons.intro.succ.cons
α : Type u_1
r : α → α → Prop
c✝ : Cycle α
d : ℕ
hd :
  ∀ (a : α) (l : List α) (b : α) (m : List α),
    rotate (a :: l) d = b :: m → (List.Chain r a (l ++ [a]) ↔ List.Chain r b (m ++ [b]))
a b : α
m : List α
c : α
s : List α
hn : rotate (a :: c :: s) (Nat.succ d) = b :: m
⊢ List.Chain r a (c :: s ++ [a]) ↔ List.Chain r b (m ++ [b])

Next tactic:
rw [Nat.succ_eq_one_add, ← rotate_rotate, rotate_cons_succ, rotate_zero,
              cons_append] at hn