Skip to content

Commit 7a22cc6

Browse files
authored
Seção 5.4.lean
1 parent 22dbec7 commit 7a22cc6

File tree

1 file changed

+266
-0
lines changed

1 file changed

+266
-0
lines changed

Fad/Assignment04.lean

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import Fad.Chapter3
12
import Fad.Chapter4
23
import Fad.Chapter5
34

@@ -161,3 +162,268 @@ opções de seções:
161162
- 7.4 Decimal fractions in TEX
162163
163164
-/
165+
166+
-- ## Section 5.4 Bucketsort and Radixsort
167+
168+
namespace Bucketsort
169+
170+
variable {α: Type}
171+
172+
inductive Tree (α : Type)
173+
| leaf : α → Tree α
174+
| node : List (Tree α) → Tree α
175+
deriving Repr
176+
177+
def ptn₀ {β : Type} [BEq β] (rng : List β)
178+
(f : α → β) (xs : List α) : List (List α) :=
179+
rng.map (λ b => xs.filter (λ x => f x == b))
180+
181+
def mktree {β : Type} [BEq β]
182+
(rng : List β)
183+
(ds : List (α → β)) (xs : List α) : Tree (List α) :=
184+
match ds with
185+
| [] => .leaf xs
186+
| d :: ds' =>
187+
.node (List.map (mktree rng ds') (ptn₀ rng d xs))
188+
189+
def Tree.flatten (r : Tree (List α)) : List α :=
190+
match r with
191+
| .leaf v => v
192+
| .node ts =>
193+
List.flatten <| ts.map flatten
194+
195+
def bsort₀ {β : Type} [BEq β]
196+
(rng : List β) (ds : List (α → β)) (xs : List α) : List α :=
197+
Tree.flatten (mktree rng ds xs)
198+
199+
/-
200+
#eval bsort₀ "abc".toList
201+
[fun s => s.toList[0]!,fun s => s.toList[1]!]
202+
["ba", "ab", "aab", "bba"]
203+
-/
204+
205+
def bsort₁ {β : Type} [BEq β]
206+
(rng : List β) (ds : List (α → β)) (xs : List α) : List α :=
207+
match ds with
208+
| [] => xs
209+
| d :: ds' =>
210+
List.flatten <| List.map (bsort₁ rng ds') (ptn₀ rng d xs)
211+
212+
-- bsort₀ = bsort₁
213+
214+
theorem bsort_eq_bsort {β : Type} [BEq β]
215+
(rng : List β) (ds : List (α → β)): bsort₀ rng ds = bsort₁ rng ds := by
216+
induction ds with
217+
| nil =>
218+
funext xs
219+
simp [bsort₀, bsort₁, mktree, Tree.flatten]
220+
| cons d ds ih =>
221+
funext xs
222+
simp [bsort₀, mktree, Tree.flatten, bsort₁]
223+
simp [bsort₀] at ih
224+
rw [<- ih]
225+
congr 1
226+
227+
-- # Exercício 5.18
228+
229+
def tmap {β : Type} (f : α → β) : Tree α → Tree β
230+
| .leaf x => .leaf (f x)
231+
| .node ts => .node (ts.map (tmap f))
232+
233+
-- Claim da comutação de filters
234+
235+
theorem filter_comm {α: Type} (p q : α → Bool) (xs : List α) :
236+
(xs.filter p).filter q = (xs.filter q).filter p := by
237+
induction xs with
238+
| nil => simp
239+
| cons x xs ih =>
240+
simp only [List.filter_cons]
241+
split <;> split <;> simp_all
242+
243+
-- (5.6)
244+
245+
theorem ptn_filter_comm
246+
{β : Type} [BEq β]
247+
(rng : List β) (d : α → β) (p : α → Bool) (xs : List α) :
248+
List.map (List.filter p) (ptn₀ rng d xs) = ptn₀ rng d (xs.filter p) := by
249+
simp [ptn₀]
250+
intro a ha
251+
apply List.filter_congr
252+
intro x hx
253+
rw [Bool.and_comm]
254+
255+
-- (5.4)
256+
257+
theorem mktree_filter_comm
258+
{β : Type} [BEq β]
259+
(rng : List β) (ds : List (α → β)) (p : α → Bool) :
260+
(mktree rng ds) ∘ (List.filter p) = tmap (List.filter p) ∘ (mktree rng ds) := by
261+
induction ds with
262+
| nil =>
263+
funext xs
264+
simp [mktree, tmap]
265+
| cons d ds ih =>
266+
funext xs
267+
simp [mktree]
268+
rw [<- ptn_filter_comm]
269+
simp[ih, tmap]
270+
271+
-- Claim do Filter e Concat
272+
273+
theorem map_filter_concat_eq_filter_concat
274+
(p : α → Bool) :
275+
(List.map (List.filter p) xss).flatten = List.filter p (xss.flatten):= by
276+
induction xss with
277+
| nil =>
278+
simp [List.flatten, List.map, List.foldr]
279+
| cons xs xss ih =>
280+
simp [List.flatten, List.map, List.foldr]
281+
282+
-- Auxiliares para a prova por indução de (5.5)
283+
284+
def Tree.size {α : Type} : Tree α → Nat
285+
| leaf _ => 1
286+
| node ts => 1 + (List.map (Tree.size) ts).sum
287+
288+
theorem size_in_list {α : Type} (t : Tree α) (ts : List (Tree α))
289+
(h : t ∈ ts) : t.size < (Tree.node ts).size := by
290+
simp [Tree.size, List.foldl]
291+
induction ts with
292+
| nil => contradiction
293+
| cons t' ts ih =>
294+
simp [List.map]
295+
simp [List.mem_cons] at h
296+
cases h with
297+
| inl h_eq =>
298+
simp [h_eq]
299+
rw [Nat.add_comm]
300+
apply Nat.lt_succ_of_le
301+
apply Nat.le_add_right
302+
| inr h_tail =>
303+
have h_aux₁: t.size < 1 + (List.map Tree.size ts).sum := by simp [ih, h_tail]
304+
have h_aux₂: t.size < 1 + (t'.size + (List.map Tree.size ts).sum) := by
305+
apply Nat.lt_of_lt_of_le h_aux₁
306+
apply Nat.add_le_add_left
307+
exact Nat.le_add_left _ _
308+
exact h_aux₂
309+
310+
-- (5.5)
311+
312+
theorem flatten_tmap_filter_eq_filter_flatten
313+
(p : α → Bool):
314+
(Tree.flatten ∘ tmap (List.filter p)) = List.filter p ∘ Tree.flatten := by
315+
funext t
316+
rw [Function.comp_apply, Function.comp_apply]
317+
induction h : t.size using Nat.strong_induction_on generalizing t with
318+
| h k ih =>
319+
cases t with
320+
| leaf xs => simp [Tree.flatten, tmap]
321+
| node ts =>
322+
simp only [Tree.flatten, tmap]
323+
rw [<- map_filter_concat_eq_filter_concat]
324+
congr 1
325+
simp only [List.map_map]
326+
cases ts with
327+
| nil => simp
328+
| cons t' ts' =>
329+
simp only [List.map]
330+
congr 1
331+
case cons.e_head =>
332+
apply ih t'.size
333+
rw [<- h]
334+
apply size_in_list
335+
apply List.Mem.head
336+
rfl
337+
case cons.e_tail =>
338+
simp
339+
intro t'' h'
340+
apply ih t''.size
341+
rw [<- h]
342+
have h_aux₁: t''.size < (Tree.node ts').size := by
343+
apply size_in_list
344+
exact h'
345+
simp [Tree.size] at h_aux₁
346+
simp [Tree.size]
347+
have h_aux₂: 1 + (List.map Tree.size ts').sum ≤ 1 + (t'.size + (List.map Tree.size ts').sum) := by
348+
rw [Nat.add_le_add_iff_left]
349+
apply Nat.le_add_left
350+
apply Nat.lt_of_lt_of_le h_aux₁ h_aux₂
351+
rfl
352+
353+
theorem flatten_tmap_filter_eq_filter_flatten₁
354+
(p : α → Bool):
355+
(tmap (List.filter p) t).flatten = List.filter p (Tree.flatten t) := by
356+
cases t with
357+
| leaf xs => simp [Tree.flatten, tmap]
358+
| node ts =>
359+
simp only [Tree.flatten, tmap]
360+
rw [<- map_filter_concat_eq_filter_concat]
361+
simp only [List.map_map]
362+
rw [flatten_tmap_filter_eq_filter_flatten]
363+
364+
-- (5.3)
365+
366+
theorem bsort_partition_comm
367+
{α β : Type} [BEq β]
368+
(rng : List β) (ds : List (α → β)) (d : α → β) (xs : List α) :
369+
(List.map (bsort₀ rng ds) (ptn₀ rng d xs)) = ptn₀ rng d (bsort₀ rng ds xs) := by
370+
simp [bsort₀, ptn₀]
371+
intro a ha
372+
rw [← Function.comp_apply (f := mktree rng ds), mktree_filter_comm,
373+
Function.comp_apply (g := mktree rng ds),
374+
← Function.comp_apply (f := Tree.flatten),
375+
flatten_tmap_filter_eq_filter_flatten]
376+
simp
377+
378+
def rsort₀ {β : Type} [BEq β] (rng : List β) (ds : List (α → β)) (xs : List α) : List α :=
379+
match ds with
380+
| [] => xs
381+
| d :: ds' => List.flatten (ptn₀ rng d (rsort₀ rng ds' xs))
382+
383+
-- rsort₀ = bsort₁ = bsort₀
384+
385+
theorem rsort_eq_bsort {β : Type} [BEq β]
386+
(rng : List β) (ds : List (α → β)): rsort₀ rng ds = bsort₁ rng ds := by
387+
induction ds with
388+
| nil =>
389+
funext xs
390+
simp [rsort₀, bsort₁]
391+
| cons d ds' ih =>
392+
funext xs
393+
simp [rsort₀, bsort₁]
394+
rw [<- bsort_eq_bsort] at ih
395+
rw [<- bsort_eq_bsort, bsort_partition_comm, ih]
396+
397+
open Chapter3
398+
399+
def ptn₁ {α: Type} (r : Nat) (d : α → Nat) (xs : List α) : List (List α) :=
400+
let buckets := accumArray (flip List.cons) [] r (List.zip (xs.map d) xs)
401+
buckets.toList.map List.reverse
402+
403+
def rsort₁ {α: Type} (r : Nat) (ds : List (α → Nat)) (xs : List α) : List α :=
404+
match ds with
405+
| [] => xs
406+
| d :: ds' => List.flatten (ptn₁ r d (rsort₁ r ds' xs))
407+
408+
/-
409+
#eval rsort₁ 26
410+
[fun s => s.toList[0]!.toNat - 'a'.toNat,
411+
fun s => s.toList[1]!.toNat - 'a'.toNat]
412+
["ba", "ab", "aab", "bba"]
413+
-/
414+
415+
def pad (k : Nat) (s : String) : String :=
416+
List.foldl (· ++ ·) "" (List.replicate (k - s.length) "0") ++ s
417+
418+
def discs (xs : List Nat) : List (Nat → Nat) :=
419+
let k := (xs.map (λ x => (toString x).length)).foldr max 0
420+
List.range k |>.map (λ i => λ n =>
421+
let s := pad k (toString n)
422+
s.toList[i]! |>.toNat - '0'.toNat)
423+
424+
def insort (xs : List Nat) : List Nat :=
425+
rsort₁ 10 (discs xs) xs
426+
427+
/-
428+
#eval insort [42, 7, 13, 105, 0, 99, 4, 300]
429+
-/

0 commit comments

Comments
 (0)