Skip to content

Commit

Permalink
Overflow checks enabled. (#156)
Browse files Browse the repository at this point in the history
* Sanity workflow in debug mode.
  * Overflow occurs while calculating the Collatz sequence in a solution.
  * By some weird coincidence, this did not affect the result.
  * Running in debug mode will terminate the program upon overflow.
* Switched back to release mode, but enabled overflow checks.
* Improved logic to avoid overflow on 32-bit systems.
* Formatted.
* `Dockerfile`: more precise path.
  • Loading branch information
tfpf authored Apr 27, 2024
1 parent f515fa1 commit 40673b1
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 11 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ harness = false

[profile.release]
incremental = true
overflow-checks = true
strip = "debuginfo"
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM --platform=linux/i386 alpine:3.19
RUN apk add cargo
WORKDIR /project-euler
WORKDIR /github.com/tfpf/project-euler
COPY . .
31 changes: 21 additions & 10 deletions src/solutions/longest_collatz_sequence.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,38 @@
/// Find the length of the Collatz sequence starting from the given number
/// and ending at 1.
///
/// * `collatz_lengths` - Array to cache the lengths.
/// * `collatz_lengths` - Array to cache the lengths. Indexable with `num`.
/// * `num` - Number to find the length of the Collatz sequence for.
///
/// -> Length of Collatz sequence.
fn get_collatz_length(collatz_lengths: &mut Vec<i32>, num: usize) -> i32 {
if num == 1 {
return 1;
}
if num < collatz_lengths.len() && collatz_lengths[num] != 0 {
if collatz_lengths[num] != 0 {
return collatz_lengths[num];
}
let num_next = if num & 1 == 0 { num >> 1 } else { 3 * num + 1 };
let len = 1 + get_collatz_length(collatz_lengths, num_next);
if num < collatz_lengths.len() {
collatz_lengths[num] = len;
// In the course of Collatz iterations, a 32-bit number will overflow,
// which could lead to problems on 32-bit systems. Temporarily use a 64-bit
// number.
let mut num_next = num as u64;
for count in 1.. {
// Keep transforming this number until it can be used as an index into
// the cache.
num_next = if num_next % 2 == 0 {
num_next / 2
} else {
3 * num_next + 1
};
if num_next >= collatz_lengths.len() as u64 {
continue;
}
collatz_lengths[num] = count + get_collatz_length(collatz_lengths, num_next as usize);
return collatz_lengths[num];
}
len
unreachable!();
}

pub fn solve() -> i64 {
let mut collatz_lengths = vec![0; 1000000];
collatz_lengths[1] = 1;
let result = (2..collatz_lengths.len())
.map(|num| (get_collatz_length(&mut collatz_lengths, num), num))
.max()
Expand Down

0 comments on commit 40673b1

Please sign in to comment.