1- def even_odd_count : Unit :=
2- ()
1+ def Int.toDigits (i : Int) : List Char :=
2+ i.natAbs.toDigits (base := 10 )
3+
4+ def evenOddCount (num : Int) : Nat × Nat :=
5+ num.toDigits.foldl countDigit (0 , 0 )
6+ where
7+ countDigit (evenOdd : Nat × Nat) : Char → Nat × Nat
8+ | '0' | '2' | '4' | '6' | '8' => (evenOdd.fst + 1 , evenOdd.snd)
9+ | _ => (evenOdd.fst, evenOdd.snd + 1 )
10+
11+ example : evenOddCount (-12 ) = (1 , 1 ) := rfl
12+ example : evenOddCount 123 = (1 , 2 ) := rfl
13+ example : evenOddCount 7 = (0 , 1 ) := rfl
14+ example : evenOddCount (-78 ) = (1 , 1 ) := rfl
15+ example : evenOddCount 3452 = (2 , 2 ) := rfl
16+ example : evenOddCount 346211 = (3 , 3 ) := rfl
17+ example : evenOddCount (-345821 ) = (3 , 3 ) := rfl
18+ example : evenOddCount (-2 ) = (1 , 0 ) := rfl
19+ example : evenOddCount (-45347 ) = (2 , 3 ) := rfl
20+ example : evenOddCount 0 = (1 , 0 ) := rfl
21+
22+ def Prod.sum : Nat × Nat → Nat
23+ | (n₁, n₂) => n₁ + n₂
24+
25+ -- Applying `evenOddCount.countDigit` increases the total digit count by `1`.
26+ theorem evenOddCount.countDigit_sum (evenOdd : Nat × Nat) (d : Char) :
27+ (evenOddCount.countDigit evenOdd d).sum = evenOdd.sum + 1 := by
28+ unfold evenOddCount.countDigit
29+ split <;> simp +arith [Prod.sum]
30+
31+ -- Folding `evenOddCount.countDigit` over a given digit count `init` produces the same total digit
32+ -- count as folding `evenOddCount.countDigit` over `(0, 0)` and adding that to `init`.
33+ theorem evenOddCount.countDigit_sum_foldl (ds : List Char) (init : Nat × Nat) :
34+ (ds.foldl evenOddCount.countDigit init).sum =
35+ (ds.foldl evenOddCount.countDigit (0 , 0 )).sum + init.sum := by
36+ induction ds generalizing init
37+ case nil => simp [Prod.sum]
38+ case cons ih => simp +arith only [List.foldl_cons, ih (countDigit _ _), countDigit_sum]; rfl
39+
40+ -- The total digit count produced by `evenOddCount` matches the number of digits in the input.
41+ theorem evenOddCount_sum_eq_length : (evenOddCount i).sum = i.toDigits.length := by
42+ rw [evenOddCount]
43+ generalize i.toDigits = ds
44+ induction ds
45+ case nil => rfl
46+ case cons ih => rw [List.foldl_cons, List.length_cons, evenOddCount.countDigit_sum_foldl, ih,
47+ evenOddCount.countDigit_sum, Prod.sum]
348
449/-!
550## Prompt
@@ -48,4 +93,4 @@ def check(candidate):
4893 assert True
4994
5095```
51- -/
96+ -/
0 commit comments