l3lab/ntp-mathlib huggingface dataset:
theorem reverse_rotate (l : List α) (n : ℕ) :
    (l.rotate n).reverse = l.reverse.rotate (l.length - n % l.length) := by
  rw [← length_reverse l, ← rotate_eq_iff]
  induction' n with n hn generalizing l
  · simp
  · cases' l with hd tl
    · simp
    · rw [rotate_cons_succ, Nat.succ_eq_add_one, ← rotate_rotate, hn]
      

Proof state:
case succ.cons
α : Type u
n : ℕ
hn : ∀ (l : List α), rotate (reverse (rotate l n)) n = reverse l
hd : α
tl : List α
⊢ rotate (reverse (tl ++ [hd])) 1 = reverse (hd :: tl)

Next tactic:
simp
theorem rotate_reverse (l : List α) (n : ℕ) :
    l.reverse.rotate n = (l.rotate (l.length - n % l.length)).reverse := by
  

Proof state:
α : Type u
l : List α
n : ℕ
⊢ rotate (reverse l) n = reverse (rotate l (length l - n % length l))

Next tactic:
rw [← reverse_reverse l]
theorem rotate_reverse (l : List α) (n : ℕ) :
    l.reverse.rotate n = (l.rotate (l.length - n % l.length)).reverse := by
  rw [← reverse_reverse l]
  

Proof state:
α : Type u
l : List α
n : ℕ
⊢ rotate (reverse (reverse (reverse l))) n =
    reverse (rotate (reverse (reverse l)) (length (reverse (reverse l)) - n % length (reverse (reverse l))))

Next tactic:
simp_rw [reverse_rotate, reverse_reverse, rotate_eq_iff, rotate_rotate, length_rotate,
    length_reverse]
theorem rotate_reverse (l : List α) (n : ℕ) :
    l.reverse.rotate n = (l.rotate (l.length - n % l.length)).reverse := by
  rw [← reverse_reverse l]
  simp_rw [reverse_rotate, reverse_reverse, rotate_eq_iff, rotate_rotate, length_rotate,
    length_reverse]
  

Proof state:
α : Type u
l : List α
n : ℕ
⊢ reverse l = rotate (reverse l) (length l - (length l - n % length l) % length l + (length l - n % length l))

Next tactic:
rw [← length_reverse l]
theorem rotate_reverse (l : List α) (n : ℕ) :
    l.reverse.rotate n = (l.rotate (l.length - n % l.length)).reverse := by
  rw [← reverse_reverse l]
  simp_rw [reverse_rotate, reverse_reverse, rotate_eq_iff, rotate_rotate, length_rotate,
    length_reverse]
  rw [← length_reverse l]
  

Proof state:
α : Type u
l : List α
n : ℕ
⊢ reverse l =
    rotate (reverse l)
      (length (reverse l) - (length (reverse l) - n % length (reverse l)) % length (reverse l) +
        (length (reverse l) - n % length (reverse l)))

Next tactic:
let k := n % l.reverse.length
theorem rotate_reverse (l : List α) (n : ℕ) :
    l.reverse.rotate n = (l.rotate (l.length - n % l.length)).reverse := by
  rw [← reverse_reverse l]
  simp_rw [reverse_rotate, reverse_reverse, rotate_eq_iff, rotate_rotate, length_rotate,
    length_reverse]
  rw [← length_reverse l]
  let k := n % l.reverse.length
  

Proof state:
α : Type u
l : List α
n : ℕ
k : ℕ := n % length (reverse l)
⊢ reverse l =
    rotate (reverse l)
      (length (reverse l) - (length (reverse l) - n % length (reverse l)) % length (reverse l) +
        (length (reverse l) - n % length (reverse l)))

Next tactic:
cases' hk' : k with k'
theorem rotate_reverse (l : List α) (n : ℕ) :
    l.reverse.rotate n = (l.rotate (l.length - n % l.length)).reverse := by
  rw [← reverse_reverse l]
  simp_rw [reverse_rotate, reverse_reverse, rotate_eq_iff, rotate_rotate, length_rotate,
    length_reverse]
  rw [← length_reverse l]
  let k := n % l.reverse.length
  cases' hk' : k with k'
  · 

Proof state:
case zero
α : Type u
l : List α
n : ℕ
k : ℕ := n % length (reverse l)
hk' : k = zero
⊢ reverse l =
    rotate (reverse l)
      (length (reverse l) - (length (reverse l) - n % length (reverse l)) % length (reverse l) +
        (length (reverse l) - n % length (reverse l)))

Next tactic:
simp_all! [length_reverse, ← rotate_rotate]
theorem rotate_reverse (l : List α) (n : ℕ) :
    l.reverse.rotate n = (l.rotate (l.length - n % l.length)).reverse := by
  rw [← reverse_reverse l]
  simp_rw [reverse_rotate, reverse_reverse, rotate_eq_iff, rotate_rotate, length_rotate,
    length_reverse]
  rw [← length_reverse l]
  let k := n % l.reverse.length
  cases' hk' : k with k'
  · simp_all! [length_reverse, ← rotate_rotate]
  · 

Proof state:
case succ
α : Type u
l : List α
n : ℕ
k : ℕ := n % length (reverse l)
k' : ℕ
hk' : k = succ k'
⊢ reverse l =
    rotate (reverse l)
      (length (reverse l) - (length (reverse l) - n % length (reverse l)) % length (reverse l) +
        (length (reverse l) - n % length (reverse l)))

Next tactic:
cases' l with x l
theorem rotate_reverse (l : List α) (n : ℕ) :
    l.reverse.rotate n = (l.rotate (l.length - n % l.length)).reverse := by
  rw [← reverse_reverse l]
  simp_rw [reverse_rotate, reverse_reverse, rotate_eq_iff, rotate_rotate, length_rotate,
    length_reverse]
  rw [← length_reverse l]
  let k := n % l.reverse.length
  cases' hk' : k with k'
  · simp_all! [length_reverse, ← rotate_rotate]
  · cases' l with x l
    · 

Proof state:
case succ.nil
α : Type u
n k' : ℕ
k : ℕ := n % length (reverse [])
hk' : k = succ k'
⊢ reverse [] =
    rotate (reverse [])
      (length (reverse []) - (length (reverse []) - n % length (reverse [])) % length (reverse []) +
        (length (reverse []) - n % length (reverse [])))

Next tactic:
simp
theorem rotate_reverse (l : List α) (n : ℕ) :
    l.reverse.rotate n = (l.rotate (l.length - n % l.length)).reverse := by
  rw [← reverse_reverse l]
  simp_rw [reverse_rotate, reverse_reverse, rotate_eq_iff, rotate_rotate, length_rotate,
    length_reverse]
  rw [← length_reverse l]
  let k := n % l.reverse.length
  cases' hk' : k with k'
  · simp_all! [length_reverse, ← rotate_rotate]
  · cases' l with x l
    · simp
    · 

Proof state:
case succ.cons
α : Type u
n k' : ℕ
x : α
l : List α
k : ℕ := n % length (reverse (x :: l))
hk' : k = succ k'
⊢ reverse (x :: l) =
    rotate (reverse (x :: l))
      (length (reverse (x :: l)) -
          (length (reverse (x :: l)) - n % length (reverse (x :: l))) % length (reverse (x :: l)) +
        (length (reverse (x :: l)) - n % length (reverse (x :: l))))

Next tactic:
rw [Nat.mod_eq_of_lt, tsub_add_cancel_of_le, rotate_length]
theorem rotate_reverse (l : List α) (n : ℕ) :
    l.reverse.rotate n = (l.rotate (l.length - n % l.length)).reverse := by
  rw [← reverse_reverse l]
  simp_rw [reverse_rotate, reverse_reverse, rotate_eq_iff, rotate_rotate, length_rotate,
    length_reverse]
  rw [← length_reverse l]
  let k := n % l.reverse.length
  cases' hk' : k with k'
  · simp_all! [length_reverse, ← rotate_rotate]
  · cases' l with x l
    · simp
    · rw [Nat.mod_eq_of_lt, tsub_add_cancel_of_le, rotate_length]
      · 

Proof state:
case succ.cons
α : Type u
n k' : ℕ
x : α
l : List α
k : ℕ := n % length (reverse (x :: l))
hk' : k = succ k'
⊢ length (reverse (x :: l)) - n % length (reverse (x :: l)) ≤ length (reverse (x :: l))

Next tactic:
exact tsub_le_self
theorem rotate_reverse (l : List α) (n : ℕ) :
    l.reverse.rotate n = (l.rotate (l.length - n % l.length)).reverse := by
  rw [← reverse_reverse l]
  simp_rw [reverse_rotate, reverse_reverse, rotate_eq_iff, rotate_rotate, length_rotate,
    length_reverse]
  rw [← length_reverse l]
  let k := n % l.reverse.length
  cases' hk' : k with k'
  · simp_all! [length_reverse, ← rotate_rotate]
  · cases' l with x l
    · simp
    · rw [Nat.mod_eq_of_lt, tsub_add_cancel_of_le, rotate_length]
      · exact tsub_le_self
      · 

Proof state:
case succ.cons
α : Type u
n k' : ℕ
x : α
l : List α
k : ℕ := n % length (reverse (x :: l))
hk' : k = succ k'
⊢ length (reverse (x :: l)) - n % length (reverse (x :: l)) < length (reverse (x :: l))

Next tactic:
exact tsub_lt_self (by simp) (by simp_all!)
theorem rotate_reverse (l : List α) (n : ℕ) :
    l.reverse.rotate n = (l.rotate (l.length - n % l.length)).reverse := by
  rw [← reverse_reverse l]
  simp_rw [reverse_rotate, reverse_reverse, rotate_eq_iff, rotate_rotate, length_rotate,
    length_reverse]
  rw [← length_reverse l]
  let k := n % l.reverse.length
  cases' hk' : k with k'
  · simp_all! [length_reverse, ← rotate_rotate]
  · cases' l with x l
    · simp
    · rw [Nat.mod_eq_of_lt, tsub_add_cancel_of_le, rotate_length]
      · exact tsub_le_self
      · exact tsub_lt_self (by 

Proof state:
α : Type u
n k' : ℕ
x : α
l : List α
k : ℕ := n % length (reverse (x :: l))
hk' : k = succ k'
⊢ 0 < length (reverse (x :: l))

Next tactic:
simp
theorem rotate_reverse (l : List α) (n : ℕ) :
    l.reverse.rotate n = (l.rotate (l.length - n % l.length)).reverse := by
  rw [← reverse_reverse l]
  simp_rw [reverse_rotate, reverse_reverse, rotate_eq_iff, rotate_rotate, length_rotate,
    length_reverse]
  rw [← length_reverse l]
  let k := n % l.reverse.length
  cases' hk' : k with k'
  · simp_all! [length_reverse, ← rotate_rotate]
  · cases' l with x l
    · simp
    · rw [Nat.mod_eq_of_lt, tsub_add_cancel_of_le, rotate_length]
      · exact tsub_le_self
      · exact tsub_lt_self (by simp) (by 

Proof state:
α : Type u
n k' : ℕ
x : α
l : List α
k : ℕ := n % length (reverse (x :: l))
hk' : k = succ k'
⊢ 0 < n % length (reverse (x :: l))

Next tactic:
simp_all!
theorem map_rotate {β : Type*} (f : α → β) (l : List α) (n : ℕ) :
    map f (l.rotate n) = (map f l).rotate n := by
  

Proof state:
α : Type u
β : Type u_1
f : α → β
l : List α
n : ℕ
⊢ map f (rotate l n) = rotate (map f l) n

Next tactic:
induction' n with n hn IH generalizing l
theorem map_rotate {β : Type*} (f : α → β) (l : List α) (n : ℕ) :
    map f (l.rotate n) = (map f l).rotate n := by
  induction' n with n hn IH generalizing l
  · 

Proof state:
case zero
α : Type u
β : Type u_1
f : α → β
l : List α
⊢ map f (rotate l zero) = rotate (map f l) zero

Next tactic:
simp
theorem map_rotate {β : Type*} (f : α → β) (l : List α) (n : ℕ) :
    map f (l.rotate n) = (map f l).rotate n := by
  induction' n with n hn IH generalizing l
  · simp
  · 

Proof state:
case succ
α : Type u
β : Type u_1
f : α → β
n : ℕ
hn : ∀ (l : List α), map f (rotate l n) = rotate (map f l) n
l : List α
⊢ map f (rotate l (succ n)) = rotate (map f l) (succ n)

Next tactic:
cases' l with hd tl
theorem map_rotate {β : Type*} (f : α → β) (l : List α) (n : ℕ) :
    map f (l.rotate n) = (map f l).rotate n := by
  induction' n with n hn IH generalizing l
  · simp
  · cases' l with hd tl
    · 

Proof state:
case succ.nil
α : Type u
β : Type u_1
f : α → β
n : ℕ
hn : ∀ (l : List α), map f (rotate l n) = rotate (map f l) n
⊢ map f (rotate [] (succ n)) = rotate (map f []) (succ n)

Next tactic:
simp
theorem map_rotate {β : Type*} (f : α → β) (l : List α) (n : ℕ) :
    map f (l.rotate n) = (map f l).rotate n := by
  induction' n with n hn IH generalizing l
  · simp
  · cases' l with hd tl
    · simp
    · 

Proof state:
case succ.cons
α : Type u
β : Type u_1
f : α → β
n : ℕ
hn : ∀ (l : List α), map f (rotate l n) = rotate (map f l) n
hd : α
tl : List α
⊢ map f (rotate (hd :: tl) (succ n)) = rotate (map f (hd :: tl)) (succ n)

Next tactic:
simp [hn]
set_option linter.deprecated false in
theorem Nodup.rotate_eq_self_iff {l : List α} (hl : l.Nodup) {n : ℕ} :
    l.rotate n = l ↔ n % l.length = 0 ∨ l = [] := by
  

Proof state:
α : Type u
l : List α
hl : Nodup l
n : ℕ
⊢ rotate l n = l ↔ n % length l = 0 ∨ l = []

Next tactic:
constructor
set_option linter.deprecated false in
theorem Nodup.rotate_eq_self_iff {l : List α} (hl : l.Nodup) {n : ℕ} :
    l.rotate n = l ↔ n % l.length = 0 ∨ l = [] := by
  constructor
  · 

Proof state:
case mp
α : Type u
l : List α
hl : Nodup l
n : ℕ
⊢ rotate l n = l → n % length l = 0 ∨ l = []

Next tactic:
intro h
set_option linter.deprecated false in
theorem Nodup.rotate_eq_self_iff {l : List α} (hl : l.Nodup) {n : ℕ} :
    l.rotate n = l ↔ n % l.length = 0 ∨ l = [] := by
  constructor
  · intro h
    

Proof state:
case mp
α : Type u
l : List α
hl : Nodup l
n : ℕ
h : rotate l n = l
⊢ n % length l = 0 ∨ l = []

Next tactic:
rcases l.length.zero_le.eq_or_lt with hl' | hl'
set_option linter.deprecated false in
theorem Nodup.rotate_eq_self_iff {l : List α} (hl : l.Nodup) {n : ℕ} :
    l.rotate n = l ↔ n % l.length = 0 ∨ l = [] := by
  constructor
  · intro h
    rcases l.length.zero_le.eq_or_lt with hl' | hl'
    · 

Proof state:
case mp.inl
α : Type u
l : List α
hl : Nodup l
n : ℕ
h : rotate l n = l
hl' : 0 = length l
⊢ n % length l = 0 ∨ l = []

Next tactic:
simp [← length_eq_zero, ← hl']
set_option linter.deprecated false in
theorem Nodup.rotate_eq_self_iff {l : List α} (hl : l.Nodup) {n : ℕ} :
    l.rotate n = l ↔ n % l.length = 0 ∨ l = [] := by
  constructor
  · intro h
    rcases l.length.zero_le.eq_or_lt with hl' | hl'
    · simp [← length_eq_zero, ← hl']
    

Proof state:
case mp.inr
α : Type u
l : List α
hl : Nodup l
n : ℕ
h : rotate l n = l
hl' : 0 < length l
⊢ n % length l = 0 ∨ l = []

Next tactic:
left
set_option linter.deprecated false in
theorem Nodup.rotate_eq_self_iff {l : List α} (hl : l.Nodup) {n : ℕ} :
    l.rotate n = l ↔ n % l.length = 0 ∨ l = [] := by
  constructor
  · intro h
    rcases l.length.zero_le.eq_or_lt with hl' | hl'
    · simp [← length_eq_zero, ← hl']
    left
    

Proof state:
case mp.inr.h
α : Type u
l : List α
hl : Nodup l
n : ℕ
h : rotate l n = l
hl' : 0 < length l
⊢ n % length l = 0

Next tactic:
rw [nodup_iff_nthLe_inj] at hl
set_option linter.deprecated false in
theorem Nodup.rotate_eq_self_iff {l : List α} (hl : l.Nodup) {n : ℕ} :
    l.rotate n = l ↔ n % l.length = 0 ∨ l = [] := by
  constructor
  · intro h
    rcases l.length.zero_le.eq_or_lt with hl' | hl'
    · simp [← length_eq_zero, ← hl']
    left
    rw [nodup_iff_nthLe_inj] at hl
    

Proof state:
case mp.inr.h
α : Type u
l : List α
hl : ∀ (i j : ℕ) (h₁ : i < length l) (h₂ : j < length l), nthLe l i h₁ = nthLe l j h₂ → i = j
n : ℕ
h : rotate l n = l
hl' : 0 < length l
⊢ n % length l = 0

Next tactic:
refine' hl _ _ (mod_lt _ hl') hl' _
set_option linter.deprecated false in
theorem Nodup.rotate_eq_self_iff {l : List α} (hl : l.Nodup) {n : ℕ} :
    l.rotate n = l ↔ n % l.length = 0 ∨ l = [] := by
  constructor
  · intro h
    rcases l.length.zero_le.eq_or_lt with hl' | hl'
    · simp [← length_eq_zero, ← hl']
    left
    rw [nodup_iff_nthLe_inj] at hl
    refine' hl _ _ (mod_lt _ hl') hl' _
    

Proof state:
case mp.inr.h
α : Type u
l : List α
hl : ∀ (i j : ℕ) (h₁ : i < length l) (h₂ : j < length l), nthLe l i h₁ = nthLe l j h₂ → i = j
n : ℕ
h : rotate l n = l
hl' : 0 < length l
⊢ nthLe l (n % length l) (_ : n % length l < length l) = nthLe l 0 hl'

Next tactic:
rw [← nthLe_rotate' _ n]
set_option linter.deprecated false in
theorem Nodup.rotate_eq_self_iff {l : List α} (hl : l.Nodup) {n : ℕ} :
    l.rotate n = l ↔ n % l.length = 0 ∨ l = [] := by
  constructor
  · intro h
    rcases l.length.zero_le.eq_or_lt with hl' | hl'
    · simp [← length_eq_zero, ← hl']
    left
    rw [nodup_iff_nthLe_inj] at hl
    refine' hl _ _ (mod_lt _ hl') hl' _
    rw [← nthLe_rotate' _ n]
    

Proof state:
case mp.inr.h
α : Type u
l : List α
hl : ∀ (i j : ℕ) (h₁ : i < length l) (h₂ : j < length l), nthLe l i h₁ = nthLe l j h₂ → i = j
n : ℕ
h : rotate l n = l
hl' : 0 < length l
⊢ nthLe (rotate l n) ((length l - n % length l + n % length l) % length l)
      (_ : (length l - n % length l + n % length l) % length l < length (rotate l n)) =
    nthLe l 0 hl'

Next tactic:
simp_rw [h, tsub_add_cancel_of_le (mod_lt _ hl').le, mod_self]
set_option linter.deprecated false in
theorem Nodup.rotate_eq_self_iff {l : List α} (hl : l.Nodup) {n : ℕ} :
    l.rotate n = l ↔ n % l.length = 0 ∨ l = [] := by
  constructor
  · intro h
    rcases l.length.zero_le.eq_or_lt with hl' | hl'
    · simp [← length_eq_zero, ← hl']
    left
    rw [nodup_iff_nthLe_inj] at hl
    refine' hl _ _ (mod_lt _ hl') hl' _
    rw [← nthLe_rotate' _ n]
    simp_rw [h, tsub_add_cancel_of_le (mod_lt _ hl').le, mod_self]
  · 

Proof state:
case mpr
α : Type u
l : List α
hl : Nodup l
n : ℕ
⊢ n % length l = 0 ∨ l = [] → rotate l n = l

Next tactic:
rintro (h | h)
set_option linter.deprecated false in
theorem Nodup.rotate_eq_self_iff {l : List α} (hl : l.Nodup) {n : ℕ} :
    l.rotate n = l ↔ n % l.length = 0 ∨ l = [] := by
  constructor
  · intro h
    rcases l.length.zero_le.eq_or_lt with hl' | hl'
    · simp [← length_eq_zero, ← hl']
    left
    rw [nodup_iff_nthLe_inj] at hl
    refine' hl _ _ (mod_lt _ hl') hl' _
    rw [← nthLe_rotate' _ n]
    simp_rw [h, tsub_add_cancel_of_le (mod_lt _ hl').le, mod_self]
  · rintro (h | h)
    · 

Proof state:
case mpr.inl
α : Type u
l : List α
hl : Nodup l
n : ℕ
h : n % length l = 0
⊢ rotate l n = l

Next tactic:
rw [← rotate_mod, h]
set_option linter.deprecated false in
theorem Nodup.rotate_eq_self_iff {l : List α} (hl : l.Nodup) {n : ℕ} :
    l.rotate n = l ↔ n % l.length = 0 ∨ l = [] := by
  constructor
  · intro h
    rcases l.length.zero_le.eq_or_lt with hl' | hl'
    · simp [← length_eq_zero, ← hl']
    left
    rw [nodup_iff_nthLe_inj] at hl
    refine' hl _ _ (mod_lt _ hl') hl' _
    rw [← nthLe_rotate' _ n]
    simp_rw [h, tsub_add_cancel_of_le (mod_lt _ hl').le, mod_self]
  · rintro (h | h)
    · rw [← rotate_mod, h]
      

Proof state:
case mpr.inl
α : Type u
l : List α
hl : Nodup l
n : ℕ
h : n % length l = 0
⊢ rotate l 0 = l

Next tactic:
exact rotate_zero l
set_option linter.deprecated false in
theorem Nodup.rotate_eq_self_iff {l : List α} (hl : l.Nodup) {n : ℕ} :
    l.rotate n = l ↔ n % l.length = 0 ∨ l = [] := by
  constructor
  · intro h
    rcases l.length.zero_le.eq_or_lt with hl' | hl'
    · simp [← length_eq_zero, ← hl']
    left
    rw [nodup_iff_nthLe_inj] at hl
    refine' hl _ _ (mod_lt _ hl') hl' _
    rw [← nthLe_rotate' _ n]
    simp_rw [h, tsub_add_cancel_of_le (mod_lt _ hl').le, mod_self]
  · rintro (h | h)
    · rw [← rotate_mod, h]
      exact rotate_zero l
    · 

Proof state:
case mpr.inr
α : Type u
l : List α
hl : Nodup l
n : ℕ
h : l = []
⊢ rotate l n = l

Next tactic:
simp [h]
set_option linter.deprecated false in
theorem Nodup.rotate_congr {l : List α} (hl : l.Nodup) (hn : l ≠ []) (i j : ℕ)
    (h : l.rotate i = l.rotate j) : i % l.length = j % l.length := by
  

Proof state:
α : Type u
l : List α
hl : Nodup l
hn : l ≠ []
i j : ℕ
h : rotate l i = rotate l j
⊢ i % length l = j % length l

Next tactic:
have hi : i % l.length < l.length := mod_lt _ (length_pos_of_ne_nil hn)
set_option linter.deprecated false in
theorem Nodup.rotate_congr {l : List α} (hl : l.Nodup) (hn : l ≠ []) (i j : ℕ)
    (h : l.rotate i = l.rotate j) : i % l.length = j % l.length := by
  have hi : i % l.length < l.length := mod_lt _ (length_pos_of_ne_nil hn)
  

Proof state:
α : Type u
l : List α
hl : Nodup l
hn : l ≠ []
i j : ℕ
h : rotate l i = rotate l j
hi : i % length l < length l
⊢ i % length l = j % length l

Next tactic:
have hj : j % l.length < l.length := mod_lt _ (length_pos_of_ne_nil hn)
set_option linter.deprecated false in
theorem Nodup.rotate_congr {l : List α} (hl : l.Nodup) (hn : l ≠ []) (i j : ℕ)
    (h : l.rotate i = l.rotate j) : i % l.length = j % l.length := by
  have hi : i % l.length < l.length := mod_lt _ (length_pos_of_ne_nil hn)
  have hj : j % l.length < l.length := mod_lt _ (length_pos_of_ne_nil hn)
  

Proof state:
α : Type u
l : List α
hl : Nodup l
hn : l ≠ []
i j : ℕ
h : rotate l i = rotate l j
hi : i % length l < length l
hj : j % length l < length l
⊢ i % length l = j % length l

Next tactic:
refine' (nodup_iff_nthLe_inj.mp hl) _ _ hi hj _
set_option linter.deprecated false in
theorem Nodup.rotate_congr {l : List α} (hl : l.Nodup) (hn : l ≠ []) (i j : ℕ)
    (h : l.rotate i = l.rotate j) : i % l.length = j % l.length := by
  have hi : i % l.length < l.length := mod_lt _ (length_pos_of_ne_nil hn)
  have hj : j % l.length < l.length := mod_lt _ (length_pos_of_ne_nil hn)
  refine' (nodup_iff_nthLe_inj.mp hl) _ _ hi hj _
  

Proof state:
α : Type u
l : List α
hl : Nodup l
hn : l ≠ []
i j : ℕ
h : rotate l i = rotate l j
hi : i % length l < length l
hj : j % length l < length l
⊢ nthLe l (i % length l) hi = nthLe l (j % length l) hj

Next tactic:
rw [← nthLe_rotate' l i, ← nthLe_rotate' l j]
set_option linter.deprecated false in
theorem Nodup.rotate_congr {l : List α} (hl : l.Nodup) (hn : l ≠ []) (i j : ℕ)
    (h : l.rotate i = l.rotate j) : i % l.length = j % l.length := by
  have hi : i % l.length < l.length := mod_lt _ (length_pos_of_ne_nil hn)
  have hj : j % l.length < l.length := mod_lt _ (length_pos_of_ne_nil hn)
  refine' (nodup_iff_nthLe_inj.mp hl) _ _ hi hj _
  rw [← nthLe_rotate' l i, ← nthLe_rotate' l j]
  

Proof state:
α : Type u
l : List α
hl : Nodup l
hn : l ≠ []
i j : ℕ
h : rotate l i = rotate l j
hi : i % length l < length l
hj : j % length l < length l
⊢ nthLe (rotate l i) ((length l - i % length l + i % length l) % length l)
      (_ : (length l - i % length l + i % length l) % length l < length (rotate l i)) =
    nthLe (rotate l j) ((length l - j % length l + j % length l) % length l)
      (_ : (length l - j % length l + j % length l) % length l < length (rotate l j))

Next tactic:
simp [tsub_add_cancel_of_le, hi.le, hj.le, h]
@[refl]
theorem IsRotated.refl (l : List α) : l ~r l :=
  ⟨0, by 

Proof state:
α : Type u
l✝ l' l : List α
⊢ rotate l 0 = l

Next tactic:
simp
@[symm]
theorem IsRotated.symm (h : l ~r l') : l' ~r l := by
  

Proof state:
α : Type u
l l' : List α
h : l ~r l'
⊢ l' ~r l

Next tactic:
obtain ⟨n, rfl⟩ := h
@[symm]
theorem IsRotated.symm (h : l ~r l') : l' ~r l := by
  obtain ⟨n, rfl⟩ := h
  

Proof state:
case intro
α : Type u
l : List α
n : ℕ
⊢ rotate l n ~r l

Next tactic:
cases' l with hd tl
@[symm]
theorem IsRotated.symm (h : l ~r l') : l' ~r l := by
  obtain ⟨n, rfl⟩ := h
  cases' l with hd tl
  · 

Proof state:
case intro.nil
α : Type u
n : ℕ
⊢ rotate [] n ~r []

Next tactic:
exists 0
@[symm]
theorem IsRotated.symm (h : l ~r l') : l' ~r l := by
  obtain ⟨n, rfl⟩ := h
  cases' l with hd tl
  · exists 0
  · 

Proof state:
case intro.cons
α : Type u
n : ℕ
hd : α
tl : List α
⊢ rotate (hd :: tl) n ~r (hd :: tl)

Next tactic:
use (hd :: tl).length * n - n
@[symm]
theorem IsRotated.symm (h : l ~r l') : l' ~r l := by
  obtain ⟨n, rfl⟩ := h
  cases' l with hd tl
  · exists 0
  · use (hd :: tl).length * n - n
    

Proof state:
case h
α : Type u
n : ℕ
hd : α
tl : List α
⊢ rotate (rotate (hd :: tl) n) (length (hd :: tl) * n - n) = hd :: tl

Next tactic:
rw [rotate_rotate, add_tsub_cancel_of_le, rotate_length_mul]
@[symm]
theorem IsRotated.symm (h : l ~r l') : l' ~r l := by
  obtain ⟨n, rfl⟩ := h
  cases' l with hd tl
  · exists 0
  · use (hd :: tl).length * n - n
    rw [rotate_rotate, add_tsub_cancel_of_le, rotate_length_mul]
    

Proof state:
case h
α : Type u
n : ℕ
hd : α
tl : List α
⊢ n ≤ length (hd :: tl) * n

Next tactic:
exact Nat.le_mul_of_pos_left (by simp)
@[symm]
theorem IsRotated.symm (h : l ~r l') : l' ~r l := by
  obtain ⟨n, rfl⟩ := h
  cases' l with hd tl
  · exists 0
  · use (hd :: tl).length * n - n
    rw [rotate_rotate, add_tsub_cancel_of_le, rotate_length_mul]
    exact Nat.le_mul_of_pos_left (by 

Proof state:
α : Type u
n : ℕ
hd : α
tl : List α
⊢ 0 < length (hd :: tl)

Next tactic:
simp
@[trans]
theorem IsRotated.trans : ∀ {l l' l'' : List α}, l ~r l' → l' ~r l'' → l ~r l''
  | _, _, _, ⟨n, rfl⟩, ⟨m, rfl⟩ => ⟨n + m, by 

Proof state:
α : Type u
l l' l✝ : List α
n m : ℕ
⊢ rotate l✝ (n + m) = rotate (rotate l✝ n) m

Next tactic:
rw [rotate_rotate]
@[simp]
theorem isRotated_nil_iff : l ~r [] ↔ l = [] :=
  ⟨fun ⟨n, hn⟩ => by 

Proof state:
α : Type u
l l' : List α
x✝ : l ~r []
n : ℕ
hn : rotate l n = []
⊢ l = []

Next tactic:
simpa using hn
@[simp]
theorem isRotated_nil_iff : l ~r [] ↔ l = [] :=
  ⟨fun ⟨n, hn⟩ => by simpa using hn, fun h => h ▸ by 

Proof state:
α : Type u
l l' : List α
h : l = []
⊢ l ~r l

Next tactic:
rfl
@[simp]
theorem isRotated_nil_iff' : [] ~r l ↔ [] = l := by
  

Proof state:
α : Type u
l l' : List α
⊢ [] ~r l ↔ [] = l

Next tactic:
rw [isRotated_comm, isRotated_nil_iff, eq_comm]
@[simp]
theorem isRotated_singleton_iff {x : α} : l ~r [x] ↔ l = [x] :=
  ⟨fun ⟨n, hn⟩ => by 

Proof state:
α : Type u
l l' : List α
x : α
x✝ : l ~r [x]
n : ℕ
hn : rotate l n = [x]
⊢ l = [x]

Next tactic:
simpa using hn
@[simp]
theorem isRotated_singleton_iff {x : α} : l ~r [x] ↔ l = [x] :=
  ⟨fun ⟨n, hn⟩ => by simpa using hn, fun h => h ▸ by 

Proof state:
α : Type u
l l' : List α
x : α
h : l = [x]
⊢ l ~r l

Next tactic:
rfl
@[simp]
theorem isRotated_singleton_iff' {x : α} : [x] ~r l ↔ [x] = l := by
  

Proof state:
α : Type u
l l' : List α
x : α
⊢ [x] ~r l ↔ [x] = l

Next tactic:
rw [isRotated_comm, isRotated_singleton_iff, eq_comm]