l3lab/ntp-mathlib huggingface dataset:
theorem get?_rotate {l : List α} {n m : ℕ} (hml : m < l.length) :
    (l.rotate n).get? m = l.get? ((m + n) % l.length) := by
  rw [rotate_eq_drop_append_take_mod]
  rcases lt_or_le m (l.drop (n % l.length)).length with hm | hm
  · rw [get?_append hm, get?_drop, add_comm m, ← mod_add_mod]
    rw [length_drop, lt_tsub_iff_left] at hm
    rw [mod_eq_of_lt hm]
  · have hlt : n % length l < length l := mod_lt _ (m.zero_le.trans_lt hml)
    rw [get?_append_right hm, get?_take, length_drop]
    · congr 1
      rw [length_drop] at hm
      have hm' := tsub_le_iff_left.1 hm
      have : n % length l + m - length l < length l := by
        rw [tsub_lt_iff_left hm']
        

Proof state:
α : Type u
l : List α
n m : ℕ
hml : m < length l
hm : length l - n % length l ≤ m
hlt : n % length l < length l
hm' : length l ≤ n % length l + m
⊢ n % length l + m < length l + length l

Next tactic:
exact Nat.add_lt_add hlt hml
theorem get?_rotate {l : List α} {n m : ℕ} (hml : m < l.length) :
    (l.rotate n).get? m = l.get? ((m + n) % l.length) := by
  rw [rotate_eq_drop_append_take_mod]
  rcases lt_or_le m (l.drop (n % l.length)).length with hm | hm
  · rw [get?_append hm, get?_drop, add_comm m, ← mod_add_mod]
    rw [length_drop, lt_tsub_iff_left] at hm
    rw [mod_eq_of_lt hm]
  · have hlt : n % length l < length l := mod_lt _ (m.zero_le.trans_lt hml)
    rw [get?_append_right hm, get?_take, length_drop]
    · congr 1
      rw [length_drop] at hm
      have hm' := tsub_le_iff_left.1 hm
      have : n % length l + m - length l < length l := by
        rw [tsub_lt_iff_left hm']
        exact Nat.add_lt_add hlt hml
      

Proof state:
case inr.e_a
α : Type u
l : List α
n m : ℕ
hml : m < length l
hm : length l - n % length l ≤ m
hlt : n % length l < length l
hm' : length l ≤ n % length l + m
this : n % length l + m - length l < length l
⊢ m - (length l - n % length l) = (m + n) % length l

Next tactic:
conv_rhs => rw [add_comm m, ← mod_add_mod, mod_eq_sub_mod hm', mod_eq_of_lt this]
theorem get?_rotate {l : List α} {n m : ℕ} (hml : m < l.length) :
    (l.rotate n).get? m = l.get? ((m + n) % l.length) := by
  rw [rotate_eq_drop_append_take_mod]
  rcases lt_or_le m (l.drop (n % l.length)).length with hm | hm
  · rw [get?_append hm, get?_drop, add_comm m, ← mod_add_mod]
    rw [length_drop, lt_tsub_iff_left] at hm
    rw [mod_eq_of_lt hm]
  · have hlt : n % length l < length l := mod_lt _ (m.zero_le.trans_lt hml)
    rw [get?_append_right hm, get?_take, length_drop]
    · congr 1
      rw [length_drop] at hm
      have hm' := tsub_le_iff_left.1 hm
      have : n % length l + m - length l < length l := by
        rw [tsub_lt_iff_left hm']
        exact Nat.add_lt_add hlt hml
      conv_rhs => 

Proof state:
α : Type u
l : List α
n m : ℕ
hml : m < length l
hm : length l - n % length l ≤ m
hlt : n % length l < length l
hm' : length l ≤ n % length l + m
this : n % length l + m - length l < length l
| (m + n) % length l

Next tactic:
rw [add_comm m, ← mod_add_mod, mod_eq_sub_mod hm', mod_eq_of_lt this]
theorem get?_rotate {l : List α} {n m : ℕ} (hml : m < l.length) :
    (l.rotate n).get? m = l.get? ((m + n) % l.length) := by
  rw [rotate_eq_drop_append_take_mod]
  rcases lt_or_le m (l.drop (n % l.length)).length with hm | hm
  · rw [get?_append hm, get?_drop, add_comm m, ← mod_add_mod]
    rw [length_drop, lt_tsub_iff_left] at hm
    rw [mod_eq_of_lt hm]
  · have hlt : n % length l < length l := mod_lt _ (m.zero_le.trans_lt hml)
    rw [get?_append_right hm, get?_take, length_drop]
    · congr 1
      rw [length_drop] at hm
      have hm' := tsub_le_iff_left.1 hm
      have : n % length l + m - length l < length l := by
        rw [tsub_lt_iff_left hm']
        exact Nat.add_lt_add hlt hml
      conv_rhs => rw [add_comm m, ← mod_add_mod, mod_eq_sub_mod hm', mod_eq_of_lt this]
      

Proof state:
case inr.e_a
α : Type u
l : List α
n m : ℕ
hml : m < length l
hm : length l - n % length l ≤ m
hlt : n % length l < length l
hm' : length l ≤ n % length l + m
this : n % length l + m - length l < length l
⊢ m - (length l - n % length l) = n % length l + m - length l

Next tactic:
rw [← add_right_inj l.length, ← add_tsub_assoc_of_le, add_tsub_tsub_cancel,
        add_tsub_cancel_of_le, add_comm]
theorem get?_rotate {l : List α} {n m : ℕ} (hml : m < l.length) :
    (l.rotate n).get? m = l.get? ((m + n) % l.length) := by
  rw [rotate_eq_drop_append_take_mod]
  rcases lt_or_le m (l.drop (n % l.length)).length with hm | hm
  · rw [get?_append hm, get?_drop, add_comm m, ← mod_add_mod]
    rw [length_drop, lt_tsub_iff_left] at hm
    rw [mod_eq_of_lt hm]
  · have hlt : n % length l < length l := mod_lt _ (m.zero_le.trans_lt hml)
    rw [get?_append_right hm, get?_take, length_drop]
    · congr 1
      rw [length_drop] at hm
      have hm' := tsub_le_iff_left.1 hm
      have : n % length l + m - length l < length l := by
        rw [tsub_lt_iff_left hm']
        exact Nat.add_lt_add hlt hml
      conv_rhs => rw [add_comm m, ← mod_add_mod, mod_eq_sub_mod hm', mod_eq_of_lt this]
      rw [← add_right_inj l.length, ← add_tsub_assoc_of_le, add_tsub_tsub_cancel,
        add_tsub_cancel_of_le, add_comm]
      

Proof state:
case inr.e_a
α : Type u
l : List α
n m : ℕ
hml : m < length l
hm : length l - n % length l ≤ m
hlt : n % length l < length l
hm' : length l ≤ n % length l + m
this : n % length l + m - length l < length l
⊢ length l ≤ n % length l + m
case inr.e_a
α : Type u
l : List α
n m : ℕ
hml : m < length l
hm : length l - n % length l ≤ m
hlt : n % length l < length l
hm' : length l ≤ n % length l + m
this : n % length l + m - length l < length l
⊢ n % length l ≤ length l
case inr.e_a.h
α : Type u
l : List α
n m : ℕ
hml : m < length l
hm : length l - n % length l ≤ m
hlt : n % length l < length l
hm' : length l ≤ n % length l + m
this : n % length l + m - length l < length l
⊢ length l - n % length l ≤ m

Next tactic:
exacts [hm', hlt.le, hm]
theorem get?_rotate {l : List α} {n m : ℕ} (hml : m < l.length) :
    (l.rotate n).get? m = l.get? ((m + n) % l.length) := by
  rw [rotate_eq_drop_append_take_mod]
  rcases lt_or_le m (l.drop (n % l.length)).length with hm | hm
  · rw [get?_append hm, get?_drop, add_comm m, ← mod_add_mod]
    rw [length_drop, lt_tsub_iff_left] at hm
    rw [mod_eq_of_lt hm]
  · have hlt : n % length l < length l := mod_lt _ (m.zero_le.trans_lt hml)
    rw [get?_append_right hm, get?_take, length_drop]
    · congr 1
      rw [length_drop] at hm
      have hm' := tsub_le_iff_left.1 hm
      have : n % length l + m - length l < length l := by
        rw [tsub_lt_iff_left hm']
        exact Nat.add_lt_add hlt hml
      conv_rhs => rw [add_comm m, ← mod_add_mod, mod_eq_sub_mod hm', mod_eq_of_lt this]
      rw [← add_right_inj l.length, ← add_tsub_assoc_of_le, add_tsub_tsub_cancel,
        add_tsub_cancel_of_le, add_comm]
      exacts [hm', hlt.le, hm]
    · 

Proof state:
case inr
α : Type u
l : List α
n m : ℕ
hml : m < length l
hm : length (drop (n % length l) l) ≤ m
hlt : n % length l < length l
⊢ m - length (drop (n % length l) l) < n % length l

Next tactic:
rwa [tsub_lt_iff_left hm, length_drop, tsub_add_cancel_of_le hlt.le]
theorem get_rotate (l : List α) (n : ℕ) (k : Fin (l.rotate n).length) :
    (l.rotate n).get k =
      l.get ⟨(k + n) % l.length, mod_lt _ (length_rotate l n ▸ k.1.zero_le.trans_lt k.2)⟩ := by
  

Proof state:
α : Type u
l : List α
n : ℕ
k : Fin (length (rotate l n))
⊢ get (rotate l n) k = get l { val := (↑k + n) % length l, isLt := (_ : (↑k + n) % length l < length l) }

Next tactic:
rw [← Option.some_inj, ← get?_eq_get, ← get?_eq_get, get?_rotate]
theorem get_rotate (l : List α) (n : ℕ) (k : Fin (l.rotate n).length) :
    (l.rotate n).get k =
      l.get ⟨(k + n) % l.length, mod_lt _ (length_rotate l n ▸ k.1.zero_le.trans_lt k.2)⟩ := by
  rw [← Option.some_inj, ← get?_eq_get, ← get?_eq_get, get?_rotate]
  

Proof state:
α : Type u
l : List α
n : ℕ
k : Fin (length (rotate l n))
⊢ ↑k < length l

Next tactic:
exact k.2.trans_eq (length_rotate _ _)
theorem head?_rotate {l : List α} {n : ℕ} (h : n < l.length) : head? (l.rotate n) = l.get? n := by
  

Proof state:
α : Type u
l : List α
n : ℕ
h : n < length l
⊢ head? (rotate l n) = get? l n

Next tactic:
rw [← get?_zero, get?_rotate (n.zero_le.trans_lt h), zero_add, Nat.mod_eq_of_lt h]
/-- A version of `List.get_rotate` that represents `List.get l` in terms of
`List.get (List.rotate l n)`, not vice versa. Can be used instead of rewriting `List.get_rotate`
from right to left. -/
theorem get_eq_get_rotate (l : List α) (n : ℕ) (k : Fin l.length) :
    l.get k = (l.rotate n).get ⟨(l.length - n % l.length + k) % l.length,
      (Nat.mod_lt _ (k.1.zero_le.trans_lt k.2)).trans_eq (length_rotate _ _).symm⟩ := by
  

Proof state:
α : Type u
l : List α
n : ℕ
k : Fin (length l)
⊢ get l k =
    get (rotate l n)
      { val := (length l - n % length l + ↑k) % length l,
        isLt := (_ : (length l - n % length l + ↑k) % length l < length (rotate l n)) }

Next tactic:
rw [get_rotate]
/-- A version of `List.get_rotate` that represents `List.get l` in terms of
`List.get (List.rotate l n)`, not vice versa. Can be used instead of rewriting `List.get_rotate`
from right to left. -/
theorem get_eq_get_rotate (l : List α) (n : ℕ) (k : Fin l.length) :
    l.get k = (l.rotate n).get ⟨(l.length - n % l.length + k) % l.length,
      (Nat.mod_lt _ (k.1.zero_le.trans_lt k.2)).trans_eq (length_rotate _ _).symm⟩ := by
  rw [get_rotate]
  

Proof state:
α : Type u
l : List α
n : ℕ
k : Fin (length l)
⊢ get l k =
    get l
      {
        val :=
          (↑{ val := (length l - n % length l + ↑k) % length l,
                  isLt := (_ : (length l - n % length l + ↑k) % length l < length (rotate l n)) } +
              n) %
            length l,
        isLt :=
          (_ :
            (↑{ val := (length l - n % length l + ↑k) % length l,
                      isLt := (_ : (length l - n % length l + ↑k) % length l < length (rotate l n)) } +
                  n) %
                length l <
              length l) }

Next tactic:
refine congr_arg l.get (Fin.eq_of_val_eq ?_)
/-- A version of `List.get_rotate` that represents `List.get l` in terms of
`List.get (List.rotate l n)`, not vice versa. Can be used instead of rewriting `List.get_rotate`
from right to left. -/
theorem get_eq_get_rotate (l : List α) (n : ℕ) (k : Fin l.length) :
    l.get k = (l.rotate n).get ⟨(l.length - n % l.length + k) % l.length,
      (Nat.mod_lt _ (k.1.zero_le.trans_lt k.2)).trans_eq (length_rotate _ _).symm⟩ := by
  rw [get_rotate]
  refine congr_arg l.get (Fin.eq_of_val_eq ?_)
  

Proof state:
α : Type u
l : List α
n : ℕ
k : Fin (length l)
⊢ ↑k =
    ↑{
        val :=
          (↑{ val := (length l - n % length l + ↑k) % length l,
                  isLt := (_ : (length l - n % length l + ↑k) % length l < length (rotate l n)) } +
              n) %
            length l,
        isLt :=
          (_ :
            (↑{ val := (length l - n % length l + ↑k) % length l,
                      isLt := (_ : (length l - n % length l + ↑k) % length l < length (rotate l n)) } +
                  n) %
                length l <
              length l) }

Next tactic:
simp only [mod_add_mod]
/-- A version of `List.get_rotate` that represents `List.get l` in terms of
`List.get (List.rotate l n)`, not vice versa. Can be used instead of rewriting `List.get_rotate`
from right to left. -/
theorem get_eq_get_rotate (l : List α) (n : ℕ) (k : Fin l.length) :
    l.get k = (l.rotate n).get ⟨(l.length - n % l.length + k) % l.length,
      (Nat.mod_lt _ (k.1.zero_le.trans_lt k.2)).trans_eq (length_rotate _ _).symm⟩ := by
  rw [get_rotate]
  refine congr_arg l.get (Fin.eq_of_val_eq ?_)
  simp only [mod_add_mod]
  

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

Next tactic:
rw [← add_mod_mod, add_right_comm, tsub_add_cancel_of_le, add_mod_left, mod_eq_of_lt]
/-- A version of `List.get_rotate` that represents `List.get l` in terms of
`List.get (List.rotate l n)`, not vice versa. Can be used instead of rewriting `List.get_rotate`
from right to left. -/
theorem get_eq_get_rotate (l : List α) (n : ℕ) (k : Fin l.length) :
    l.get k = (l.rotate n).get ⟨(l.length - n % l.length + k) % l.length,
      (Nat.mod_lt _ (k.1.zero_le.trans_lt k.2)).trans_eq (length_rotate _ _).symm⟩ := by
  rw [get_rotate]
  refine congr_arg l.get (Fin.eq_of_val_eq ?_)
  simp only [mod_add_mod]
  rw [← add_mod_mod, add_right_comm, tsub_add_cancel_of_le, add_mod_left, mod_eq_of_lt]
  

Proof state:
α : Type u
l : List α
n : ℕ
k : Fin (length l)
⊢ ↑k < length l
α : Type u l : List α n : ℕ k : Fin (length l) ⊢ n % length l ≤ length l

Next tactic:
exacts [k.2, (mod_lt _ (k.1.zero_le.trans_lt k.2)).le]
theorem rotate_eq_self_iff_eq_replicate [hα : Nonempty α] :
    ∀ {l : List α}, (∀ n, l.rotate n = l) ↔ ∃ a, l = replicate l.length a
  | [] => by 

Proof state:
α : Type u
hα : Nonempty α
⊢ (∀ (n : ℕ), rotate [] n = []) ↔ ∃ a, [] = replicate (length []) a

Next tactic:
simp
theorem rotate_eq_self_iff_eq_replicate [hα : Nonempty α] :
    ∀ {l : List α}, (∀ n, l.rotate n = l) ↔ ∃ a, l = replicate l.length a
  | [] => by simp
  | a :: l => ⟨fun h => ⟨a, ext_get (length_replicate _ _).symm fun n h₁ h₂ => by
      

Proof state:
α : Type u
hα : Nonempty α
a : α
l : List α
h : ∀ (n : ℕ), rotate (a :: l) n = a :: l
n : ℕ
h₁ : n < length (a :: l)
h₂ : n < length (replicate (length (a :: l)) a)
⊢ get (a :: l) { val := n, isLt := h₁ } = get (replicate (length (a :: l)) a) { val := n, isLt := h₂ }

Next tactic:
rw [get_replicate, ← Option.some_inj, ← get?_eq_get, ← head?_rotate h₁, h, head?_cons]
theorem rotate_eq_self_iff_eq_replicate [hα : Nonempty α] :
    ∀ {l : List α}, (∀ n, l.rotate n = l) ↔ ∃ a, l = replicate l.length a
  | [] => by simp
  | a :: l => ⟨fun h => ⟨a, ext_get (length_replicate _ _).symm fun n h₁ h₂ => by
      rw [get_replicate, ← Option.some_inj, ← get?_eq_get, ← head?_rotate h₁, h, head?_cons]⟩,
    fun ⟨b, hb⟩ n => by 

Proof state:
α : Type u
hα : Nonempty α
a : α
l : List α
x✝ : ∃ a_1, a :: l = replicate (length (a :: l)) a_1
n : ℕ
b : α
hb : a :: l = replicate (length (a :: l)) b
⊢ rotate (a :: l) n = a :: l

Next tactic:
rw [hb, rotate_replicate]
theorem rotate_one_eq_self_iff_eq_replicate [Nonempty α] {l : List α} :
    l.rotate 1 = l ↔ ∃ a : α, l = List.replicate l.length a :=
  ⟨fun h =>
    rotate_eq_self_iff_eq_replicate.mp fun n =>
      Nat.rec l.rotate_zero (fun n hn => by 

Proof state:
α : Type u
inst✝ : Nonempty α
l : List α
h : rotate l 1 = l
n✝ n : ℕ
hn : rotate l n = l
⊢ rotate l (succ n) = l

Next tactic:
rwa [Nat.succ_eq_add_one, ← l.rotate_rotate, hn]
theorem rotate_injective (n : ℕ) : Function.Injective fun l : List α => l.rotate n := by
  

Proof state:
α : Type u
n : ℕ
⊢ Injective fun l => rotate l n

Next tactic:
rintro l l' (h : l.rotate n = l'.rotate n)
theorem rotate_injective (n : ℕ) : Function.Injective fun l : List α => l.rotate n := by
  rintro l l' (h : l.rotate n = l'.rotate n)
  

Proof state:
α : Type u
n : ℕ
l l' : List α
h : rotate l n = rotate l' n
⊢ l = l'

Next tactic:
have hle : l.length = l'.length := (l.length_rotate n).symm.trans (h.symm ▸ l'.length_rotate n)
theorem rotate_injective (n : ℕ) : Function.Injective fun l : List α => l.rotate n := by
  rintro l l' (h : l.rotate n = l'.rotate n)
  have hle : l.length = l'.length := (l.length_rotate n).symm.trans (h.symm ▸ l'.length_rotate n)
  

Proof state:
α : Type u
n : ℕ
l l' : List α
h : rotate l n = rotate l' n
hle : length l = length l'
⊢ l = l'

Next tactic:
rw [rotate_eq_drop_append_take_mod, rotate_eq_drop_append_take_mod] at h
theorem rotate_injective (n : ℕ) : Function.Injective fun l : List α => l.rotate n := by
  rintro l l' (h : l.rotate n = l'.rotate n)
  have hle : l.length = l'.length := (l.length_rotate n).symm.trans (h.symm ▸ l'.length_rotate n)
  rw [rotate_eq_drop_append_take_mod, rotate_eq_drop_append_take_mod] at h
  

Proof state:
α : Type u
n : ℕ
l l' : List α
h : drop (n % length l) l ++ take (n % length l) l = drop (n % length l') l' ++ take (n % length l') l'
hle : length l = length l'
⊢ l = l'

Next tactic:
obtain ⟨hd, ht⟩ := append_inj h (by simp_all)
theorem rotate_injective (n : ℕ) : Function.Injective fun l : List α => l.rotate n := by
  rintro l l' (h : l.rotate n = l'.rotate n)
  have hle : l.length = l'.length := (l.length_rotate n).symm.trans (h.symm ▸ l'.length_rotate n)
  rw [rotate_eq_drop_append_take_mod, rotate_eq_drop_append_take_mod] at h
  obtain ⟨hd, ht⟩ := append_inj h (by 

Proof state:
α : Type u
n : ℕ
l l' : List α
h : drop (n % length l) l ++ take (n % length l) l = drop (n % length l') l' ++ take (n % length l') l'
hle : length l = length l'
⊢ length (drop (n % length l) l) = length (drop (n % length l') l')

Next tactic:
simp_all
theorem rotate_injective (n : ℕ) : Function.Injective fun l : List α => l.rotate n := by
  rintro l l' (h : l.rotate n = l'.rotate n)
  have hle : l.length = l'.length := (l.length_rotate n).symm.trans (h.symm ▸ l'.length_rotate n)
  rw [rotate_eq_drop_append_take_mod, rotate_eq_drop_append_take_mod] at h
  obtain ⟨hd, ht⟩ := append_inj h (by simp_all)
  

Proof state:
case intro
α : Type u
n : ℕ
l l' : List α
h : drop (n % length l) l ++ take (n % length l) l = drop (n % length l') l' ++ take (n % length l') l'
hle : length l = length l'
hd : drop (n % length l) l = drop (n % length l') l'
ht : take (n % length l) l = take (n % length l') l'
⊢ l = l'

Next tactic:
rw [← take_append_drop _ l, ht, hd, take_append_drop]
theorem rotate_eq_iff {l l' : List α} {n : ℕ} :
    l.rotate n = l' ↔ l = l'.rotate (l'.length - n % l'.length) := by
  

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

Next tactic:
rw [← @rotate_eq_rotate _ l _ n, rotate_rotate, ← rotate_mod l', add_mod]
theorem rotate_eq_iff {l l' : List α} {n : ℕ} :
    l.rotate n = l' ↔ l = l'.rotate (l'.length - n % l'.length) := by
  rw [← @rotate_eq_rotate _ l _ n, rotate_rotate, ← rotate_mod l', add_mod]
  

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

Next tactic:
rcases l'.length.zero_le.eq_or_lt with hl | hl
theorem rotate_eq_iff {l l' : List α} {n : ℕ} :
    l.rotate n = l' ↔ l = l'.rotate (l'.length - n % l'.length) := by
  rw [← @rotate_eq_rotate _ l _ n, rotate_rotate, ← rotate_mod l', add_mod]
  rcases l'.length.zero_le.eq_or_lt with hl | hl
  · 

Proof state:
case inl
α : Type u
l l' : List α
n : ℕ
hl : 0 = length l'
⊢ rotate l n = l' ↔ rotate l n = rotate l' (((length l' - n % length l') % length l' + n % length l') % length l')

Next tactic:
rw [eq_nil_of_length_eq_zero hl.symm, rotate_nil, rotate_eq_nil_iff]
theorem rotate_eq_iff {l l' : List α} {n : ℕ} :
    l.rotate n = l' ↔ l = l'.rotate (l'.length - n % l'.length) := by
  rw [← @rotate_eq_rotate _ l _ n, rotate_rotate, ← rotate_mod l', add_mod]
  rcases l'.length.zero_le.eq_or_lt with hl | hl
  · rw [eq_nil_of_length_eq_zero hl.symm, rotate_nil, rotate_eq_nil_iff]
  · 

Proof state:
case inr
α : Type u
l l' : List α
n : ℕ
hl : 0 < length l'
⊢ rotate l n = l' ↔ rotate l n = rotate l' (((length l' - n % length l') % length l' + n % length l') % length l')

Next tactic:
rcases (Nat.zero_le (n % l'.length)).eq_or_lt with hn | hn
theorem rotate_eq_iff {l l' : List α} {n : ℕ} :
    l.rotate n = l' ↔ l = l'.rotate (l'.length - n % l'.length) := by
  rw [← @rotate_eq_rotate _ l _ n, rotate_rotate, ← rotate_mod l', add_mod]
  rcases l'.length.zero_le.eq_or_lt with hl | hl
  · rw [eq_nil_of_length_eq_zero hl.symm, rotate_nil, rotate_eq_nil_iff]
  · rcases (Nat.zero_le (n % l'.length)).eq_or_lt with hn | hn
    · 

Proof state:
case inr.inl
α : Type u
l l' : List α
n : ℕ
hl : 0 < length l'
hn : 0 = n % length l'
⊢ rotate l n = l' ↔ rotate l n = rotate l' (((length l' - n % length l') % length l' + n % length l') % length l')

Next tactic:
simp [← hn]
theorem rotate_eq_iff {l l' : List α} {n : ℕ} :
    l.rotate n = l' ↔ l = l'.rotate (l'.length - n % l'.length) := by
  rw [← @rotate_eq_rotate _ l _ n, rotate_rotate, ← rotate_mod l', add_mod]
  rcases l'.length.zero_le.eq_or_lt with hl | hl
  · rw [eq_nil_of_length_eq_zero hl.symm, rotate_nil, rotate_eq_nil_iff]
  · rcases (Nat.zero_le (n % l'.length)).eq_or_lt with hn | hn
    · simp [← hn]
    · 

Proof state:
case inr.inr
α : Type u
l l' : List α
n : ℕ
hl : 0 < length l'
hn : 0 < n % length l'
⊢ rotate l n = l' ↔ rotate l n = rotate l' (((length l' - n % length l') % length l' + n % length l') % length l')

Next tactic:
rw [mod_eq_of_lt (tsub_lt_self hl hn), tsub_add_cancel_of_le, mod_self, rotate_zero]
theorem rotate_eq_iff {l l' : List α} {n : ℕ} :
    l.rotate n = l' ↔ l = l'.rotate (l'.length - n % l'.length) := by
  rw [← @rotate_eq_rotate _ l _ n, rotate_rotate, ← rotate_mod l', add_mod]
  rcases l'.length.zero_le.eq_or_lt with hl | hl
  · rw [eq_nil_of_length_eq_zero hl.symm, rotate_nil, rotate_eq_nil_iff]
  · rcases (Nat.zero_le (n % l'.length)).eq_or_lt with hn | hn
    · simp [← hn]
    · rw [mod_eq_of_lt (tsub_lt_self hl hn), tsub_add_cancel_of_le, mod_self, rotate_zero]
      

Proof state:
case inr.inr
α : Type u
l l' : List α
n : ℕ
hl : 0 < length l'
hn : 0 < n % length l'
⊢ n % length l' ≤ length l'

Next tactic:
exact (Nat.mod_lt _ hl).le
@[simp]
theorem rotate_eq_singleton_iff {l : List α} {n : ℕ} {x : α} : l.rotate n = [x] ↔ l = [x] := by
  

Proof state:
α : Type u
l : List α
n : ℕ
x : α
⊢ rotate l n = [x] ↔ l = [x]

Next tactic:
rw [rotate_eq_iff, rotate_singleton]
@[simp]
theorem singleton_eq_rotate_iff {l : List α} {n : ℕ} {x : α} : [x] = l.rotate n ↔ [x] = l := by
  

Proof state:
α : Type u
l : List α
n : ℕ
x : α
⊢ [x] = rotate l n ↔ [x] = l

Next tactic:
rw [eq_comm, rotate_eq_singleton_iff, eq_comm]
theorem reverse_rotate (l : List α) (n : ℕ) :
    (l.rotate n).reverse = l.reverse.rotate (l.length - n % l.length) := by
  

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

Next tactic:
rw [← length_reverse l, ← rotate_eq_iff]
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]
  

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

Next tactic:
induction' n with n hn generalizing l
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
  · 

Proof state:
case zero
α : Type u
l : List α
⊢ rotate (reverse (rotate l zero)) zero = reverse l

Next tactic:
simp
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
  · 

Proof state:
case succ
α : Type u
n : ℕ
hn : ∀ (l : List α), rotate (reverse (rotate l n)) n = reverse l
l : List α
⊢ rotate (reverse (rotate l (succ n))) (succ n) = reverse l

Next tactic:
cases' l with hd tl
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
    · 

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

Next tactic:
simp
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
    · 

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

Next tactic:
rw [rotate_cons_succ, Nat.succ_eq_add_one, ← rotate_rotate, hn]