l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem rotate'_length (l : List α) : rotate' l l.length = l := by
  rw [rotate'_eq_drop_append_take le_rfl]; 

Proof state:
α : Type u
l : List α
⊢ drop (length l) l ++ take (length l) l = l

Next tactic:
simp
@[simp]
theorem rotate'_length_mul (l : List α) : ∀ n : ℕ, l.rotate' (l.length * n) = l
  | 0 => by 

Proof state:
α : Type u
l : List α
⊢ rotate' l (length l * 0) = l

Next tactic:
simp
@[simp]
theorem rotate'_length_mul (l : List α) : ∀ n : ℕ, l.rotate' (l.length * n) = l
  | 0 => by simp
  | n + 1 =>
    calc
      l.rotate' (l.length * (n + 1)) =
          (l.rotate' (l.length * n)).rotate' (l.rotate' (l.length * n)).length :=
        by 

Proof state:
α : Type u
l : List α
n : ℕ
⊢ rotate' l (length l * (n + 1)) = rotate' (rotate' l (length l * n)) (length (rotate' l (length l * n)))

Next tactic:
simp [-rotate'_length, Nat.mul_succ, rotate'_rotate']
@[simp]
theorem rotate'_length_mul (l : List α) : ∀ n : ℕ, l.rotate' (l.length * n) = l
  | 0 => by simp
  | n + 1 =>
    calc
      l.rotate' (l.length * (n + 1)) =
          (l.rotate' (l.length * n)).rotate' (l.rotate' (l.length * n)).length :=
        by simp [-rotate'_length, Nat.mul_succ, rotate'_rotate']
      _ = l := by 

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

Next tactic:
rw [rotate'_length, rotate'_length_mul l n]
theorem rotate'_mod (l : List α) (n : ℕ) : l.rotate' (n % l.length) = l.rotate' n :=
  calc
    l.rotate' (n % l.length) =
        (l.rotate' (n % l.length)).rotate' ((l.rotate' (n % l.length)).length * (n / l.length)) :=
      by 

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

Next tactic:
rw [rotate'_length_mul]
theorem rotate'_mod (l : List α) (n : ℕ) : l.rotate' (n % l.length) = l.rotate' n :=
  calc
    l.rotate' (n % l.length) =
        (l.rotate' (n % l.length)).rotate' ((l.rotate' (n % l.length)).length * (n / l.length)) :=
      by rw [rotate'_length_mul]
    _ = l.rotate' n := by 

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

Next tactic:
rw [rotate'_rotate', length_rotate', Nat.mod_add_div]
theorem rotate_eq_rotate' (l : List α) (n : ℕ) : l.rotate n = l.rotate' n :=
  if h : l.length = 0 then by 

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

Next tactic:
simp_all [length_eq_zero]
theorem rotate_eq_rotate' (l : List α) (n : ℕ) : l.rotate n = l.rotate' n :=
  if h : l.length = 0 then by simp_all [length_eq_zero]
  else by
    

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

Next tactic:
rw [← rotate'_mod,
        rotate'_eq_drop_append_take (le_of_lt (Nat.mod_lt _ (Nat.pos_of_ne_zero h)))]
theorem rotate_eq_rotate' (l : List α) (n : ℕ) : l.rotate n = l.rotate' n :=
  if h : l.length = 0 then by simp_all [length_eq_zero]
  else by
    rw [← rotate'_mod,
        rotate'_eq_drop_append_take (le_of_lt (Nat.mod_lt _ (Nat.pos_of_ne_zero h)))];
      

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

Next tactic:
simp [rotate]
theorem rotate_cons_succ (l : List α) (a : α) (n : ℕ) :
    (a :: l : List α).rotate n.succ = (l ++ [a]).rotate n := by
  

Proof state:
α : Type u
l : List α
a : α
n : ℕ
⊢ rotate (a :: l) (succ n) = rotate (l ++ [a]) n

Next tactic:
rw [rotate_eq_rotate', rotate_eq_rotate', rotate'_cons_succ]
@[simp]
theorem mem_rotate : ∀ {l : List α} {a : α} {n : ℕ}, a ∈ l.rotate n ↔ a ∈ l
  | [], _, n => by 

Proof state:
α : Type u
x✝ : α
n : ℕ
⊢ x✝ ∈ rotate [] n ↔ x✝ ∈ []

Next tactic:
simp
@[simp]
theorem mem_rotate : ∀ {l : List α} {a : α} {n : ℕ}, a ∈ l.rotate n ↔ a ∈ l
  | [], _, n => by simp
  | a :: l, _, 0 => by 

Proof state:
α : Type u
a : α
l : List α
x✝ : α
⊢ x✝ ∈ rotate (a :: l) 0 ↔ x✝ ∈ a :: l

Next tactic:
simp
@[simp]
theorem mem_rotate : ∀ {l : List α} {a : α} {n : ℕ}, a ∈ l.rotate n ↔ a ∈ l
  | [], _, n => by simp
  | a :: l, _, 0 => by simp
  | a :: l, _, n + 1 => by 

Proof state:
α : Type u
a : α
l : List α
x✝ : α
n : ℕ
⊢ x✝ ∈ rotate (a :: l) (n + 1) ↔ x✝ ∈ a :: l

Next tactic:
simp [rotate_cons_succ, mem_rotate, or_comm]
@[simp]
theorem length_rotate (l : List α) (n : ℕ) : (l.rotate n).length = l.length := by
  

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

Next tactic:
rw [rotate_eq_rotate', length_rotate']
theorem rotate_replicate (a : α) (n : ℕ) (k : ℕ) : (replicate n a).rotate k = replicate n a :=
  eq_replicate.2 ⟨by 

Proof state:
α : Type u
a : α
n k : ℕ
⊢ length (rotate (replicate n a) k) = n

Next tactic:
rw [length_rotate, length_replicate]
theorem rotate_eq_drop_append_take {l : List α} {n : ℕ} :
    n ≤ l.length → l.rotate n = l.drop n ++ l.take n := by
  

Proof state:
α : Type u
l : List α
n : ℕ
⊢ n ≤ length l → rotate l n = drop n l ++ take n l

Next tactic:
rw [rotate_eq_rotate']
theorem rotate_eq_drop_append_take {l : List α} {n : ℕ} :
    n ≤ l.length → l.rotate n = l.drop n ++ l.take n := by
  rw [rotate_eq_rotate']; 

Proof state:
α : Type u
l : List α
n : ℕ
⊢ n ≤ length l → rotate' l n = drop n l ++ take n l

Next tactic:
exact rotate'_eq_drop_append_take
theorem rotate_eq_drop_append_take_mod {l : List α} {n : ℕ} :
    l.rotate n = l.drop (n % l.length) ++ l.take (n % l.length) := by
  

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

Next tactic:
rcases l.length.zero_le.eq_or_lt with hl | hl
theorem rotate_eq_drop_append_take_mod {l : List α} {n : ℕ} :
    l.rotate n = l.drop (n % l.length) ++ l.take (n % l.length) := by
  rcases l.length.zero_le.eq_or_lt with hl | hl
  · 

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

Next tactic:
simp [eq_nil_of_length_eq_zero hl.symm]
theorem rotate_eq_drop_append_take_mod {l : List α} {n : ℕ} :
    l.rotate n = l.drop (n % l.length) ++ l.take (n % l.length) := by
  rcases l.length.zero_le.eq_or_lt with hl | hl
  · simp [eq_nil_of_length_eq_zero hl.symm]
  

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

Next tactic:
rw [← rotate_eq_drop_append_take (n.mod_lt hl).le, rotate_mod]
@[simp]
theorem rotate_append_length_eq (l l' : List α) : (l ++ l').rotate l.length = l' ++ l := by
  

Proof state:
α : Type u
l l' : List α
⊢ rotate (l ++ l') (length l) = l' ++ l

Next tactic:
rw [rotate_eq_rotate']
@[simp]
theorem rotate_append_length_eq (l l' : List α) : (l ++ l').rotate l.length = l' ++ l := by
  rw [rotate_eq_rotate']
  

Proof state:
α : Type u
l l' : List α
⊢ rotate' (l ++ l') (length l) = l' ++ l

Next tactic:
induction l generalizing l'
@[simp]
theorem rotate_append_length_eq (l l' : List α) : (l ++ l').rotate l.length = l' ++ l := by
  rw [rotate_eq_rotate']
  induction l generalizing l'
  · 

Proof state:
case nil
α : Type u
l' : List α
⊢ rotate' ([] ++ l') (length []) = l' ++ []

Next tactic:
simp
@[simp]
theorem rotate_append_length_eq (l l' : List α) : (l ++ l').rotate l.length = l' ++ l := by
  rw [rotate_eq_rotate']
  induction l generalizing l'
  · simp
  · 

Proof state:
case cons
α : Type u
head✝ : α
tail✝ : List α
tail_ih✝ : ∀ (l' : List α), rotate' (tail✝ ++ l') (length tail✝) = l' ++ tail✝
l' : List α
⊢ rotate' (head✝ :: tail✝ ++ l') (length (head✝ :: tail✝)) = l' ++ head✝ :: tail✝

Next tactic:
simp_all [rotate']
theorem rotate_rotate (l : List α) (n m : ℕ) : (l.rotate n).rotate m = l.rotate (n + m) := by
  

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

Next tactic:
rw [rotate_eq_rotate', rotate_eq_rotate', rotate_eq_rotate', rotate'_rotate']
@[simp]
theorem rotate_length (l : List α) : rotate l l.length = l := by
  

Proof state:
α : Type u
l : List α
⊢ rotate l (length l) = l

Next tactic:
rw [rotate_eq_rotate', rotate'_length]
@[simp]
theorem rotate_length_mul (l : List α) (n : ℕ) : l.rotate (l.length * n) = l := by
  

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

Next tactic:
rw [rotate_eq_rotate', rotate'_length_mul]
theorem prod_rotate_eq_one_of_prod_eq_one [Group α] :
    ∀ {l : List α} (_ : l.prod = 1) (n : ℕ), (l.rotate n).prod = 1
  | [], _, _ => by 

Proof state:
α : Type u
inst✝ : Group α
x✝¹ : prod [] = 1
x✝ : ℕ
⊢ prod (rotate [] x✝) = 1

Next tactic:
simp
theorem prod_rotate_eq_one_of_prod_eq_one [Group α] :
    ∀ {l : List α} (_ : l.prod = 1) (n : ℕ), (l.rotate n).prod = 1
  | [], _, _ => by simp
  | a :: l, hl, n => by
    

Proof state:
α : Type u
inst✝ : Group α
a : α
l : List α
hl : prod (a :: l) = 1
n : ℕ
⊢ prod (rotate (a :: l) n) = 1

Next tactic:
have : n % List.length (a :: l) ≤ List.length (a :: l) := le_of_lt (Nat.mod_lt _ (by simp))
theorem prod_rotate_eq_one_of_prod_eq_one [Group α] :
    ∀ {l : List α} (_ : l.prod = 1) (n : ℕ), (l.rotate n).prod = 1
  | [], _, _ => by simp
  | a :: l, hl, n => by
    have : n % List.length (a :: l) ≤ List.length (a :: l) := le_of_lt (Nat.mod_lt _ (by 

Proof state:
α : Type u
inst✝ : Group α
a : α
l : List α
hl : prod (a :: l) = 1
n : ℕ
⊢ length (a :: l) > 0

Next tactic:
simp
theorem prod_rotate_eq_one_of_prod_eq_one [Group α] :
    ∀ {l : List α} (_ : l.prod = 1) (n : ℕ), (l.rotate n).prod = 1
  | [], _, _ => by simp
  | a :: l, hl, n => by
    have : n % List.length (a :: l) ≤ List.length (a :: l) := le_of_lt (Nat.mod_lt _ (by simp))
    

Proof state:
α : Type u
inst✝ : Group α
a : α
l : List α
hl : prod (a :: l) = 1
n : ℕ
this : n % length (a :: l) ≤ length (a :: l)
⊢ prod (rotate (a :: l) n) = 1

Next tactic:
rw [← List.take_append_drop (n % List.length (a :: l)) (a :: l)] at hl
theorem prod_rotate_eq_one_of_prod_eq_one [Group α] :
    ∀ {l : List α} (_ : l.prod = 1) (n : ℕ), (l.rotate n).prod = 1
  | [], _, _ => by simp
  | a :: l, hl, n => by
    have : n % List.length (a :: l) ≤ List.length (a :: l) := le_of_lt (Nat.mod_lt _ (by simp))
    rw [← List.take_append_drop (n % List.length (a :: l)) (a :: l)] at hl;
      

Proof state:
α : Type u
inst✝ : Group α
a : α
l : List α
n : ℕ
hl : prod (take (n % length (a :: l)) (a :: l) ++ drop (n % length (a :: l)) (a :: l)) = 1
this : n % length (a :: l) ≤ length (a :: l)
⊢ prod (rotate (a :: l) n) = 1

Next tactic:
rw [← rotate_mod, rotate_eq_drop_append_take this, List.prod_append, mul_eq_one_iff_inv_eq, ←
        one_mul (List.prod _)⁻¹, ← hl, List.prod_append, mul_assoc, mul_inv_self, mul_one]
theorem rotate_perm (l : List α) (n : ℕ) : l.rotate n ~ l := by
  

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

Next tactic:
rw [rotate_eq_rotate']
theorem rotate_perm (l : List α) (n : ℕ) : l.rotate n ~ l := by
  rw [rotate_eq_rotate']
  

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

Next tactic:
induction' n with n hn generalizing l
theorem rotate_perm (l : List α) (n : ℕ) : l.rotate n ~ l := by
  rw [rotate_eq_rotate']
  induction' n with n hn generalizing l
  · 

Proof state:
case zero
α : Type u
l : List α
⊢ rotate' l zero ~ l

Next tactic:
simp
theorem rotate_perm (l : List α) (n : ℕ) : l.rotate n ~ l := by
  rw [rotate_eq_rotate']
  induction' n with n hn generalizing l
  · simp
  · 

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

Next tactic:
cases' l with hd tl
theorem rotate_perm (l : List α) (n : ℕ) : l.rotate n ~ l := by
  rw [rotate_eq_rotate']
  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' l n ~ l
⊢ rotate' [] (succ n) ~ []

Next tactic:
simp
theorem rotate_perm (l : List α) (n : ℕ) : l.rotate n ~ l := by
  rw [rotate_eq_rotate']
  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' l n ~ l
hd : α
tl : List α
⊢ rotate' (hd :: tl) (succ n) ~ hd :: tl

Next tactic:
rw [rotate'_cons_succ]
theorem rotate_perm (l : List α) (n : ℕ) : l.rotate n ~ l := by
  rw [rotate_eq_rotate']
  induction' n with n hn generalizing l
  · simp
  · cases' l with hd tl
    · simp
    · rw [rotate'_cons_succ]
      

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

Next tactic:
exact (hn _).trans (perm_append_singleton _ _)
@[simp]
theorem rotate_eq_nil_iff {l : List α} {n : ℕ} : l.rotate n = [] ↔ l = [] := by
  

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

Next tactic:
induction' n with n hn generalizing l
@[simp]
theorem rotate_eq_nil_iff {l : List α} {n : ℕ} : l.rotate n = [] ↔ l = [] := by
  induction' n with n hn generalizing l
  · 

Proof state:
case zero
α : Type u
l : List α
⊢ rotate l zero = [] ↔ l = []

Next tactic:
simp
@[simp]
theorem rotate_eq_nil_iff {l : List α} {n : ℕ} : l.rotate n = [] ↔ l = [] := by
  induction' n with n hn generalizing l
  · simp
  · 

Proof state:
case succ
α : Type u
n : ℕ
hn : ∀ {l : List α}, rotate l n = [] ↔ l = []
l : List α
⊢ rotate l (succ n) = [] ↔ l = []

Next tactic:
cases' l with hd tl
@[simp]
theorem rotate_eq_nil_iff {l : List α} {n : ℕ} : l.rotate n = [] ↔ l = [] := by
  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 l n = [] ↔ l = []
⊢ rotate [] (succ n) = [] ↔ [] = []

Next tactic:
simp
@[simp]
theorem rotate_eq_nil_iff {l : List α} {n : ℕ} : l.rotate n = [] ↔ l = [] := by
  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 l n = [] ↔ l = []
hd : α
tl : List α
⊢ rotate (hd :: tl) (succ n) = [] ↔ hd :: tl = []

Next tactic:
simp [rotate_cons_succ, hn]
@[simp]
theorem nil_eq_rotate_iff {l : List α} {n : ℕ} : [] = l.rotate n ↔ [] = l := by
  

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

Next tactic:
rw [eq_comm, rotate_eq_nil_iff, eq_comm]
theorem zipWith_rotate_distrib {α β γ : Type*} (f : α → β → γ) (l : List α) (l' : List β) (n : ℕ)
    (h : l.length = l'.length) :
    (zipWith f l l').rotate n = zipWith f (l.rotate n) (l'.rotate n) := by
  

Proof state:
α✝ : Type u
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β → γ
l : List α
l' : List β
n : ℕ
h : length l = length l'
⊢ rotate (zipWith f l l') n = zipWith f (rotate l n) (rotate l' n)

Next tactic:
rw [rotate_eq_drop_append_take_mod, rotate_eq_drop_append_take_mod,
    rotate_eq_drop_append_take_mod, h, zipWith_append, ← zipWith_distrib_drop, ←
    zipWith_distrib_take, List.length_zipWith, h, min_self]
theorem zipWith_rotate_distrib {α β γ : Type*} (f : α → β → γ) (l : List α) (l' : List β) (n : ℕ)
    (h : l.length = l'.length) :
    (zipWith f l l').rotate n = zipWith f (l.rotate n) (l'.rotate n) := by
  rw [rotate_eq_drop_append_take_mod, rotate_eq_drop_append_take_mod,
    rotate_eq_drop_append_take_mod, h, zipWith_append, ← zipWith_distrib_drop, ←
    zipWith_distrib_take, List.length_zipWith, h, min_self]
  

Proof state:
case h
α✝ : Type u
α : Type u_1
β : Type u_2
γ : Type u_3
f : α → β → γ
l : List α
l' : List β
n : ℕ
h : length l = length l'
⊢ length (drop (n % length l') l) = length (drop (n % length l') l')

Next tactic:
rw [length_drop, length_drop, h]
theorem zipWith_rotate_one {β : Type*} (f : α → α → β) (x y : α) (l : List α) :
    zipWith f (x :: y :: l) ((x :: y :: l).rotate 1) = f x y :: zipWith f (y :: l) (l ++ [x]) := by
  

Proof state:
α : Type u
β : Type u_1
f : α → α → β
x y : α
l : List α
⊢ zipWith f (x :: y :: l) (rotate (x :: y :: l) 1) = f x y :: zipWith f (y :: l) (l ++ [x])

Next tactic:
simp
theorem get?_rotate {l : List α} {n m : ℕ} (hml : m < l.length) :
    (l.rotate n).get? m = l.get? ((m + n) % l.length) := by
  

Proof state:
α : Type u
l : List α
n m : ℕ
hml : m < length l
⊢ get? (rotate l n) m = get? l ((m + n) % length l)

Next tactic:
rw [rotate_eq_drop_append_take_mod]
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]
  

Proof state:
α : Type u
l : List α
n m : ℕ
hml : m < length l
⊢ get? (drop (n % length l) l ++ take (n % length l) l) m = get? l ((m + n) % length l)

Next tactic:
rcases lt_or_le m (l.drop (n % l.length)).length with hm | 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
  · 

Proof state:
case inl
α : Type u
l : List α
n m : ℕ
hml : m < length l
hm : m < length (drop (n % length l) l)
⊢ get? (drop (n % length l) l ++ take (n % length l) l) m = get? l ((m + n) % length l)

Next tactic:
rw [get?_append hm, get?_drop, add_comm m, ← mod_add_mod]
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]
    

Proof state:
case inl
α : Type u
l : List α
n m : ℕ
hml : m < length l
hm : m < length (drop (n % length l) l)
⊢ get? l (n % length l + m) = get? l ((n % length l + m) % length l)

Next tactic:
rw [length_drop, lt_tsub_iff_left] at 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
    

Proof state:
case inl
α : Type u
l : List α
n m : ℕ
hml : m < length l
hm : n % length l + m < length l
⊢ get? l (n % length l + m) = get? l ((n % length l + m) % length l)

Next tactic:
rw [mod_eq_of_lt 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]
  · 

Proof state:
case inr
α : Type u
l : List α
n m : ℕ
hml : m < length l
hm : length (drop (n % length l) l) ≤ m
⊢ get? (drop (n % length l) l ++ take (n % length l) l) m = get? l ((m + n) % length l)

Next tactic:
have hlt : n % length l < length l := mod_lt _ (m.zero_le.trans_lt 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)
    

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
⊢ get? (drop (n % length l) l ++ take (n % length l) l) m = get? l ((m + n) % length l)

Next tactic:
rw [get?_append_right hm, get?_take, length_drop]
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]
    · 

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
⊢ get? l (m - (length l - n % length l)) = get? l ((m + n) % length l)

Next tactic:
congr 1
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
      

Proof state:
case inr.e_a
α : 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 l - n % length l) = (m + n) % length l

Next tactic:
rw [length_drop] at 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
      

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
⊢ m - (length l - n % length l) = (m + n) % length l

Next tactic:
have hm' := tsub_le_iff_left.1 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
      

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
⊢ m - (length l - n % length l) = (m + n) % length l

Next tactic:
have : n % length l + m - length l < length l := by
        rw [tsub_lt_iff_left hm']
        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
        

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:
rw [tsub_lt_iff_left hm']