Skip to content

Instantly share code, notes, and snippets.

@koivunej
Created December 9, 2023 10:17
Show Gist options
  • Save koivunej/94ac3027e380f7d8d81fc960a6a4c068 to your computer and use it in GitHub Desktop.
Save koivunej/94ac3027e380f7d8d81fc960a6a4c068 to your computer and use it in GitHub Desktop.
aoc 2023 day 06
fn main() {
// Time: 56 71 79 99
// Distance: 334 1135 1350 2430
let input = [(56, 334), (71, 1135), (79, 1350), (99, 2430)];
let phase1 = input
.iter()
.copied()
.map(|(race_millis, minimum_distance)| {
ways_to_win_with_immediate_accel(race_millis, minimum_distance)
})
.product::<usize>();
assert_eq!(phase1, 211_904);
let input = (56_71_79_99, 334_1135_1350_2430);
let phase2 = ways_to_win_with_immediate_accel(input.0, input.1);
assert_eq!(phase2, 43_364_472);
}
#[test]
fn example_1() {
// Time: 7 15 30
// Distance: 9 40 200
let input = [(7, 9), (15, 40), (30, 200)];
let phase1 = input
.iter()
.copied()
.map(|(race_millis, minimum_distance)| {
ways_to_win_with_immediate_accel(race_millis, minimum_distance)
})
.product::<usize>();
assert_eq!(288, phase1);
}
#[test]
fn example_2() {
let input = (71530, 940200);
assert_eq!(71503, ways_to_win_with_immediate_accel(input.0, input.1));
}
#[test]
#[cfg(not_now)]
fn example_9_millimeters_in_7_milliseconds_is_not_physical() {
let ways_to_win = 4;
let race_millis = 7;
let minimum_distance = 9;
// x = x_0 + v_0*t + 0.5 * a * t^2
// x = 0 + 0 + 0.5 * a * t^2
// x_done_accel = 0.5 * a * t^2
//
// until max-v then
//
// x_post_accel = x_done_accel + v_done_accel * t_done_accel + 0.5 * a * 0
// x_post_accel = x_done_accel + v_done_accel * t_done_accel
//
// so:
//
// x_total = x_post_accel
// x_total = 0.5 * a * t_accel^2 + v_done_accel * t_accel
//
// v_done_accel = v_0 + a * t_accel
//
// x_total = 0.5 * a * t_accel^2 + v_0 + a * t_accel * t_accel
// x_total = 0.5 * a * t_accel^2 + 0 + a * t_accel^2
// x_total = 1.5 * a * t_accel^2
//
// we want x_total > 9:
//
// 9 < 1.5 * a * t_accel^2
//
// accel is always 1 millimeters/milliseconds^2
//
// 9 > 3/2 * t_accel^2
// 9 * 2 / 3 > t_accel^2
// 18 / 3 > t_accel^2
// 6 > t_accel^2
// sqrt(6) > t_accel (t_accel > 0)
//
// or t_accel > sqrt(minimum_distance * 2 / 3)
let min_t_accel = (minimum_distance as f64 * 2.0 / 3.0).sqrt() as u64;
for hold_down_time in min_t_accel..(race_millis - min_t_accel) {
let mut pos = 0;
let mut vel = 0;
let accel = hold_down_time;
for t in 0..hold_down_time {
vel += t;
pos += vel;
}
for t in hold_down_time..race_millis {
pos += vel;
}
println!(
"{hold_down_time}ms => {}mm or {pos}mm",
3 * hold_down_time.pow(2) / 2
);
}
todo!()
}
#[test]
fn example_first_race_immediate_accel() {
let ways = ways_to_win_with_immediate_accel(7, 9);
assert_eq!(ways, 4);
let ways = ways_to_win_with_immediate_accel(15, 40);
assert_eq!(ways, 8);
let ways = ways_to_win_with_immediate_accel(30, 200);
assert_eq!(ways, 9);
}
fn ways_to_win_with_immediate_accel(race_millis: u64, minimum_distance: u64) -> usize {
// now v_0 = hold_down_time_millis
//
// x = x_0 + v_0 * t_remain
// x = v_0 * t_remain
//
// again x > minimum_distance
//
// minimum_distance < v_0 * t_remain
// v_0 * t_remain > minimum_distance
// v_0 * t_remain - minimum_distance > 0
(1..race_millis)
.filter_map(|hold_down_time| {
let t_remain = race_millis - hold_down_time;
let v_0 = hold_down_time;
if v_0 * t_remain > minimum_distance {
Some((hold_down_time, v_0 * t_remain))
} else {
None
}
})
.count()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment