@@ -18,19 +18,6 @@ style: |
18
18
<!--
19
19
```moonbit
20
20
let pi = 3.1415
21
-
22
- fn put(map: @map.Map[Int, Int64], num: Int, result: Int64) -> @map.Map[Int, Int64] {
23
- map.insert(num, result)
24
- }
25
-
26
- fn get(map: @map.Map[Int, Int64], num: Int) -> Option[Int64] {
27
- map.lookup(num)
28
- }
29
-
30
- fn make() -> @map.Map[Int, Int64] {
31
- @map.empty()
32
- }
33
-
34
21
```
35
22
-->
36
23
@@ -116,13 +103,13 @@ fn add_char(ch: Char, str: String) -> String {
116
103
let moonbit: String = add_char(Char::from_int(109), "oonbit")
117
104
```
118
105
119
- $$ \begin{align }
106
+ $$ \begin{aligned }
120
107
& \texttt{add\_char(Char::from\_int(109), "oonbit")} \\
121
108
\mapsto & \texttt{add\_char('m', "oonbit")} & \text{because \texttt{Char::from\_int(109)} $\mapsto$ \texttt{'m'}} \\
122
109
\mapsto & \texttt{'m'.to\_string() + "oonbit"} & \text{replace the occurrences of the parameters} \\
123
110
\mapsto & \texttt{"m" + "oonbit"} & \text{because \texttt{m.to\_string()} $\mapsto$ \texttt{"m"}} \\
124
111
\mapsto & \texttt{"moonbit"} & \text{because \texttt{"m" + "oonbit"} $\mapsto$ \texttt{"moonbit"}}
125
- \end{align } $$
112
+ \end{aligned } $$
126
113
127
114
---
128
115
@@ -207,7 +194,7 @@ let x: Int = answer() // 42
207
194
- Sometimes, we have data with the following characteristics:
208
195
- The data is ordered.
209
196
- The data can be duplicated.
210
- - The quantity of data is uncertain .
197
+ - The data can vary in length .
211
198
- For example:
212
199
- Words in a sentence: [ ` "Words" ` ` "in" ` ` "a" ` ` "sentence" ` ]
213
200
- DNA sequence: [ ` G ` ` A ` ` T ` ` T ` ` A ` ` C ` ` A ` ]
@@ -401,7 +388,7 @@ fn get(option_int: Option[Int64]) -> Int64 {
401
388
402
389
# Recursions
403
390
404
- - Recursion is the process of breaking down a problem into smaller subproblems that are similar to the original problem but of a ** smaller scale** .
391
+ - Recursion is the process of breaking down a problem into smaller subproblems that are similar to the original problem but of a ** reduced scale** .
405
392
- A recursion should have one or more ** base cases** .
406
393
- In the definition of a function, it directly or indirectly calls itself.
407
394
@@ -413,10 +400,10 @@ fn fib(n: Int) -> Int {
413
400
414
401
``` moonbit
415
402
fn even(n: Int) -> Bool {
416
- n != 1 && (n == 0 || odd(n - 1) )
403
+ n == 0 || odd(n - 1)
417
404
}
418
405
fn odd(n: Int) -> Bool {
419
- n != 0 && (n == 1 || even(n - 1) )
406
+ n == 1 || even(n - 1)
420
407
}
421
408
```
422
409
@@ -582,7 +569,7 @@ A large number of duplicated subproblems was observed.
582
569
583
570
# Dynamic Programming
584
571
585
- - Decompose the problem into smaller subproblems that are similar to the original problem but of a smaller scale.
572
+ - Decompose the problem into smaller subproblems that are similar to the original problem but of a reduced scale.
586
573
- Applicable to problems that have:
587
574
- ** Duplicated subproblems** : Dynamic programming solves each subproblem once and caches the result, avoiding redundant computations.
588
575
- ** Optimal substructure** : The global solution can be built from subproblems.
@@ -592,7 +579,7 @@ A large number of duplicated subproblems was observed.
592
579
593
580
---
594
581
595
- # Dynamic Programming: Fibonacci Sequence
582
+ # Solving Fibonacci Sequence with DP
596
583
597
584
- Dynamic programming is applicable to this problem.
598
585
- Duplicated subproblems: Both ` fib(n + 1) ` and ` fib(n + 2) ` require ` fib(n) ` .
@@ -607,13 +594,14 @@ A large number of duplicated subproblems was observed.
607
594
- We need a data structure whose average access efficiency is independent of the data size, and it should have the following interfaces:
608
595
609
596
``` moonbit no-check
610
- fn empty() -> IntMap // Create
611
- fn insert(map : IntMap, num : Int, value: Int64) -> IntMap // Store
612
- fn lookup(map : IntMap, num : Int) -> Option[Int64] // Retrieve
597
+ fn empty() -> IntMap // Create
598
+ fn insert(self : IntMap, key : Int, value: Int64) -> IntMap // Store
599
+ fn lookup(self : IntMap, key : Int) -> Option[Int64] // Retrieve
613
600
```
614
601
615
602
- There are many siutable data structures, e.g., ` @map.Map[Int, Int64] ` .
616
- - Its implementation is not our main focus, and it can be repleced with ` @vec.Vector[Option[Int64]] ` .
603
+ - Its implementation is not our main focus.
604
+ - It can be repleced with other suitable data structures.
617
605
618
606
---
619
607
@@ -626,16 +614,16 @@ fn lookup(map: IntMap, num: Int) -> Option[Int64] // Retrieve
626
614
``` moonbit expr
627
615
fn fib1(num: Int) -> Int64 {
628
616
fn aux(num: Int, map: @map.Map[Int, Int64]) -> (Int64, @map.Map[Int, Int64]) {
629
- match get( map, num) {
617
+ match map.lookup( num) {
630
618
Some(result) => (result, map)
631
619
None => {
632
620
let (result_1, map_1) = aux(num - 1, map)
633
621
let (result_2, map_2) = aux(num - 2, map_1)
634
- (result_1 + result_2, put( map_2, num, result_1 + result_2))
622
+ (result_1 + result_2, map_2.insert( num, result_1 + result_2))
635
623
}
636
624
}
637
625
}
638
- let map = put(put(make(), 1, 1L), 2, 1L)
626
+ let map = @map.empty().insert( 1, 1L).insert( 2, 1L)
639
627
aux(num, map).0
640
628
}
641
629
```
@@ -650,15 +638,15 @@ To simplify the code, MoonBit supports mutable variables.
650
638
``` moonbit expr
651
639
fn fib1_mut(num: Int) -> Int64 {
652
640
// Declare a mutable variable with let mut
653
- let mut map = put(put(make(), 1, 1L), 2, 1L)
641
+ let mut map = @map.empty().insert( 1, 1L).insert( 2, 1L)
654
642
fn aux(num: Int) -> Int64 {
655
- match get( map, num) {
643
+ match map.lookup( num) {
656
644
Some(result) => result
657
645
None => {
658
646
let result_1 = aux(num - 1)
659
647
let result_2 = aux(num - 2)
660
648
// Update the binding with <variable> = <expression>
661
- map = put( map, num, result_1 + result_2)
649
+ map = map.insert( num, result_1 + result_2)
662
650
result_1 + result_2
663
651
}
664
652
}
@@ -676,12 +664,12 @@ Starting from the first one, calculate and store the subsequent items sequential
676
664
``` moonbit expr
677
665
fn fib2(num: Int) -> Int64 {
678
666
fn aux(n: Int, map: @map.Map[Int, Int64]) -> Int64 {
679
- let result = get_or_else(get( map, n - 1), 1L) +
680
- get_or_else(get( map, n - 2), 1L)
681
- if n == num { result }
682
- else { aux(n + 1, put( map, n, result)) }
667
+ let result = get_or_else(map.lookup( n - 1), 1L) +
668
+ get_or_else(map.lookup( n - 2), 1L)
669
+ if n == num { result }
670
+ else { aux(n + 1, map.insert( n, result)) }
683
671
}
684
- let map = put(put(make(), 0, 0L), 1, 1L)
672
+ let map = @map.empty().insert( 0, 0L).insert( 1, 1L)
685
673
aux(1, map)
686
674
}
687
675
```
@@ -715,9 +703,9 @@ fn fib2(num : Int) -> Int64 {
715
703
- Data structure: lists and pattern matching on lists
716
704
- Algorithm: recursions and dynamic programming
717
705
- Extended reading:
718
- - _ Software Foundations, Volume 1: Logical Foundations _
706
+ - _ ** Software Foundations, Volume 1: Logical Foundations ** _
719
707
Basics, Induction & Lists
720
- - _ Programming Language Foundations in Agda _
708
+ - _ ** Programming Language Foundations in Agda ** _
721
709
Naturals, Induction & Relations
722
- - _ Introduction to Algorithms _
723
- Chapter 15 (3e) / Chapter 14 (4e): Dynamic Programming
710
+ - _ ** Introduction to Algorithms ** _
711
+ Chapter 15 (3e) / Chapter 14 (4e) - Dynamic Programming
0 commit comments