I thought that rewriting "Mathematical puzzles to train the programmer's brain" with Rust might be just right for preventing blurring.
The original Ruby code (p.015).
pre1_2.rb
M, N = 10, 100
@memo = {}
def check(remain, pre)
return @memo[[remain, pre]] if @memo[[remain,pre]]
return 0 if remain < 0
return 1 if remain == 0
cnt = 0
pre.upto(M) do |i|
cnt += check(remain - i, i)
end
@memo[[remain, pre]] = cnt
end
puts check(N, 2)
Rust solid transplant.
main.rs
use std::collections::HashMap;
fn main() {
let mut memo: HashMap<(i64, i64), i64> = HashMap::new();
println!("{}", check(&mut memo, 10, 100, 2));
}
fn check(
memo: &mut HashMap<(i64, i64), i64>,
max_seat_at_one_table: i64,
remain: i64,
pre: i64,
) -> i64 {
match memo.get(&(remain, pre)) {
Some(cnt) => return *cnt,
_ => {
if remain < 0 {
return 0;
} else if remain == 0 {
return 1;
} else {
let mut count = 0;
for i in pre..=max_seat_at_one_table {
count += check(memo, max_seat_at_one_table, remain - i, i);
}
memo.insert((remain, pre), count);
return count;
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_check() {
let max_seat_at_one_table = 10;
let number_of_people = 100;
let mut memo: HashMap<(i64, i64), i64> = HashMap::new();
assert_eq!(
check(&mut memo, max_seat_at_one_table, number_of_people, 2),
437_420
);
}
}
To get Rust's for
to do something similar to Ruby's ʻupto`, you have to +1.
If you think, @scivola pointed out. Thank you!
It's a global variable that I don't think in Ruby's shortcode, but I'm carrying it around because I don't know how to do it with Rust. Although it was also in Amazon's book review, if you omit variables like mathematics, you will not understand the reason, so I made it a long name only in the terrible part.
Once again, I feel the ease of Ruby (= trust in programmers) in the processing of conditional branching. Rust is compact but doesn't allow it to come off, but this is a good feeling.
Implemented again after being pointed out about the handling of global variables. A plan to realize global variables as struct
. This is already one foot in the design pattern.
main.rs
use std::collections::HashMap;
struct Checker {
memo: HashMap<(i64, i64), i64>,
max_seat_at_one_table: i64,
}
impl Checker {
pub fn check(&mut self, remain: i64, pre: i64) -> i64 {
match &self.memo.get(&(remain, pre)) {
Some(cnt) => return **cnt,
_ => {
if remain < 0 {
return 0;
} else if remain == 0 {
return 1;
} else {
let mut count = 0;
for i in pre..=self.max_seat_at_one_table {
count += self.check(remain - i, i);
}
&self.memo.insert((remain, pre), count);
return count;
}
}
}
}
}
fn main() {
let mut chk = Checker {
memo: HashMap::new(),
max_seat_at_one_table: 10,
};
println!("{}", chk.check(100, 2));
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_check() {
let number_of_people = 100;
let mut chk = Checker {
memo: HashMap::new(),
max_seat_at_one_table: 10,
};
assert_eq!(chk.check(number_of_people, 2), 437_420);
}
}
Recommended Posts