11module
22
3- def will_it_fly : Unit :=
4- ()
3+ /-!
4+ ## Missing API
5+ -/
6+
7+ @ [specialize P]
8+ def decideBallLTImpl (Q : Nat → Prop ) (n : Nat) (h : ∀ k, k < n → Q k) (P : ∀ k : Nat, Q k → Bool) : Bool :=
9+ match n with
10+ | 0 => true
11+ | n' + 1 => P n' (h n' (Nat.lt_add_one _)) && decideBallLTImpl Q n' (fun _ h' => h _ (Nat.lt_add_right 1 h')) P
12+
13+ theorem decidableBallLTImpl_iff :
14+ decideBallLTImpl Q n h P ↔ ∀ (k : Nat) (hk : k < n), P k (h k hk) := by
15+ induction n
16+ · simp [decideBallLTImpl]
17+ · rename_i n ih
18+ simp [decideBallLTImpl, ih]
19+ constructor
20+ · intro h k hk
21+ by_cases hkn : k = n
22+ · exact hkn ▸ h.1
23+ · apply h.2
24+ omega
25+ · intro h
26+ constructor
27+ · apply h
28+ exact Nat.lt_add_one _
29+ · intro k hk
30+ apply h k
31+ exact Nat.lt_add_right 1 hk
32+
33+ theorem decideBallLTImpl_eq_false_iff :
34+ decideBallLTImpl Q n h P = false ↔ ∃ (k : Nat) (hk : k < n), ¬ P k (h k hk) := by
35+ rw [← Bool.not_eq_true, decidableBallLTImpl_iff]
36+ simp
37+
38+ instance decidableBallLTImpl (n : Nat) (P : ∀ k, k < n → Prop ) [∀ n h, Decidable (P n h)] :
39+ Decidable (∀ n h, P n h) :=
40+ match h : decideBallLTImpl _ n (fun _ => id) (P · ·) with
41+ | false => isFalse (by simpa [decideBallLTImpl_eq_false_iff] using h)
42+ | true => isTrue (by simpa [decidableBallLTImpl_iff] using h)
43+
44+ attribute [- instance ] Nat.decidableBallLT
45+
46+ /-!
47+ ## Implementation
48+ -/
49+
50+ /--
51+ Efficient, short-circuiting
52+ -/
53+ def willItFly (q : List Nat) (w : Nat) : Bool :=
54+ q.sum ≤ w ∧ ∀ (i : Nat) (hi : i < q.length / 2 ), q[i] = q[q.length - 1 - i]
55+
56+ /-!
57+ ## Tests
58+ -/
59+
60+ set_option cbv.warning false
61+
62+ example : willItFly [3 , 2 , 3 ] 9 = true := by cbv
63+ example : willItFly [1 , 2 ] 5 = false := by cbv
64+ example : willItFly [3 ] 5 = true := by cbv
65+ example : willItFly [3 , 2 , 3 ] 1 = false := by cbv
66+ example : willItFly [1 , 2 , 3 ] 6 = false := by cbv
67+ example : willItFly [5 ] 5 = true := by cbv
68+
69+ /-!
70+ ## Verification
71+ -/
72+
73+ theorem willItFly_iff_le_and_forall :
74+ willItFly q w ↔ q.sum ≤ w ∧ ∀ (i : Nat) (hi : i < q.length), q[i] = q[q.length - 1 - i] := by
75+ grind [willItFly]
76+
77+ theorem willItFly_iff_le_and_reverse_eq_self :
78+ willItFly q w ↔ q.sum ≤ w ∧ q.reverse = q := by
79+ rw [List.ext_getElem_iff]
80+ grind [willItFly]
581
682/-!
783## Prompt
@@ -14,7 +90,7 @@ def will_it_fly(q,w):
1490 The object q will fly if it's balanced (it is a palindromic list) and the sum of its elements is less than or equal the maximum possible weight w.
1591
1692 Example:
17- will_it_fly([1, 2], 5) ➞ False
93+ will_it_fly([1, 2], 5) ➞ False
1894 # 1+2 is less than the maximum possible weight, but it's unbalanced.
1995
2096 will_it_fly([3, 2, 3], 1) ➞ False
@@ -60,4 +136,4 @@ def check(candidate):
60136 assert candidate([5], 5) is True
61137
62138```
63- -/
139+ -/
0 commit comments