l3lab/ntp-mathlib huggingface dataset:
theorem perm_permutations'Aux_comm (a b : α) (l : List α) :
    (permutations'Aux a l).bind (permutations'Aux b) ~
      (permutations'Aux b l).bind (permutations'Aux a) := by
  induction' l with c l ih
  · simp [swap]
  simp only [permutations'Aux, cons_bind, map_cons, map_map, cons_append]
  apply Perm.swap'
  have :
    ∀ a b,
      (map (cons c) (permutations'Aux a l)).bind (permutations'Aux b) ~
        map (cons b ∘ cons c) (permutations'Aux a l) ++
          map (cons c) ((permutations'Aux a l).bind (permutations'Aux b)) := by
    intros a' b'
    simp only [map_bind, permutations'Aux]
    show List.bind (permutations'Aux _ l) (fun a => ([b' :: c :: a] ++
      map (cons c) (permutations'Aux _ a))) ~ _
    refine' (bind_append_perm _ (fun x => [b' :: c :: x]) _).symm.trans _
    rw [← map_eq_bind, ← bind_map]
    exact Perm.refl _
  refine' (((this _ _).append_left _).trans _).trans ((this _ _).append_left _).symm
  rw [← append_assoc, ← append_assoc]
  

Proof state:
case cons.p
α : Type u_1
β : Type u_2
l✝ l₁ l₂ : List α
a✝ a b c : α
l : List α
ih : List.bind (permutations'Aux a l) (permutations'Aux b) ~ List.bind (permutations'Aux b l) (permutations'Aux a)
this :
  ∀ (a b : α),
    List.bind (map (cons c) (permutations'Aux a l)) (permutations'Aux b) ~
      map (cons b ∘ cons c) (permutations'Aux a l) ++
        map (cons c) (List.bind (permutations'Aux a l) (permutations'Aux b))
⊢ map (cons a ∘ cons c) (permutations'Aux b l) ++ map (cons b ∘ cons c) (permutations'Aux a l) ++
      map (cons c) (List.bind (permutations'Aux a l) (permutations'Aux b)) ~
    map (cons b ∘ cons c) (permutations'Aux a l) ++ map (cons a ∘ cons c) (permutations'Aux b l) ++
      map (cons c) (List.bind (permutations'Aux b l) (permutations'Aux a))

Next tactic:
exact perm_append_comm.append (ih.map _)
theorem Perm.permutations' {s t : List α} (p : s ~ t) : permutations' s ~ permutations' t := by
  

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
s t : List α
p : s ~ t
⊢ List.permutations' s ~ List.permutations' t

Next tactic:
induction' p with a s t _ IH a b l s t u _ _ IH₁ IH₂
theorem Perm.permutations' {s t : List α} (p : s ~ t) : permutations' s ~ permutations' t := by
  induction' p with a s t _ IH a b l s t u _ _ IH₁ IH₂; · 

Proof state:
case nil
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
s t : List α
⊢ List.permutations' [] ~ List.permutations' []

Next tactic:
simp
theorem Perm.permutations' {s t : List α} (p : s ~ t) : permutations' s ~ permutations' t := by
  induction' p with a s t _ IH a b l s t u _ _ IH₁ IH₂; · simp
  · 

Proof state:
case cons
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a✝¹ : α
s✝ t✝ : List α
a : α
s t : List α
a✝ : s ~ t
IH : List.permutations' s ~ List.permutations' t
⊢ List.permutations' (a :: s) ~ List.permutations' (a :: t)

Next tactic:
exact IH.bind_right _
theorem Perm.permutations' {s t : List α} (p : s ~ t) : permutations' s ~ permutations' t := by
  induction' p with a s t _ IH a b l s t u _ _ IH₁ IH₂; · simp
  · exact IH.bind_right _
  · 

Proof state:
case swap
α : Type u_1
β : Type u_2
l✝ l₁ l₂ : List α
a✝ : α
s t : List α
a b : α
l : List α
⊢ List.permutations' (b :: a :: l) ~ List.permutations' (a :: b :: l)

Next tactic:
dsimp [permutations']
theorem Perm.permutations' {s t : List α} (p : s ~ t) : permutations' s ~ permutations' t := by
  induction' p with a s t _ IH a b l s t u _ _ IH₁ IH₂; · simp
  · exact IH.bind_right _
  · dsimp [permutations']
    

Proof state:
case swap
α : Type u_1
β : Type u_2
l✝ l₁ l₂ : List α
a✝ : α
s t : List α
a b : α
l : List α
⊢ List.bind (List.bind (List.permutations' l) (permutations'Aux a)) (permutations'Aux b) ~
    List.bind (List.bind (List.permutations' l) (permutations'Aux b)) (permutations'Aux a)

Next tactic:
rw [bind_assoc, bind_assoc]
theorem Perm.permutations' {s t : List α} (p : s ~ t) : permutations' s ~ permutations' t := by
  induction' p with a s t _ IH a b l s t u _ _ IH₁ IH₂; · simp
  · exact IH.bind_right _
  · dsimp [permutations']
    rw [bind_assoc, bind_assoc]
    

Proof state:
case swap
α : Type u_1
β : Type u_2
l✝ l₁ l₂ : List α
a✝ : α
s t : List α
a b : α
l : List α
⊢ (List.bind (List.permutations' l) fun x => List.bind (permutations'Aux a x) (permutations'Aux b)) ~
    List.bind (List.permutations' l) fun x => List.bind (permutations'Aux b x) (permutations'Aux a)

Next tactic:
apply Perm.bind_left
theorem Perm.permutations' {s t : List α} (p : s ~ t) : permutations' s ~ permutations' t := by
  induction' p with a s t _ IH a b l s t u _ _ IH₁ IH₂; · simp
  · exact IH.bind_right _
  · dsimp [permutations']
    rw [bind_assoc, bind_assoc]
    apply Perm.bind_left
    

Proof state:
case swap.h
α : Type u_1
β : Type u_2
l✝ l₁ l₂ : List α
a✝ : α
s t : List α
a b : α
l : List α
⊢ ∀ a_1 ∈ List.permutations' l,
    List.bind (permutations'Aux a a_1) (permutations'Aux b) ~ List.bind (permutations'Aux b a_1) (permutations'Aux a)

Next tactic:
intro l' _
theorem Perm.permutations' {s t : List α} (p : s ~ t) : permutations' s ~ permutations' t := by
  induction' p with a s t _ IH a b l s t u _ _ IH₁ IH₂; · simp
  · exact IH.bind_right _
  · dsimp [permutations']
    rw [bind_assoc, bind_assoc]
    apply Perm.bind_left
    intro l' _
    

Proof state:
case swap.h
α : Type u_1
β : Type u_2
l✝ l₁ l₂ : List α
a✝¹ : α
s t : List α
a b : α
l l' : List α
a✝ : l' ∈ List.permutations' l
⊢ List.bind (permutations'Aux a l') (permutations'Aux b) ~ List.bind (permutations'Aux b l') (permutations'Aux a)

Next tactic:
apply perm_permutations'Aux_comm
theorem Perm.permutations' {s t : List α} (p : s ~ t) : permutations' s ~ permutations' t := by
  induction' p with a s t _ IH a b l s t u _ _ IH₁ IH₂; · simp
  · exact IH.bind_right _
  · dsimp [permutations']
    rw [bind_assoc, bind_assoc]
    apply Perm.bind_left
    intro l' _
    apply perm_permutations'Aux_comm
  · 

Proof state:
case trans
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
s✝ t✝ s t u : List α
a✝¹ : s ~ t
a✝ : t ~ u
IH₁ : List.permutations' s ~ List.permutations' t
IH₂ : List.permutations' t ~ List.permutations' u
⊢ List.permutations' s ~ List.permutations' u

Next tactic:
exact IH₁.trans IH₂
theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.permutations' := by
  

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
ts : List α
⊢ permutations ts ~ permutations' ts

Next tactic:
obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.permutations' := by
  obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
  

Proof state:
case intro
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
ts : List α
n : ℕ
h : length ts < n
⊢ permutations ts ~ permutations' ts

Next tactic:
induction' n with n IH generalizing ts
theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.permutations' := by
  obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
  induction' n with n IH generalizing ts; · 

Proof state:
case intro.zero
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
ts : List α
h : length ts < zero
⊢ permutations ts ~ permutations' ts

Next tactic:
cases h
theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.permutations' := by
  obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
  induction' n with n IH generalizing ts; · cases h
  

Proof state:
case intro.succ
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts : List α
h : length ts < succ n
⊢ permutations ts ~ permutations' ts

Next tactic:
refine' List.reverseRecOn ts (fun _ => _) (fun ts t _ h => _) h
theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.permutations' := by
  obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
  induction' n with n IH generalizing ts; · cases h
  refine' List.reverseRecOn ts (fun _ => _) (fun ts t _ h => _) h; · 

Proof state:
case intro.succ.refine'_1
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts : List α
h : length ts < succ n
x✝ : length [] < succ n
⊢ permutations [] ~ permutations' []

Next tactic:
simp [permutations]
theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.permutations' := by
  obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
  induction' n with n IH generalizing ts; · cases h
  refine' List.reverseRecOn ts (fun _ => _) (fun ts t _ h => _) h; · simp [permutations]
  

Proof state:
case intro.succ.refine'_2
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length (ts ++ [t]) < succ n
⊢ permutations (ts ++ [t]) ~ permutations' (ts ++ [t])

Next tactic:
rw [← concat_eq_append, length_concat, Nat.succ_lt_succ_iff] at h
theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.permutations' := by
  obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
  induction' n with n IH generalizing ts; · cases h
  refine' List.reverseRecOn ts (fun _ => _) (fun ts t _ h => _) h; · simp [permutations]
  rw [← concat_eq_append, length_concat, Nat.succ_lt_succ_iff] at h
  

Proof state:
case intro.succ.refine'_2
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
⊢ permutations (ts ++ [t]) ~ permutations' (ts ++ [t])

Next tactic:
have IH₂ := (IH ts.reverse (by rwa [length_reverse])).trans (reverse_perm _).permutations'
theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.permutations' := by
  obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
  induction' n with n IH generalizing ts; · cases h
  refine' List.reverseRecOn ts (fun _ => _) (fun ts t _ h => _) h; · simp [permutations]
  rw [← concat_eq_append, length_concat, Nat.succ_lt_succ_iff] at h
  have IH₂ := (IH ts.reverse (by 

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
⊢ length (reverse ts) < n

Next tactic:
rwa [length_reverse]
theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.permutations' := by
  obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
  induction' n with n IH generalizing ts; · cases h
  refine' List.reverseRecOn ts (fun _ => _) (fun ts t _ h => _) h; · simp [permutations]
  rw [← concat_eq_append, length_concat, Nat.succ_lt_succ_iff] at h
  have IH₂ := (IH ts.reverse (by rwa [length_reverse])).trans (reverse_perm _).permutations'
  

Proof state:
case intro.succ.refine'_2
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
IH₂ : permutations (reverse ts) ~ permutations' ts
⊢ permutations (ts ++ [t]) ~ permutations' (ts ++ [t])

Next tactic:
simp only [permutations_append, foldr_permutationsAux2, permutationsAux_nil,
    permutationsAux_cons, append_nil]
theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.permutations' := by
  obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
  induction' n with n IH generalizing ts; · cases h
  refine' List.reverseRecOn ts (fun _ => _) (fun ts t _ h => _) h; · simp [permutations]
  rw [← concat_eq_append, length_concat, Nat.succ_lt_succ_iff] at h
  have IH₂ := (IH ts.reverse (by rwa [length_reverse])).trans (reverse_perm _).permutations'
  simp only [permutations_append, foldr_permutationsAux2, permutationsAux_nil,
    permutationsAux_cons, append_nil]
  

Proof state:
case intro.succ.refine'_2
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
IH₂ : permutations (reverse ts) ~ permutations' ts
⊢ (map (fun x => x ++ [t]) (permutations ts) ++
      List.bind (permutations (reverse ts)) fun y => (permutationsAux2 t [] [] y id).2) ~
    permutations' (ts ++ [t])

Next tactic:
refine'
    (perm_append_comm.trans ((IH₂.bind_right _).append ((IH _ h).map _))).trans
      (Perm.trans _ perm_append_comm.permutations')
theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.permutations' := by
  obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
  induction' n with n IH generalizing ts; · cases h
  refine' List.reverseRecOn ts (fun _ => _) (fun ts t _ h => _) h; · simp [permutations]
  rw [← concat_eq_append, length_concat, Nat.succ_lt_succ_iff] at h
  have IH₂ := (IH ts.reverse (by rwa [length_reverse])).trans (reverse_perm _).permutations'
  simp only [permutations_append, foldr_permutationsAux2, permutationsAux_nil,
    permutationsAux_cons, append_nil]
  refine'
    (perm_append_comm.trans ((IH₂.bind_right _).append ((IH _ h).map _))).trans
      (Perm.trans _ perm_append_comm.permutations')
  

Proof state:
case intro.succ.refine'_2
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
IH₂ : permutations (reverse ts) ~ permutations' ts
⊢ (List.bind (permutations' ts) fun y => (permutationsAux2 t [] [] y id).2) ++
      map (fun x => x ++ [t]) (permutations' ts) ~
    permutations' ([t] ++ ts)

Next tactic:
rw [map_eq_bind, singleton_append, permutations']
theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.permutations' := by
  obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
  induction' n with n IH generalizing ts; · cases h
  refine' List.reverseRecOn ts (fun _ => _) (fun ts t _ h => _) h; · simp [permutations]
  rw [← concat_eq_append, length_concat, Nat.succ_lt_succ_iff] at h
  have IH₂ := (IH ts.reverse (by rwa [length_reverse])).trans (reverse_perm _).permutations'
  simp only [permutations_append, foldr_permutationsAux2, permutationsAux_nil,
    permutationsAux_cons, append_nil]
  refine'
    (perm_append_comm.trans ((IH₂.bind_right _).append ((IH _ h).map _))).trans
      (Perm.trans _ perm_append_comm.permutations')
  rw [map_eq_bind, singleton_append, permutations']
  

Proof state:
case intro.succ.refine'_2
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
IH₂ : permutations (reverse ts) ~ permutations' ts
⊢ ((List.bind (permutations' ts) fun y => (permutationsAux2 t [] [] y id).2) ++
      List.bind (permutations' ts) fun x => [x ++ [t]]) ~
    List.bind (permutations' ts) (permutations'Aux t)

Next tactic:
refine' (bind_append_perm _ _ _).trans _
theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.permutations' := by
  obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
  induction' n with n IH generalizing ts; · cases h
  refine' List.reverseRecOn ts (fun _ => _) (fun ts t _ h => _) h; · simp [permutations]
  rw [← concat_eq_append, length_concat, Nat.succ_lt_succ_iff] at h
  have IH₂ := (IH ts.reverse (by rwa [length_reverse])).trans (reverse_perm _).permutations'
  simp only [permutations_append, foldr_permutationsAux2, permutationsAux_nil,
    permutationsAux_cons, append_nil]
  refine'
    (perm_append_comm.trans ((IH₂.bind_right _).append ((IH _ h).map _))).trans
      (Perm.trans _ perm_append_comm.permutations')
  rw [map_eq_bind, singleton_append, permutations']
  refine' (bind_append_perm _ _ _).trans _
  

Proof state:
case intro.succ.refine'_2
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
IH₂ : permutations (reverse ts) ~ permutations' ts
⊢ (List.bind (permutations' ts) fun x => (permutationsAux2 t [] [] x id).2 ++ [x ++ [t]]) ~
    List.bind (permutations' ts) (permutations'Aux t)

Next tactic:
refine' Perm.of_eq _
theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.permutations' := by
  obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
  induction' n with n IH generalizing ts; · cases h
  refine' List.reverseRecOn ts (fun _ => _) (fun ts t _ h => _) h; · simp [permutations]
  rw [← concat_eq_append, length_concat, Nat.succ_lt_succ_iff] at h
  have IH₂ := (IH ts.reverse (by rwa [length_reverse])).trans (reverse_perm _).permutations'
  simp only [permutations_append, foldr_permutationsAux2, permutationsAux_nil,
    permutationsAux_cons, append_nil]
  refine'
    (perm_append_comm.trans ((IH₂.bind_right _).append ((IH _ h).map _))).trans
      (Perm.trans _ perm_append_comm.permutations')
  rw [map_eq_bind, singleton_append, permutations']
  refine' (bind_append_perm _ _ _).trans _
  refine' Perm.of_eq _
  

Proof state:
case intro.succ.refine'_2
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
IH₂ : permutations (reverse ts) ~ permutations' ts
⊢ (List.bind (permutations' ts) fun x => (permutationsAux2 t [] [] x id).2 ++ [x ++ [t]]) =
    List.bind (permutations' ts) (permutations'Aux t)

Next tactic:
congr
theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.permutations' := by
  obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
  induction' n with n IH generalizing ts; · cases h
  refine' List.reverseRecOn ts (fun _ => _) (fun ts t _ h => _) h; · simp [permutations]
  rw [← concat_eq_append, length_concat, Nat.succ_lt_succ_iff] at h
  have IH₂ := (IH ts.reverse (by rwa [length_reverse])).trans (reverse_perm _).permutations'
  simp only [permutations_append, foldr_permutationsAux2, permutationsAux_nil,
    permutationsAux_cons, append_nil]
  refine'
    (perm_append_comm.trans ((IH₂.bind_right _).append ((IH _ h).map _))).trans
      (Perm.trans _ perm_append_comm.permutations')
  rw [map_eq_bind, singleton_append, permutations']
  refine' (bind_append_perm _ _ _).trans _
  refine' Perm.of_eq _
  congr
  

Proof state:
case intro.succ.refine'_2.e_b
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
IH₂ : permutations (reverse ts) ~ permutations' ts
⊢ (fun x => (permutationsAux2 t [] [] x id).2 ++ [x ++ [t]]) = permutations'Aux t

Next tactic:
funext _
theorem permutations_perm_permutations' (ts : List α) : ts.permutations ~ ts.permutations' := by
  obtain ⟨n, h⟩ : ∃ n, length ts < n := ⟨_, Nat.lt_succ_self _⟩
  induction' n with n IH generalizing ts; · cases h
  refine' List.reverseRecOn ts (fun _ => _) (fun ts t _ h => _) h; · simp [permutations]
  rw [← concat_eq_append, length_concat, Nat.succ_lt_succ_iff] at h
  have IH₂ := (IH ts.reverse (by rwa [length_reverse])).trans (reverse_perm _).permutations'
  simp only [permutations_append, foldr_permutationsAux2, permutationsAux_nil,
    permutationsAux_cons, append_nil]
  refine'
    (perm_append_comm.trans ((IH₂.bind_right _).append ((IH _ h).map _))).trans
      (Perm.trans _ perm_append_comm.permutations')
  rw [map_eq_bind, singleton_append, permutations']
  refine' (bind_append_perm _ _ _).trans _
  refine' Perm.of_eq _
  congr
  funext _
  

Proof state:
case intro.succ.refine'_2.e_b.h
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
n : ℕ
IH : ∀ (ts : List α), length ts < n → permutations ts ~ permutations' ts
ts✝ : List α
h✝ : length ts✝ < succ n
ts : List α
t : α
x✝¹ : length ts < succ n → permutations ts ~ permutations' ts
h : length ts < n
IH₂ : permutations (reverse ts) ~ permutations' ts
x✝ : List α
⊢ (permutationsAux2 t [] [] x✝ id).2 ++ [x✝ ++ [t]] = permutations'Aux t x✝

Next tactic:
rw [permutations'Aux_eq_permutationsAux2, permutationsAux2_append]
set_option linter.deprecated false in
theorem nthLe_permutations'Aux (s : List α) (x : α) (n : ℕ)
    (hn : n < length (permutations'Aux x s)) :
    (permutations'Aux x s).nthLe n hn = s.insertNth n x := by
  

Proof state:
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a : α
s : List α
x : α
n : ℕ
hn : n < length (permutations'Aux x s)
⊢ nthLe (permutations'Aux x s) n hn = insertNth n x s

Next tactic:
induction' s with y s IH generalizing n
set_option linter.deprecated false in
theorem nthLe_permutations'Aux (s : List α) (x : α) (n : ℕ)
    (hn : n < length (permutations'Aux x s)) :
    (permutations'Aux x s).nthLe n hn = s.insertNth n x := by
  induction' s with y s IH generalizing n
  · 

Proof state:
case nil
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a x : α
n : ℕ
hn : n < length (permutations'Aux x [])
⊢ nthLe (permutations'Aux x []) n hn = insertNth n x []

Next tactic:
simp only [length, zero_add, lt_one_iff] at hn
set_option linter.deprecated false in
theorem nthLe_permutations'Aux (s : List α) (x : α) (n : ℕ)
    (hn : n < length (permutations'Aux x s)) :
    (permutations'Aux x s).nthLe n hn = s.insertNth n x := by
  induction' s with y s IH generalizing n
  · simp only [length, zero_add, lt_one_iff] at hn
    

Proof state:
case nil
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a x : α
n : ℕ
hn✝ : n < length (permutations'Aux x [])
hn : n = 0
⊢ nthLe (permutations'Aux x []) n hn✝ = insertNth n x []

Next tactic:
simp [hn]
set_option linter.deprecated false in
theorem nthLe_permutations'Aux (s : List α) (x : α) (n : ℕ)
    (hn : n < length (permutations'Aux x s)) :
    (permutations'Aux x s).nthLe n hn = s.insertNth n x := by
  induction' s with y s IH generalizing n
  · simp only [length, zero_add, lt_one_iff] at hn
    simp [hn]
  · 

Proof state:
case cons
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a x y : α
s : List α
IH : ∀ (n : ℕ) (hn : n < length (permutations'Aux x s)), nthLe (permutations'Aux x s) n hn = insertNth n x s
n : ℕ
hn : n < length (permutations'Aux x (y :: s))
⊢ nthLe (permutations'Aux x (y :: s)) n hn = insertNth n x (y :: s)

Next tactic:
cases n
set_option linter.deprecated false in
theorem nthLe_permutations'Aux (s : List α) (x : α) (n : ℕ)
    (hn : n < length (permutations'Aux x s)) :
    (permutations'Aux x s).nthLe n hn = s.insertNth n x := by
  induction' s with y s IH generalizing n
  · simp only [length, zero_add, lt_one_iff] at hn
    simp [hn]
  · cases n
    · 

Proof state:
case cons.zero
α : Type u_1
β : Type u_2
l l₁ l₂ : List α
a x y : α
s : List α
IH : ∀ (n : ℕ) (hn : n < length (permutations'Aux x s)), nthLe (permutations'Aux x s) n hn = insertNth n x s
hn : zero < length (permutations'Aux x (y :: s))
⊢ nthLe (permutations'Aux x (y :: s)) zero hn = insertNth zero x (y :: s)

Next tactic:
simp [nthLe]