l3lab/ntp-mathlib huggingface dataset:
theorem lookmap_id' (h : ∀ (a), ∀ b ∈ f a, a = b) (l : List α) : l.lookmap f = l := by
  rw [← map_id (l.lookmap f), lookmap_map_eq, map_id]; 

Proof state:
case h
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → Option α
h : ∀ (a b : α), b ∈ f a → a = b
l : List α
⊢ ∀ (a b : α), b ∈ f a → id a = id b

Next tactic:
exact h
theorem length_lookmap (l : List α) : length (l.lookmap f) = length l := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → Option α
l : List α
⊢ length (lookmap f l) = length l

Next tactic:
rw [← length_map, lookmap_map_eq _ fun _ => (), length_map]
theorem length_lookmap (l : List α) : length (l.lookmap f) = length l := by
  rw [← length_map, lookmap_map_eq _ fun _ => (), length_map]; 

Proof state:
case h
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → Option α
l : List α
⊢ ∀ (a b : α), b ∈ f a → () = ()

Next tactic:
simp
@[simp]
theorem reduceOption_cons_of_some (x : α) (l : List (Option α)) :
    reduceOption (some x :: l) = x :: l.reduceOption := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
x : α
l : List (Option α)
⊢ reduceOption (some x :: l) = x :: reduceOption l

Next tactic:
simp only [reduceOption, filterMap, id.def, eq_self_iff_true, and_self_iff]
@[simp]
theorem reduceOption_cons_of_none (l : List (Option α)) :
    reduceOption (none :: l) = l.reduceOption := by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
l : List (Option α)
⊢ reduceOption (none :: l) = reduceOption l

Next tactic:
simp only [reduceOption, filterMap, id.def]
@[simp]
theorem reduceOption_map {l : List (Option α)} {f : α → β} :
    reduceOption (map (Option.map f) l) = map f (reduceOption l) := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
l : List (Option α)
f : α → β
⊢ reduceOption (map (Option.map f) l) = map f (reduceOption l)

Next tactic:
induction' l with hd tl hl
@[simp]
theorem reduceOption_map {l : List (Option α)} {f : α → β} :
    reduceOption (map (Option.map f) l) = map f (reduceOption l) := by
  induction' l with hd tl hl
  · 

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

Next tactic:
simp only [reduceOption_nil, map_nil]
@[simp]
theorem reduceOption_map {l : List (Option α)} {f : α → β} :
    reduceOption (map (Option.map f) l) = map f (reduceOption l) := by
  induction' l with hd tl hl
  · simp only [reduceOption_nil, map_nil]
  · 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
hd : Option α
tl : List (Option α)
hl : reduceOption (map (Option.map f) tl) = map f (reduceOption tl)
⊢ reduceOption (map (Option.map f) (hd :: tl)) = map f (reduceOption (hd :: tl))

Next tactic:
cases hd
@[simp]
theorem reduceOption_map {l : List (Option α)} {f : α → β} :
    reduceOption (map (Option.map f) l) = map f (reduceOption l) := by
  induction' l with hd tl hl
  · simp only [reduceOption_nil, map_nil]
  · cases hd <;>
      

Proof state:
case cons.none
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
tl : List (Option α)
hl : reduceOption (map (Option.map f) tl) = map f (reduceOption tl)
⊢ reduceOption (map (Option.map f) (none :: tl)) = map f (reduceOption (none :: tl))

Next tactic:
simpa [true_and_iff, Option.map_some', map, eq_self_iff_true,
        reduceOption_cons_of_some] using hl
@[simp]
theorem reduceOption_map {l : List (Option α)} {f : α → β} :
    reduceOption (map (Option.map f) l) = map f (reduceOption l) := by
  induction' l with hd tl hl
  · simp only [reduceOption_nil, map_nil]
  · cases hd <;>
      

Proof state:
case cons.some
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
f : α → β
tl : List (Option α)
hl : reduceOption (map (Option.map f) tl) = map f (reduceOption tl)
val✝ : α
⊢ reduceOption (map (Option.map f) (some val✝ :: tl)) = map f (reduceOption (some val✝ :: tl))

Next tactic:
simpa [true_and_iff, Option.map_some', map, eq_self_iff_true,
        reduceOption_cons_of_some] using hl
theorem reduceOption_length_le (l : List (Option α)) : l.reduceOption.length ≤ l.length := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
l : List (Option α)
⊢ length (reduceOption l) ≤ length l

Next tactic:
induction' l with hd tl hl
theorem reduceOption_length_le (l : List (Option α)) : l.reduceOption.length ≤ l.length := by
  induction' l with hd tl hl
  · 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
⊢ length (reduceOption []) ≤ length []

Next tactic:
simp [reduceOption_nil, length]
theorem reduceOption_length_le (l : List (Option α)) : l.reduceOption.length ≤ l.length := by
  induction' l with hd tl hl
  · simp [reduceOption_nil, length]
  · 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
hd : Option α
tl : List (Option α)
hl : length (reduceOption tl) ≤ length tl
⊢ length (reduceOption (hd :: tl)) ≤ length (hd :: tl)

Next tactic:
cases hd
theorem reduceOption_length_le (l : List (Option α)) : l.reduceOption.length ≤ l.length := by
  induction' l with hd tl hl
  · simp [reduceOption_nil, length]
  · cases hd
    · 

Proof state:
case cons.none
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
tl : List (Option α)
hl : length (reduceOption tl) ≤ length tl
⊢ length (reduceOption (none :: tl)) ≤ length (none :: tl)

Next tactic:
exact Nat.le_succ_of_le hl
theorem reduceOption_length_le (l : List (Option α)) : l.reduceOption.length ≤ l.length := by
  induction' l with hd tl hl
  · simp [reduceOption_nil, length]
  · cases hd
    · exact Nat.le_succ_of_le hl
    · 

Proof state:
case cons.some
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
tl : List (Option α)
hl : length (reduceOption tl) ≤ length tl
val✝ : α
⊢ length (reduceOption (some val✝ :: tl)) ≤ length (some val✝ :: tl)

Next tactic:
simpa only [length, add_le_add_iff_right, reduceOption_cons_of_some] using hl
theorem reduceOption_length_eq_iff {l : List (Option α)} :
    l.reduceOption.length = l.length ↔ ∀ x ∈ l, Option.isSome x := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
l : List (Option α)
⊢ length (reduceOption l) = length l ↔ ∀ (x : Option α), x ∈ l → Option.isSome x = true

Next tactic:
induction' l with hd tl hl
theorem reduceOption_length_eq_iff {l : List (Option α)} :
    l.reduceOption.length = l.length ↔ ∀ x ∈ l, Option.isSome x := by
  induction' l with hd tl hl
  · 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
⊢ length (reduceOption []) = length [] ↔ ∀ (x : Option α), x ∈ [] → Option.isSome x = true

Next tactic:
simp only [forall_const, reduceOption_nil, not_mem_nil, forall_prop_of_false, eq_self_iff_true,
      length, not_false_iff]
theorem reduceOption_length_eq_iff {l : List (Option α)} :
    l.reduceOption.length = l.length ↔ ∀ x ∈ l, Option.isSome x := by
  induction' l with hd tl hl
  · simp only [forall_const, reduceOption_nil, not_mem_nil, forall_prop_of_false, eq_self_iff_true,
      length, not_false_iff]
  · 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
hd : Option α
tl : List (Option α)
hl : length (reduceOption tl) = length tl ↔ ∀ (x : Option α), x ∈ tl → Option.isSome x = true
⊢ length (reduceOption (hd :: tl)) = length (hd :: tl) ↔ ∀ (x : Option α), x ∈ hd :: tl → Option.isSome x = true

Next tactic:
cases hd
theorem reduceOption_length_eq_iff {l : List (Option α)} :
    l.reduceOption.length = l.length ↔ ∀ x ∈ l, Option.isSome x := by
  induction' l with hd tl hl
  · simp only [forall_const, reduceOption_nil, not_mem_nil, forall_prop_of_false, eq_self_iff_true,
      length, not_false_iff]
  · cases hd
    · 

Proof state:
case cons.none
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
tl : List (Option α)
hl : length (reduceOption tl) = length tl ↔ ∀ (x : Option α), x ∈ tl → Option.isSome x = true
⊢ length (reduceOption (none :: tl)) = length (none :: tl) ↔ ∀ (x : Option α), x ∈ none :: tl → Option.isSome x = true

Next tactic:
simp only [mem_cons, forall_eq_or_imp, Bool.coe_sort_false, false_and_iff,
        reduceOption_cons_of_none, length, Option.isSome_none, iff_false_iff]
theorem reduceOption_length_eq_iff {l : List (Option α)} :
    l.reduceOption.length = l.length ↔ ∀ x ∈ l, Option.isSome x := by
  induction' l with hd tl hl
  · simp only [forall_const, reduceOption_nil, not_mem_nil, forall_prop_of_false, eq_self_iff_true,
      length, not_false_iff]
  · cases hd
    · simp only [mem_cons, forall_eq_or_imp, Bool.coe_sort_false, false_and_iff,
        reduceOption_cons_of_none, length, Option.isSome_none, iff_false_iff]
      

Proof state:
case cons.none
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
tl : List (Option α)
hl : length (reduceOption tl) = length tl ↔ ∀ (x : Option α), x ∈ tl → Option.isSome x = true
⊢ ¬length (reduceOption tl) = length tl + 1

Next tactic:
intro H
theorem reduceOption_length_eq_iff {l : List (Option α)} :
    l.reduceOption.length = l.length ↔ ∀ x ∈ l, Option.isSome x := by
  induction' l with hd tl hl
  · simp only [forall_const, reduceOption_nil, not_mem_nil, forall_prop_of_false, eq_self_iff_true,
      length, not_false_iff]
  · cases hd
    · simp only [mem_cons, forall_eq_or_imp, Bool.coe_sort_false, false_and_iff,
        reduceOption_cons_of_none, length, Option.isSome_none, iff_false_iff]
      intro H
      

Proof state:
case cons.none
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
tl : List (Option α)
hl : length (reduceOption tl) = length tl ↔ ∀ (x : Option α), x ∈ tl → Option.isSome x = true
H : length (reduceOption tl) = length tl + 1
⊢ False

Next tactic:
have := reduceOption_length_le tl
theorem reduceOption_length_eq_iff {l : List (Option α)} :
    l.reduceOption.length = l.length ↔ ∀ x ∈ l, Option.isSome x := by
  induction' l with hd tl hl
  · simp only [forall_const, reduceOption_nil, not_mem_nil, forall_prop_of_false, eq_self_iff_true,
      length, not_false_iff]
  · cases hd
    · simp only [mem_cons, forall_eq_or_imp, Bool.coe_sort_false, false_and_iff,
        reduceOption_cons_of_none, length, Option.isSome_none, iff_false_iff]
      intro H
      have := reduceOption_length_le tl
      

Proof state:
case cons.none
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
tl : List (Option α)
hl : length (reduceOption tl) = length tl ↔ ∀ (x : Option α), x ∈ tl → Option.isSome x = true
H : length (reduceOption tl) = length tl + 1
this : length (reduceOption tl) ≤ length tl
⊢ False

Next tactic:
rw [H] at this
theorem reduceOption_length_eq_iff {l : List (Option α)} :
    l.reduceOption.length = l.length ↔ ∀ x ∈ l, Option.isSome x := by
  induction' l with hd tl hl
  · simp only [forall_const, reduceOption_nil, not_mem_nil, forall_prop_of_false, eq_self_iff_true,
      length, not_false_iff]
  · cases hd
    · simp only [mem_cons, forall_eq_or_imp, Bool.coe_sort_false, false_and_iff,
        reduceOption_cons_of_none, length, Option.isSome_none, iff_false_iff]
      intro H
      have := reduceOption_length_le tl
      rw [H] at this
      

Proof state:
case cons.none
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
tl : List (Option α)
hl : length (reduceOption tl) = length tl ↔ ∀ (x : Option α), x ∈ tl → Option.isSome x = true
H : length (reduceOption tl) = length tl + 1
this : length tl + 1 ≤ length tl
⊢ False

Next tactic:
exact absurd (Nat.lt_succ_self _) (not_lt_of_le this)
theorem reduceOption_length_eq_iff {l : List (Option α)} :
    l.reduceOption.length = l.length ↔ ∀ x ∈ l, Option.isSome x := by
  induction' l with hd tl hl
  · simp only [forall_const, reduceOption_nil, not_mem_nil, forall_prop_of_false, eq_self_iff_true,
      length, not_false_iff]
  · cases hd
    · simp only [mem_cons, forall_eq_or_imp, Bool.coe_sort_false, false_and_iff,
        reduceOption_cons_of_none, length, Option.isSome_none, iff_false_iff]
      intro H
      have := reduceOption_length_le tl
      rw [H] at this
      exact absurd (Nat.lt_succ_self _) (not_lt_of_le this)
    · 

Proof state:
case cons.some
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
tl : List (Option α)
hl : length (reduceOption tl) = length tl ↔ ∀ (x : Option α), x ∈ tl → Option.isSome x = true
val✝ : α
⊢ length (reduceOption (some val✝ :: tl)) = length (some val✝ :: tl) ↔
    ∀ (x : Option α), x ∈ some val✝ :: tl → Option.isSome x = true

Next tactic:
simp only [length, add_left_inj, find?, mem_cons, forall_eq_or_imp, Option.isSome_some,
        ← hl, reduceOption, true_and]
theorem reduceOption_length_lt_iff {l : List (Option α)} :
    l.reduceOption.length < l.length ↔ none ∈ l := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
l : List (Option α)
⊢ length (reduceOption l) < length l ↔ none ∈ l

Next tactic:
rw [(reduceOption_length_le l).lt_iff_ne, Ne, reduceOption_length_eq_iff]
theorem reduceOption_length_lt_iff {l : List (Option α)} :
    l.reduceOption.length < l.length ↔ none ∈ l := by
  rw [(reduceOption_length_le l).lt_iff_ne, Ne, reduceOption_length_eq_iff]
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
l : List (Option α)
⊢ (¬∀ (x : Option α), x ∈ l → Option.isSome x = true) ↔ none ∈ l

Next tactic:
induction l
theorem reduceOption_length_lt_iff {l : List (Option α)} :
    l.reduceOption.length < l.length ↔ none ∈ l := by
  rw [(reduceOption_length_le l).lt_iff_ne, Ne, reduceOption_length_eq_iff]
  induction l <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
⊢ (¬∀ (x : Option α), x ∈ [] → Option.isSome x = true) ↔ none ∈ []

Next tactic:
simp [*]
theorem reduceOption_length_lt_iff {l : List (Option α)} :
    l.reduceOption.length < l.length ↔ none ∈ l := by
  rw [(reduceOption_length_le l).lt_iff_ne, Ne, reduceOption_length_eq_iff]
  induction l <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
head✝ : Option α
tail✝ : List (Option α)
tail_ih✝ : (¬∀ (x : Option α), x ∈ tail✝ → Option.isSome x = true) ↔ none ∈ tail✝
⊢ (¬∀ (x : Option α), x ∈ head✝ :: tail✝ → Option.isSome x = true) ↔ none ∈ head✝ :: tail✝

Next tactic:
simp [*]
theorem reduceOption_length_lt_iff {l : List (Option α)} :
    l.reduceOption.length < l.length ↔ none ∈ l := by
  rw [(reduceOption_length_le l).lt_iff_ne, Ne, reduceOption_length_eq_iff]
  induction l <;> simp [*]
  

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
head✝ : Option α
tail✝ : List (Option α)
tail_ih✝ : (¬∀ (x : Option α), x ∈ tail✝ → Option.isSome x = true) ↔ none ∈ tail✝
⊢ (Option.isSome head✝ = true → ∃ x, x ∈ tail✝ ∧ Option.isNone x = true) ↔ none = head✝ ∨ none ∈ tail✝

Next tactic:
rw [@eq_comm _ none, ← Option.not_isSome_iff_eq_none, Decidable.imp_iff_not_or]
theorem reduceOption_length_lt_iff {l : List (Option α)} :
    l.reduceOption.length < l.length ↔ none ∈ l := by
  rw [(reduceOption_length_le l).lt_iff_ne, Ne, reduceOption_length_eq_iff]
  induction l <;> simp [*]
  rw [@eq_comm _ none, ← Option.not_isSome_iff_eq_none, Decidable.imp_iff_not_or]
  

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
head✝ : Option α
tail✝ : List (Option α)
tail_ih✝ : (¬∀ (x : Option α), x ∈ tail✝ → Option.isSome x = true) ↔ none ∈ tail✝
⊢ (¬Option.isSome head✝ = true ∨ ∃ x, x ∈ tail✝ ∧ Option.isNone x = true) ↔ ¬Option.isSome head✝ = true ∨ none ∈ tail✝

Next tactic:
simp [Option.isNone_iff_eq_none]
theorem reduceOption_singleton (x : Option α) : [x].reduceOption = x.toList := by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
x : Option α
⊢ reduceOption [x] = Option.toList x

Next tactic:
cases x
theorem reduceOption_singleton (x : Option α) : [x].reduceOption = x.toList := by cases x <;> 

Proof state:
case none
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
⊢ reduceOption [none] = Option.toList none

Next tactic:
rfl
theorem reduceOption_singleton (x : Option α) : [x].reduceOption = x.toList := by cases x <;> 

Proof state:
case some
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
val✝ : α
⊢ reduceOption [some val✝] = Option.toList (some val✝)

Next tactic:
rfl
theorem reduceOption_concat (l : List (Option α)) (x : Option α) :
    (l.concat x).reduceOption = l.reduceOption ++ x.toList := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
l : List (Option α)
x : Option α
⊢ reduceOption (concat l x) = reduceOption l ++ Option.toList x

Next tactic:
induction' l with hd tl hl generalizing x
theorem reduceOption_concat (l : List (Option α)) (x : Option α) :
    (l.concat x).reduceOption = l.reduceOption ++ x.toList := by
  induction' l with hd tl hl generalizing x
  · 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
x : Option α
⊢ reduceOption (concat [] x) = reduceOption [] ++ Option.toList x

Next tactic:
cases x
theorem reduceOption_concat (l : List (Option α)) (x : Option α) :
    (l.concat x).reduceOption = l.reduceOption ++ x.toList := by
  induction' l with hd tl hl generalizing x
  · cases x <;> 

Proof state:
case nil.none
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
⊢ reduceOption (concat [] none) = reduceOption [] ++ Option.toList none

Next tactic:
simp [Option.toList]
theorem reduceOption_concat (l : List (Option α)) (x : Option α) :
    (l.concat x).reduceOption = l.reduceOption ++ x.toList := by
  induction' l with hd tl hl generalizing x
  · cases x <;> 

Proof state:
case nil.some
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
val✝ : α
⊢ reduceOption (concat [] (some val✝)) = reduceOption [] ++ Option.toList (some val✝)

Next tactic:
simp [Option.toList]
theorem reduceOption_concat (l : List (Option α)) (x : Option α) :
    (l.concat x).reduceOption = l.reduceOption ++ x.toList := by
  induction' l with hd tl hl generalizing x
  · cases x <;> simp [Option.toList]
  · 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
hd : Option α
tl : List (Option α)
hl : ∀ (x : Option α), reduceOption (concat tl x) = reduceOption tl ++ Option.toList x
x : Option α
⊢ reduceOption (concat (hd :: tl) x) = reduceOption (hd :: tl) ++ Option.toList x

Next tactic:
simp only [concat_eq_append, reduceOption_append] at hl
theorem reduceOption_concat (l : List (Option α)) (x : Option α) :
    (l.concat x).reduceOption = l.reduceOption ++ x.toList := by
  induction' l with hd tl hl generalizing x
  · cases x <;> simp [Option.toList]
  · simp only [concat_eq_append, reduceOption_append] at hl
    

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
hd : Option α
tl : List (Option α)
x : Option α
hl : ∀ (x : Option α), reduceOption tl ++ reduceOption [x] = reduceOption tl ++ Option.toList x
⊢ reduceOption (concat (hd :: tl) x) = reduceOption (hd :: tl) ++ Option.toList x

Next tactic:
cases hd
theorem reduceOption_concat (l : List (Option α)) (x : Option α) :
    (l.concat x).reduceOption = l.reduceOption ++ x.toList := by
  induction' l with hd tl hl generalizing x
  · cases x <;> simp [Option.toList]
  · simp only [concat_eq_append, reduceOption_append] at hl
    cases hd <;> 

Proof state:
case cons.none
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
tl : List (Option α)
x : Option α
hl : ∀ (x : Option α), reduceOption tl ++ reduceOption [x] = reduceOption tl ++ Option.toList x
⊢ reduceOption (concat (none :: tl) x) = reduceOption (none :: tl) ++ Option.toList x

Next tactic:
simp [hl, reduceOption_append]
theorem reduceOption_concat (l : List (Option α)) (x : Option α) :
    (l.concat x).reduceOption = l.reduceOption ++ x.toList := by
  induction' l with hd tl hl generalizing x
  · cases x <;> simp [Option.toList]
  · simp only [concat_eq_append, reduceOption_append] at hl
    cases hd <;> 

Proof state:
case cons.some
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
tl : List (Option α)
x : Option α
hl : ∀ (x : Option α), reduceOption tl ++ reduceOption [x] = reduceOption tl ++ Option.toList x
val✝ : α
⊢ reduceOption (concat (some val✝ :: tl) x) = reduceOption (some val✝ :: tl) ++ Option.toList x

Next tactic:
simp [hl, reduceOption_append]
theorem reduceOption_concat_of_some (l : List (Option α)) (x : α) :
    (l.concat (some x)).reduceOption = l.reduceOption.concat x := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
l : List (Option α)
x : α
⊢ reduceOption (concat l (some x)) = concat (reduceOption l) x

Next tactic:
simp only [reduceOption_nil, concat_eq_append, reduceOption_append, reduceOption_cons_of_some]
theorem reduceOption_mem_iff {l : List (Option α)} {x : α} : x ∈ l.reduceOption ↔ some x ∈ l := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
l : List (Option α)
x : α
⊢ x ∈ reduceOption l ↔ some x ∈ l

Next tactic:
simp only [reduceOption, id.def, mem_filterMap, exists_eq_right]
theorem reduceOption_get?_iff {l : List (Option α)} {x : α} :
    (∃ i, l.get? i = some (some x)) ↔ ∃ i, l.reduceOption.get? i = some x := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
l : List (Option α)
x : α
⊢ (∃ i, get? l i = some (some x)) ↔ ∃ i, get? (reduceOption l) i = some x

Next tactic:
rw [← mem_iff_get?, ← mem_iff_get?, reduceOption_mem_iff]
theorem filter_eq_foldr (p : α → Bool) (l : List α) :
    filter p l = foldr (fun a out => bif p a then a :: out else out) [] l := by
  

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ p : α → Bool
l : List α
⊢ filter p l = foldr (fun a out => bif p a then a :: out else out) [] l

Next tactic:
induction l
theorem filter_eq_foldr (p : α → Bool) (l : List α) :
    filter p l = foldr (fun a out => bif p a then a :: out else out) [] l := by
  induction l <;> 

Proof state:
case nil
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ p : α → Bool
⊢ filter p [] = foldr (fun a out => bif p a then a :: out else out) [] []

Next tactic:
simp [*, filter]
theorem filter_eq_foldr (p : α → Bool) (l : List α) :
    filter p l = foldr (fun a out => bif p a then a :: out else out) [] l := by
  induction l <;> 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ p : α → Bool
head✝ : α
tail✝ : List α
tail_ih✝ : filter p tail✝ = foldr (fun a out => bif p a then a :: out else out) [] tail✝
⊢ filter p (head✝ :: tail✝) = foldr (fun a out => bif p a then a :: out else out) [] (head✝ :: tail✝)

Next tactic:
simp [*, filter]
theorem filter_eq_foldr (p : α → Bool) (l : List α) :
    filter p l = foldr (fun a out => bif p a then a :: out else out) [] l := by
  induction l <;> simp [*, filter]; 

Proof state:
case cons
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p✝ p : α → Bool
head✝ : α
tail✝ : List α
tail_ih✝ : filter p tail✝ = foldr (fun a out => bif p a then a :: out else out) [] tail✝
⊢ (match p head✝ with
    | true => head✝ :: foldr (fun a out => bif p a then a :: out else out) [] tail✝
    | false => foldr (fun a out => bif p a then a :: out else out) [] tail✝) =
    bif p head✝ then head✝ :: foldr (fun a out => bif p a then a :: out else out) [] tail✝
    else foldr (fun a out => bif p a then a :: out else out) [] tail✝

Next tactic:
rfl
theorem of_mem_filter {a : α} : ∀ {l}, a ∈ filter p l → p a
  | b :: l, ain =>
    if pb : p b then
      have : a ∈ b :: filter p l := by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
a b : α
l : List α
ain : a ∈ filter p (b :: l)
pb : p b = true
⊢ a ∈ b :: filter p l

Next tactic:
simpa only [filter_cons_of_pos _ pb] using ain
theorem of_mem_filter {a : α} : ∀ {l}, a ∈ filter p l → p a
  | b :: l, ain =>
    if pb : p b then
      have : a ∈ b :: filter p l := by simpa only [filter_cons_of_pos _ pb] using ain
      Or.elim (eq_or_mem_of_mem_cons this) (fun h : a = b => by 

Proof state:
ι : Type u_1
α : Type u
β : Type v
γ : Type w
l₁ l₂ : List α
p : α → Bool
a b : α
l : List α
ain : a ∈ filter p (b :: l)
pb : p b = true
this : a ∈ b :: filter p l
h : a = b
⊢ p a = true

Next tactic:
rw [← h] at pb