Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 761f917

Browse files
committed
chore(archive/100-theorems-list/30_ballot_problem): golf (#18126)
Also add some supporting lemmas.
1 parent 7a030ab commit 761f917

File tree

4 files changed

+57
-131
lines changed

4 files changed

+57
-131
lines changed

archive/100-theorems-list/30_ballot_problem.lean

Lines changed: 34 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -66,73 +66,44 @@ This represents vote sequences where candidate `+1` receives `p` votes and candi
6666
def counted_sequence (p q : ℕ) : set (list ℤ) :=
6767
{l | l.count 1 = p ∧ l.count (-1) = q ∧ ∀ x ∈ l, x = (1 : ℤ) ∨ x = -1}
6868

69-
@[simp] lemma counted_right_zero (p : ℕ) : counted_sequence p 0 = {list.repeat 1 p} :=
69+
/-- An alternative definition of `counted_sequence` that uses `list.perm`. -/
70+
lemma mem_counted_sequence_iff_perm {p q l} :
71+
l ∈ counted_sequence p q ↔ l ~ list.repeat (1 : ℤ) p ++ list.repeat (-1) q :=
7072
begin
71-
ext l,
72-
rw [counted_sequence, mem_singleton_iff],
73-
split,
74-
{ rintro ⟨hl₀, hl₁, hl₂⟩,
75-
rw list.eq_repeat,
76-
have : ∀ x ∈ l, (1 : ℤ) = x,
77-
{ intros x hx,
78-
obtain rfl | rfl := hl₂ x hx,
79-
{ refl },
80-
{ exact false.elim (list.not_mem_of_count_eq_zero hl₁ hx) } },
81-
split,
82-
{ rwa ← list.count_eq_length.2 this },
83-
{ exact λ x hx, (this x hx).symm } },
84-
{ rintro rfl,
85-
simp only [mem_set_of_eq, list.count_repeat_self, eq_self_iff_true, true_and],
86-
refine ⟨list.count_eq_zero_of_not_mem _, λ x, _⟩; rw list.mem_repeat,
87-
{ norm_num },
88-
{ rintro ⟨-, rfl⟩,
89-
exact or.inl rfl } }
73+
rw [list.perm_repeat_append_repeat],
74+
{ simp only [counted_sequence, list.subset_def, mem_set_of_eq, list.mem_cons_iff,
75+
list.mem_singleton] },
76+
{ norm_num1 }
9077
end
9178

79+
@[simp] lemma counted_right_zero (p : ℕ) : counted_sequence p 0 = {list.repeat 1 p} :=
80+
by { ext l, simp [mem_counted_sequence_iff_perm] }
81+
9282
@[simp] lemma counted_left_zero (q : ℕ) : counted_sequence 0 q = {list.repeat (-1) q} :=
93-
begin
94-
ext l,
95-
rw [counted_sequence, mem_singleton_iff],
96-
split,
97-
{ rintro ⟨hl₀, hl₁, hl₂⟩,
98-
rw list.eq_repeat,
99-
have : ∀ x ∈ l, (-1 : ℤ) = x,
100-
{ intros x hx,
101-
obtain rfl | rfl := hl₂ x hx,
102-
{ exact false.elim (list.not_mem_of_count_eq_zero hl₀ hx) },
103-
{ refl } },
104-
split,
105-
{ rwa ← list.count_eq_length.2 this },
106-
{ exact λ x hx, (this x hx).symm } },
107-
{ rintro rfl,
108-
simp only [mem_set_of_eq, list.count_repeat_self, eq_self_iff_true, true_and],
109-
refine ⟨list.count_eq_zero_of_not_mem _, λ x, _⟩; rw list.mem_repeat,
110-
{ norm_num },
111-
{ rintro ⟨-, rfl⟩,
112-
exact or.inr rfl } }
113-
end
83+
by { ext l, simp [mem_counted_sequence_iff_perm] }
84+
85+
lemma mem_of_mem_counted_sequence {p q} {l} (hl : l ∈ counted_sequence p q) {x : ℤ} (hx : x ∈ l) :
86+
x = 1 ∨ x = -1 :=
87+
hl.2.2 x hx
88+
89+
lemma length_of_mem_counted_sequence {p q} {l : list ℤ} (hl : l ∈ counted_sequence p q) :
90+
l.length = p + q :=
91+
by simp [(mem_counted_sequence_iff_perm.1 hl).length_eq]
92+
93+
lemma counted_eq_nil_iff {p q : ℕ} {l : list ℤ} (hl : l ∈ counted_sequence p q) :
94+
l = [] ↔ p = 0 ∧ q = 0 :=
95+
list.length_eq_zero.symm.trans $ by simp [length_of_mem_counted_sequence hl]
11496

11597
lemma counted_ne_nil_left {p q : ℕ} (hp : p ≠ 0) {l : list ℤ} (hl : l ∈ counted_sequence p q) :
116-
l ≠ list.nil :=
117-
begin
118-
obtain ⟨hl₀, hl₁, hl₂⟩ := hl,
119-
rintro rfl,
120-
rw list.count_nil at hl₀,
121-
exact hp hl₀.symm,
122-
end
98+
l ≠ [] :=
99+
by simp [counted_eq_nil_iff hl, hp]
123100

124-
lemma counted_ne_nil_right {p q : ℕ} (hp : q ≠ 0) {l : list ℤ} (hl : l ∈ counted_sequence p q) :
125-
l ≠ list.nil :=
126-
begin
127-
obtain ⟨hl₀, hl₁, hl₂⟩ := hl,
128-
rintro rfl,
129-
rw list.count_nil at hl₁,
130-
exact hp hl₁.symm,
131-
end
101+
lemma counted_ne_nil_right {p q : ℕ} (hq : q ≠ 0) {l : list ℤ} (hl : l ∈ counted_sequence p q) :
102+
l ≠ [] :=
103+
by simp [counted_eq_nil_iff hl, hq]
132104

133105
lemma counted_succ_succ (p q : ℕ) : counted_sequence (p + 1) (q + 1) =
134-
(counted_sequence p (q + 1)).image (list.cons 1) ∪
135-
(counted_sequence (p + 1) q).image (list.cons (-1)) :=
106+
list.cons 1 '' counted_sequence p (q + 1) ∪ list.cons (-1) '' counted_sequence (p + 1) q :=
136107
begin
137108
ext l,
138109
rw [counted_sequence, counted_sequence, counted_sequence],
@@ -193,79 +164,13 @@ lemma counted_sequence_nonempty : ∀ (p q : ℕ), (counted_sequence p q).nonemp
193164
exact or.inl (counted_sequence_nonempty _ _),
194165
end
195166

196-
lemma sum_of_mem_counted_sequence :
197-
∀ {p q : ℕ} {l : list ℤ} (hl : l ∈ counted_sequence p q), l.sum = p - q
198-
| 0 q l hl :=
199-
begin
200-
rw [counted_left_zero, mem_singleton_iff] at hl,
201-
simp [hl],
202-
end
203-
| p 0 l hl :=
204-
begin
205-
rw [counted_right_zero, mem_singleton_iff] at hl,
206-
simp [hl],
207-
end
208-
| (p + 1) (q + 1) l hl :=
209-
begin
210-
simp only [counted_succ_succ, mem_union, mem_image] at hl,
211-
rcases hl with (⟨l, hl, rfl⟩ | ⟨l, hl, rfl⟩),
212-
{ rw [list.sum_cons, sum_of_mem_counted_sequence hl],
213-
push_cast,
214-
ring },
215-
{ rw [list.sum_cons, sum_of_mem_counted_sequence hl],
216-
push_cast,
217-
ring }
218-
end
219-
220-
lemma mem_of_mem_counted_sequence :
221-
∀ {p q : ℕ} {l} (hl : l ∈ counted_sequence p q) {x : ℤ} (hx : x ∈ l), x = 1 ∨ x = -1
222-
| 0 q l hl x hx :=
223-
begin
224-
rw [counted_left_zero, mem_singleton_iff] at hl,
225-
subst hl,
226-
exact or.inr (list.eq_of_mem_repeat hx),
227-
end
228-
| p 0 l hl x hx :=
229-
begin
230-
rw [counted_right_zero, mem_singleton_iff] at hl,
231-
subst hl,
232-
exact or.inl (list.eq_of_mem_repeat hx),
233-
end
234-
| (p + 1) (q + 1) l hl x hx :=
235-
begin
236-
simp only [counted_succ_succ, mem_union, mem_image] at hl,
237-
rcases hl with (⟨l, hl, rfl⟩ | ⟨l, hl, rfl⟩);
238-
rcases hx with (rfl | hx),
239-
{ left, refl },
240-
{ exact mem_of_mem_counted_sequence hl hx },
241-
{ right, refl },
242-
{ exact mem_of_mem_counted_sequence hl hx },
243-
end
244-
245-
lemma length_of_mem_counted_sequence :
246-
∀ {p q : ℕ} {l : list ℤ} (hl : l ∈ counted_sequence p q), l.length = p + q
247-
| 0 q l hl :=
248-
begin
249-
rw [counted_left_zero, mem_singleton_iff] at hl,
250-
simp [hl],
251-
end
252-
| p 0 l hl :=
253-
begin
254-
rw [counted_right_zero, mem_singleton_iff] at hl,
255-
simp [hl],
256-
end
257-
| (p + 1) (q + 1) l hl :=
258-
begin
259-
simp only [counted_succ_succ, mem_union, mem_image] at hl,
260-
rcases hl with (⟨l, hl, rfl⟩ | ⟨l, hl, rfl⟩),
261-
{ rw [list.length_cons, length_of_mem_counted_sequence hl, add_right_comm] },
262-
{ rw [list.length_cons, length_of_mem_counted_sequence hl, ←add_assoc] }
263-
end
167+
lemma sum_of_mem_counted_sequence {p q} {l : list ℤ} (hl : l ∈ counted_sequence p q) :
168+
l.sum = p - q :=
169+
by simp [(mem_counted_sequence_iff_perm.1 hl).sum_eq, sub_eq_add_neg]
264170

265171
lemma disjoint_bits (p q : ℕ) :
266-
disjoint
267-
((counted_sequence p (q + 1)).image (list.cons 1))
268-
((counted_sequence (p + 1) q).image (list.cons (-1))) :=
172+
disjoint (list.cons 1 '' counted_sequence p (q + 1))
173+
(list.cons (-1) '' counted_sequence (p + 1) q) :=
269174
begin
270175
simp_rw [disjoint_left, mem_image, not_exists, exists_imp_distrib],
271176
rintros _ _ ⟨_, rfl⟩ _ ⟨_, _, _⟩,

src/data/list/basic.lean

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,8 @@ iff.intro or_exists_of_exists_mem_cons
318318

319319
/-! ### list subset -/
320320

321+
instance : is_trans (list α) (⊆) := ⟨λ _ _ _, list.subset.trans⟩
322+
321323
theorem subset_def {l₁ l₂ : list α} : l₁ ⊆ l₂ ↔ ∀ ⦃a : α⦄, a ∈ l₁ → a ∈ l₂ := iff.rfl
322324

323325
theorem subset_append_of_subset_left (l l₁ l₂ : list α) : l ⊆ l₁ → l ⊆ l₁++l₂ :=

src/data/list/perm.lean

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ theorem perm.subset {l₁ l₂ : list α} (p : l₁ ~ l₂) : l₁ ⊆ l₂ :=
7979
theorem perm.mem_iff {a : α} {l₁ l₂ : list α} (h : l₁ ~ l₂) : a ∈ l₁ ↔ a ∈ l₂ :=
8080
iff.intro (λ m, h.subset m) (λ m, h.symm.subset m)
8181

82+
lemma perm.subset_congr_left {l₁ l₂ l₃ : list α} (h : l₁ ~ l₂) : l₁ ⊆ l₃ ↔ l₂ ⊆ l₃ :=
83+
⟨h.symm.subset.trans, h.subset.trans⟩
84+
85+
lemma perm.subset_congr_right {l₁ l₂ l₃ : list α} (h : l₁ ~ l₂) : l₃ ⊆ l₁ ↔ l₃ ⊆ l₂ :=
86+
⟨λ h', h'.trans h.subset, λ h', h'.trans h.symm.subset⟩
87+
8288
theorem perm.append_right {l₁ l₂ : list α} (t₁ : list α) (p : l₁ ~ l₂) : l₁++t₁ ~ l₂++t₁ :=
8389
perm.rec_on p
8490
(perm.refl ([] ++ t₁))
@@ -730,6 +736,16 @@ theorem perm_iff_count {l₁ l₂ : list α} : l₁ ~ l₂ ↔ ∀ a, count a l
730736
by_cases b = a; simp [h] at H ⊢; assumption }
731737
end
732738

739+
theorem perm_repeat_append_repeat {l : list α} {a b : α} {m n : ℕ} (h : a ≠ b) :
740+
l ~ repeat a m ++ repeat b n ↔ count a l = m ∧ count b l = n ∧ l ⊆ [a, b] :=
741+
begin
742+
rw [perm_iff_count, ← decidable.and_forall_ne a, ← decidable.and_forall_ne b],
743+
suffices : l ⊆ [a, b] ↔ ∀ c, c ≠ b → c ≠ a → c ∉ l,
744+
{ simp [count_repeat, h, h.symm, this] { contextual := tt } },
745+
simp_rw [ne.def, ← and_imp, ← not_or_distrib, decidable.not_imp_not, subset_def, mem_cons_iff,
746+
not_mem_nil, or_false, or_comm],
747+
end
748+
733749
lemma subperm.cons_right {α : Type*} {l l' : list α} (x : α) (h : l <+~ l') : l <+~ x :: l' :=
734750
h.trans (sublist_cons x l').subperm
735751

src/logic/basic.lean

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,10 +1146,13 @@ by simp [and_comm]
11461146
@[simp] theorem forall_eq' {a' : α} : (∀a, a' = a → p a) ↔ p a' :=
11471147
by simp [@eq_comm _ a']
11481148

1149-
theorem and_forall_ne (a : α) : (p a ∧ ∀ b ≠ a, p b) ↔ ∀ b, p b :=
1150-
by simp only [← @forall_eq _ p a, ← forall_and_distrib, ← or_imp_distrib, classical.em,
1149+
theorem decidable.and_forall_ne [decidable_eq α] (a : α) : (p a ∧ ∀ b ≠ a, p b) ↔ ∀ b, p b :=
1150+
by simp only [← @forall_eq _ p a, ← forall_and_distrib, ← or_imp_distrib, decidable.em,
11511151
forall_const]
11521152

1153+
theorem and_forall_ne (a : α) : (p a ∧ ∀ b ≠ a, p b) ↔ ∀ b, p b :=
1154+
decidable.and_forall_ne a
1155+
11531156
-- this lemma is needed to simplify the output of `list.mem_cons_iff`
11541157
@[simp] theorem forall_eq_or_imp {a' : α} : (∀ a, a = a' ∨ q a → p a) ↔ p a' ∧ ∀ a, q a → p a :=
11551158
by simp only [or_imp_distrib, forall_and_distrib, forall_eq]

0 commit comments

Comments
 (0)