l3lab/ntp-mathlib huggingface dataset:
@[simp]
theorem map₂Right'_nil_left : map₂Right' f [] bs = (bs.map (f none), []) := by cases bs <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : Option α → β → γ
a : α
as : List α
b head✝ : β
tail✝ : List β
⊢ map₂Right' f [] (head✝ :: tail✝) = (map (f none) (head✝ :: tail✝), [])

Next tactic:
rfl
@[simp]
theorem zipLeft'_nil_right : zipLeft' as ([] : List β) = (as.map fun a => (a, none), []) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as : List α
b : β
bs : List β
⊢ zipLeft' as [] = (map (fun a => (a, none)) as, [])

Next tactic:
cases as
@[simp]
theorem zipLeft'_nil_right : zipLeft' as ([] : List β) = (as.map fun a => (a, none), []) := by
  cases as <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
b : β
bs : List β
⊢ zipLeft' [] [] = (map (fun a => (a, none)) [], [])

Next tactic:
rfl
@[simp]
theorem zipLeft'_nil_right : zipLeft' as ([] : List β) = (as.map fun a => (a, none), []) := by
  cases as <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
b : β
bs : List β
head✝ : α
tail✝ : List α
⊢ zipLeft' (head✝ :: tail✝) [] = (map (fun a => (a, none)) (head✝ :: tail✝), [])

Next tactic:
rfl
@[simp]
theorem zipRight'_nil_left : zipRight' ([] : List α) bs = (bs.map fun b => (none, b), []) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as : List α
b : β
bs : List β
⊢ zipRight' [] bs = (map (fun b => (none, b)) bs, [])

Next tactic:
cases bs
@[simp]
theorem zipRight'_nil_left : zipRight' ([] : List α) bs = (bs.map fun b => (none, b), []) := by
  cases bs <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as : List α
b : β
⊢ zipRight' [] [] = (map (fun b => (none, b)) [], [])

Next tactic:
rfl
@[simp]
theorem zipRight'_nil_left : zipRight' ([] : List α) bs = (bs.map fun b => (none, b), []) := by
  cases bs <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as : List α
b head✝ : β
tail✝ : List β
⊢ zipRight' [] (head✝ :: tail✝) = (map (fun b => (none, b)) (head✝ :: tail✝), [])

Next tactic:
rfl
@[simp]
theorem map₂Left_nil_right : map₂Left f as [] = as.map fun a => f a none := by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → Option β → γ
as : List α
⊢ map₂Left f as [] = map (fun a => f a none) as

Next tactic:
cases as
@[simp]
theorem map₂Left_nil_right : map₂Left f as [] = as.map fun a => f a none := by cases as <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → Option β → γ
⊢ map₂Left f [] [] = map (fun a => f a none) []

Next tactic:
rfl
@[simp]
theorem map₂Left_nil_right : map₂Left f as [] = as.map fun a => f a none := by cases as <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → Option β → γ
head✝ : α
tail✝ : List α
⊢ map₂Left f (head✝ :: tail✝) [] = map (fun a => f a none) (head✝ :: tail✝)

Next tactic:
rfl
theorem map₂Left_eq_map₂Left' : ∀ as bs, map₂Left f as bs = (map₂Left' f as bs).fst
  | [], _ => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → Option β → γ
as : List α
x✝ : List β
⊢ map₂Left f [] x✝ = (map₂Left' f [] x✝).1

Next tactic:
simp
theorem map₂Left_eq_map₂Left' : ∀ as bs, map₂Left f as bs = (map₂Left' f as bs).fst
  | [], _ => by simp
  | a :: as, [] => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → Option β → γ
as✝ : List α
a : α
as : List α
⊢ map₂Left f (a :: as) [] = (map₂Left' f (a :: as) []).1

Next tactic:
simp
theorem map₂Left_eq_map₂Left' : ∀ as bs, map₂Left f as bs = (map₂Left' f as bs).fst
  | [], _ => by simp
  | a :: as, [] => by simp
  | a :: as, b :: bs => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → Option β → γ
as✝ : List α
a : α
as : List α
b : β
bs : List β
⊢ map₂Left f (a :: as) (b :: bs) = (map₂Left' f (a :: as) (b :: bs)).1

Next tactic:
simp [map₂Left_eq_map₂Left']
theorem map₂Left_eq_zipWith :
    ∀ as bs, length as ≤ length bs → map₂Left f as bs = zipWith (fun a b => f a (some b)) as bs
  | [], [], _ => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → Option β → γ
as : List α
x✝ : length [] ≤ length []
⊢ map₂Left f [] [] = zipWith (fun a b => f a (some b)) [] []

Next tactic:
simp
theorem map₂Left_eq_zipWith :
    ∀ as bs, length as ≤ length bs → map₂Left f as bs = zipWith (fun a b => f a (some b)) as bs
  | [], [], _ => by simp
  | [], _ :: _, _ => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → Option β → γ
as : List α
head✝ : β
tail✝ : List β
x✝ : length [] ≤ length (head✝ :: tail✝)
⊢ map₂Left f [] (head✝ :: tail✝) = zipWith (fun a b => f a (some b)) [] (head✝ :: tail✝)

Next tactic:
simp
theorem map₂Left_eq_zipWith :
    ∀ as bs, length as ≤ length bs → map₂Left f as bs = zipWith (fun a b => f a (some b)) as bs
  | [], [], _ => by simp
  | [], _ :: _, _ => by simp
  | a :: as, [], h => by
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → Option β → γ
as✝ : List α
a : α
as : List α
h : length (a :: as) ≤ length []
⊢ map₂Left f (a :: as) [] = zipWith (fun a b => f a (some b)) (a :: as) []

Next tactic:
simp at h
theorem map₂Left_eq_zipWith :
    ∀ as bs, length as ≤ length bs → map₂Left f as bs = zipWith (fun a b => f a (some b)) as bs
  | [], [], _ => by simp
  | [], _ :: _, _ => by simp
  | a :: as, [], h => by
    simp at h
  | a :: as, b :: bs, h => by
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → Option β → γ
as✝ : List α
a : α
as : List α
b : β
bs : List β
h : length (a :: as) ≤ length (b :: bs)
⊢ map₂Left f (a :: as) (b :: bs) = zipWith (fun a b => f a (some b)) (a :: as) (b :: bs)

Next tactic:
simp only [length_cons, succ_le_succ_iff] at h
theorem map₂Left_eq_zipWith :
    ∀ as bs, length as ≤ length bs → map₂Left f as bs = zipWith (fun a b => f a (some b)) as bs
  | [], [], _ => by simp
  | [], _ :: _, _ => by simp
  | a :: as, [], h => by
    simp at h
  | a :: as, b :: bs, h => by
    simp only [length_cons, succ_le_succ_iff] at h
    

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → Option β → γ
as✝ : List α
a : α
as : List α
b : β
bs : List β
h : length as ≤ length bs
⊢ map₂Left f (a :: as) (b :: bs) = zipWith (fun a b => f a (some b)) (a :: as) (b :: bs)

Next tactic:
simp [h, map₂Left_eq_zipWith]
@[simp]
theorem map₂Right_nil_left : map₂Right f [] bs = bs.map (f none) := by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : Option α → β → γ
a : α
as : List α
b : β
bs : List β
⊢ map₂Right f [] bs = map (f none) bs

Next tactic:
cases bs
@[simp]
theorem map₂Right_nil_left : map₂Right f [] bs = bs.map (f none) := by cases bs <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : Option α → β → γ
a : α
as : List α
b : β
⊢ map₂Right f [] [] = map (f none) []

Next tactic:
rfl
@[simp]
theorem map₂Right_nil_left : map₂Right f [] bs = bs.map (f none) := by cases bs <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : Option α → β → γ
a : α
as : List α
b head✝ : β
tail✝ : List β
⊢ map₂Right f [] (head✝ :: tail✝) = map (f none) (head✝ :: tail✝)

Next tactic:
rfl
theorem map₂Right_eq_map₂Right' : map₂Right f as bs = (map₂Right' f as bs).fst := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : Option α → β → γ
a : α
as : List α
b : β
bs : List β
⊢ map₂Right f as bs = (map₂Right' f as bs).1

Next tactic:
simp only [map₂Right, map₂Right', map₂Left_eq_map₂Left']
theorem map₂Right_eq_zipWith (h : length bs ≤ length as) :
    map₂Right f as bs = zipWith (fun a b => f (some a) b) as bs := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : Option α → β → γ
a : α
as : List α
b : β
bs : List β
h : length bs ≤ length as
⊢ map₂Right f as bs = zipWith (fun a b => f (some a) b) as bs

Next tactic:
have : (fun a b => flip f a (some b)) = flip fun a b => f (some a) b := rfl
theorem map₂Right_eq_zipWith (h : length bs ≤ length as) :
    map₂Right f as bs = zipWith (fun a b => f (some a) b) as bs := by
  have : (fun a b => flip f a (some b)) = flip fun a b => f (some a) b := rfl
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : Option α → β → γ
a : α
as : List α
b : β
bs : List β
h : length bs ≤ length as
this : (fun a b => flip f a (some b)) = flip fun a b => f (some a) b
⊢ map₂Right f as bs = zipWith (fun a b => f (some a) b) as bs

Next tactic:
simp only [map₂Right, map₂Left_eq_zipWith, zipWith_flip, *]
@[simp]
theorem zipLeft_nil_right : zipLeft as ([] : List β) = as.map fun a => (a, none) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as : List α
b : β
bs : List β
⊢ zipLeft as [] = map (fun a => (a, none)) as

Next tactic:
cases as
@[simp]
theorem zipLeft_nil_right : zipLeft as ([] : List β) = as.map fun a => (a, none) := by
  cases as <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
b : β
bs : List β
⊢ zipLeft [] [] = map (fun a => (a, none)) []

Next tactic:
rfl
@[simp]
theorem zipLeft_nil_right : zipLeft as ([] : List β) = as.map fun a => (a, none) := by
  cases as <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
b : β
bs : List β
head✝ : α
tail✝ : List α
⊢ zipLeft (head✝ :: tail✝) [] = map (fun a => (a, none)) (head✝ :: tail✝)

Next tactic:
rfl
theorem zipLeft_eq_zipLeft' (as : List α) (bs : List β) : zipLeft as bs = (zipLeft' as bs).fst := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as✝ : List α
b : β
bs✝ : List β
as : List α
bs : List β
⊢ zipLeft as bs = (zipLeft' as bs).1

Next tactic:
rw [zipLeft, zipLeft']
theorem zipLeft_eq_zipLeft' (as : List α) (bs : List β) : zipLeft as bs = (zipLeft' as bs).fst := by
  rw [zipLeft, zipLeft']
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as✝ : List α
b : β
bs✝ : List β
as : List α
bs : List β
⊢ zipWithLeft Prod.mk as bs = (zipWithLeft' Prod.mk as bs).1

Next tactic:
cases as with
  | nil => rfl
  | cons _ atl =>
    cases bs with
    | nil => rfl
    | cons _ btl => rw [zipWithLeft, zipWithLeft', cons_inj]; exact @zipLeft_eq_zipLeft' atl btl
theorem zipLeft_eq_zipLeft' (as : List α) (bs : List β) : zipLeft as bs = (zipLeft' as bs).fst := by
  rw [zipLeft, zipLeft']
  cases as with
  

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as : List α
b : β
bs✝ bs : List β
⊢ zipWithLeft Prod.mk [] bs = (zipWithLeft' Prod.mk [] bs).1

Next tactic:
| nil => rfl
theorem zipLeft_eq_zipLeft' (as : List α) (bs : List β) : zipLeft as bs = (zipLeft' as bs).fst := by
  rw [zipLeft, zipLeft']
  cases as with
  | nil => 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as : List α
b : β
bs✝ bs : List β
⊢ zipWithLeft Prod.mk [] bs = (zipWithLeft' Prod.mk [] bs).1

Next tactic:
rfl
theorem zipLeft_eq_zipLeft' (as : List α) (bs : List β) : zipLeft as bs = (zipLeft' as bs).fst := by
  rw [zipLeft, zipLeft']
  cases as with
  | nil => rfl
  

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as : List α
b : β
bs✝ bs : List β
head✝ : α
atl : List α
⊢ zipWithLeft Prod.mk (head✝ :: atl) bs = (zipWithLeft' Prod.mk (head✝ :: atl) bs).1

Next tactic:
| cons _ atl =>
    cases bs with
    | nil => rfl
    | cons _ btl => rw [zipWithLeft, zipWithLeft', cons_inj]; exact @zipLeft_eq_zipLeft' atl btl
theorem zipLeft_eq_zipLeft' (as : List α) (bs : List β) : zipLeft as bs = (zipLeft' as bs).fst := by
  rw [zipLeft, zipLeft']
  cases as with
  | nil => rfl
  | cons _ atl =>
    

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as : List α
b : β
bs✝ bs : List β
head✝ : α
atl : List α
⊢ zipWithLeft Prod.mk (head✝ :: atl) bs = (zipWithLeft' Prod.mk (head✝ :: atl) bs).1

Next tactic:
cases bs with
    | nil => rfl
    | cons _ btl => rw [zipWithLeft, zipWithLeft', cons_inj]; exact @zipLeft_eq_zipLeft' atl btl
theorem zipLeft_eq_zipLeft' (as : List α) (bs : List β) : zipLeft as bs = (zipLeft' as bs).fst := by
  rw [zipLeft, zipLeft']
  cases as with
  | nil => rfl
  | cons _ atl =>
    cases bs with
    

Proof state:
case cons.nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as : List α
b : β
bs : List β
head✝ : α
atl : List α
⊢ zipWithLeft Prod.mk (head✝ :: atl) [] = (zipWithLeft' Prod.mk (head✝ :: atl) []).1

Next tactic:
| nil => rfl
theorem zipLeft_eq_zipLeft' (as : List α) (bs : List β) : zipLeft as bs = (zipLeft' as bs).fst := by
  rw [zipLeft, zipLeft']
  cases as with
  | nil => rfl
  | cons _ atl =>
    cases bs with
    | nil => 

Proof state:
case cons.nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as : List α
b : β
bs : List β
head✝ : α
atl : List α
⊢ zipWithLeft Prod.mk (head✝ :: atl) [] = (zipWithLeft' Prod.mk (head✝ :: atl) []).1

Next tactic:
rfl
theorem zipLeft_eq_zipLeft' (as : List α) (bs : List β) : zipLeft as bs = (zipLeft' as bs).fst := by
  rw [zipLeft, zipLeft']
  cases as with
  | nil => rfl
  | cons _ atl =>
    cases bs with
    | nil => rfl
    

Proof state:
case cons.cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as : List α
b : β
bs : List β
head✝¹ : α
atl : List α
head✝ : β
btl : List β
⊢ zipWithLeft Prod.mk (head✝¹ :: atl) (head✝ :: btl) = (zipWithLeft' Prod.mk (head✝¹ :: atl) (head✝ :: btl)).1

Next tactic:
| cons _ btl => rw [zipWithLeft, zipWithLeft', cons_inj]; exact @zipLeft_eq_zipLeft' atl btl
theorem zipLeft_eq_zipLeft' (as : List α) (bs : List β) : zipLeft as bs = (zipLeft' as bs).fst := by
  rw [zipLeft, zipLeft']
  cases as with
  | nil => rfl
  | cons _ atl =>
    cases bs with
    | nil => rfl
    | cons _ btl => 

Proof state:
case cons.cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as : List α
b : β
bs : List β
head✝¹ : α
atl : List α
head✝ : β
btl : List β
⊢ zipWithLeft Prod.mk (head✝¹ :: atl) (head✝ :: btl) = (zipWithLeft' Prod.mk (head✝¹ :: atl) (head✝ :: btl)).1

Next tactic:
rw [zipWithLeft, zipWithLeft', cons_inj]
theorem zipLeft_eq_zipLeft' (as : List α) (bs : List β) : zipLeft as bs = (zipLeft' as bs).fst := by
  rw [zipLeft, zipLeft']
  cases as with
  | nil => rfl
  | cons _ atl =>
    cases bs with
    | nil => rfl
    | cons _ btl => rw [zipWithLeft, zipWithLeft', cons_inj]; 

Proof state:
case cons.cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as : List α
b : β
bs : List β
head✝¹ : α
atl : List α
head✝ : β
btl : List β
⊢ zipWithLeft Prod.mk atl btl = (zipWithLeft' Prod.mk atl btl).1

Next tactic:
exact @zipLeft_eq_zipLeft' atl btl
@[simp]
theorem zipRight_nil_left : zipRight ([] : List α) bs = bs.map fun b => (none, b) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as : List α
b : β
bs : List β
⊢ zipRight [] bs = map (fun b => (none, b)) bs

Next tactic:
cases bs
@[simp]
theorem zipRight_nil_left : zipRight ([] : List α) bs = bs.map fun b => (none, b) := by
  cases bs <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as : List α
b : β
⊢ zipRight [] [] = map (fun b => (none, b)) []

Next tactic:
rfl
@[simp]
theorem zipRight_nil_left : zipRight ([] : List α) bs = bs.map fun b => (none, b) := by
  cases bs <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as : List α
b head✝ : β
tail✝ : List β
⊢ zipRight [] (head✝ :: tail✝) = map (fun b => (none, b)) (head✝ :: tail✝)

Next tactic:
rfl
theorem zipRight_eq_zipRight' : zipRight as bs = (zipRight' as bs).fst := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
as : List α
b : β
bs : List β
⊢ zipRight as bs = (zipRight' as bs).1

Next tactic:
induction as generalizing bs
theorem zipRight_eq_zipRight' : zipRight as bs = (zipRight' as bs).fst := by
  induction as generalizing bs <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
b : β
bs : List β
⊢ zipRight [] bs = (zipRight' [] bs).1

Next tactic:
cases bs
theorem zipRight_eq_zipRight' : zipRight as bs = (zipRight' as bs).fst := by
  induction as generalizing bs <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
b : β
head✝ : α
tail✝ : List α
tail_ih✝ : ∀ (bs : List β), zipRight tail✝ bs = (zipRight' tail✝ bs).1
bs : List β
⊢ zipRight (head✝ :: tail✝) bs = (zipRight' (head✝ :: tail✝) bs).1

Next tactic:
cases bs
theorem zipRight_eq_zipRight' : zipRight as bs = (zipRight' as bs).fst := by
  induction as generalizing bs <;> cases bs <;> 

Proof state:
case nil.nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
b : β
⊢ zipRight [] [] = (zipRight' [] []).1

Next tactic:
simp [*]
theorem zipRight_eq_zipRight' : zipRight as bs = (zipRight' as bs).fst := by
  induction as generalizing bs <;> cases bs <;> 

Proof state:
case nil.cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
b head✝ : β
tail✝ : List β
⊢ zipRight [] (head✝ :: tail✝) = (zipRight' [] (head✝ :: tail✝)).1

Next tactic:
simp [*]
theorem zipRight_eq_zipRight' : zipRight as bs = (zipRight' as bs).fst := by
  induction as generalizing bs <;> cases bs <;> 

Proof state:
case cons.nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
b : β
head✝ : α
tail✝ : List α
tail_ih✝ : ∀ (bs : List β), zipRight tail✝ bs = (zipRight' tail✝ bs).1
⊢ zipRight (head✝ :: tail✝) [] = (zipRight' (head✝ :: tail✝) []).1

Next tactic:
simp [*]
theorem zipRight_eq_zipRight' : zipRight as bs = (zipRight' as bs).fst := by
  induction as generalizing bs <;> cases bs <;> 

Proof state:
case cons.cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
b : β
head✝¹ : α
tail✝¹ : List α
tail_ih✝ : ∀ (bs : List β), zipRight tail✝¹ bs = (zipRight' tail✝¹ bs).1
head✝ : β
tail✝ : List β
⊢ zipRight (head✝¹ :: tail✝¹) (head✝ :: tail✝) = (zipRight' (head✝¹ :: tail✝¹) (head✝ :: tail✝)).1

Next tactic:
simp [*]
theorem forall_iff_forall_mem : ∀ {l : List α}, Forall p l ↔ ∀ x ∈ l, p x
  | [] => (iff_true_intro <| forall_mem_nil _).symm
  | x :: l => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p q : α → Prop
l✝ : List α
x : α
l : List α
⊢ Forall p (x :: l) ↔ ∀ (x_1 : α), x_1 ∈ x :: l → p x_1

Next tactic:
rw [forall_mem_cons, forall_cons, forall_iff_forall_mem]
theorem Forall.imp (h : ∀ x, p x → q x) : ∀ {l : List α}, Forall p l → Forall q l
  | [] => id
  | x :: l => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p q : α → Prop
l✝ : List α
h : ∀ (x : α), p x → q x
x : α
l : List α
⊢ Forall p (x :: l) → Forall q (x :: l)

Next tactic:
simp
theorem Forall.imp (h : ∀ x, p x → q x) : ∀ {l : List α}, Forall p l → Forall q l
  | [] => id
  | x :: l => by simp; 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p q : α → Prop
l✝ : List α
h : ∀ (x : α), p x → q x
x : α
l : List α
⊢ p x → Forall p l → q x ∧ Forall q l

Next tactic:
rw [← and_imp]
theorem Forall.imp (h : ∀ x, p x → q x) : ∀ {l : List α}, Forall p l → Forall q l
  | [] => id
  | x :: l => by simp; rw [← and_imp]; 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p q : α → Prop
l✝ : List α
h : ∀ (x : α), p x → q x
x : α
l : List α
⊢ p x ∧ Forall p l → q x ∧ Forall q l

Next tactic:
exact And.imp (h x) (Forall.imp h)
@[simp]
theorem forall_map_iff {p : β → Prop} (f : α → β) : Forall p (l.map f) ↔ Forall (p ∘ f) l := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ q : α → Prop
l : List α
p : β → Prop
f : α → β
⊢ Forall p (map f l) ↔ Forall (p ∘ f) l

Next tactic:
induction l
@[simp]
theorem forall_map_iff {p : β → Prop} (f : α → β) : Forall p (l.map f) ↔ Forall (p ∘ f) l := by
  induction l <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ q : α → Prop
l : List α
p : β → Prop
f : α → β
⊢ Forall p (map f []) ↔ Forall (p ∘ f) []

Next tactic:
simp [*]
@[simp]
theorem forall_map_iff {p : β → Prop} (f : α → β) : Forall p (l.map f) ↔ Forall (p ∘ f) l := by
  induction l <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ q : α → Prop
l : List α
p : β → Prop
f : α → β
head✝ : α
tail✝ : List α
tail_ih✝ : Forall p (map f tail✝) ↔ Forall (p ∘ f) tail✝
⊢ Forall p (map f (head✝ :: tail✝)) ↔ Forall (p ∘ f) (head✝ :: tail✝)

Next tactic:
simp [*]
theorem getLast_reverse {l : List α} (hl : l.reverse ≠ [])
    (hl' : 0 < l.length := (by
      

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
hl : reverse l ≠ []
⊢ 0 < length l

Next tactic:
contrapose! hl
theorem getLast_reverse {l : List α} (hl : l.reverse ≠ [])
    (hl' : 0 < l.length := (by
      contrapose! hl
      

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
hl : length l ≤ 0
⊢ reverse l = []

Next tactic:
simpa [length_eq_zero] using hl
theorem getLast_reverse {l : List α} (hl : l.reverse ≠ [])
    (hl' : 0 < l.length := (by
      contrapose! hl
      simpa [length_eq_zero] using hl)) :
    l.reverse.getLast hl = l.get ⟨0, hl'⟩ := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
hl : reverse l ≠ []
hl' : optParam (0 < length l) (_ : 0 < length l)
⊢ getLast (reverse l) hl = get l { val := 0, isLt := hl' }

Next tactic:
rw [getLast_eq_get, get_reverse']
theorem getLast_reverse {l : List α} (hl : l.reverse ≠ [])
    (hl' : 0 < l.length := (by
      contrapose! hl
      simpa [length_eq_zero] using hl)) :
    l.reverse.getLast hl = l.get ⟨0, hl'⟩ := by
  rw [getLast_eq_get, get_reverse']
  · 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
hl : reverse l ≠ []
hl' : optParam (0 < length l) (_ : 0 < length l)
⊢ get l
      {
        val :=
          length l - 1 - ↑{ val := length (reverse l) - 1, isLt := (_ : length (reverse l) - 1 < length (reverse l)) },
        isLt := ?hn' } =
    get l { val := 0, isLt := hl' }

Next tactic:
simp
theorem getLast_reverse {l : List α} (hl : l.reverse ≠ [])
    (hl' : 0 < l.length := (by
      contrapose! hl
      simpa [length_eq_zero] using hl)) :
    l.reverse.getLast hl = l.get ⟨0, hl'⟩ := by
  rw [getLast_eq_get, get_reverse']
  · simp
  · 

Proof state:
case hn'
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ l : List α
hl : reverse l ≠ []
hl' : optParam (0 < length l) (_ : 0 < length l)
⊢ length l - 1 - ↑{ val := length (reverse l) - 1, isLt := (_ : length (reverse l) - 1 < length (reverse l)) } <
    length l

Next tactic:
simpa using hl'
theorem ilast'_mem : ∀ a l, @ilast' α a l ∈ a :: l
  | a, [] => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a : α
⊢ ilast' a [] ∈ [a]

Next tactic:
simp [ilast']
theorem ilast'_mem : ∀ a l, @ilast' α a l ∈ a :: l
  | a, [] => by simp [ilast']
  | a, b :: l => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a b : α
l : List α
⊢ ilast' a (b :: l) ∈ a :: b :: l

Next tactic:
rw [mem_cons]
theorem ilast'_mem : ∀ a l, @ilast' α a l ∈ a :: l
  | a, [] => by simp [ilast']
  | a, b :: l => by rw [mem_cons]; 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
a b : α
l : List α
⊢ ilast' a (b :: l) = a ∨ ilast' a (b :: l) ∈ b :: l

Next tactic:
exact Or.inr (ilast'_mem b l)
@[simp]
theorem get_attach (L : List α) (i) :
    (L.attach.get i).1 = L.get ⟨i, length_attach L ▸ i.2⟩ :=
  calc
    (L.attach.get i).1 = (L.attach.map Subtype.val).get ⟨i, by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ L : List α
i : Fin (length (attach L))
⊢ ↑i < length (map Subtype.val (attach L))

Next tactic:
simpa using i.2