1- def choose_num : Unit :=
2- ()
1+ def Nat.isEven (n : Nat) : Bool :=
2+ n % 2 = 0
3+
4+ def chooseNum (lo hi : Nat) : Int :=
5+ match compare lo hi, hi.isEven with
6+ | .lt, true | .eq, true => hi
7+ | .lt, false => hi - 1
8+ | _, _ => -1
9+
10+ example : chooseNum 12 15 = 14 := rfl
11+ example : chooseNum 13 12 = -1 := rfl
12+ example : chooseNum 12 15 = 14 := rfl
13+ example : chooseNum 13 12 = -1 := rfl
14+ example : chooseNum 33 12354 = 12354 := rfl
15+ example : chooseNum 5234 5233 = -1 := rfl
16+ example : chooseNum 6 29 = 28 := rfl
17+ example : chooseNum 27 10 = -1 := rfl
18+ example : chooseNum 7 7 = -1 := rfl
19+ example : chooseNum 546 546 = 546 := rfl
20+
21+ macro "chooseNum_cases" lo:ident hi:ident : tactic => `(tactic|(
22+ cases _ : compare $lo $hi <;> cases _ : $(hi).isEven <;> simp only [chooseNum, *] at *
23+ ))
24+
25+ macro "chooseNum_trivial" : tactic => `(tactic|(
26+ simp only [(· ∈ ·), Nat.isEven, Nat.compare_eq_eq, Nat.compare_eq_lt, Nat.compare_eq_gt,
27+ decide_eq_false_iff_not, decide_eq_true_eq] at *
28+ omega
29+ ))
30+
31+ namespace Std.Range
32+
33+ -- A specification for `m` being the even maximum of range `r`.
34+ structure EvenMax (r : Range) (m : Nat) : Prop where
35+ mem : m ∈ r := by chooseNum_trivial
36+ even : m.isEven := by chooseNum_trivial
37+ max_even : ∀ n ∈ r, n.isEven → n ≤ m := by chooseNum_trivial
38+
39+ namespace EvenMax
40+
41+ theorem unique (h₁ : [lo:hi].EvenMax m₁) (h₂ : [lo:hi].EvenMax m₂) : m₁ = m₂ :=
42+ Nat.le_antisymm (h₂.max_even _ h₁.mem h₁.even) (h₁.max_even _ h₂.mem h₂.even)
43+
44+ theorem to_chooseNum (h : [lo:hi + 1 ].EvenMax m) : chooseNum lo hi = m := by
45+ have ⟨_, _, _⟩ := h
46+ chooseNum_cases lo hi <;> try chooseNum_trivial
47+ · have : [lo:hi + 1 ].EvenMax (hi - 1 ) := { }
48+ simp only [h.unique this, Nat.isEven, decide_eq_true_eq, decide_eq_false_iff_not] at *
49+ omega
50+ · rw [h.unique { : [lo:hi + 1 ].EvenMax hi }]
51+
52+ -- A given number `m` is the even maximum of the range `{lo, ..., hi}` iff `chooseNum` says so.
53+ theorem iff_chooseNum : [lo:hi + 1 ].EvenMax m ↔ chooseNum lo hi = m where
54+ mp := EvenMax.to_chooseNum
55+ mpr h := by constructor <;> chooseNum_cases lo hi <;> chooseNum_trivial
56+
57+ -- There does not exist an even maximum of the range `{lo, ..., hi}` iff `chooseNum` returns `-1`.
58+ theorem not_iff_chooseNum : ¬(∃ m, [lo:hi + 1 ].EvenMax m) ↔ (chooseNum lo hi = -1 ) where
59+ mpr h := fun ⟨_, ⟨_, _, _⟩⟩ => by chooseNum_cases lo hi <;> chooseNum_trivial
60+ mp h := by
61+ chooseNum_cases lo hi <;> exfalso
62+ · exact h ⟨hi - 1 , {}⟩
63+ · exact h ⟨hi, {}⟩
64+ · exact h ⟨hi, {}⟩
65+
66+ end Std.Range.EvenMax
367
468/-!
569## Prompt
@@ -8,7 +72,7 @@ def choose_num : Unit :=
872
973def choose_num(x, y):
1074 """This function takes two positive numbers x and y and returns the
11- biggest even integer number that is in the range [x, y] inclusive. If
75+ biggest even integer number that is in the range [x, y] inclusive. If
1276 there's no such number, then the function should return -1.
1377
1478 For example:
@@ -47,4 +111,4 @@ def check(candidate):
47111 assert candidate(546, 546) == 546
48112
49113```
50- -/
114+ -/
0 commit comments