Systems in Rust
gccgitgitgitgitFor the general case of an arbitrary number of input sequences, the problem is NP-hard. When the number of sequences is constant, the problem is solvable in polynomial time by dynamic programming.
simplifying a complicated problem by breaking it down into simpler sub-problems in a recursive manner.
The purpose of this work is to provide an introduction to the mathe- matical theory of multi-stage decision processes. Since these constitute a somewhat formidable set of terms we have coined the term ‘dynamic programming’ to describe the subject matter.
If a problem can be solved by combining optimal solutions to non-overlapping sub-problems, the strategy is called “divide and conquer” instead. This is why merge sort and quick sort are not classified as dynamic programming problems.
\[ F_0 = 0 F_1 = 1 F_n = F_{n-1} + F_{n-2} \]
fib \[
\mathcal{O}(n) = \mathcal{O}(n-1) + \mathcal{O}(n-2)
\]Vec, and definitely not a HashMap
Vec so we’ll use usize
usize?fib we’ll use a helper functions, which we wrap.Vec and cast n to usizeVecVec contains the solution.fn main() {
for i in 0..11 {
println!("fib({}) = {}, fib_fast({}) = {}", i, fib(i), i, fib_fast(i));
}
}src/main.rs
fn fib(n: u64) -> u64 {
return match n {
0 => 0,
1 => 1,
n => fib(n - 1) + fib(n - 2),
};
}
// We "cheat" using `usize` to avoid casting.
fn fib_fast(n: u64) -> u64 {
let mem: Vec<usize> = vec![0, 1];
fn inner(x: usize, mut m: Vec<usize>) -> (usize, Vec<usize>) {
let ret: usize;
if x >= m.len() {
(_, m) = inner(x - 1, m);
ret = m[x - 1] + m[x - 2];
m.push(ret);
} else {
ret = m[x];
}
return (ret, m);
}
return inner(n as usize, mem).0 as u64;
}
fn main() {
for i in 0..11 {
println!("fib({}) = {}, fib_fast({}) = {}", i, fib(i), i, fib_fast(i));
}
}$ cargo run
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
Running `target/debug/scratch`
fib(0) = 0, fib_fast(0) = 0
fib(1) = 1, fib_fast(1) = 1
fib(2) = 1, fib_fast(2) = 1
fib(3) = 2, fib_fast(3) = 2
fib(4) = 3, fib_fast(4) = 3
fib(5) = 5, fib_fast(5) = 5
fib(6) = 8, fib_fast(6) = 8
fib(7) = 13, fib_fast(7) = 13
fib(8) = 21, fib_fast(8) = 21
fib(9) = 34, fib_fast(9) = 34
fib(10) = 55, fib_fast(10) = 55fib and fib_fast to print a line whenever performing an addition.fibinnermain to accept a command line \(n\) rather than just looping.main to accept a fast or slow flag f or s - after the \(n\).cargo bench for this, if you like cargo (I don’t)mainwc to count lines.user@cd-desk:~/tmp/scratch$ cargo run 2 s | wc
Compiling scratch v0.1.0 (/home/user/tmp/scratch)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.21s
Running `target/debug/scratch 2 s`
1 1 5
user@cd-desk:~/tmp/scratch$ cargo run 2 f | wc
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
Running `target/debug/scratch 2 f`
1 1 5$ (cargo run 40 s | wc ; cargo run 40 f | wc) 2>/dev/null
165580140 165580140 827900700
39 39 195
$ echo $((165580140/39))
4245644$ (time cargo run 40 s ; time cargo run 40 f )
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
Running `target/debug/scratch 40 s`
real 0m1.041s
user 0m1.058s
sys 0m0.012s
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
Running `target/debug/scratch 40 f`
real 0m0.043s
user 0m0.033s
sys 0m0.012s
$ echo $((1041/43))
24