-- Mathlib/.lake/packages/lean4/src/lean/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddResult.lean
theorem size_insertUnit_fold :
    ∀ unitsAcc : Array (Literal (PosFin n)), ∀ assignments : Array Assignment, ∀ b : Bool,
      Array.size (List.foldl insertUnit (unitsAcc, assignments, b) units).2.1 = assignments.size

Proof state:
n : Nat
hd : Literal (PosFin n)
tl : List (Literal (PosFin n))
ih :
  ∀ (unitsAcc : Array (Literal (PosFin n))) (assignments : Array Assignment) (b : Bool),
    (List.foldl insertUnit (unitsAcc, assignments, b) tl).snd.fst.size = assignments.size
unitsAcc : Array (Literal (PosFin n))
assignments : Array Assignment
b : Bool
⊢ (List.foldl insertUnit (insertUnit (unitsAcc, assignments, b) hd) tl).snd.fst.size = assignments.size

Tactic:
let hd_res := insertUnit (unitsAcc, assignments, b) hd

Result:
n : Nat
hd : Literal (PosFin n)
tl : List (Literal (PosFin n))
ih :
  ∀ (unitsAcc : Array (Literal (PosFin n))) (assignments : Array Assignment) (b : Bool),
    (List.foldl insertUnit (unitsAcc, assignments, b) tl).snd.fst.size = assignments.size
unitsAcc : Array (Literal (PosFin n))
assignments : Array Assignment
b : Bool
hd_res : Array (Literal (PosFin n)) × Array Assignment × Bool := insertUnit (unitsAcc, assignments, b) hd
⊢ (List.foldl insertUnit (insertUnit (unitsAcc, assignments, b) hd) tl).snd.fst.size = assignments.size

Proof state:
n : Nat
units : List (Literal (PosFin n))
⊢ ∀ (unitsAcc : Array (Literal (PosFin n))) (assignments : Array Assignment) (b : Bool),
    (List.foldl insertUnit (unitsAcc, assignments, b) units).snd.fst.size = assignments.size

Tactic:
induction units

Result:
case nil
n : Nat
⊢ ∀ (unitsAcc : Array (Literal (PosFin n))) (assignments : Array Assignment) (b : Bool),
    (List.foldl insertUnit (unitsAcc, assignments, b) []).snd.fst.size = assignments.size

case cons
n : Nat
head✝ : Literal (PosFin n)
tail✝ : List (Literal (PosFin n))
tail_ih✝ :
  ∀ (unitsAcc : Array (Literal (PosFin n))) (assignments : Array Assignment) (b : Bool),
    (List.foldl insertUnit (unitsAcc, assignments, b) tail✝).snd.fst.size = assignments.size
⊢ ∀ (unitsAcc : Array (Literal (PosFin n))) (assignments : Array Assignment) (b : Bool),
    (List.foldl insertUnit (unitsAcc, assignments, b) (head✝ :: tail✝)).snd.fst.size = assignments.size

Proof state:
n : Nat
hd : Literal (PosFin n)
tl : List (Literal (PosFin n))
unitsAcc : Array (Literal (PosFin n))
assignments : Array Assignment
b : Bool
hd_res : Array (Literal (PosFin n)) × Array Assignment × Bool := insertUnit (unitsAcc, assignments, b) hd
ih : (List.foldl insertUnit (hd_res.fst, hd_res.snd.fst, hd_res.snd.snd) tl).snd.fst.size = hd_res.snd.fst.size
⊢ (List.foldl insertUnit (insertUnit (unitsAcc, assignments, b) hd) tl).snd.fst.size = assignments.size

Tactic:
rw [ih, size_insertUnit]

Result:
no goals

Proof state:
case cons
n : Nat
head✝ : Literal (PosFin n)
tail✝ : List (Literal (PosFin n))
tail_ih✝ :
  ∀ (unitsAcc : Array (Literal (PosFin n))) (assignments : Array Assignment) (b : Bool),
    (List.foldl insertUnit (unitsAcc, assignments, b) tail✝).snd.fst.size = assignments.size
⊢ ∀ (unitsAcc : Array (Literal (PosFin n))) (assignments : Array Assignment) (b : Bool),
    (List.foldl insertUnit (unitsAcc, assignments, b) (head✝ :: tail✝)).snd.fst.size = assignments.size

Tactic:
next hd tl ih =>
intro unitsAcc assignments b
simp only [List.foldl]
let hd_res := insertUnit (unitsAcc, assignments, b) hd
specialize ih hd_res.1 hd_res.2.1 hd_res.2.2
rw [ih, size_insertUnit]

Result:
no goals

Proof state:
n : Nat
hd : Literal (PosFin n)
tl : List (Literal (PosFin n))
ih :
  ∀ (unitsAcc : Array (Literal (PosFin n))) (assignments : Array Assignment) (b : Bool),
    (List.foldl insertUnit (unitsAcc, assignments, b) tl).snd.fst.size = assignments.size
⊢ ∀ (unitsAcc : Array (Literal (PosFin n))) (assignments : Array Assignment) (b : Bool),
    (List.foldl insertUnit (unitsAcc, assignments, b) (hd :: tl)).snd.fst.size = assignments.size

Tactic:
intro unitsAcc assignments b

Result:
n : Nat
hd : Literal (PosFin n)
tl : List (Literal (PosFin n))
ih :
  ∀ (unitsAcc : Array (Literal (PosFin n))) (assignments : Array Assignment) (b : Bool),
    (List.foldl insertUnit (unitsAcc, assignments, b) tl).snd.fst.size = assignments.size
unitsAcc : Array (Literal (PosFin n))
assignments : Array Assignment
b : Bool
⊢ (List.foldl insertUnit (unitsAcc, assignments, b) (hd :: tl)).snd.fst.size = assignments.size

Proof state:
n : Nat
hd : Literal (PosFin n)
tl : List (Literal (PosFin n))
ih :
  ∀ (unitsAcc : Array (Literal (PosFin n))) (assignments : Array Assignment) (b : Bool),
    (List.foldl insertUnit (unitsAcc, assignments, b) tl).snd.fst.size = assignments.size
unitsAcc : Array (Literal (PosFin n))
assignments : Array Assignment
b : Bool
hd_res : Array (Literal (PosFin n)) × Array Assignment × Bool := insertUnit (unitsAcc, assignments, b) hd
⊢ (List.foldl insertUnit (insertUnit (unitsAcc, assignments, b) hd) tl).snd.fst.size = assignments.size

Tactic:
specialize ih hd_res.1 hd_res.2.1 hd_res.2.2

Result:
n : Nat
hd : Literal (PosFin n)
tl : List (Literal (PosFin n))
unitsAcc : Array (Literal (PosFin n))
assignments : Array Assignment
b : Bool
hd_res : Array (Literal (PosFin n)) × Array Assignment × Bool := insertUnit (unitsAcc, assignments, b) hd
ih : (List.foldl insertUnit (hd_res.fst, hd_res.snd.fst, hd_res.snd.snd) tl).snd.fst.size = hd_res.snd.fst.size
⊢ (List.foldl insertUnit (insertUnit (unitsAcc, assignments, b) hd) tl).snd.fst.size = assignments.size

Proof state:
case nil
n : Nat
⊢ ∀ (unitsAcc : Array (Literal (PosFin n))) (assignments : Array Assignment) (b : Bool),
    (List.foldl insertUnit (unitsAcc, assignments, b) []).snd.fst.size = assignments.size

Tactic:
simp only [List.foldl, forall_const]

Result:
no goals

Proof state:
n : Nat
hd : Literal (PosFin n)
tl : List (Literal (PosFin n))
ih :
  ∀ (unitsAcc : Array (Literal (PosFin n))) (assignments : Array Assignment) (b : Bool),
    (List.foldl insertUnit (unitsAcc, assignments, b) tl).snd.fst.size = assignments.size
unitsAcc : Array (Literal (PosFin n))
assignments : Array Assignment
b : Bool
⊢ (List.foldl insertUnit (unitsAcc, assignments, b) (hd :: tl)).snd.fst.size = assignments.size

Tactic:
simp only [List.foldl]

Result:
n : Nat
hd : Literal (PosFin n)
tl : List (Literal (PosFin n))
ih :
  ∀ (unitsAcc : Array (Literal (PosFin n))) (assignments : Array Assignment) (b : Bool),
    (List.foldl insertUnit (unitsAcc, assignments, b) tl).snd.fst.size = assignments.size
unitsAcc : Array (Literal (PosFin n))
assignments : Array Assignment
b : Bool
⊢ (List.foldl insertUnit (insertUnit (unitsAcc, assignments, b) hd) tl).snd.fst.size = assignments.size