Rust 첫걸음 연습 문서의 문제 3 풀이 코드다.
//! 04 Rust 첫걸음 연습 p3: 콜라츠 단계 수를 loop의 break 값으로 돌려준다. 3n + 1이 u32를 넘으면 None.
//! 의존성: 없음 (표준 라이브러리만)
//! 실행: python3 "_시스템/Rust 계획/rs_check.py" "Rust/4.연습문제/04_rust-basics-practice_p3.rs"
/// n이 1이 될 때까지 짝수면 반으로, 홀수면 3n + 1로 바꾼다. 몇 번 바꿨는지 돌려준다.
/// n = 0이면 영원히 0이라 None, 중간에 u32를 넘으면 None.
fn collatz_steps(n: u32) -> Option<u32> {
if n == 0 {
return None;
}
let mut n = n;
let mut steps = 0;
loop {
if n == 1 {
break Some(steps);
}
n = if n.is_multiple_of(2) {
n / 2
} else {
match n.checked_mul(3).and_then(|m| m.checked_add(1)) {
Some(next) => next,
None => break None,
}
};
steps += 1;
}
}
fn main() {
assert_eq!(collatz_steps(1), Some(0));
assert_eq!(collatz_steps(6), Some(8)); // 6 3 10 5 16 8 4 2 1
assert_eq!(collatz_steps(7), Some(16));
assert_eq!(collatz_steps(27), Some(111));
assert_eq!(collatz_steps(0), None);
assert_eq!(collatz_steps(u32::MAX), None); // 홀수라 바로 3n + 1을 하고 넘친다
println!(
"1 -> {:?}, 6 -> {:?}, 27 -> {:?}, 0 -> {:?}, u32::MAX -> {:?}",
collatz_steps(1),
collatz_steps(6),
collatz_steps(27),
collatz_steps(0),
collatz_steps(u32::MAX)
);
// 1..10000에서 가장 오래 걸리는 수.
let (best, steps) = (1..10_000u32)
.map(|n| (n, collatz_steps(n).expect("작은 수는 넘치지 않는다")))
.max_by_key(|&(_, s)| s)
.unwrap();
assert_eq!((best, steps), (6171, 261));
println!("1..10000에서 가장 긴 것: {best} ({steps}단계)");
println!("ALL CHECKS PASSED");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn example() {
assert_eq!(collatz_steps(6), Some(8));
assert_eq!(collatz_steps(0), None);
}
}