import Mathlib
import Aesop

set_option maxHeartbeats 0

open Set Function

theorem putnam_1964_a4
(u : ℕ → ℤ)
(boundedu : ∃ B T : ℤ, ∀ n : ℕ, B ≤ u n ∧ u n ≤ T)
(hu : ∀ n ≥ 4, u n = ((u (n - 1) + u (n - 2) + u (n - 3) * u (n - 4)) : ℝ) / (u (n - 1) * u (n - 2) + u (n - 3) + u (n - 4)) ∧ (u (n - 1) * u (n - 2) + u (n - 3) + u (n - 4)) ≠ 0)
: (∃ N c : ℕ, c > 0 ∧ ∀ n ≥ N, u (n + c) = u n) := by
  have h_main : ∃ (i j : ℕ), i < j ∧ (u i = u j ∧ u (i + 1) = u (j + 1) ∧ u (i + 2) = u (j + 2) ∧ u (i + 3) = u (j + 3)) := by
    obtain ⟨B, T, hB⟩ := boundedu
    have h₁ : ∃ (i j : ℕ), i < j ∧ (u i = u j ∧ u (i + 1) = u (j + 1) ∧ u (i + 2) = u (j + 2) ∧ u (i + 3) = u (j + 3)) := by

      classical

      let f : ℕ → (ℤ × ℤ × ℤ × ℤ) := fun n => (u n, u (n + 1), u (n + 2), u (n + 3))
      have h₂ : Set.Finite (Set.range f) := by
        have h₃ : Set.range f ⊆ Set.Icc (B, B, B, B) (T, T, T, T) := by
          intro x hx
          rcases hx with ⟨n, rfl⟩
          have h₄ := hB n
          have h₅ := hB (n + 1)
          have h₆ := hB (n + 2)
          have h₇ := hB (n + 3)
          simp only [Set.mem_Icc, Prod.le_def] at h₄ h₅ h₆ h₇ ⊢
          constructor <;>
          (try constructor) <;>
          (try constructor) <;>
          (try constructor) <;>
          (try simp_all [f]) <;>
          (try nlinarith)

        have h₄ : Set.Finite (Set.Icc (B, B, B, B) (T, T, T, T)) := by
          apply Set.Finite.subset (Set.finite_mem_finset (Finset.Icc (B, B, B, B) (T, T, T, T)))
          intro x hx
          simp_all [Set.mem_Icc]
          <;>
          (try aesop)
        exact Set.Finite.subset h₄ h₃

      have h₃ : ∃ (i j : ℕ), i < j ∧ f i = f j := by
        by_contra! h₄
        have h₅ : Function.Injective f := by
          intro i j h₆
          by_cases h₇ : i = j
          · exact h₇
          · have h₈ : i < j ∨ j < i := by omega
            cases h₈ with
            | inl h₈ =>
              have h₉ := h₄ i j h₈
              simp_all
            | inr h₈ =>
              have h₉ := h₄ j i h₈
              simp_all
        have h₆ : Set.Infinite (Set.range f) := Set.infinite_range_of_injective h₅
        exact Set.not_infinite.mpr h₂ h₆

      obtain ⟨i, j, h₄, h₅⟩ := h₃
      refine' ⟨i, j, h₄, _⟩
      simp [f] at h₅ ⊢
      <;>
      (try simp_all [Prod.ext_iff]) <;>
      (try omega) <;>
      (try aesop)
    exact h₁

  have h_periodic : ∃ N c : ℕ, c > 0 ∧ ∀ n ≥ N, u (n + c) = u n := by
    obtain ⟨i, j, hij, h_eq⟩ := h_main
    have h₁ : ∀ m : ℕ, u (i + m) = u (j + m) := by
      intro m
      have h₂ : ∀ m : ℕ, u (i + m) = u (j + m) := by
        intro m
        induction m using Nat.strong_induction_on with
        | h m ih =>
          match m with
          | 0 =>
            have h₃ := h_eq.1
            simp at h₃ ⊢
            <;> simp_all [add_assoc]
          | 1 =>
            have h₃ := h_eq.2.1
            simp at h₃ ⊢
            <;> simp_all [add_assoc]
            <;> ring_nf at *
            <;> omega
          | 2 =>
            have h₃ := h_eq.2.2.1
            simp at h₃ ⊢
            <;> simp_all [add_assoc]
            <;> ring_nf at *
            <;> omega
          | 3 =>
            have h₃ := h_eq.2.2.2
            simp at h₃ ⊢
            <;> simp_all [add_assoc]
            <;> ring_nf at *
            <;> omega
          | m + 4 =>
            have h₃ : i + (m + 4) ≥ 4 := by
              have h₄ : i ≥ 0 := by linarith
              omega
            have h₄ : u (i + (m + 4)) = ((u (i + (m + 4) - 1) + u (i + (m + 4) - 2) + u (i + (m + 4) - 3) * u (i + (m + 4) - 4)) : ℝ) / (u (i + (m + 4) - 1) * u (i + (m + 4) - 2) + u (i + (m + 4) - 3) + u (i + (m + 4) - 4)) := by
              have h₅ := hu (i + (m + 4)) (by omega)
              have h₆ := h₅.1
              norm_cast at h₆ ⊢
              <;> simp_all [add_assoc]
              <;> ring_nf at *
              <;> norm_num at *
              <;> linarith
            have h₅ : u (j + (m + 4)) = ((u (j + (m + 4) - 1) + u (j + (m + 4) - 2) + u (j + (m + 4) - 3) * u (j + (m + 4) - 4)) : ℝ) / (u (j + (m + 4) - 1) * u (j + (m + 4) - 2) + u (j + (m + 4) - 3) + u (j + (m + 4) - 4)) := by
              have h₆ := hu (j + (m + 4)) (by
                have h₇ : j ≥ i + 1 := by omega
                omega
              )
              have h₇ := h₆.1
              norm_cast at h₇ ⊢
              <;> simp_all [add_assoc]
              <;> ring_nf at *
              <;> norm_num at *
              <;> linarith
            have h₆ : (i + (m + 4) - 1 : ℕ) = i + (m + 3) := by
              omega
            have h₇ : (i + (m + 4) - 2 : ℕ) = i + (m + 2) := by
              omega
            have h₈ : (i + (m + 4) - 3 : ℕ) = i + (m + 1) := by
              omega
            have h₉ : (i + (m + 4) - 4 : ℕ) = i + m := by
              omega
            have h₁₀ : (j + (m + 4) - 1 : ℕ) = j + (m + 3) := by
              omega
            have h₁₁ : (j + (m + 4) - 2 : ℕ) = j + (m + 2) := by
              omega
            have h₁₂ : (j + (m + 4) - 3 : ℕ) = j + (m + 1) := by
              omega
            have h₁₃ : (j + (m + 4) - 4 : ℕ) = j + m := by
              omega
            have h₁₄ : u (i + (m + 3)) = u (j + (m + 3)) := by
              have h₁₅ := ih (m + 3) (by omega)
              simp [add_assoc] at h₁₅ ⊢
              <;> omega
            have h₁₅ : u (i + (m + 2)) = u (j + (m + 2)) := by
              have h₁₆ := ih (m + 2) (by omega)
              simp [add_assoc] at h₁₆ ⊢
              <;> omega
            have h₁₆ : u (i + (m + 1)) = u (j + (m + 1)) := by
              have h₁₇ := ih (m + 1) (by omega)
              simp [add_assoc] at h₁₇ ⊢
              <;> omega
            have h₁₇ : u (i + m) = u (j + m) := by
              have h₁₈ := ih m (by omega)
              simp [add_assoc] at h₁₈ ⊢
              <;> omega
            have h₁₈ : (u (i + (m + 4)) : ℝ) = (u (j + (m + 4)) : ℝ) := by
              rw [h₄, h₅]
              simp [h₆, h₇, h₈, h₉, h₁₀, h₁₁, h₁₂, h₁₃] at *
              norm_cast at *
              <;>
              (try simp_all [h₁₄, h₁₅, h₁₆, h₁₇]) <;>
              (try ring_nf at *) <;>
              (try field_simp at *) <;>
              (try norm_cast at *) <;>
              (try linarith)
            norm_cast at h₁₈ ⊢
            <;>
            (try simp_all) <;>
            (try linarith)
      exact h₂ m
    have h₂ : ∃ N c : ℕ, c > 0 ∧ ∀ n ≥ N, u (n + c) = u n := by
      use i, (j - i)
      have h₃ : j - i > 0 := by
        omega
      constructor
      · exact h₃
      · intro n hn
        have h₄ : u (n + (j - i)) = u n := by
          have h₅ : u (i + (n - i)) = u (j + (n - i)) := by
            have h₆ := h₁ (n - i)
            simp [add_assoc] at h₆ ⊢
            <;> omega
          have h₆ : i + (n - i) = n := by
            omega
          have h₇ : j + (n - i) = n + (j - i) := by
            omega
          rw [h₆] at h₅
          rw [h₇] at h₅
          linarith
        exact h₄
    exact h₂

  exact h_periodic


import Mathlib
import Aesop

set_option maxHeartbeats 0

open Filter Topology Real

theorem putnam_1995_a3
(relation : (Fin 9 → ℤ) → (Fin 9 → ℤ) → Prop)
(digits_to_num : (Fin 9 → ℤ) → ℤ)
(hdigits_to_num : digits_to_num = fun dig => ∑ i : Fin 9, (dig i) * 10^i.1)
(hrelation : ∀ d e : (Fin 9 → ℤ), relation d e ↔ (∀ i : Fin 9, d i < 10 ∧ d i ≥ 0 ∧ e i < 10 ∧ e i ≥ 0) ∧ (∀ i : Fin 9, 7 ∣ (digits_to_num (fun j : Fin 9 => if j = i then e j else d j))))
: ∀ d e f : (Fin 9 → ℤ), ((relation d e) ∧ (relation e f)) → (∀ i : Fin 9, 7 ∣ d i - f i) := by
  have h_main : ∀ (d e f : (Fin 9 → ℤ)), ((relation d e) ∧ (relation e f)) → (∀ i : Fin 9, 7 ∣ d i - f i) := by
    intro d e f h
    have h₁ : relation d e := h.1
    have h₂ : relation e f := h.2
    have h₃ : ∀ (i : Fin 9), 7 ∣ (digits_to_num (fun j : Fin 9 => if j = i then e j else d j)) := by
      have h₄ : (∀ i : Fin 9, 7 ∣ (digits_to_num (fun j : Fin 9 => if j = i then e j else d j))) := (hrelation d e).mp h₁ |>.2
      exact h₄
    have h₄ : ∀ (i : Fin 9), 7 ∣ (digits_to_num (fun j : Fin 9 => if j = i then f j else e j)) := by
      have h₅ : (∀ i : Fin 9, 7 ∣ (digits_to_num (fun j : Fin 9 => if j = i then f j else e j))) := (hrelation e f).mp h₂ |>.2
      exact h₅

    have h₅ : ∀ (i : Fin 9), 7 ∣ (e i - d i) * (10 : ℤ) ^ (i : ℕ) + digits_to_num d := by
      intro i
      have h₆ : 7 ∣ (digits_to_num (fun j : Fin 9 => if j = i then e j else d j)) := h₃ i
      have h₇ : (digits_to_num (fun j : Fin 9 => if j = i then e j else d j)) = digits_to_num d + (e i - d i) * (10 : ℤ) ^ (i : ℕ) := by
        calc
          (digits_to_num (fun j : Fin 9 => if j = i then e j else d j)) = ∑ j : Fin 9, (if j = i then e j else d j) * (10 : ℤ) ^ (j : ℕ) := by
            simp [hdigits_to_num]
            <;>
            rfl
          _ = ∑ j : Fin 9, (if j = i then e j else d j) * (10 : ℤ) ^ (j : ℕ) := rfl
          _ = (∑ j : Fin 9, d j * (10 : ℤ) ^ (j : ℕ)) + (e i - d i) * (10 : ℤ) ^ (i : ℕ) := by
            calc
              (∑ j : Fin 9, (if j = i then e j else d j) * (10 : ℤ) ^ (j : ℕ)) = ∑ j : Fin 9, (d j * (10 : ℤ) ^ (j : ℕ) + (if j = i then (e j - d j) else 0) * (10 : ℤ) ^ (j : ℕ)) := by
                apply Finset.sum_congr rfl
                intro j _
                by_cases h : j = i
                · simp [h]
                  <;> ring
                · simp [h]
                  <;> ring
              _ = (∑ j : Fin 9, d j * (10 : ℤ) ^ (j : ℕ)) + ∑ j : Fin 9, (if j = i then (e j - d j) else 0) * (10 : ℤ) ^ (j : ℕ) := by
                rw [Finset.sum_add_distrib]
              _ = (∑ j : Fin 9, d j * (10 : ℤ) ^ (j : ℕ)) + (e i - d i) * (10 : ℤ) ^ (i : ℕ) := by
                have h₈ : ∑ j : Fin 9, (if j = i then (e j - d j) else 0) * (10 : ℤ) ^ (j : ℕ) = (e i - d i) * (10 : ℤ) ^ (i : ℕ) := by
                  calc
                    _ = ∑ j : Fin 9, (if j = i then (e j - d j) else 0) * (10 : ℤ) ^ (j : ℕ) := rfl
                    _ = (if i = i then (e i - d i) else 0) * (10 : ℤ) ^ (i : ℕ) := by

                      simp [Finset.sum_ite_eq', Finset.mem_univ, i.is_lt]
                    _ = (e i - d i) * (10 : ℤ) ^ (i : ℕ) := by simp
                rw [h₈]
                <;> simp [hdigits_to_num]
                <;>
                rfl
          _ = digits_to_num d + (e i - d i) * (10 : ℤ) ^ (i : ℕ) := by
            simp [hdigits_to_num]
            <;>
            rfl
      have h₈ : 7 ∣ digits_to_num d + (e i - d i) * (10 : ℤ) ^ (i : ℕ) := by
        rw [h₇] at h₆
        exact h₆

      have h₉ : 7 ∣ (e i - d i) * (10 : ℤ) ^ (i : ℕ) + digits_to_num d := by

        have h₁₀ : (e i - d i) * (10 : ℤ) ^ (i : ℕ) + digits_to_num d = digits_to_num d + (e i - d i) * (10 : ℤ) ^ (i : ℕ) := by ring
        rw [h₁₀]
        exact h₈
      exact h₉

    have h₆ : ∀ (i : Fin 9), 7 ∣ (f i - e i) * (10 : ℤ) ^ (i : ℕ) + digits_to_num e := by
      intro i
      have h₇ : 7 ∣ (digits_to_num (fun j : Fin 9 => if j = i then f j else e j)) := h₄ i
      have h₈ : (digits_to_num (fun j : Fin 9 => if j = i then f j else e j)) = digits_to_num e + (f i - e i) * (10 : ℤ) ^ (i : ℕ) := by
        calc
          (digits_to_num (fun j : Fin 9 => if j = i then f j else e j)) = ∑ j : Fin 9, (if j = i then f j else e j) * (10 : ℤ) ^ (j : ℕ) := by
            simp [hdigits_to_num]
            <;>
            rfl
          _ = ∑ j : Fin 9, (if j = i then f j else e j) * (10 : ℤ) ^ (j : ℕ) := rfl
          _ = (∑ j : Fin 9, e j * (10 : ℤ) ^ (j : ℕ)) + (f i - e i) * (10 : ℤ) ^ (i : ℕ) := by
            calc
              (∑ j : Fin 9, (if j = i then f j else e j) * (10 : ℤ) ^ (j : ℕ)) = ∑ j : Fin 9, (e j * (10 : ℤ) ^ (j : ℕ) + (if j = i then (f j - e j) else 0) * (10 : ℤ) ^ (j : ℕ)) := by
                apply Finset.sum_congr rfl
                intro j _
                by_cases h : j = i
                · simp [h]
                  <;> ring
                · simp [h]
                  <;> ring
              _ = (∑ j : Fin 9, e j * (10 : ℤ) ^ (j : ℕ)) + ∑ j : Fin 9, (if j = i then (f j - e j) else 0) * (10 : ℤ) ^ (j : ℕ) := by
                rw [Finset.sum_add_distrib]
              _ = (∑ j : Fin 9, e j * (10 : ℤ) ^ (j : ℕ)) + (f i - e i) * (10 : ℤ) ^ (i : ℕ) := by
                have h₉ : ∑ j : Fin 9, (if j = i then (f j - e j) else 0) * (10 : ℤ) ^ (j : ℕ) = (f i - e i) * (10 : ℤ) ^ (i : ℕ) := by
                  calc
                    _ = ∑ j : Fin 9, (if j = i then (f j - e j) else 0) * (10 : ℤ) ^ (j : ℕ) := rfl
                    _ = (if i = i then (f i - e i) else 0) * (10 : ℤ) ^ (i : ℕ) := by

                      simp [Finset.sum_ite_eq', Finset.mem_univ, i.is_lt]
                    _ = (f i - e i) * (10 : ℤ) ^ (i : ℕ) := by simp
                rw [h₉]
                <;> simp [hdigits_to_num]
                <;>
                rfl
          _ = digits_to_num e + (f i - e i) * (10 : ℤ) ^ (i : ℕ) := by
            simp [hdigits_to_num]
            <;>
            rfl
      have h₉ : 7 ∣ digits_to_num e + (f i - e i) * (10 : ℤ) ^ (i : ℕ) := by
        rw [h₈] at h₇
        exact h₇

      have h₁₀ : 7 ∣ (f i - e i) * (10 : ℤ) ^ (i : ℕ) + digits_to_num e := by

        have h₁₁ : (f i - e i) * (10 : ℤ) ^ (i : ℕ) + digits_to_num e = digits_to_num e + (f i - e i) * (10 : ℤ) ^ (i : ℕ) := by ring
        rw [h₁₁]
        exact h₉
      exact h₁₀

    have h₇ : 7 ∣ digits_to_num e + digits_to_num d := by
      have h₈ : digits_to_num e = digits_to_num d + ∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ) := by
        calc
          digits_to_num e = ∑ i : Fin 9, e i * (10 : ℤ) ^ (i : ℕ) := by simp [hdigits_to_num]
          _ = ∑ i : Fin 9, (d i + (e i - d i)) * (10 : ℤ) ^ (i : ℕ) := by
            apply Finset.sum_congr rfl
            intro i _
            ring
          _ = ∑ i : Fin 9, (d i * (10 : ℤ) ^ (i : ℕ) + (e i - d i) * (10 : ℤ) ^ (i : ℕ)) := by
            apply Finset.sum_congr rfl
            intro i _
            ring
          _ = (∑ i : Fin 9, d i * (10 : ℤ) ^ (i : ℕ)) + ∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ) := by
            rw [Finset.sum_add_distrib]
          _ = digits_to_num d + ∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ) := by
            simp [hdigits_to_num]
            <;>
            rfl
      have h₉ : ∀ i : Fin 9, 7 ∣ (e i - d i) * (10 : ℤ) ^ (i : ℕ) + digits_to_num d := h₅
      have h₁₀ : 7 ∣ ∑ i : Fin 9, ((e i - d i) * (10 : ℤ) ^ (i : ℕ) + digits_to_num d) := by
        apply Finset.dvd_sum
        intro i _
        exact h₉ i
      have h₁₁ : ∑ i : Fin 9, ((e i - d i) * (10 : ℤ) ^ (i : ℕ) + digits_to_num d) = ∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ) + 9 * digits_to_num d := by
        calc
          ∑ i : Fin 9, ((e i - d i) * (10 : ℤ) ^ (i : ℕ) + digits_to_num d) = ∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ) + ∑ i : Fin 9, digits_to_num d := by
            rw [Finset.sum_add_distrib]
          _ = ∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ) + 9 * digits_to_num d := by
            simp [Finset.sum_const, Finset.card_fin]
            <;> ring
            <;> norm_num
      have h₁₂ : 7 ∣ ∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ) + 9 * digits_to_num d := by
        rw [h₁₁] at h₁₀
        exact h₁₀
      have h₁₃ : 7 ∣ digits_to_num e + digits_to_num d := by
        have h₁₄ : digits_to_num e + digits_to_num d = 2 * digits_to_num d + ∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ) := by
          linarith
        rw [h₁₄]
        have h₁₅ : 7 ∣ 2 * digits_to_num d + ∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ) := by
          have h₁₆ : 7 ∣ ∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ) + 9 * digits_to_num d := h₁₂
          have h₁₇ : 7 ∣ 2 * digits_to_num d + ∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ) := by

            have h₁₈ : (∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ) + 9 * digits_to_num d) = (∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ)) + 9 * digits_to_num d := by ring
            rw [h₁₈] at h₁₆

            have h₁₉ : 7 ∣ (∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ)) + 2 * digits_to_num d := by

              have h₂₀ : 7 ∣ (∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ)) + 9 * digits_to_num d := h₁₆
              have h₂₁ : 7 ∣ 7 * digits_to_num d := by
                use digits_to_num d
                <;> ring
              have h₂₂ : 7 ∣ (∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ)) + 2 * digits_to_num d := by

                have h₂₃ : (∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ)) + 2 * digits_to_num d = ((∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ)) + 9 * digits_to_num d) - 7 * digits_to_num d := by ring
                rw [h₂₃]
                exact dvd_sub h₂₀ h₂₁
              exact h₂₂

            have h₂₀ : 7 ∣ 2 * digits_to_num d + ∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ) := by

              have h₂₁ : 2 * digits_to_num d + ∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ) = (∑ i : Fin 9, (e i - d i) * (10 : ℤ) ^ (i : ℕ)) + 2 * digits_to_num d := by ring
              rw [h₂₁]
              exact h₁₉
            exact h₂₀
          exact h₁₇
        exact h₁₅
      exact h₁₃

    have h₈ : ∀ (i : Fin 9), 7 ∣ (f i - d i) * (10 : ℤ) ^ (i : ℕ) := by
      intro i
      have h₉ : 7 ∣ (f i - e i) * (10 : ℤ) ^ (i : ℕ) + digits_to_num e := h₆ i
      have h₁₀ : 7 ∣ (e i - d i) * (10 : ℤ) ^ (i : ℕ) + digits_to_num d := h₅ i
      have h₁₁ : 7 ∣ digits_to_num e + digits_to_num d := h₇

      have h₁₂ : 7 ∣ (f i - e i) * (10 : ℤ) ^ (i : ℕ) - digits_to_num d := by

        have h₁₃ : 7 ∣ (f i - e i) * (10 : ℤ) ^ (i : ℕ) + digits_to_num e := h₆ i
        have h₁₄ : 7 ∣ digits_to_num e + digits_to_num d := h₇

        have h₁₅ : 7 ∣ ((f i - e i) * (10 : ℤ) ^ (i : ℕ) + digits_to_num e) - (digits_to_num e + digits_to_num d) := by
          exact dvd_sub h₁₃ h₁₄

        have h₁₆ : ((f i - e i) * (10 : ℤ) ^ (i : ℕ) + digits_to_num e) - (digits_to_num e + digits_to_num d) = (f i - e i) * (10 : ℤ) ^ (i : ℕ) - digits_to_num d := by
          ring
        rw [h₁₆] at h₁₅
        exact h₁₅

      have h₁₃ : 7 ∣ (f i - d i) * (10 : ℤ) ^ (i : ℕ) := by
        have h₁₄ : 7 ∣ (f i - e i) * (10 : ℤ) ^ (i : ℕ) - digits_to_num d := h₁₂
        have h₁₅ : 7 ∣ (e i - d i) * (10 : ℤ) ^ (i : ℕ) + digits_to_num d := h₅ i

        have h₁₆ : 7 ∣ ((f i - e i) * (10 : ℤ) ^ (i : ℕ) - digits_to_num d) + ((e i - d i) * (10 : ℤ) ^ (i : ℕ) + digits_to_num d) := by
          exact dvd_add h₁₄ h₁₅

        have h₁₇ : ((f i - e i) * (10 : ℤ) ^ (i : ℕ) - digits_to_num d) + ((e i - d i) * (10 : ℤ) ^ (i : ℕ) + digits_to_num d) = (f i - d i) * (10 : ℤ) ^ (i : ℕ) := by
          ring
        rw [h₁₇] at h₁₆
        exact h₁₆
      exact h₁₃

    have h₉ : ∀ (i : Fin 9), 7 ∣ d i - f i := by
      intro i
      have h₁₀ : 7 ∣ (f i - d i) * (10 : ℤ) ^ (i : ℕ) := h₈ i
      have h₁₁ : 7 ∣ (f i - d i) := by

        have h₁₂ : (7 : ℤ) ∣ (f i - d i) * (10 : ℤ) ^ (i : ℕ) := h₁₀

        have h₁₃ : (7 : ℕ).Prime := by decide
        have h₁₄ : ¬(7 : ℤ) ∣ (10 : ℤ) ^ (i : ℕ) := by

          intro h
          have h₁₅ : (7 : ℕ) ∣ (10 : ℕ) ^ (i : ℕ) := by
            norm_cast at h ⊢
            <;> simpa [Int.coe_nat_dvd_left] using h
          have h₁₆ : (7 : ℕ) ∣ 10 := by

            exact Nat.Prime.dvd_of_dvd_pow h₁₃ h₁₅
          norm_num at h₁₆
          <;> contradiction

        have h₁₅ : (7 : ℤ) ∣ (f i - d i) := by

          have h₁₆ : (7 : ℤ) ∣ (f i - d i) * (10 : ℤ) ^ (i : ℕ) := h₁₂
          have h₁₇ : ¬(7 : ℤ) ∣ (10 : ℤ) ^ (i : ℕ) := h₁₄

          have h₁₈ : (7 : ℤ) ∣ (f i - d i) := by

            have h₁₉ : (7 : ℤ) ∣ (f i - d i) * (10 : ℤ) ^ (i : ℕ) := h₁₂
            have h₂₀ : (7 : ℕ).Prime := by decide
            have h₂₁ : (7 : ℤ) ∣ (f i - d i) ∨ (7 : ℤ) ∣ (10 : ℤ) ^ (i : ℕ) := by

              have h₂₂ : (7 : ℤ) ∣ (f i - d i) * (10 : ℤ) ^ (i : ℕ) := h₁₂
              have h₂₃ : (7 : ℤ) ∣ (f i - d i) ∨ (7 : ℤ) ∣ (10 : ℤ) ^ (i : ℕ) := by

                apply (Int.prime_iff_natAbs_prime.mpr (by decide)).dvd_mul.mp
                exact h₂₂
              exact h₂₃
            cases h₂₁ with
            | inl h₂₁ =>
              exact h₂₁
            | inr h₂₁ =>
              exfalso
              exact h₁₄ h₂₁
          exact h₁₈
        exact h₁₅

      have h₁₂ : 7 ∣ d i - f i := by
        have h₁₃ : 7 ∣ (f i - d i) := h₁₁
        have h₁₄ : 7 ∣ -(f i - d i) := by
          exact dvd_neg.mpr h₁₃
        have h₁₅ : -(f i - d i) = d i - f i := by ring
        rw [h₁₅] at h₁₄
        exact h₁₄
      exact h₁₂

    intro i
    have h₁₀ : 7 ∣ d i - f i := h₉ i
    exact h₁₀
  exact h_main


import Mathlib
import Aesop

set_option maxHeartbeats 0

open Set

theorem putnam_1988_a2
    (f : ℝ → ℝ)
    (hf : f = fun x ↦ Real.exp (x ^ 2)) :
    ((True) : Prop ) ↔
    (∃ a b : ℝ,
      a < b ∧
      ∃ g : ℝ → ℝ,
        (∃ x ∈ Ioo a b, g x ≠ 0) ∧
        DifferentiableOn ℝ g (Ioo a b) ∧
        ∀ x ∈ Ioo a b, deriv (fun y ↦ f y * g y) x = (deriv f x) * (deriv g x)) :=
  by
  have h_main : (∃ (a b : ℝ), a < b ∧ ∃ (g : ℝ → ℝ), (∃ x ∈ Set.Ioo a b, g x ≠ 0) ∧ DifferentiableOn ℝ g (Set.Ioo a b) ∧ ∀ x ∈ Set.Ioo a b, deriv (fun y ↦ f y * g y) x = (deriv f x) * (deriv g x)) := by
    use 1, 2
    constructor
    · norm_num
    ·
      use fun x => Real.exp x * Real.sqrt (2 * x - 1)
      constructor
      ·
        use 3 / 2
        constructor
        ·
          norm_num [Set.mem_Ioo]
        ·
          have h₁ : Real.exp (3 / 2 : ℝ) > 0 := Real.exp_pos _
          have h₂ : Real.sqrt (2 * (3 / 2 : ℝ) - 1) > 0 := by
            apply Real.sqrt_pos_of_pos
            norm_num
          have h₃ : Real.exp (3 / 2 : ℝ) * Real.sqrt (2 * (3 / 2 : ℝ) - 1) > 0 := by positivity
          intro h₄
          linarith
      · constructor
        ·
          have h₁ : DifferentiableOn ℝ (fun x : ℝ => Real.exp x * Real.sqrt (2 * x - 1)) (Set.Ioo 1 2) := by
            apply DifferentiableOn.mul
            · exact DifferentiableOn.exp (differentiableOn_id)
            · apply DifferentiableOn.sqrt
              ·
                have h₂ : DifferentiableOn ℝ (fun x : ℝ => (2 : ℝ) * x - 1) (Set.Ioo 1 2) := by
                  apply DifferentiableOn.sub
                  · apply DifferentiableOn.const_mul
                    exact differentiableOn_id
                  · exact differentiableOn_const _
                exact h₂
              ·
                intro x hx
                have h₃ : 1 < x := hx.1
                have h₄ : x < 2 := hx.2
                have h₅ : (2 : ℝ) * x - 1 > 0 := by linarith
                linarith
          exact h₁
        ·
          intro x hx
          have h₁ : x ∈ Set.Ioo 1 2 := hx
          have h₂ : 1 < x := h₁.1
          have h₃ : x < 2 := h₁.2
          have h₄ : (2 : ℝ) * x - 1 > 0 := by linarith
          have h₅ : Real.sqrt (2 * x - 1) > 0 := Real.sqrt_pos.mpr h₄
          have h₆ : HasDerivAt (fun x : ℝ => Real.exp x * Real.sqrt (2 * x - 1)) (Real.exp x * Real.sqrt (2 * x - 1) + Real.exp x / Real.sqrt (2 * x - 1)) x := by

            have h₇ : HasDerivAt (fun x : ℝ => Real.exp x) (Real.exp x) x := Real.hasDerivAt_exp x
            have h₈ : HasDerivAt (fun x : ℝ => Real.sqrt (2 * x - 1)) (1 / Real.sqrt (2 * x - 1)) x := by
              have h₉ : HasDerivAt (fun x : ℝ => (2 : ℝ) * x - 1) 2 x := by
                simpa using (hasDerivAt_id x).const_mul 2 |>.sub_const 1
              have h₁₀ : HasDerivAt (fun x : ℝ => Real.sqrt (2 * x - 1)) (1 / Real.sqrt (2 * x - 1)) x := by
                convert HasDerivAt.sqrt h₉ (by positivity) using 1 <;>
                  field_simp [h₄.ne'] <;>
                  ring_nf <;>
                  field_simp [h₄.ne'] <;>
                  ring
              exact h₁₀
            have h₁₁ : HasDerivAt (fun x : ℝ => Real.exp x * Real.sqrt (2 * x - 1)) (Real.exp x * Real.sqrt (2 * x - 1) + Real.exp x / Real.sqrt (2 * x - 1)) x := by
              convert h₇.mul h₈ using 1 <;>
                field_simp [h₄.ne'] <;>
                ring_nf <;>
                field_simp [h₄.ne'] <;>
                ring
            exact h₁₁
          have h₇ : deriv (fun x : ℝ => Real.exp x * Real.sqrt (2 * x - 1)) x = Real.exp x * Real.sqrt (2 * x - 1) + Real.exp x / Real.sqrt (2 * x - 1) := by
            apply HasDerivAt.deriv
            exact h₆

          have h₈ : f = fun x => Real.exp (x ^ 2) := hf
          have h₉ : deriv f x = 2 * x * Real.exp (x ^ 2) := by
            rw [h₈]

            have h₁₀ : HasDerivAt (fun x : ℝ => Real.exp (x ^ 2)) (2 * x * Real.exp (x ^ 2)) x := by
              have h₁₁ : HasDerivAt (fun x : ℝ => x ^ 2) (2 * x) x := by
                simpa using (hasDerivAt_pow 2 x)
              have h₁₂ : HasDerivAt (fun x : ℝ => Real.exp (x ^ 2)) (Real.exp (x ^ 2) * (2 * x)) x := by
                apply HasDerivAt.exp
                exact h₁₁
              convert h₁₂ using 1 <;> ring
            have h₁₃ : deriv (fun x : ℝ => Real.exp (x ^ 2)) x = 2 * x * Real.exp (x ^ 2) := by
              apply HasDerivAt.deriv
              exact h₁₀
            exact h₁₃
          have h₁₀ : deriv (fun y : ℝ => f y * (Real.exp y * Real.sqrt (2 * y - 1))) x = (deriv f x) * (deriv (fun y : ℝ => Real.exp y * Real.sqrt (2 * y - 1)) x) := by

            have h₁₁ : deriv (fun y : ℝ => f y * (Real.exp y * Real.sqrt (2 * y - 1))) x = deriv f x * (Real.exp x * Real.sqrt (2 * x - 1)) + f x * (Real.exp x * Real.sqrt (2 * x - 1) + Real.exp x / Real.sqrt (2 * x - 1)) := by

              have h₁₂ : HasDerivAt (fun y : ℝ => f y * (Real.exp y * Real.sqrt (2 * y - 1))) (deriv f x * (Real.exp x * Real.sqrt (2 * x - 1)) + f x * (Real.exp x * Real.sqrt (2 * x - 1) + Real.exp x / Real.sqrt (2 * x - 1))) x := by
                have h₁₃ : HasDerivAt f (deriv f x) x := by
                  have h₁₄ : DifferentiableAt ℝ f x := by
                    rw [h₈]
                    apply DifferentiableAt.exp
                    apply DifferentiableAt.pow
                    exact differentiableAt_id
                  exact h₁₄.hasDerivAt
                have h₁₄ : HasDerivAt (fun y : ℝ => Real.exp y * Real.sqrt (2 * y - 1)) (Real.exp x * Real.sqrt (2 * x - 1) + Real.exp x / Real.sqrt (2 * x - 1)) x := by
                  convert h₆ using 1
                have h₁₅ : HasDerivAt (fun y : ℝ => f y * (Real.exp y * Real.sqrt (2 * y - 1))) (deriv f x * (Real.exp x * Real.sqrt (2 * x - 1)) + f x * (Real.exp x * Real.sqrt (2 * x - 1) + Real.exp x / Real.sqrt (2 * x - 1))) x := by
                  convert h₁₃.mul h₁₄ using 1 <;>
                    simp [h₉, h₈, mul_assoc]
                  <;>
                  ring_nf
                  <;>
                  field_simp [h₄.ne']
                  <;>
                  ring
                exact h₁₅
              have h₁₆ : deriv (fun y : ℝ => f y * (Real.exp y * Real.sqrt (2 * y - 1))) x = deriv f x * (Real.exp x * Real.sqrt (2 * x - 1)) + f x * (Real.exp x * Real.sqrt (2 * x - 1) + Real.exp x / Real.sqrt (2 * x - 1)) := by
                apply HasDerivAt.deriv
                exact h₁₂
              exact h₁₆
            have h₁₇ : deriv f x * (Real.exp x * Real.sqrt (2 * x - 1)) + f x * (Real.exp x * Real.sqrt (2 * x - 1) + Real.exp x / Real.sqrt (2 * x - 1)) = (deriv f x) * (deriv (fun y : ℝ => Real.exp y * Real.sqrt (2 * y - 1)) x) := by

              have h₁₈ : deriv f x = 2 * x * Real.exp (x ^ 2) := h₉
              have h₁₉ : f x = Real.exp (x ^ 2) := by
                rw [h₈]
                <;> simp
              have h₂₀ : deriv (fun y : ℝ => Real.exp y * Real.sqrt (2 * y - 1)) x = Real.exp x * Real.sqrt (2 * x - 1) + Real.exp x / Real.sqrt (2 * x - 1) := h₇
              have h₂₁ : 2 * x * (Real.exp x * Real.sqrt (2 * x - 1)) + (Real.exp x * Real.sqrt (2 * x - 1) + Real.exp x / Real.sqrt (2 * x - 1)) = 2 * x * (Real.exp x * Real.sqrt (2 * x - 1) + Real.exp x / Real.sqrt (2 * x - 1)) := by

                have h₂₂ : Real.exp x > 0 := Real.exp_pos x
                have h₂₃ : Real.sqrt (2 * x - 1) > 0 := Real.sqrt_pos.mpr (by linarith)
                field_simp [h₂₃.ne', h₂₂.ne']
                <;>
                nlinarith [Real.sq_sqrt (show 0 ≤ 2 * x - 1 by linarith)]
              calc
                deriv f x * (Real.exp x * Real.sqrt (2 * x - 1)) + f x * (Real.exp x * Real.sqrt (2 * x - 1) + Real.exp x / Real.sqrt (2 * x - 1)) = (2 * x * Real.exp (x ^ 2)) * (Real.exp x * Real.sqrt (2 * x - 1)) + Real.exp (x ^ 2) * (Real.exp x * Real.sqrt (2 * x - 1) + Real.exp x / Real.sqrt (2 * x - 1)) := by
                  rw [h₁₈, h₁₉]
                _ = Real.exp (x ^ 2) * (2 * x * (Real.exp x * Real.sqrt (2 * x - 1)) + (Real.exp x * Real.sqrt (2 * x - 1) + Real.exp x / Real.sqrt (2 * x - 1))) := by
                  ring_nf
                  <;>
                  field_simp [Real.exp_ne_zero]
                  <;>
                  ring_nf
                _ = Real.exp (x ^ 2) * (2 * x * (Real.exp x * Real.sqrt (2 * x - 1) + Real.exp x / Real.sqrt (2 * x - 1))) := by
                  rw [h₂₁]
                  <;>
                  ring_nf
                _ = (2 * x * Real.exp (x ^ 2)) * (Real.exp x * Real.sqrt (2 * x - 1) + Real.exp x / Real.sqrt (2 * x - 1)) := by
                  ring_nf
                _ = (deriv f x) * (deriv (fun y : ℝ => Real.exp y * Real.sqrt (2 * y - 1)) x) := by
                  rw [h₁₈, h₂₀]
                  <;>
                  ring_nf
                  <;>
                  field_simp [Real.exp_ne_zero]
                  <;>
                  ring_nf
            rw [h₁₁]
            rw [h₁₇]

          have h₁₁ : deriv (fun y : ℝ => f y * (Real.exp y * Real.sqrt (2 * y - 1))) x = (deriv f x) * (deriv (fun y : ℝ => Real.exp y * Real.sqrt (2 * y - 1)) x) := h₁₀
          simpa [h₈] using h₁₁

  have h_final : ((True) : Prop ) ↔ (∃ a b : ℝ, a < b ∧ ∃ g : ℝ → ℝ, (∃ x ∈ Set.Ioo a b, g x ≠ 0) ∧ DifferentiableOn ℝ g (Set.Ioo a b) ∧ ∀ x ∈ Set.Ioo a b, deriv (fun y ↦ f y * g y) x = (deriv f x) * (deriv g x)) := by
    constructor
    · intro _
      exact h_main
    · intro h
      trivial

  exact h_final


import Mathlib
import Aesop

set_option maxHeartbeats 0

open Topology Filter Polynomial Set

theorem putnam_2001_b1
  (n : ℕ)
  (hn : n > 0) (hn' : Even n)
  (nums : Fin n → Fin n → ℤ)
  (colors : Fin n → Fin n → Fin 2)
  (hnums : ∀ k l, nums k l = k * n + l + 1)
  (hcolorsrows : ∀ k, (∑ l, (if (colors k l = 0) then 1 else 0)) = n / 2)
  (hcolorscols : ∀ l, (∑ k, (if (colors k l = 0) then 1 else 0)) = n / 2) :
  (∑ k, ∑ l, (if (colors k l = 0) then (nums k l) else 0)) = (∑ k, ∑ l, (if (colors k l = 1) then (nums k l) else 0)) := by
  have hrow_sum_zero : ∀ (k : Fin n), (∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1)) = 0 := by
    intro k
    have h1 : (∑ l : Fin n, (if colors k l = 0 then (1 : ℤ) else 0)) = n / 2 := by
      norm_cast at hcolorsrows ⊢
      simpa using hcolorsrows k
    have h2 : (∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1)) = 0 := by
      calc
        (∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1)) = (∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0))) - ∑ l : Fin n, (1 : ℤ) := by
          rw [Finset.sum_sub_distrib]
        _ = 2 * (∑ l : Fin n, (if colors k l = 0 then (1 : ℤ) else 0)) - ∑ l : Fin n, (1 : ℤ) := by
          rw [Finset.mul_sum]
        _ = 2 * (n / 2 : ℤ) - n := by
          rw [h1]
          simp [Finset.sum_const, Finset.card_fin]
          <;> norm_cast
          <;> simp [nsmul_eq_mul]
          <;> ring_nf
          <;> simp_all [Nat.cast_inj]
          <;> omega
        _ = 0 := by
          have h3 : (n : ℤ) % 2 = 0 := by
            have h4 : Even n := hn'
            rw [even_iff_two_dvd] at h4
            obtain ⟨m, hm⟩ := h4
            norm_cast at hm ⊢
            omega
          have h4 : (n : ℤ) / 2 * 2 = n := by
            have h5 : (n : ℤ) % 2 = 0 := h3
            have h6 : (n : ℤ) = 2 * ((n : ℤ) / 2) := by
              omega
            linarith
          ring_nf at *
          <;> omega
    exact h2

  have hcol_sum_zero : ∀ (l : Fin n), (∑ k : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1)) = 0 := by
    intro l
    have h1 : (∑ k : Fin n, (if colors k l = 0 then (1 : ℤ) else 0)) = n / 2 := by
      norm_cast at hcolorscols ⊢
      simpa using hcolorscols l
    have h2 : (∑ k : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1)) = 0 := by
      calc
        (∑ k : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1)) = (∑ k : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0))) - ∑ k : Fin n, (1 : ℤ) := by
          rw [Finset.sum_sub_distrib]
        _ = 2 * (∑ k : Fin n, (if colors k l = 0 then (1 : ℤ) else 0)) - ∑ k : Fin n, (1 : ℤ) := by
          rw [Finset.mul_sum]
        _ = 2 * (n / 2 : ℤ) - n := by
          rw [h1]
          simp [Finset.sum_const, Finset.card_fin]
          <;> norm_cast
          <;> simp [nsmul_eq_mul]
          <;> ring_nf
          <;> simp_all [Nat.cast_inj]
          <;> omega
        _ = 0 := by
          have h3 : (n : ℤ) % 2 = 0 := by
            have h4 : Even n := hn'
            rw [even_iff_two_dvd] at h4
            obtain ⟨m, hm⟩ := h4
            norm_cast at hm ⊢
            omega
          have h4 : (n : ℤ) / 2 * 2 = n := by
            have h5 : (n : ℤ) % 2 = 0 := h3
            have h6 : (n : ℤ) = 2 * ((n : ℤ) / 2) := by
              omega
            linarith
          ring_nf at *
          <;> omega
    exact h2

  have hsum_diff : (∑ k : Fin n, ∑ l : Fin n, (if colors k l = 0 then (nums k l : ℤ) else 0)) - (∑ k : Fin n, ∑ l : Fin n, (if colors k l = 1 then (nums k l : ℤ) else 0)) = ∑ k : Fin n, ∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * (nums k l : ℤ) := by
    have h₁ : (∑ k : Fin n, ∑ l : Fin n, (if colors k l = 0 then (nums k l : ℤ) else 0)) - (∑ k : Fin n, ∑ l : Fin n, (if colors k l = 1 then (nums k l : ℤ) else 0)) = ∑ k : Fin n, ∑ l : Fin n, ((if colors k l = 0 then (nums k l : ℤ) else 0) - (if colors k l = 1 then (nums k l : ℤ) else 0)) := by
      simp [Finset.sum_sub_distrib, Finset.sum_add_distrib]
      <;>
      simp_all [Finset.sum_sub_distrib]
      <;>
      rfl
    have h₂ : ∀ (k : Fin n) (l : Fin n), ((if colors k l = 0 then (nums k l : ℤ) else 0) - (if colors k l = 1 then (nums k l : ℤ) else 0)) = (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * (nums k l : ℤ) := by
      intro k l
      have h₃ : colors k l = 0 ∨ colors k l = 1 := by
        have h₄ : colors k l = 0 ∨ colors k l = 1 := by
          have h₅ : colors k l = 0 ∨ colors k l = 1 := by
            have : colors k l = 0 ∨ colors k l = 1 := by
              have h₆ : (colors k l : ℕ) < 2 := by
                have : (colors k l : ℕ) < 2 := by
                  simp [Fin.is_lt]
                exact this
              omega
            exact this
          exact h₅
        exact h₄
      rcases h₃ with (h₃ | h₃)
      ·
        simp [h₃]
        <;>
        (try norm_num) <;>
        (try ring_nf) <;>
        (try simp_all)
        <;>
        (try omega)
      ·
        simp [h₃]
        <;>
        (try norm_num) <;>
        (try ring_nf) <;>
        (try simp_all)
        <;>
        (try omega)
    calc
      (∑ k : Fin n, ∑ l : Fin n, (if colors k l = 0 then (nums k l : ℤ) else 0)) - (∑ k : Fin n, ∑ l : Fin n, (if colors k l = 1 then (nums k l : ℤ) else 0)) = ∑ k : Fin n, ∑ l : Fin n, ((if colors k l = 0 then (nums k l : ℤ) else 0) - (if colors k l = 1 then (nums k l : ℤ) else 0)) := by rw [h₁]
      _ = ∑ k : Fin n, ∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * (nums k l : ℤ) := by
        apply Finset.sum_congr rfl
        intro k _
        apply Finset.sum_congr rfl
        intro l _
        rw [h₂ k l]

  have hsum_split_zero : (∑ k : Fin n, ∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * (nums k l : ℤ)) = 0 := by
    have h₁ : (∑ k : Fin n, ∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * (nums k l : ℤ)) = ∑ k : Fin n, ∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * ((k : ℤ) * n + (l : ℤ) + 1) := by
      apply Finset.sum_congr rfl
      intro k _
      apply Finset.sum_congr rfl
      intro l _
      rw [hnums]
      <;> simp [Fin.val_mk]
      <;> norm_cast
      <;> ring_nf
    rw [h₁]
    have h₂ : (∑ k : Fin n, ∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * ((k : ℤ) * n + (l : ℤ) + 1)) = (∑ k : Fin n, ∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * ((k : ℤ) * n)) + (∑ k : Fin n, ∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * ((l : ℤ) + 1)) := by
      calc
        (∑ k : Fin n, ∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * ((k : ℤ) * n + (l : ℤ) + 1)) = ∑ k : Fin n, ∑ l : Fin n, ((2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * ((k : ℤ) * n) + (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * ((l : ℤ) + 1)) := by
          apply Finset.sum_congr rfl
          intro k _
          apply Finset.sum_congr rfl
          intro l _
          ring_nf
        _ = (∑ k : Fin n, ∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * ((k : ℤ) * n)) + (∑ k : Fin n, ∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * ((l : ℤ) + 1)) := by
          simp [Finset.sum_add_distrib]
    rw [h₂]
    have h₃ : (∑ k : Fin n, ∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * ((k : ℤ) * n)) = 0 := by
      have h₄ : ∀ (k : Fin n), (∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * ((k : ℤ) * n)) = 0 := by
        intro k
        have h₅ : (∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1)) = 0 := hrow_sum_zero k
        calc
          (∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * ((k : ℤ) * n)) = ∑ l : Fin n, ((k : ℤ) * n) * (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) := by
            apply Finset.sum_congr rfl
            intro l _
            ring_nf
          _ = ((k : ℤ) * n) * ∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) := by
            rw [Finset.mul_sum]
          _ = ((k : ℤ) * n) * 0 := by rw [h₅]
          _ = 0 := by ring
      calc
        (∑ k : Fin n, ∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * ((k : ℤ) * n)) = ∑ k : Fin n, (∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * ((k : ℤ) * n)) := by simp [Finset.sum_sigma']
        _ = ∑ k : Fin n, 0 := by
          apply Finset.sum_congr rfl
          intro k _
          rw [h₄ k]
        _ = 0 := by simp
    have h₄ : (∑ k : Fin n, ∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * ((l : ℤ) + 1)) = 0 := by
      have h₅ : ∀ (l : Fin n), (∑ k : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1)) = 0 := by
        intro l
        exact hcol_sum_zero l
      calc
        (∑ k : Fin n, ∑ l : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * ((l : ℤ) + 1)) = ∑ l : Fin n, ∑ k : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * ((l : ℤ) + 1) := by
          rw [Finset.sum_comm]
        _ = ∑ l : Fin n, ((l : ℤ) + 1) * (∑ k : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1)) := by
          apply Finset.sum_congr rfl
          intro l _
          calc
            (∑ k : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) * ((l : ℤ) + 1)) = ∑ k : Fin n, ((l : ℤ) + 1) * (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) := by
              apply Finset.sum_congr rfl
              intro k _
              ring_nf
            _ = ((l : ℤ) + 1) * ∑ k : Fin n, (2 * (if colors k l = 0 then (1 : ℤ) else 0) - 1) := by
              rw [Finset.mul_sum]
        _ = ∑ l : Fin n, ((l : ℤ) + 1) * 0 := by
          apply Finset.sum_congr rfl
          intro l _
          rw [h₅ l]
        _ = ∑ l : Fin n, 0 := by
          apply Finset.sum_congr rfl
          intro l _
          ring_nf
        _ = 0 := by simp
    rw [h₃, h₄]
    <;> simp

  have hfinal : (∑ k, ∑ l, (if (colors k l = 0) then (nums k l) else 0)) = (∑ k, ∑ l, (if (colors k l = 1) then (nums k l) else 0)) := by
    have h₁ : (∑ k : Fin n, ∑ l : Fin n, (if colors k l = 0 then (nums k l : ℤ) else 0)) - (∑ k : Fin n, ∑ l : Fin n, (if colors k l = 1 then (nums k l : ℤ) else 0)) = 0 := by
      rw [hsum_diff]
      rw [hsum_split_zero]
    have h₂ : (∑ k : Fin n, ∑ l : Fin n, (if colors k l = 0 then (nums k l : ℤ) else 0)) = (∑ k : Fin n, ∑ l : Fin n, (if colors k l = 1 then (nums k l : ℤ) else 0)) := by
      linarith
    simpa using h₂

  exact hfinal


import Mathlib
import Aesop

set_option maxHeartbeats 0

open Set Function Filter Topology

theorem putnam_1964_b2
(S : Type*) [Fintype S] [Nonempty S]
(P : Finset (Set S))
(hPP : ∀ T ∈ P, ∀ U ∈ P, T ∩ U ≠ ∅)
(hPS : ¬∃ T : Set S, T ∉ P ∧ (∀ U ∈ P, T ∩ U ≠ ∅))
: (P.card = 2 ^ (Fintype.card S - 1)) := by
  have h_no_empty : ∀ (T : Set S), T ∈ P → T.Nonempty := by
    intro T hT
    have h₁ : T ∩ T ≠ ∅ := hPP T hT T hT
    have h₂ : T ∩ T = T := by simp [Set.ext_iff]
    rw [h₂] at h₁
    exact Set.nonempty_iff_ne_empty.mpr h₁

  have h_subset_or_compl : ∀ (A : Set S), A ∈ P ∨ Aᶜ ∈ P := by
    intro A
    by_contra! h
    have h₁ : A ∉ P := h.1
    have h₂ : Aᶜ ∉ P := h.2

    have h₃ : ∃ (U : Set S), U ∈ P ∧ A ∩ U = ∅ := by
      have h₄ : ¬(A ∉ P ∧ ∀ (U : Set S), U ∈ P → A ∩ U ≠ ∅) := by
        intro h₅
        have h₆ : ∃ (T : Set S), T ∉ P ∧ (∀ U ∈ P, T ∩ U ≠ ∅) := by
          refine' ⟨A, _⟩
          constructor
          · exact h₅.1
          · intro U hU
            have h₇ := h₅.2 U hU
            have h₈ : A ∩ U ≠ ∅ := h₇
            have h₉ : A ∩ U = U ∩ A := by
              ext x
              simp [Set.mem_inter_iff]
              <;> tauto
            have h₁₀ : U ∩ A ≠ ∅ := by
              intro h₁₁
              apply h₈
              simp_all [Set.ext_iff]
              <;> aesop
            simpa [Set.inter_comm] using h₁₀
        exact hPS h₆
      by_cases h₅ : A ∉ P
      · have h₆ : ¬(∀ (U : Set S), U ∈ P → A ∩ U ≠ ∅) := by
          intro h₇
          exact h₄ ⟨h₅, h₇⟩
        push_neg at h₆
        obtain ⟨U, hU, h₈⟩ := h₆
        refine' ⟨U, hU, _⟩
        have h₉ : A ∩ U = ∅ := by
          by_contra h₁₀
          have h₁₁ : A ∩ U ≠ ∅ := h₁₀
          simp_all [Set.ext_iff]
          <;> aesop
        exact h₉
      · exfalso
        simp_all

    have h₄ : ∃ (V : Set S), V ∈ P ∧ Aᶜ ∩ V = ∅ := by
      have h₅ : ¬(Aᶜ ∉ P ∧ ∀ (U : Set S), U ∈ P → Aᶜ ∩ U ≠ ∅) := by
        intro h₆
        have h₇ : ∃ (T : Set S), T ∉ P ∧ (∀ U ∈ P, T ∩ U ≠ ∅) := by
          refine' ⟨Aᶜ, _⟩
          constructor
          · exact h₆.1
          · intro U hU
            have h₈ := h₆.2 U hU
            have h₉ : Aᶜ ∩ U ≠ ∅ := h₈
            have h₁₀ : Aᶜ ∩ U = U ∩ Aᶜ := by
              ext x
              simp [Set.mem_inter_iff]
              <;> tauto
            have h₁₁ : U ∩ Aᶜ ≠ ∅ := by
              intro h₁₂
              apply h₉
              simp_all [Set.ext_iff]
              <;> aesop
            simpa [Set.inter_comm] using h₁₁
        exact hPS h₇
      by_cases h₆ : Aᶜ ∉ P
      · have h₇ : ¬(∀ (U : Set S), U ∈ P → Aᶜ ∩ U ≠ ∅) := by
          intro h₈
          exact h₅ ⟨h₆, h₈⟩
        push_neg at h₇
        obtain ⟨V, hV, h₈⟩ := h₇
        refine' ⟨V, hV, _⟩
        have h₉ : Aᶜ ∩ V = ∅ := by
          by_contra h₁₀
          have h₁₁ : Aᶜ ∩ V ≠ ∅ := h₁₀
          simp_all [Set.ext_iff]
          <;> aesop
        exact h₉
      · exfalso
        simp_all

    obtain ⟨U, hU, hU'⟩ := h₃
    obtain ⟨V, hV, hV'⟩ := h₄

    have h₅ : U ⊆ Aᶜ := by
      intro x hx
      by_contra h₆
      have h₇ : x ∈ A := by simp_all [Set.mem_compl_iff]
      have h₈ : x ∈ A ∩ U := Set.mem_inter h₇ hx
      rw [hU'] at h₈
      simp at h₈
      <;> aesop
    have h₆ : V ⊆ A := by
      intro x hx
      by_contra h₇
      have h₈ : x ∈ Aᶜ := by simp_all [Set.mem_compl_iff]
      have h₉ : x ∈ Aᶜ ∩ V := Set.mem_inter h₈ hx
      rw [hV'] at h₉
      simp at h₉
      <;> aesop

    have h₇ : U ∩ V = ∅ := by
      apply Set.eq_empty_of_forall_not_mem
      intro x hx
      have h₈ : x ∈ U := Set.mem_of_mem_inter_left hx
      have h₉ : x ∈ V := Set.mem_of_mem_inter_right hx
      have h₁₀ : x ∈ Aᶜ := h₅ h₈
      have h₁₁ : x ∈ A := h₆ h₉
      simp_all [Set.mem_compl_iff]
      <;> aesop

    have h₈ : U ∩ V ≠ ∅ := hPP U hU V hV
    simp_all [Set.ext_iff]
    <;> aesop

  have h_not_both : ∀ (A : Set S), A ∈ P → Aᶜ ∉ P := by
    intro A hA
    by_contra h
    have h₁ : Aᶜ ∈ P := h
    have h₂ : A ∩ Aᶜ = ∅ := by
      ext x
      simp [Set.mem_inter_iff]
      <;> tauto
    have h₃ : A ∩ Aᶜ ≠ ∅ := hPP A hA Aᶜ h₁
    rw [h₂] at h₃
    contradiction

  have h_card : P.card = 2 ^ (Fintype.card S - 1) := by
    classical

    let Q : Finset (Set S) := (Finset.univ : Finset (Set S)) \ P

    have h₁ : P.card = Q.card := by

      have h₂ : ∀ (A : Set S), A ∈ P → Aᶜ ∈ Q := by
        intro A hA
        have h₃ : Aᶜ ∈ (Finset.univ : Finset (Set S)) := Finset.mem_univ _
        have h₄ : Aᶜ ∉ P := h_not_both A hA
        simp only [Q, Finset.mem_sdiff] at *
        tauto
      have h₃ : ∀ (A : Set S), A ∈ Q → Aᶜ ∈ P := by
        intro A hA
        have h₄ : A ∈ (Finset.univ : Finset (Set S)) := by
          simp only [Q, Finset.mem_sdiff] at hA
          tauto
        have h₅ : A ∉ P := by
          simp only [Q, Finset.mem_sdiff] at hA
          tauto
        have h₆ : A ∈ (Finset.univ : Finset (Set S)) := by tauto
        have h₇ : A ∈ P ∨ Aᶜ ∈ P := h_subset_or_compl A
        cases h₇ with
        | inl h₈ =>
          exfalso
          tauto
        | inr h₈ =>
          exact h₈

      have h₄ : P.card = Q.card := by

        have h₅ : P.card = Q.card := by

          have h₆ : ∀ (A : Set S), A ∈ P → Aᶜ ∈ Q := h₂
          have h₇ : ∀ (A : Set S), A ∈ Q → Aᶜ ∈ P := h₃

          have h₈ : P.card = Q.card := by

            apply Finset.card_bij' (fun A _ => Aᶜ) (fun A _ => Aᶜ)
            <;> simp_all [Set.ext_iff]
            <;>
            (try
              {
                aesop
              })
            <;>
            (try
              {
                tauto
              })
            <;>
            (try
              {
                intros
                <;>
                simp_all [Set.ext_iff]
                <;>
                tauto
              })
            <;>
            (try
              {
                intros
                <;>
                simp_all [Set.ext_iff]
                <;>
                tauto
              })
          exact h₈
        exact h₅
      exact h₄

    have h₂ : P.card + Q.card = 2 ^ Fintype.card S := by
      have h₃ : P.card + Q.card = (Finset.univ : Finset (Set S)).card := by
        have h₄ : Disjoint P Q := by
          rw [Finset.disjoint_left]
          intro A hA hA'
          simp only [Q, Finset.mem_sdiff] at hA'
          tauto
        have h₅ : P ∪ Q = (Finset.univ : Finset (Set S)) := by
          apply Finset.ext
          intro A
          simp only [Q, Finset.mem_union, Finset.mem_sdiff, Finset.mem_univ, true_and]
          <;>
          by_cases h₆ : A ∈ P <;> simp_all [h_subset_or_compl]
          <;>
          (try tauto)
          <;>
          (try
            {
              have h₇ := h_subset_or_compl A
              cases h₇ with
              | inl h₈ => tauto
              | inr h₈ =>
                have h₉ : Aᶜ ∈ P := h₈
                have h₁₀ : A ∈ P ∨ Aᶜ ∈ P := by tauto
                tauto
            })
        have h₆ : P.card + Q.card = (P ∪ Q).card := by
          rw [← Finset.card_union_add_card_inter P Q]
          have h₇ : P ∩ Q = ∅ := Finset.disjoint_iff_inter_eq_empty.mp h₄
          rw [h₇]
          simp
        rw [h₅] at h₆
        exact h₆
      have h₄ : (Finset.univ : Finset (Set S)).card = 2 ^ Fintype.card S := by
        simp [Fintype.card_fun]
        <;>
        simp_all [Fintype.card_fun]
        <;>
        ring_nf
        <;>
        simp_all [Fintype.card_fun]
        <;>
        norm_num
        <;>
        aesop
      linarith

    have h₃ : P.card * 2 = 2 ^ Fintype.card S := by
      have h₄ : P.card + Q.card = 2 ^ Fintype.card S := h₂
      have h₅ : P.card = Q.card := h₁
      linarith

    have h₄ : Fintype.card S ≥ 1 := by
      have h₅ : Nonempty S := inferInstance
      have h₆ : 0 < Fintype.card S := by
        apply Fintype.card_pos_iff.mpr
        exact ⟨Classical.choice h₅⟩
      omega
    have h₅ : P.card = 2 ^ (Fintype.card S - 1) := by
      have h₆ : P.card * 2 = 2 ^ Fintype.card S := h₃
      have h₇ : Fintype.card S ≥ 1 := h₄
      have h₈ : 2 ^ (Fintype.card S - 1) * 2 = 2 ^ Fintype.card S := by
        have h₉ : Fintype.card S - 1 + 1 = Fintype.card S := by
          have h₁₀ : Fintype.card S ≥ 1 := h₄
          omega
        calc
          2 ^ (Fintype.card S - 1) * 2 = 2 ^ (Fintype.card S - 1) * 2 ^ 1 := by norm_num
          _ = 2 ^ ((Fintype.card S - 1) + 1) := by
            rw [← pow_add]
          _ = 2 ^ Fintype.card S := by
            rw [h₉]
            <;> simp [add_comm]
      have h₉ : P.card = 2 ^ (Fintype.card S - 1) := by
        have h₁₀ : P.card * 2 = 2 ^ Fintype.card S := h₃
        have h₁₁ : 2 ^ (Fintype.card S - 1) * 2 = 2 ^ Fintype.card S := h₈
        have h₁₂ : P.card = 2 ^ (Fintype.card S - 1) := by
          nlinarith
        exact h₁₂
      exact h₉
    exact h₅

  exact h_card


import Mathlib
import Aesop

set_option maxHeartbeats 0

theorem putnam_2007_a1
    (P : (ℝ → ℝ) → Prop)
    (P_def : ∀ f, P f ↔ ∃ x y, f x = y ∧ f y = x ∧ deriv f x * deriv f y = 1)
    (α : ℝ) :
    P (fun t ↦ α * t ^ 2 + α * t + 1 / 24) ↔ α ∈ (({2 / 3, 3 / 2, (13 + √601) / 12, (13 - √601) / 12}) : Set ℝ ) :=
  by
  have h_main : P (fun t : ℝ => α * t ^ 2 + α * t + 1 / 24) ↔ α = 2 / 3 ∨ α = 3 / 2 ∨ α = (13 + Real.sqrt 601) / 12 ∨ α = (13 - Real.sqrt 601) / 12 := by
    have h₁ : P (fun t : ℝ => α * t ^ 2 + α * t + 1 / 24) ↔ ∃ (x y : ℝ), (α * x ^ 2 + α * x + 1 / 24 : ℝ) = y ∧ (α * y ^ 2 + α * y + 1 / 24 : ℝ) = x ∧ (2 * α * x + α) * (2 * α * y + α) = 1 := by
      have h₂ : P (fun t : ℝ => α * t ^ 2 + α * t + 1 / 24) ↔ ∃ x y, (fun t : ℝ => α * t ^ 2 + α * t + 1 / 24) x = y ∧ (fun t : ℝ => α * t ^ 2 + α * t + 1 / 24) y = x ∧ deriv (fun t : ℝ => α * t ^ 2 + α * t + 1 / 24) x * deriv (fun t : ℝ => α * t ^ 2 + α * t + 1 / 24) y = 1 := by
        rw [P_def]
        <;> simp
      rw [h₂]
      have h₃ : ∀ (x : ℝ), deriv (fun t : ℝ => α * t ^ 2 + α * t + 1 / 24) x = 2 * α * x + α := by
        intro x

        have h₄ : deriv (fun t : ℝ => α * t ^ 2 + α * t + 1 / 24) x = deriv (fun t : ℝ => α * t ^ 2 + α * t + 1 / 24) x := rfl
        rw [h₄]

        have h₅ : HasDerivAt (fun t : ℝ => α * t ^ 2 + α * t + 1 / 24) (2 * α * x + α) x := by

          have h₆ : HasDerivAt (fun t : ℝ => α * t ^ 2) (2 * α * x) x := by

            have h₇ : HasDerivAt (fun t : ℝ => t ^ 2) (2 * x) x := by
              simpa using (hasDerivAt_pow 2 x)
            have h₈ : HasDerivAt (fun t : ℝ => α * t ^ 2) (α * (2 * x)) x := by
              convert HasDerivAt.const_mul α h₇ using 1 <;> ring
            convert h₈ using 1 <;> ring
          have h₉ : HasDerivAt (fun t : ℝ => α * t) α x := by

            have h₁₀ : HasDerivAt (fun t : ℝ => t) 1 x := by
              simpa using hasDerivAt_id x
            have h₁₁ : HasDerivAt (fun t : ℝ => α * t) (α * 1) x := by
              convert HasDerivAt.const_mul α h₁₀ using 1 <;> ring
            convert h₁₁ using 1 <;> ring
          have h₁₂ : HasDerivAt (fun t : ℝ => (1 : ℝ) / 24) 0 x := by

            simpa using hasDerivAt_const x (1 / 24 : ℝ)

          have h₁₃ : HasDerivAt (fun t : ℝ => α * t ^ 2 + α * t + 1 / 24) (2 * α * x + α) x := by
            convert h₆.add h₉ |>.add h₁₂ using 1 <;> ring
          exact h₁₃

        have h₁₄ : deriv (fun t : ℝ => α * t ^ 2 + α * t + 1 / 24) x = 2 * α * x + α := by
          apply HasDerivAt.deriv
          exact h₅
        rw [h₁₄]

      constructor
      · intro h
        obtain ⟨x, y, h₁₅, h₁₆, h₁₇⟩ := h
        refine' ⟨x, y, _, _, _⟩ <;>
          (try simp_all [h₃]) <;>
          (try ring_nf at * <;> simp_all) <;>
          (try nlinarith)
      · intro h
        obtain ⟨x, y, h₁₅, h₁₆, h₁₇⟩ := h
        refine' ⟨x, y, _, _, _⟩ <;>
          (try simp_all [h₃]) <;>
          (try ring_nf at * <;> simp_all) <;>
          (try nlinarith)
    rw [h₁]
    constructor
    ·
      intro h
      have h₂ : ∃ (x y : ℝ), (α * x ^ 2 + α * x + 1 / 24 : ℝ) = y ∧ (α * y ^ 2 + α * y + 1 / 24 : ℝ) = x ∧ (2 * α * x + α) * (2 * α * y + α) = 1 := h
      obtain ⟨x, y, h₃, h₄, h₅⟩ := h₂
      have h₆ : (x - y) * (α * (x + y + 1) + 1) = 0 := by
        have h₇ : α * x ^ 2 + α * x + 1 / 24 = y := h₃
        have h₈ : α * y ^ 2 + α * y + 1 / 24 = x := h₄
        have h₉ : α * (x ^ 2 - y ^ 2) + α * (x - y) = (y - x) := by
          linarith
        have h₁₀ : α * (x - y) * (x + y) + α * (x - y) = -(x - y) := by
          linarith
        have h₁₁ : (x - y) * (α * (x + y) + α + 1) = 0 := by
          linarith
        have h₁₂ : (x - y) * (α * (x + y + 1) + 1) = 0 := by
          linarith
        exact h₁₂
      by_cases h₇ : x = y
      ·
        have h₈ : α * x ^ 2 + α * x + 1 / 24 = x := by
          linarith
        have h₉ : (2 * α * x + α) * (2 * α * x + α) = 1 := by
          have h₁₀ : (2 * α * x + α) * (2 * α * y + α) = 1 := h₅
          have h₁₁ : (2 * α * x + α) * (2 * α * x + α) = 1 := by
            simpa [h₇] using h₁₀
          exact h₁₁
        have h₁₀ : (2 * α * x + α) = 1 ∨ (2 * α * x + α) = -1 := by
          have h₁₁ : (2 * α * x + α) ^ 2 = 1 := by
            nlinarith
          have h₁₂ : (2 * α * x + α) = 1 ∨ (2 * α * x + α) = -1 := by
            apply or_iff_not_imp_left.mpr
            intro h₁₃
            apply eq_of_sub_eq_zero
            apply mul_left_cancel₀ (sub_ne_zero.mpr h₁₃)
            nlinarith
          exact h₁₂
        cases h₁₀ with
        | inl h₁₀ =>

          have h₁₁ : 2 * α * x + α = 1 := h₁₀
          have h₁₂ : α ≠ 0 := by
            by_contra h₁₃
            rw [h₁₃] at h₁₁
            norm_num at h₁₁
            <;> linarith
          have h₁₃ : x = (1 - α) / (2 * α) := by
            have h₁₄ : 2 * α * x + α = 1 := h₁₁
            field_simp at h₁₄ ⊢
            nlinarith
          have h₁₄ : α * x ^ 2 + (α - 1) * x + 1 / 24 = 0 := by
            have h₁₅ : α * x ^ 2 + α * x + 1 / 24 = x := h₈
            linarith
          rw [h₁₃] at h₁₄
          have h₁₅ : α * ((1 - α) / (2 * α)) ^ 2 + (α - 1) * ((1 - α) / (2 * α)) + 1 / 24 = 0 := h₁₄
          have h₁₆ : 6 * α ^ 2 - 13 * α + 6 = 0 := by
            field_simp at h₁₅
            ring_nf at h₁₅ ⊢
            nlinarith [sq_pos_of_ne_zero h₁₂]
          have h₁₇ : α = 2 / 3 ∨ α = 3 / 2 := by
            have h₁₈ : (α - 2 / 3) * (α - 3 / 2) = 0 := by
              nlinarith
            have h₁₉ : α - 2 / 3 = 0 ∨ α - 3 / 2 = 0 := by
              apply eq_zero_or_eq_zero_of_mul_eq_zero h₁₈
            cases h₁₉ with
            | inl h₁₉ =>
              have h₂₀ : α = 2 / 3 := by linarith
              exact Or.inl h₂₀
            | inr h₁₉ =>
              have h₂₀ : α = 3 / 2 := by linarith
              exact Or.inr h₂₀
          cases h₁₇ with
          | inl h₁₇ =>
            exact Or.inl h₁₇
          | inr h₁₇ =>
            exact Or.inr (Or.inl h₁₇)
        | inr h₁₀ =>

          have h₁₁ : 2 * α * x + α = -1 := h₁₀
          have h₁₂ : α ≠ 0 := by
            by_contra h₁₃
            rw [h₁₃] at h₁₁
            norm_num at h₁₁
            <;> linarith
          have h₁₃ : x = (-1 - α) / (2 * α) := by
            have h₁₄ : 2 * α * x + α = -1 := h₁₁
            field_simp at h₁₄ ⊢
            nlinarith
          have h₁₄ : α * x ^ 2 + (α - 1) * x + 1 / 24 = 0 := by
            have h₁₅ : α * x ^ 2 + α * x + 1 / 24 = x := h₈
            linarith
          rw [h₁₃] at h₁₄
          have h₁₅ : α * ((-1 - α) / (2 * α)) ^ 2 + (α - 1) * ((-1 - α) / (2 * α)) + 1 / 24 = 0 := h₁₄
          have h₁₆ : 6 * α ^ 2 - 13 * α - 18 = 0 := by
            field_simp at h₁₅
            ring_nf at h₁₅ ⊢
            nlinarith [sq_pos_of_ne_zero h₁₂]
          have h₁₇ : α = (13 + Real.sqrt 601) / 12 ∨ α = (13 - Real.sqrt 601) / 12 := by
            have h₁₈ : α = (13 + Real.sqrt 601) / 12 ∨ α = (13 - Real.sqrt 601) / 12 := by
              have h₁₉ : α = (13 + Real.sqrt 601) / 12 ∨ α = (13 - Real.sqrt 601) / 12 := by
                have h₂₀ : (α - (13 + Real.sqrt 601) / 12) * (α - (13 - Real.sqrt 601) / 12) = 0 := by
                  have h₂₁ : Real.sqrt 601 ≥ 0 := Real.sqrt_nonneg _
                  nlinarith [Real.sq_sqrt (show 0 ≤ 601 by norm_num)]
                have h₂₂ : α - (13 + Real.sqrt 601) / 12 = 0 ∨ α - (13 - Real.sqrt 601) / 12 = 0 := by
                  apply eq_zero_or_eq_zero_of_mul_eq_zero h₂₀
                cases h₂₂ with
                | inl h₂₂ =>
                  have h₂₃ : α = (13 + Real.sqrt 601) / 12 := by linarith
                  exact Or.inl h₂₃
                | inr h₂₂ =>
                  have h₂₃ : α = (13 - Real.sqrt 601) / 12 := by linarith
                  exact Or.inr h₂₃
              exact h₁₉
            exact h₁₈
          cases h₁₇ with
          | inl h₁₇ =>
            exact Or.inr (Or.inr (Or.inl h₁₇))
          | inr h₁₇ =>
            exact Or.inr (Or.inr (Or.inr h₁₇))
      ·
        have h₈ : α * (x + y + 1) + 1 = 0 := by
          apply mul_left_cancel₀ (sub_ne_zero.mpr h₇)
          nlinarith
        have h₉ : (2 * α * x + α) + (2 * α * y + α) = -2 := by
          have h₁₀ : α * (x + y + 1) + 1 = 0 := h₈
          have h₁₁ : α * (x + y + 1) = -1 := by linarith
          have h₁₂ : 2 * α * (x + y + 1) = -2 := by linarith
          have h₁₃ : 2 * α * x + 2 * α * y + 2 * α = -2 := by linarith
          linarith
        have h₁₀ : (2 * α * x + α) * (2 * α * y + α) = 1 := h₅
        have h₁₁ : (2 * α * x + α) = -1 := by
          have h₁₂ : (2 * α * x + α) + (2 * α * y + α) = -2 := h₉
          have h₁₃ : (2 * α * x + α) * (2 * α * y + α) = 1 := h₁₀
          have h₁₄ : (2 * α * x + α) = -1 := by
            nlinarith [sq_nonneg ((2 * α * x + α) - (2 * α * y + α))]
          exact h₁₄
        have h₁₂ : (2 * α * y + α) = -1 := by
          have h₁₃ : (2 * α * x + α) + (2 * α * y + α) = -2 := h₉
          have h₁₄ : (2 * α * x + α) = -1 := h₁₁
          linarith
        have h₁₃ : 2 * α * x + α = -1 := h₁₁
        have h₁₄ : 2 * α * y + α = -1 := h₁₂
        have h₁₅ : x = y := by
          have h₁₆ : 2 * α * x + α = 2 * α * y + α := by linarith
          have h₁₇ : 2 * α * x = 2 * α * y := by linarith
          by_cases h₁₈ : α = 0
          · have h₁₉ : α = 0 := h₁₈
            rw [h₁₉] at h₁₃
            norm_num at h₁₃
            <;> linarith
          · have h₁₉ : α ≠ 0 := h₁₈
            have h₂₀ : x = y := by
              apply mul_left_cancel₀ (show (2 : ℝ) * α ≠ 0 by
                intro h₂₁
                apply h₁₉
                linarith)
              linarith
            exact h₂₀
        contradiction
    ·
      intro h
      have h₂ : α = 2 / 3 ∨ α = 3 / 2 ∨ α = (13 + Real.sqrt 601) / 12 ∨ α = (13 - Real.sqrt 601) / 12 := h
      cases h₂ with
      | inl h₂ =>

        have h₃ : α = 2 / 3 := h₂
        have h₄ : ∃ (x y : ℝ), (α * x ^ 2 + α * x + 1 / 24 : ℝ) = y ∧ (α * y ^ 2 + α * y + 1 / 24 : ℝ) = x ∧ (2 * α * x + α) * (2 * α * y + α) = 1 := by
          use 1 / 4, 1 / 4
          rw [h₃]
          norm_num
          <;>
          (try ring_nf) <;>
          (try norm_num) <;>
          (try linarith)
        exact h₄
      | inr h₂ =>
        cases h₂ with
        | inl h₂ =>

          have h₃ : α = 3 / 2 := h₂
          have h₄ : ∃ (x y : ℝ), (α * x ^ 2 + α * x + 1 / 24 : ℝ) = y ∧ (α * y ^ 2 + α * y + 1 / 24 : ℝ) = x ∧ (2 * α * x + α) * (2 * α * y + α) = 1 := by
            use -1 / 6, -1 / 6
            rw [h₃]
            norm_num
            <;>
            (try ring_nf) <;>
            (try norm_num) <;>
            (try linarith)
          exact h₄
        | inr h₂ =>
          cases h₂ with
          | inl h₂ =>

            have h₃ : α = (13 + Real.sqrt 601) / 12 := h₂
            have h₄ : ∃ (x y : ℝ), (α * x ^ 2 + α * x + 1 / 24 : ℝ) = y ∧ (α * y ^ 2 + α * y + 1 / 24 : ℝ) = x ∧ (2 * α * x + α) * (2 * α * y + α) = 1 := by
              have h₅ : α ≠ 0 := by
                rw [h₃]
                nlinarith [Real.sqrt_nonneg 601, Real.sq_sqrt (show 0 ≤ 601 by norm_num)]
              use (-1 - α) / (2 * α), (-1 - α) / (2 * α)
              constructor
              ·
                have h₆ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + α * ((-1 - α) / (2 * α)) + 1 / 24 = (-1 - α) / (2 * α) := by
                  have h₇ : α ≠ 0 := h₅
                  have h₈ : 6 * α ^ 2 - 13 * α - 18 = 0 := by
                    rw [h₃]
                    nlinarith [Real.sq_sqrt (show (0 : ℝ) ≤ 601 by norm_num)]
                  have h₉ : (3 + 2 * α - α ^ 2) / (4 * α) + 1 / 24 = 0 := by
                    have h₁₀ : 6 * α ^ 2 = 13 * α + 18 := by linarith
                    field_simp [h₇]
                    nlinarith
                  have h₁₀ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + (α - 1) * ((-1 - α) / (2 * α)) + 1 / 24 = 0 := by
                    have h₁₁ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + (α - 1) * ((-1 - α) / (2 * α)) + 1 / 24 = (3 + 2 * α - α ^ 2) / (4 * α) + 1 / 24 := by
                      field_simp [h₇]
                      <;> ring_nf
                      <;> field_simp [h₇]
                      <;> ring_nf
                    rw [h₁₁]
                    linarith
                  have h₁₁ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + α * ((-1 - α) / (2 * α)) + 1 / 24 = (-1 - α) / (2 * α) := by
                    have h₁₂ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + (α - 1) * ((-1 - α) / (2 * α)) + 1 / 24 = 0 := h₁₀
                    have h₁₃ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + α * ((-1 - α) / (2 * α)) + 1 / 24 = (-1 - α) / (2 * α) := by
                      linarith
                    exact h₁₃
                  exact h₁₁
                exact h₆
              · constructor
                ·
                  have h₆ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + α * ((-1 - α) / (2 * α)) + 1 / 24 = (-1 - α) / (2 * α) := by
                    have h₇ : α ≠ 0 := h₅
                    have h₈ : 6 * α ^ 2 - 13 * α - 18 = 0 := by
                      rw [h₃]
                      nlinarith [Real.sq_sqrt (show 0 ≤ 601 by norm_num)]
                    have h₉ : (3 + 2 * α - α ^ 2) / (4 * α) + 1 / 24 = 0 := by
                      have h₁₀ : 6 * α ^ 2 = 13 * α + 18 := by linarith
                      field_simp [h₇]
                      nlinarith
                    have h₁₀ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + (α - 1) * ((-1 - α) / (2 * α)) + 1 / 24 = 0 := by
                      have h₁₁ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + (α - 1) * ((-1 - α) / (2 * α)) + 1 / 24 = (3 + 2 * α - α ^ 2) / (4 * α) + 1 / 24 := by
                        field_simp [h₇]
                        <;> ring_nf
                        <;> field_simp [h₇]
                        <;> ring_nf
                      rw [h₁₁]
                      linarith
                    have h₁₁ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + α * ((-1 - α) / (2 * α)) + 1 / 24 = (-1 - α) / (2 * α) := by
                      have h₁₂ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + (α - 1) * ((-1 - α) / (2 * α)) + 1 / 24 = 0 := h₁₀
                      have h₁₃ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + α * ((-1 - α) / (2 * α)) + 1 / 24 = (-1 - α) / (2 * α) := by
                        linarith
                      exact h₁₃
                    exact h₁₁
                  linarith
                ·
                  have h₆ : (2 * α * ((-1 - α) / (2 * α)) + α) * (2 * α * ((-1 - α) / (2 * α)) + α) = 1 := by
                    have h₇ : α ≠ 0 := h₅
                    field_simp [h₇]
                    <;> ring_nf
                    <;> nlinarith [Real.sqrt_nonneg 601, Real.sq_sqrt (show 0 ≤ 601 by norm_num)]
                  exact h₆
            exact h₄
          | inr h₂ =>

            have h₃ : α = (13 - Real.sqrt 601) / 12 := h₂
            have h₄ : ∃ (x y : ℝ), (α * x ^ 2 + α * x + 1 / 24 : ℝ) = y ∧ (α * y ^ 2 + α * y + 1 / 24 : ℝ) = x ∧ (2 * α * x + α) * (2 * α * y + α) = 1 := by
              have h₅ : α ≠ 0 := by
                rw [h₃]
                nlinarith [Real.sqrt_nonneg 601, Real.sq_sqrt (show 0 ≤ 601 by norm_num)]
              use (-1 - α) / (2 * α), (-1 - α) / (2 * α)
              constructor
              ·
                have h₆ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + α * ((-1 - α) / (2 * α)) + 1 / 24 = (-1 - α) / (2 * α) := by
                  have h₇ : α ≠ 0 := h₅
                  have h₈ : 6 * α ^ 2 - 13 * α - 18 = 0 := by
                    rw [h₃]
                    nlinarith [Real.sq_sqrt (show (0 : ℝ) ≤ 601 by norm_num)]
                  have h₉ : (3 + 2 * α - α ^ 2) / (4 * α) + 1 / 24 = 0 := by
                    have h₁₀ : 6 * α ^ 2 = 13 * α + 18 := by linarith
                    field_simp [h₇]
                    nlinarith
                  have h₁₀ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + (α - 1) * ((-1 - α) / (2 * α)) + 1 / 24 = 0 := by
                    have h₁₁ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + (α - 1) * ((-1 - α) / (2 * α)) + 1 / 24 = (3 + 2 * α - α ^ 2) / (4 * α) + 1 / 24 := by
                      field_simp [h₇]
                      <;> ring_nf
                      <;> field_simp [h₇]
                      <;> ring_nf
                    rw [h₁₁]
                    linarith
                  have h₁₁ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + α * ((-1 - α) / (2 * α)) + 1 / 24 = (-1 - α) / (2 * α) := by
                    have h₁₂ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + (α - 1) * ((-1 - α) / (2 * α)) + 1 / 24 = 0 := h₁₀
                    have h₁₃ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + α * ((-1 - α) / (2 * α)) + 1 / 24 = (-1 - α) / (2 * α) := by
                      linarith
                    exact h₁₃
                  exact h₁₁
                exact h₆
              · constructor
                ·
                  have h₆ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + α * ((-1 - α) / (2 * α)) + 1 / 24 = (-1 - α) / (2 * α) := by
                    have h₇ : α ≠ 0 := h₅
                    have h₈ : 6 * α ^ 2 - 13 * α - 18 = 0 := by
                      rw [h₃]
                      nlinarith [Real.sq_sqrt (show 0 ≤ 601 by norm_num)]
                    have h₉ : (3 + 2 * α - α ^ 2) / (4 * α) + 1 / 24 = 0 := by
                      have h₁₀ : 6 * α ^ 2 = 13 * α + 18 := by linarith
                      field_simp [h₇]
                      nlinarith
                    have h₁₀ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + (α - 1) * ((-1 - α) / (2 * α)) + 1 / 24 = 0 := by
                      have h₁₁ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + (α - 1) * ((-1 - α) / (2 * α)) + 1 / 24 = (3 + 2 * α - α ^ 2) / (4 * α) + 1 / 24 := by
                        field_simp [h₇]
                        <;> ring_nf
                        <;> field_simp [h₇]
                        <;> ring_nf
                      rw [h₁₁]
                      linarith
                    have h₁₁ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + α * ((-1 - α) / (2 * α)) + 1 / 24 = (-1 - α) / (2 * α) := by
                      have h₁₂ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + (α - 1) * ((-1 - α) / (2 * α)) + 1 / 24 = 0 := h₁₀
                      have h₁₃ : (α : ℝ) * ((-1 - α) / (2 * α)) ^ 2 + α * ((-1 - α) / (2 * α)) + 1 / 24 = (-1 - α) / (2 * α) := by
                        linarith
                      exact h₁₃
                    exact h₁₁
                  linarith
                ·
                  have h₆ : (2 * α * ((-1 - α) / (2 * α)) + α) * (2 * α * ((-1 - α) / (2 * α)) + α) = 1 := by
                    have h₇ : α ≠ 0 := h₅
                    field_simp [h₇]
                    <;> ring_nf
                    <;> nlinarith [Real.sqrt_nonneg 601, Real.sq_sqrt (show 0 ≤ 601 by norm_num)]
                  exact h₆
            exact h₄

  have h_final : (α = 2 / 3 ∨ α = 3 / 2 ∨ α = (13 + Real.sqrt 601) / 12 ∨ α = (13 - Real.sqrt 601) / 12) ↔ α ∈ (({2 / 3, 3 / 2, (13 + √601) / 12, (13 - √601) / 12}) : Set ℝ) := by
    constructor
    ·
      intro h
      simp only [Set.mem_insert_iff, Set.mem_singleton_iff]
      tauto
    ·
      intro h
      simp only [Set.mem_insert_iff, Set.mem_singleton_iff] at h
      tauto

  have h_result : P (fun t ↦ α * t ^ 2 + α * t + 1 / 24) ↔ α ∈ (({2 / 3, 3 / 2, (13 + √601) / 12, (13 - √601) / 12}) : Set ℝ) := by
    rw [h_main]
    rw [h_final]
    <;>
    simp_all
    <;>
    tauto

  exact h_result


import Mathlib
import Aesop

set_option maxHeartbeats 0

open Metric Set EuclideanGeometry Filter Topology

theorem putnam_1970_b5
(ramp : ℤ → (ℝ → ℝ))
(ramp_def : ramp = fun (n : ℤ) => (fun (x : ℝ) => if x ≤ -n then (-n : ℝ) else (if -n < x ∧ x ≤ n then x else (n : ℝ))))
(F : ℝ → ℝ)
: Continuous F ↔ (∀ n : ℕ, Continuous ((ramp n) ∘ F)) := by
  have h_ramp_def : ∀ (n : ℤ) (x : ℝ), ramp n x = if x ≤ -n then (-n : ℝ) else (if -n < x ∧ x ≤ n then x else (n : ℝ)) := by
    intro n x
    rw [ramp_def]
    <;> simp [n]
    <;> aesop

  have h_imp : Continuous F → (∀ n : ℕ, Continuous ((ramp n) ∘ F)) := by
    intro hF
    intro n
    have h₁ : Continuous (ramp n) := by
      have h₂ : Continuous (fun x : ℝ => min (max x (-(n : ℝ))) (n : ℝ)) := by
        continuity
      have h₃ : (ramp n) = (fun x : ℝ => min (max x (-(n : ℝ))) (n : ℝ)) := by
        funext x
        have h₄ : ramp n x = if x ≤ (-(n : ℝ)) then (-(n : ℝ)) else (if (-(n : ℝ) : ℝ) < x ∧ x ≤ (n : ℝ) then x else (n : ℝ)) := by
          have h₅ := h_ramp_def (n : ℤ) x
          simp [Int.cast_neg, Int.cast_ofNat] at h₅ ⊢
          <;>
          (try norm_num at h₅ ⊢) <;>
          (try ring_nf at h₅ ⊢) <;>
          (try simp_all) <;>
          (try linarith)
          <;>
          (try
            {
              split_ifs at h₅ ⊢ <;>
              simp_all [Int.cast_neg, Int.cast_ofNat] <;>
              norm_num at * <;>
              (try linarith)
            })
        rw [h₄]
        split_ifs <;>
          (try {
            simp_all [max_eq_left, max_eq_right, min_eq_left, min_eq_right, le_of_lt]
            <;>
            (try { nlinarith }) <;>
            (try { linarith })
          }) <;>
          (try {
            cases' le_total x (n : ℝ) with h₆ h₆ <;>
              simp_all [max_eq_left, max_eq_right, min_eq_left, min_eq_right, le_of_lt] <;>
              (try { nlinarith }) <;>
              (try { linarith })
          })
      rw [h₃]
      exact h₂

    exact h₁.comp hF

  have h_conv : (∀ n : ℕ, Continuous ((ramp n) ∘ F)) → Continuous F := by
    intro h
    have h₁ : Continuous F := by
      have h₂ : ∀ (x₀ : ℝ), ContinuousAt F x₀ := by
        intro x₀

        have h₃ : ∀ (ε : ℝ), ε > 0 → (∃ (δ : ℝ), δ > 0 ∧ ∀ (x : ℝ), |x - x₀| < δ → |F x - F x₀| < ε) := by
          intro ε εpos

          have h₄ : ∃ (n : ℕ), (n : ℝ) > |F x₀| + ε := by
            obtain ⟨n, hn⟩ := exists_nat_gt (|F x₀| + ε)
            refine' ⟨n, _⟩
            exact_mod_cast hn
          obtain ⟨n, hn⟩ := h₄
          have h₅ : (n : ℝ) > |F x₀| + ε := hn
          have h₆ : Continuous ((ramp n) ∘ F) := h n
          have h₇ : ContinuousAt ((ramp n) ∘ F) x₀ := h₆.continuousAt

          have h₈ : ∀ (ε : ℝ), ε > 0 → (∃ (δ : ℝ), δ > 0 ∧ ∀ (x : ℝ), |x - x₀| < δ → |(ramp n ∘ F) x - (ramp n ∘ F) x₀| < ε) := by
            intro ε εpos
            have h₉ : ContinuousAt ((ramp n) ∘ F) x₀ := h₇
            exact Metric.continuousAt_iff.mp h₉ ε εpos
          have h₉ : ∃ (δ : ℝ), δ > 0 ∧ ∀ (x : ℝ), |x - x₀| < δ → |(ramp n ∘ F) x - (ramp n ∘ F) x₀| < ε := h₈ ε εpos
          obtain ⟨δ, δpos, hδ⟩ := h₉
          use δ
          constructor
          · exact δpos
          · intro x hx
            have h₁₀ : |(ramp n ∘ F) x - (ramp n ∘ F) x₀| < ε := hδ x hx
            have h₁₁ : (ramp n ∘ F) x = ramp n (F x) := rfl
            have h₁₂ : (ramp n ∘ F) x₀ = ramp n (F x₀) := rfl
            rw [h₁₁, h₁₂] at h₁₀

            have h₁₃ : ramp n (F x₀) = F x₀ := by
              have h₁₄ : (F x₀ : ℝ) ≤ (n : ℝ) := by
                have h₁₅ : |F x₀| + ε < (n : ℝ) := by linarith
                have h₁₆ : |F x₀| < (n : ℝ) := by linarith
                have h₁₇ : F x₀ ≤ |F x₀| := by
                  cases' abs_cases (F x₀) with h₁₈ h₁₈ <;> linarith
                linarith
              have h₁₅ : (F x₀ : ℝ) > (-(n : ℝ)) := by
                have h₁₆ : |F x₀| + ε < (n : ℝ) := by linarith
                have h₁₇ : |F x₀| < (n : ℝ) := by linarith
                have h₁₈ : - (n : ℝ) < F x₀ := by
                  cases' abs_cases (F x₀) with h₁₉ h₁₉ <;> linarith
                linarith
              have h₁₆ : (F x₀ : ℝ) > (-(n : ℝ)) ∧ (F x₀ : ℝ) ≤ (n : ℝ) := ⟨h₁₅, h₁₄⟩
              have h₁₇ : ramp n (F x₀) = (F x₀ : ℝ) := by
                have h₁₈ : ramp n (F x₀) = if (F x₀ : ℝ) ≤ (-(n : ℝ)) then (-(n : ℝ)) else (if (-(n : ℝ)) < (F x₀ : ℝ) ∧ (F x₀ : ℝ) ≤ (n : ℝ) then (F x₀ : ℝ) else (n : ℝ)) := by
                  rw [h_ramp_def]
                  <;> simp [Int.cast_neg, Int.cast_ofNat]
                  <;> norm_num
                  <;>
                  (try
                    {
                      ring_nf
                      <;>
                      norm_cast
                    })
                  <;>
                  (try
                    {
                      simp_all [Int.cast_neg, Int.cast_ofNat]
                      <;>
                      norm_num
                      <;>
                      linarith
                    })
                rw [h₁₈]
                have h₁₉ : ¬((F x₀ : ℝ) ≤ (-(n : ℝ))) := by
                  intro h₂₀
                  have h₂₁ : (F x₀ : ℝ) ≤ (-(n : ℝ)) := h₂₀
                  have h₂₂ : (-(n : ℝ)) < (F x₀ : ℝ) := by
                    have h₂₃ : |F x₀| + ε < (n : ℝ) := by linarith
                    have h₂₄ : |F x₀| < (n : ℝ) := by linarith
                    cases' abs_cases (F x₀) with h₂₅ h₂₅ <;> linarith
                  linarith
                have h₂₀ : (-(n : ℝ)) < (F x₀ : ℝ) ∧ (F x₀ : ℝ) ≤ (n : ℝ) := h₁₆
                split_ifs at * <;> simp_all [h₁₉] <;>
                  (try { contradiction }) <;>
                  (try { linarith })
              rw [h₁₇]
            have h₁₄ : ramp n (F x) = F x := by
              by_contra h₁₅
              have h₁₆ : ramp n (F x) ≠ F x := h₁₅
              have h₁₇ : ramp n (F x) = (-(n : ℝ)) ∨ ramp n (F x) = (n : ℝ) := by
                have h₁₈ : ramp n (F x) = if (F x : ℝ) ≤ (-(n : ℝ)) then (-(n : ℝ)) else (if (-(n : ℝ)) < (F x : ℝ) ∧ (F x : ℝ) ≤ (n : ℝ) then (F x : ℝ) else (n : ℝ)) := by
                  rw [h_ramp_def]
                  <;> simp [Int.cast_neg, Int.cast_ofNat]
                  <;> norm_num
                  <;>
                  (try
                    {
                      ring_nf
                      <;>
                      norm_cast
                    })
                  <;>
                  (try
                    {
                      simp_all [Int.cast_neg, Int.cast_ofNat]
                      <;>
                      norm_num
                      <;>
                      linarith
                    })
                rw [h₁₈] at *
                split_ifs at * <;>
                  (try { simp_all }) <;>
                  (try {
                    left
                    <;>
                    linarith
                  }) <;>
                  (try {
                    right
                    <;>
                    linarith
                  }) <;>
                  (try {
                    exfalso
                    apply h₁₆
                    <;>
                    simp_all
                  })
              cases h₁₇ with
              | inl h₁₇ =>
                have h₁₈ : ramp n (F x) = (-(n : ℝ)) := h₁₇
                have h₁₉ : |(ramp n (F x) : ℝ) - (ramp n (F x₀) : ℝ)| < ε := by simpa [h₁₃] using h₁₀
                have h₂₀ : |(-(n : ℝ) : ℝ) - (F x₀ : ℝ)| < ε := by simpa [h₁₈, h₁₃] using h₁₉
                have h₂₁ : (n : ℝ) > |F x₀| + ε := by exact_mod_cast hn
                have h₂₂ : |(-(n : ℝ) : ℝ) - (F x₀ : ℝ)| ≥ (n : ℝ) - |F x₀| := by
                  cases' abs_cases (F x₀) with h₂₃ h₂₃ <;>
                    cases' abs_cases (-(n : ℝ) - F x₀) with h₂₄ h₂₄ <;>
                      linarith
                have h₂₃ : (n : ℝ) - |F x₀| > ε := by linarith
                linarith
              | inr h₁₇ =>
                have h₁₈ : ramp n (F x) = (n : ℝ) := h₁₇
                have h₁₉ : |(ramp n (F x) : ℝ) - (ramp n (F x₀) : ℝ)| < ε := by simpa [h₁₃] using h₁₀
                have h₂₀ : |(n : ℝ) - (F x₀ : ℝ)| < ε := by simpa [h₁₈, h₁₃] using h₁₉
                have h₂₁ : (n : ℝ) > |F x₀| + ε := by exact_mod_cast hn
                have h₂₂ : |(n : ℝ) - (F x₀ : ℝ)| ≥ (n : ℝ) - |F x₀| := by
                  cases' abs_cases (F x₀) with h₂₃ h₂₃ <;>
                    cases' abs_cases ((n : ℝ) - F x₀) with h₂₄ h₂₄ <;>
                      linarith
                have h₂₃ : (n : ℝ) - |F x₀| > ε := by linarith
                linarith
            have h₁₅ : |F x - F x₀| < ε := by
              have h₁₆ : ramp n (F x) = F x := h₁₄
              have h₁₇ : ramp n (F x₀) = F x₀ := h₁₃
              have h₁₈ : |(ramp n (F x) : ℝ) - (ramp n (F x₀) : ℝ)| < ε := by simpa [h₁₆, h₁₇] using h₁₀
              simpa [h₁₆, h₁₇] using h₁₈
            exact h₁₅
          <;>
          simp_all [abs_lt]
          <;>
          linarith

        have h₄ : ContinuousAt F x₀ := by
          rw [Metric.continuousAt_iff]
          intro ε εpos
          obtain ⟨δ, δpos, hδ⟩ := h₃ ε εpos
          refine' ⟨δ, δpos, _⟩
          intro x hx
          have h₅ : |F x - F x₀| < ε := hδ x hx
          exact h₅
        exact h₄

      exact continuous_iff_continuousAt.mpr h₂
    exact h₁

  constructor
  · intro h
    exact h_imp h
  · intro h
    exact h_conv h


theorem putnam_1968_a1
: 22/7 - Real.pi = ∫ x in (0)..1, x^4 * (1 - x)^4 / (1 + x^2) := by
  have h_main : (∫ x in (0)..1, x^4 * (1 - x)^4 / (1 + x^2)) = 22/7 - Real.pi := by
    have h₁ : (∫ x in (0)..1, x^4 * (1 - x)^4 / (1 + x^2)) = (∫ x in (0)..1, (x^6 - 4*x^5 + 5*x^4 - 4*x^2 + 4 : ℝ) - 4 / (1 + x^2)) := by
      have h₁₁ : ∀ (x : ℝ), x^4 * (1 - x)^4 / (1 + x^2) = (x^6 - 4*x^5 + 5*x^4 - 4*x^2 + 4 : ℝ) - 4 / (1 + x^2) := by
        intro x
        have h₁₂ : (1 + x^2 : ℝ) ≠ 0 := by nlinarith
        have h₁₃ : x^4 * (1 - x)^4 = (x^6 - 4*x^5 + 5*x^4 - 4*x^2 + 4 : ℝ) * (1 + x^2) - 4 := by
          ring_nf
          <;>
          nlinarith [sq_nonneg (x ^ 2), sq_nonneg (x ^ 3), sq_nonneg (x - 1), sq_nonneg (x + 1)]
        have h₁₄ : x^4 * (1 - x)^4 / (1 + x^2) = ((x^6 - 4*x^5 + 5*x^4 - 4*x^2 + 4 : ℝ) * (1 + x^2) - 4) / (1 + x^2) := by
          rw [h₁₃]
        rw [h₁₄]
        field_simp [h₁₂]
        <;> ring_nf
        <;> field_simp [h₁₂]
        <;> ring_nf

      congr
      ext x
      rw [h₁₁ x]
    rw [h₁]

    have h₂ : (∫ x in (0)..1, (x^6 - 4*x^5 + 5*x^4 - 4*x^2 + 4 : ℝ) - 4 / (1 + x^2)) = (∫ x in (0)..1, (x^6 - 4*x^5 + 5*x^4 - 4*x^2 + 4 : ℝ)) - (∫ x in (0)..1, (4 : ℝ) / (1 + x^2)) := by
      apply intervalIntegral.integral_sub
      ·
        apply Continuous.intervalIntegrable
        continuity
      ·
        apply Continuous.intervalIntegrable

        have h₃ : Continuous (fun x : ℝ => (4 : ℝ) / (1 + x ^ 2)) := by
          apply Continuous.div
          · exact continuous_const
          · exact Continuous.add continuous_const (continuous_pow 2)
          · intro x
            have h₄ : (1 + x ^ 2 : ℝ) ≠ 0 := by nlinarith
            exact h₄
        exact h₃
    rw [h₂]

    have h₃ : (∫ x in (0)..1, (x^6 - 4*x^5 + 5*x^4 - 4*x^2 + 4 : ℝ)) = (22 / 7 : ℝ) := by
      norm_num [integral_id, mul_comm]
      <;>
      ring_nf
      <;>
      norm_num
      <;>
      linarith [Real.pi_pos]

    have h₄ : (∫ x in (0)..1, (4 : ℝ) / (1 + x^2)) = Real.pi := by
      have h₄₁ : (∫ x in (0)..1, (4 : ℝ) / (1 + x ^ 2)) = 4 * (∫ x in (0)..1, (1 : ℝ) / (1 + x ^ 2)) := by

        have h₄₂ : (∫ x in (0)..1, (4 : ℝ) / (1 + x ^ 2)) = (∫ x in (0)..1, 4 * (1 : ℝ) / (1 + x ^ 2)) := by
          congr
          ext x
          <;> ring_nf
        rw [h₄₂]
        have h₄₃ : (∫ x in (0)..1, 4 * (1 : ℝ) / (1 + x ^ 2)) = 4 * (∫ x in (0)..1, (1 : ℝ) / (1 + x ^ 2)) := by

          simp [intervalIntegral.integral_comp_mul_left (fun x => (1 : ℝ) / (1 + x ^ 2))]
          <;>
          norm_num
          <;>
          field_simp
          <;>
          ring_nf
          <;>
          norm_num
          <;>
          linarith [Real.pi_pos]
        rw [h₄₃]
      rw [h₄₁]
      have h₄₄ : (∫ x in (0)..1, (1 : ℝ) / (1 + x ^ 2)) = Real.pi / 4 := by

        have h₄₅ : (∫ x in (0)..1, (1 : ℝ) / (1 + x ^ 2)) = Real.arctan 1 - Real.arctan 0 := by

          rw [integral_one_div_one_add_sq]
          <;>
          norm_num
        rw [h₄₅]
        have h₄₆ : Real.arctan 1 = Real.pi / 4 := by

          norm_num [Real.arctan_one]
        have h₄₇ : Real.arctan 0 = 0 := by

          norm_num [Real.arctan_zero]
        rw [h₄₆, h₄₇]
        <;>
        ring_nf
        <;>
        norm_num
      rw [h₄₄]
      <;>
      ring_nf
      <;>
      norm_num

    rw [h₃, h₄]
    <;>
    ring_nf
    <;>
    norm_num

  have h_final : 22/7 - Real.pi = ∫ x in (0)..1, x^4 * (1 - x)^4 / (1 + x^2) := by
    rw [h_main]
    <;>
    linarith [Real.pi_pos]

  exact h_final


import Mathlib
import Aesop

set_option maxHeartbeats 0

open Filter Topology

theorem putnam_1991_b1
  (m S : ℤ → ℤ)
  (A : ℤ)
  (a : ℕ → ℤ)
  (hm : ∀ n, 0 ≤ n → (m n) ^ 2 ≤ n ∧ (∀ m' : ℤ, m' ^ 2 ≤ n → m' ≤ m n))
  (hS : ∀ n, 0 ≤ n → S n = n - (m n) ^ 2)
  (ha : a 0 = A ∧ (∀ k, a (k + 1) = a k + S (a k)))
  (hA : A > 0) :
  (∃ (K : ℕ) (c : ℕ), ∀ k ≥ K, a k = c) ↔ A ∈ (({A : ℤ | ∃ x > 0, A = x ^ 2}) : Set ℤ ) := by
  have h_nonneg : ∀ (k : ℕ), a k ≥ 0 := by
    intro k
    induction k with
    | zero =>
      have h₁ : a 0 = A := ha.1
      linarith
    | succ k ih =>
      have h₁ : a (k + 1) = a k + S (a k) := ha.2 k
      rw [h₁]
      have h₂ : 0 ≤ a k := ih
      have h₃ : S (a k) = a k - (m (a k)) ^ 2 := hS (a k) h₂
      have h₄ : (m (a k)) ^ 2 ≤ a k := (hm (a k) h₂).1
      have h₅ : S (a k) ≥ 0 := by
        rw [h₃]
        linarith
      linarith

  have h_nondec : ∀ k, a (k + 1) ≥ a k := by
    intro k
    have h₁ : a (k + 1) = a k + S (a k) := (ha.2) k
    rw [h₁]
    have h₂ : 0 ≤ a k := h_nonneg k
    have h₃ : S (a k) = a k - (m (a k)) ^ 2 := hS (a k) h₂
    have h₄ : (m (a k)) ^ 2 ≤ a k := (hm (a k) h₂).1
    have h₅ : S (a k) ≥ 0 := by
      rw [h₃]
      linarith
    linarith

  have h_S_pos : ∀ (n : ℤ), 0 ≤ n → (∀ (t : ℤ), n ≠ t ^ 2) → S n ≥ 1 := by
    intro n hn hnotsquare
    have h₁ : S n = n - (m n) ^ 2 := hS n hn
    rw [h₁]
    have h₂ : (m n) ^ 2 ≤ n := (hm n hn).1
    have h₃ : ∀ (m' : ℤ), m' ^ 2 ≤ n → m' ≤ m n := (hm n hn).2

    have h₄ : n - (m n) ^ 2 ≥ 1 := by
      by_contra h

      have h₅ : n - (m n) ^ 2 ≤ 0 := by
        linarith

      have h₆ : (m n + 1 : ℤ) ^ 2 > n := by
        by_contra h₆
        have h₇ : (m n + 1 : ℤ) ^ 2 ≤ n := by linarith
        have h₈ : m n + 1 ≤ m n := h₃ (m n + 1) h₇
        linarith

      have h₇ : (m n : ℤ) ^ 2 ≤ n := h₂
      have h₈ : (m n + 1 : ℤ) ^ 2 > n := h₆
      have h₉ : (m n + 1 : ℤ) ^ 2 > n := h₈

      have h₁₀ : (m n : ℤ) ^ 2 = n := by
        nlinarith

      have h₁₁ : ∃ (t : ℤ), n = t ^ 2 := by
        refine' ⟨m n, _⟩
        linarith

      obtain ⟨t, ht⟩ := h₁₁
      have h₁₂ : n = t ^ 2 := ht
      have h₁₃ : n ≠ t ^ 2 := hnotsquare t
      contradiction

    linarith

  have h_no_new_squares : ∀ (k : ℕ), (∀ (t : ℤ), a k ≠ t ^ 2) → (∀ (t : ℤ), a (k + 1) ≠ t ^ 2) := by
    intro k hk
    intro t ht
    have h₁ : a (k + 1) = a k + S (a k) := ha.2 k
    have h₂ : 0 ≤ a k := h_nonneg k
    have h₃ : S (a k) = a k - (m (a k)) ^ 2 := hS (a k) h₂
    have h₄ : a (k + 1) = a k + (a k - (m (a k)) ^ 2) := by
      rw [h₁, h₃]
      <;> ring
    have h₅ : a (k + 1) = 2 * a k - (m (a k)) ^ 2 := by
      linarith
    have h₆ : a (k + 1) = t ^ 2 := ht
    have h₇ : 2 * a k - (m (a k)) ^ 2 = t ^ 2 := by linarith
    have h₈ : (m (a k)) ^ 2 ≤ a k := (hm (a k) h₂).1
    have h₉ : ∀ (m' : ℤ), m' ^ 2 ≤ a k → m' ≤ m (a k) := (hm (a k) h₂).2
    have h₁₀ : a k < (m (a k) + 1) ^ 2 := by
      by_contra h
      have h₁₁ : (m (a k) + 1 : ℤ) ^ 2 ≤ a k := by linarith
      have h₁₂ : m (a k) + 1 ≤ m (a k) := h₉ (m (a k) + 1) h₁₁
      linarith

    have h₁₁ : m (a k) ≥ 0 := by
      by_contra h
      have h₁₂ : m (a k) < 0 := by linarith
      have h₁₃ : (m (a k)) ^ 2 > 0 := by nlinarith
      have h₁₄ : (m (a k) + 1 : ℤ) ^ 2 ≤ a k := by
        nlinarith [h₈]
      have h₁₅ : m (a k) + 1 ≤ m (a k) := h₉ (m (a k) + 1) h₁₄
      linarith

    have h₁₂ : t ^ 2 = 2 * a k - (m (a k)) ^ 2 := by linarith
    have h₁₃ : (m (a k)) ^ 2 < t ^ 2 := by
      have h₁₄ : (m (a k)) ^ 2 < a k := by
        by_contra h₁₄
        have h₁₅ : (m (a k)) ^ 2 ≥ a k := by linarith
        have h₁₆ : (m (a k)) ^ 2 ≤ a k := h₈
        have h₁₇ : (m (a k)) ^ 2 = a k := by linarith
        have h₁₈ : ∃ (t : ℤ), a k = t ^ 2 := by
          refine' ⟨m (a k), _⟩
          linarith
        obtain ⟨t', ht'⟩ := h₁₈
        have h₁₉ : a k = t' ^ 2 := ht'
        have h₂₀ : a k ≠ t' ^ 2 := hk t'
        contradiction
      nlinarith
    have h₁₄ : t ^ 2 < (m (a k) + 2) ^ 2 := by
      nlinarith [h₁₀]

    have h₁₅ : t = m (a k) + 1 ∨ t = -(m (a k) + 1) := by
      have h₁₆ : m (a k) ≥ 0 := h₁₁
      have h₁₇ : t ^ 2 < (m (a k) + 2) ^ 2 := h₁₄
      have h₁₈ : (m (a k)) ^ 2 < t ^ 2 := h₁₃
      have h₁₉ : t ≤ m (a k) + 1 := by
        nlinarith
      have h₂₀ : t ≥ -(m (a k) + 1) := by
        nlinarith
      have h₂₁ : t ≥ m (a k) + 1 ∨ t ≤ -(m (a k) + 1) := by
        by_contra! h₂₂
        have h₂₃ : -(m (a k) + 1) < t := by linarith
        have h₂₄ : t < m (a k) + 1 := by linarith
        have h₂₅ : t ^ 2 < (m (a k) + 1) ^ 2 := by
          nlinarith
        nlinarith
      cases h₂₁ with
      | inl h₂₁ =>
        have h₂₂ : t = m (a k) + 1 := by
          nlinarith
        exact Or.inl h₂₂
      | inr h₂₁ =>
        have h₂₂ : t = -(m (a k) + 1) := by
          nlinarith
        exact Or.inr h₂₂

    cases h₁₅ with
    | inl h₁₅ =>
      have h₁₆ : t = m (a k) + 1 := h₁₅
      have h₁₇ : t ^ 2 = (m (a k) + 1) ^ 2 := by
        rw [h₁₆]
        <;> ring_nf
      have h₁₈ : 2 * a k - (m (a k)) ^ 2 = (m (a k) + 1) ^ 2 := by
        linarith
      have h₁₉ : 2 * a k = 2 * (m (a k)) ^ 2 + 2 * m (a k) + 1 := by
        nlinarith
      have h₂₀ : (2 : ℤ) * a k % 2 = 1 := by
        have h₂₁ : (2 : ℤ) * a k = 2 * (m (a k)) ^ 2 + 2 * m (a k) + 1 := h₁₉
        omega
      have h₂₁ : (2 : ℤ) * a k % 2 = 0 := by
        have h₂₂ : (2 : ℤ) * a k % 2 = 0 := by
          have h₂₃ : (2 : ℤ) * a k % 2 = 0 := by
            omega
          exact h₂₃
        exact h₂₂
      omega
    | inr h₁₅ =>
      have h₁₆ : t = -(m (a k) + 1) := h₁₅
      have h₁₇ : t ^ 2 = (m (a k) + 1) ^ 2 := by
        rw [h₁₆]
        <;> ring_nf
        <;> simp [sq]
        <;> linarith
      have h₁₈ : 2 * a k - (m (a k)) ^ 2 = (m (a k) + 1) ^ 2 := by
        linarith
      have h₁₉ : 2 * a k = 2 * (m (a k)) ^ 2 + 2 * m (a k) + 1 := by
        nlinarith
      have h₂₀ : (2 : ℤ) * a k % 2 = 1 := by
        have h₂₁ : (2 : ℤ) * a k = 2 * (m (a k)) ^ 2 + 2 * m (a k) + 1 := h₁₉
        omega
      have h₂₁ : (2 : ℤ) * a k % 2 = 0 := by
        have h₂₂ : (2 : ℤ) * a k % 2 = 0 := by
          have h₂₃ : (2 : ℤ) * a k % 2 = 0 := by
            omega
          exact h₂₃
        exact h₂₂
      omega

  have h_strict_increasing : (∀ (t : ℤ), A ≠ t ^ 2) → ∀ (k : ℕ), a (k + 1) > a k := by
    intro hA_not_square k
    have h₁ : ∀ (k : ℕ), (∀ (t : ℤ), a k ≠ t ^ 2) := by
      intro k
      induction k with
      | zero =>
        intro t ht
        have h₂ : a 0 = A := ha.1
        rw [h₂] at ht
        exact hA_not_square t ht
      | succ k ih =>
        intro t ht
        have h₂ : (∀ (t : ℤ), a k ≠ t ^ 2) := ih
        have h₃ : (∀ (t : ℤ), a (k + 1) ≠ t ^ 2) := h_no_new_squares k h₂
        exact h₃ t ht
    have h₂ : (∀ (t : ℤ), a k ≠ t ^ 2) := h₁ k
    have h₃ : 0 ≤ a k := h_nonneg k
    have h₄ : S (a k) ≥ 1 := h_S_pos (a k) h₃ h₂
    have h₅ : a (k + 1) = a k + S (a k) := ha.2 k
    have h₆ : a (k + 1) > a k := by
      linarith
    exact h₆

  have h_imp : (∃ (K : ℕ) (c : ℕ), ∀ k ≥ K, a k = c) → A ∈ (({A : ℤ | ∃ x > 0, A = x ^ 2}) : Set ℤ) := by
    intro h
    by_contra h₁

    have h₂ : ∀ (t : ℤ), A ≠ t ^ 2 := by
      intro t ht
      have h₃ : A ∈ ({A : ℤ | ∃ x > 0, A = x ^ 2} : Set ℤ) := by
        refine' ⟨t.natAbs, _⟩
        have h₄ : A = t ^ 2 := ht
        have h₅ : (t.natAbs : ℤ) > 0 := by
          have h₆ : t ≠ 0 := by
            by_contra h₆
            rw [h₆] at h₄
            have h₇ : A = 0 := by
              norm_num at h₄ ⊢
              <;> linarith
            linarith
          have h₈ : t.natAbs > 0 := by
            exact Nat.pos_of_ne_zero (by
              intro h₉
              have h₁₀ : t.natAbs = 0 := h₉
              have h₁₁ : t = 0 := by
                simp [Int.natAbs_eq_zero] at h₁₀ ⊢
                <;> omega
              contradiction
            )
          exact_mod_cast h₈
        have h₉ : A = (t.natAbs : ℤ) ^ 2 := by
          have h₁₀ : A = t ^ 2 := ht
          have h₁₁ : (t.natAbs : ℤ) ^ 2 = t ^ 2 := by
            simp [sq, Int.natAbs_mul]
            <;> cases' le_or_lt 0 t with h₁₂ h₁₂ <;> simp_all [Int.natAbs_of_nonneg, Int.natAbs_of_nonpos, pow_two] <;>
              ring_nf <;> nlinarith
          linarith
        exact ⟨by exact_mod_cast h₅, by linarith⟩
      contradiction

    have h₃ : ∀ (k : ℕ), a (k + 1) > a k := h_strict_increasing h₂

    obtain ⟨K, c, h₄⟩ := h
    have h₅ : a (K + 1) > a K := h₃ K
    have h₆ : a (K + 1) = c := by
      have h₇ : K + 1 ≥ K := by linarith
      have h₈ : a (K + 1) = c := h₄ (K + 1) h₇
      exact h₈
    have h₇ : a K = c := by
      have h₈ : K ≥ K := by linarith
      have h₉ : a K = c := h₄ K h₈
      exact h₉
    linarith

  have h_conv : A ∈ (({A : ℤ | ∃ x > 0, A = x ^ 2}) : Set ℤ) → (∃ (K : ℕ) (c : ℕ), ∀ k ≥ K, a k = c) := by
    intro h
    obtain ⟨x, hx, hx'⟩ := h
    have h₁ : a 0 = A := ha.1
    have h₂ : ∀ k, a (k + 1) = a k + S (a k) := ha.2
    have h₃ : ∀ k, a k = A := by
      intro k
      induction k with
      | zero => simp [h₁]
      | succ k ih =>
        have h₄ : a (k + 1) = a k + S (a k) := h₂ k
        rw [h₄]
        have h₅ : a k = A := ih
        rw [h₅]
        have h₆ : S A = 0 := by
          have h₇ : 0 ≤ A := by linarith
          have h₈ : S A = A - (m A) ^ 2 := hS A h₇
          rw [h₈]
          have h₉ : (m A) ^ 2 ≤ A := (hm A h₇).1
          have h₁₀ : ∀ (m' : ℤ), m' ^ 2 ≤ A → m' ≤ m A := (hm A h₇).2
          have h₁₁ : A = x ^ 2 := by
            norm_cast at hx' ⊢
            <;> simp_all [pow_two]
            <;> nlinarith
          have h₁₂ : (m A : ℤ) = x := by
            have h₁₃ : (m A : ℤ) ≥ 0 := by
              by_contra h₁₄
              have h₁₅ : (m A : ℤ) < 0 := by linarith
              have h₁₆ : (m A : ℤ) ^ 2 > 0 := by nlinarith
              have h₁₇ : (m A + 1 : ℤ) ^ 2 ≤ A := by
                nlinarith [h₉]
              have h₁₈ : m A + 1 ≤ m A := h₁₀ (m A + 1) h₁₇
              linarith
            have h₁₉ : (m A : ℤ) ≤ x := by
              have h₂₀ : (m A : ℤ) ^ 2 ≤ A := h₉
              have h₂₁ : A = x ^ 2 := by
                norm_cast at hx' ⊢
                <;> simp_all [pow_two]
                <;> nlinarith
              have h₂₂ : (m A : ℤ) ^ 2 ≤ x ^ 2 := by
                linarith
              nlinarith
            have h₂₀ : (m A : ℤ) ≥ x := by
              by_contra h₂₁
              have h₂₂ : (m A : ℤ) < x := by linarith
              have h₂₃ : (m A + 1 : ℤ) ≤ x := by
                linarith
              have h₂₄ : (m A + 1 : ℤ) ^ 2 ≤ x ^ 2 := by
                have h₂₅ : (m A + 1 : ℤ) ≤ x := by linarith
                have h₂₆ : 0 ≤ (m A + 1 : ℤ) := by
                  nlinarith [h₁₃]
                nlinarith
              have h₂₅ : (m A + 1 : ℤ) ^ 2 ≤ A := by
                have h₂₆ : A = x ^ 2 := by
                  norm_cast at hx' ⊢
                  <;> simp_all [pow_two]
                  <;> nlinarith
                linarith
              have h₂₆ : m A + 1 ≤ m A := h₁₀ (m A + 1) h₂₅
              linarith
            linarith
          have h₂₁ : (m A : ℤ) = x := h₁₂
          have h₂₂ : (m A : ℤ) ^ 2 = x ^ 2 := by
            rw [h₂₁]
          have h₂₃ : A = x ^ 2 := by
            norm_cast at hx' ⊢
            <;> simp_all [pow_two]
            <;> nlinarith
          linarith
        linarith
    refine' ⟨0, Int.toNat A, _⟩
    intro k hk
    have h₄ : a k = A := h₃ k
    have h₅ : 0 ≤ A := by linarith
    have h₆ : (A : ℤ) = Int.toNat A := by
      rw [Int.toNat_of_nonneg h₅]
      <;> simp
    rw [h₄]
    <;> norm_cast at h₆ ⊢ <;> simp_all
    <;>
    (try omega)

  constructor
  ·
    intro h
    exact h_imp h
  ·
    intro h
    exact h_conv h