|
| 1 | +import Fad.Chapter3 |
1 | 2 | import Fad.Chapter4 |
2 | 3 | import Fad.Chapter5 |
3 | 4 |
|
@@ -161,3 +162,268 @@ opções de seções: |
161 | 162 | - 7.4 Decimal fractions in TEX |
162 | 163 |
|
163 | 164 | -/ |
| 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