add: broken stuff

This commit is contained in:
Charles
2024-12-16 22:48:56 -08:00
parent 3b5da4379c
commit eec91476dc
13 changed files with 802 additions and 11 deletions
+9 -11
View File
@@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet};
use advent_of_code_2024::{make_main, next, Pair, SResult}; use advent_of_code_2024::{make_main, next, Pair, SResult};
use good_lp::{ use good_lp::{
coin_cbc, constraint::{self, eq}, variable, variables, Constraint, Expression, ProblemVariables, coin_cbc, constraint::{self, eq, geq, leq}, variable, variables, Constraint, Expression, ProblemVariables,
Solution, SolverModel, WithMipGap, Solution, SolverModel, WithMipGap,
}; };
use regex::Regex; use regex::Regex;
@@ -30,11 +30,7 @@ fn solve(lines: Vec<String>) -> SResult<(usize, usize)> {
let xpos = caps["xpos"].parse::<usize>().unwrap(); let xpos = caps["xpos"].parse::<usize>().unwrap();
let ypos = caps["ypos"].parse::<usize>().unwrap(); let ypos = caps["ypos"].parse::<usize>().unwrap();
total += solve2(&buttons, (xpos, ypos)); total += solve2(&buttons, (xpos, ypos));
let ans2 = solve2(&buttons, (xpos + 10000000000000, ypos + 10000000000000)); total2 += solve2(&buttons, (xpos + 10000000000000, ypos + 10000000000000));
if ans2 > 0 {
println!("Solved for pos {}, {}", xpos, ypos);
}
total2 += ans2;
} }
} }
Ok((total, total2)) Ok((total, total2))
@@ -51,17 +47,19 @@ fn solve2(buttons: &HashMap<String, Pair>, prize: Pair) -> usize {
0 <= b (integer) ; 0 <= b (integer) ;
} }
let prec = 0.001;
let sol = match vars2.minimise(a * 3 + b) let sol = match vars2.minimise(a * 3 + b)
.using(coin_cbc) .using(coin_cbc)
.with(eq(a*ax+b*bx, prize.0 as f64)) .with(geq((a+prec)*ax+(b+prec)*bx, prize.0 as f64))
.with(eq(a*ay+b*by, prize.1 as f64)) .with(leq((a-prec)*ax+(b-prec)*bx, prize.0 as f64))
.with(geq((a+prec)*ay+(b+prec)*by, prize.1 as f64))
.with(leq((a-prec)*ay+(b-prec)*by, prize.1 as f64))
.solve() { .solve() {
Ok(s) => s, Ok(s) => s,
Err(_) => return 0, Err(_) => return 0,
}; };
println!("a {}", sol.value(a));
println!("b {}", sol.value(b));
let a = sol.value(a).round() as usize; let a = sol.value(a).round() as usize;
let b = sol.value(b).round() as usize; let b = sol.value(b).round() as usize;
@@ -84,6 +82,6 @@ mod tests {
fn lp_solve() { fn lp_solve() {
let strings: Vec<String> = input!("d13p1.txt"); let strings: Vec<String> = input!("d13p1.txt");
let got = solve(strings).unwrap(); let got = solve(strings).unwrap();
assert_eq!(got, (480, 0)); assert_eq!(got, (480, 875318608908));
} }
} }
+135
View File
@@ -0,0 +1,135 @@
use std::{
collections::{HashMap, HashSet},
thread,
time::Duration,
};
use advent_of_code_2024::{make_main, next, Pair, SResult};
use regex::Regex;
make_main!();
fn solve(lines: Vec<String>) -> SResult<(usize, usize)> {
// NOTE: this needs to be adjusted for the size of the grid
let dims = (101, 103);
let pos_regex = Regex::new(r"p=(?<x>\d+),(?<y>\d+) v=(?<xvel>-?\d+),(?<yvel>-?\d+)").unwrap();
let mut robots = vec![];
for line in lines {
let caps = pos_regex.captures(&line.trim()).unwrap();
let x = caps["x"].parse::<usize>().unwrap();
let y = caps["y"].parse::<usize>().unwrap();
let xvel = caps["xvel"].parse::<i64>().unwrap();
let yvel = caps["yvel"].parse::<i64>().unwrap();
robots.push(Robot {
vel: (xvel, yvel),
pos: (x, y),
})
}
// Simulation GO
// 79, 388, 491, 697, 800, 903, 1006, 1109, 1212, 1315
let millis = Duration::from_millis(10);
let mut n = 0;
let mut tens = 11usize;
let mut ones = 24usize;
loop {
if (n / 100 == tens && n % 100 == ones) || (n >= 800 && (n - 800) % 103 == 0) {
print!("{}[2J", 27 as char);
println!("{}", n);
print_grid(&robots, dims);
if (n / 100 == tens && n % 100 == ones) {
tens += 1;
ones += 1;
}
thread::sleep(millis);
}
n += 1;
for robot in robots.iter_mut() {
robot.advance(dims);
}
}
//Ok((calc_safety(&robots, dims).iter().fold(1, |x, y| x * y), 0))
}
#[derive(Debug)]
struct Robot {
vel: Pair<i64>,
pos: Pair,
}
impl Robot {
fn advance(&mut self, dims: Pair) {
self.pos.0 = roll(self.pos.0, self.vel.0, dims.0);
self.pos.1 = roll(self.pos.1, self.vel.1, dims.1);
}
}
fn roll(pos: usize, vel: i64, dim: usize) -> usize {
let ipos = pos as i64;
if ipos + vel >= 0 {
((ipos + vel) as usize) % dim
} else {
((ipos + vel) + dim as i64) as usize
}
}
fn calc_safety(robots: &[Robot], dims: Pair) -> [usize; 4] {
let mut scores = [0usize; 4];
for robot in robots {
let xhalf = part(robot.pos.0, dims.0);
let yhalf = part(robot.pos.1, dims.1);
match (xhalf, yhalf) {
(0, 0) => scores[0] += 1,
(0, 1) => scores[1] += 1,
(1, 0) => scores[2] += 1,
(1, 1) => scores[3] += 1,
_ => {
// Do nothing; this is expected
}
}
}
scores
}
fn part(pos: usize, dim: usize) -> usize {
if pos < dim / 2 {
0
} else if pos > dim / 2 {
1
} else {
2
}
}
fn print_grid(robots: &[Robot], dims: Pair) {
println!("");
let mut pos = HashMap::new();
for rob in robots {
*pos.entry(rob.pos).or_insert(0) += 1;
}
for j in 0..dims.1 {
for i in 0..dims.0 {
if let Some(count) = pos.get(&(i, j)) {
print!("{}", count);
} else {
print!(" ");
}
}
println!("");
}
println!("");
}
#[cfg(test)]
mod tests {
use advent_of_code_2024::input;
use super::*;
#[test]
fn d14p1() {
return;
let strings: Vec<String> = input!("d14p1.txt");
let got = solve(strings).unwrap();
assert_eq!(got, (12, 0));
}
}
+12
View File
@@ -0,0 +1,12 @@
p=0,4 v=3,-3
p=6,3 v=-1,-3
p=10,3 v=-1,2
p=2,0 v=2,-1
p=0,0 v=1,3
p=3,0 v=-2,-2
p=7,6 v=-1,-3
p=3,0 v=-1,-2
p=9,3 v=2,3
p=7,3 v=-1,2
p=2,4 v=2,-3
p=9,5 v=-3,-3
+21
View File
@@ -0,0 +1,21 @@
##########
#..O..O.O#
#......O.#
#.OO..O.O#
#..O@..O.#
#O#..O...#
#O..O..O.#
#.OO.O.OO#
#....O...#
##########
<vv>^<v^>v>^vv^v>v<>v^v<v<^vv<<<^><<><>>v<vvv<>^v^>^<<<><<v<<<v^vv^v>^
vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<<v<^v>^<^^>>>^<v<v
><>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^<v>v^^<^^vv<
<<v<^>>^^^^>>>v^<>vvv^><v<<<>^^^vv^<vvv>^>v<^^^^v<>^>vvvv><>>v^<<^^^^^
^><^><>>><>^^<<^^v>>><^<v>^<vv>>v>>>^v><>^v><<<<v>>v<v<v>vvv>^<><<>^><
^>><>^v<><^vvv<^^<><v<<<<<><^v<<<><<<^^<v<^^^><^>>^<v^><<<^>>^v<v^v<v^
>^>>^v>vv>^<<^v<>><<><<v<<v><>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^
<><^^>^^^<><vvvvv^v<v<<>^v<v>v<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>
^^>vv<^v^v<vv>^<><v<^v>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><<v>
v^^>>><<^^<>>^v^<v^vv<>v^<<>^<^v^v><^<<<><<^<v><v<>vv>>v><v^<vv<>v^<<^
+10
View File
@@ -0,0 +1,10 @@
########
#..O.O.#
##@.O..#
#...O..#
#.#.O..#
#...O..#
#......#
########
<^^>>>vv<v>>v<<
+189
View File
@@ -0,0 +1,189 @@
use std::{
collections::{HashMap, HashSet},
thread,
time::Duration,
};
use advent_of_code_2024::{make_main, next, next2, Pair, SResult};
use regex::Regex;
make_main!();
fn solve(lines: Vec<String>) -> SResult<(usize, usize)> {
// Read in the grid
let mut grid: Vec<Vec<char>> = Vec::with_capacity(lines.len());
let mut grid2: Vec<Vec<char>> = Vec::with_capacity(lines.len());
for line in &lines {
if line.trim() == "" {
break;
}
let mut row = Vec::with_capacity(line.len());
let mut row2 = Vec::with_capacity(2 * line.len());
for c in line.trim().chars() {
row.push(c);
match c {
'#' => {
row2.push('#');
row2.push('#');
}
'O' => {
row2.push('[');
row2.push(']');
}
'.' => {
row2.push('.');
row2.push('.');
}
'@' => {
row2.push('@');
row2.push('.');
}
c => panic!("unknown char: {}", c),
}
}
grid.push(row);
grid2.push(row2);
}
assert_eq!(grid.len(), grid[0].len());
// Read in the rest of the puzzle
let mut actions = Vec::new();
for line in &lines[grid.len() + 1..] {
for char in line.trim().chars() {
actions.push(char);
}
}
// Find starting position
let mut pos = find_pos(&grid);
let mut pos2 = find_pos(&grid2);
for action in actions {
let mut temp_grid = grid.clone();
if let Some(new_pos) = mov(pos, vel(action), &mut temp_grid) {
grid = temp_grid;
grid[pos.0][pos.1] = '.';
pos = new_pos;
grid[pos.0][pos.1] = '@';
}
let mut temp_grid = grid2.clone();
if let Some(new_pos) = mov(pos2, vel(action), &mut temp_grid) {
grid2 = temp_grid;
grid2[pos2.0][pos2.1] = '.';
pos2 = new_pos;
grid2[pos2.0][pos2.1] = '@';
}
}
Ok((sum(&grid), sum(&grid2)))
}
// attempts to move; returns false if it can't be done
fn mov(pos: Pair, vel: Pair<i64>, grid: &mut [Vec<char>]) -> Option<Pair> {
if grid[pos.0][pos.1] == '.' {
return Some(pos);
}
if grid[pos.0][pos.1] == '#' {
return None;
}
let mut to_move = vec![(pos, grid[pos.0][pos.1])];
if grid[pos.0][pos.1] == '[' && vel.0 != 0 {
assert_eq!(grid[pos.0][pos.1+1], ']');
let pos = (pos.0, pos.1 + 1);
to_move.push((pos, grid[pos.0][pos.1]));
} else if grid[pos.0][pos.1] == ']' && vel.0 != 0 {
assert_eq!(grid[pos.0][pos.1-1], '[');
let pos = (pos.0, pos.1 - 1);
to_move.push((pos, grid[pos.0][pos.1]));
}
let mut valid = true;
let mut moved_pos = pos;
for pos in to_move {
let next = if let Some(n) = next2(pos.0, vel, (grid.len(), grid[0].len())) {
n
} else {
valid = false;
break;
};
if let Some(_) = mov(next, vel, grid) {
let old_char = pos.1;
let pos = pos.0;
grid[next.0][next.1] = grid[pos.0][pos.1];
// assert that the previous position did not change;
// in case of a stack that somehow cycles (not sure how this could happen?)
assert_eq!(old_char, grid[pos.0][pos.1]);
grid[pos.0][pos.1] = '.';
moved_pos = next;
} else {
valid = false;
break;
}
}
if valid {
Some(moved_pos)
} else {
None
}
}
fn find_pos(grid: &[Vec<char>]) -> Pair {
for i in 0..grid.len() {
for j in 0..grid[i].len() {
if grid[i][j] == '@' {
return (i, j);
}
}
}
panic!("No @ found");
}
fn vel(m: char) -> Pair<i64> {
match m {
'>' => (0, 1),
'<' => (0, -1),
'^' => (-1, 0),
'v' => (1, 0),
c => panic!("not implemented: {}", c),
}
}
fn sum(grid: &[Vec<char>]) -> usize {
let mut sum = 0;
for i in 0..grid.len() {
for j in 0..grid[i].len() {
if grid[i][j] == 'O' || grid[i][j] == '[' {
sum += 100 * i + j;
}
}
}
sum
}
fn print_grid(grid: &[Vec<char>]) {
println!("");
for i in 0..grid.len() {
for j in 0..grid[i].len() {
print!("{}", grid[i][j]);
}
println!("");
}
}
#[cfg(test)]
mod tests {
use advent_of_code_2024::input;
use super::*;
#[test]
fn d15i1() {
let strings: Vec<String> = input!("d15i1.txt");
let got = solve(strings).unwrap();
assert_eq!(got, (10092, 9021));
}
#[test]
fn d15i2() {
return;
let strings: Vec<String> = input!("d15i2.txt");
let got = solve(strings).unwrap();
assert_eq!(got, (2028, 105));
}
}
+15
View File
@@ -0,0 +1,15 @@
###############
#.......#....E#
#.#.###.#.###.#
#.....#.#...#.#
#.###.#####.#.#
#.#.#.......#.#
#.#.#####.###.#
#...........#.#
###.#.#####.#.#
#...#.....#.#.#
#.#.#.###.#.#.#
#.....#...#.#.#
#.###.#.#.#.#.#
#S..#.....#...#
###############
+17
View File
@@ -0,0 +1,17 @@
#################
#...#...#...#..E#
#.#.#.#.#.#.#.#.#
#.#.#.#...#...#.#
#.#.#.#.###.#.#.#
#...#.#.#.....#.#
#.#.#.#.#.#####.#
#.#...#.#.#.....#
#.#.#####.#.###.#
#.#.#.......#...#
#.#.###.#####.###
#.#.#...#.....#.#
#.#.#.#####.###.#
#.#.#.........#.#
#.#.#.#########.#
#S#.............#
#################
+202
View File
@@ -0,0 +1,202 @@
use std::{
cmp::min,
collections::{HashMap, HashSet, VecDeque},
thread,
time::Duration,
usize,
};
use advent_of_code_2024::{make_main, mul_pair, next, next2, Pair, SResult};
use regex::Regex;
make_main!();
fn solve(lines: Vec<String>) -> SResult<(usize, usize)> {
// Read in the grid
let mut grid: Vec<Vec<char>> = Vec::with_capacity(lines.len());
let mut start = (0, 0);
let mut end = (0, 0);
for (i, line) in lines.iter().enumerate() {
let mut row = Vec::with_capacity(lines[i].len());
for (j, c) in line.chars().enumerate() {
row.push(c);
if c == 'S' {
start = (i, j);
}
if c == 'E' {
end = (i, j);
}
}
grid.push(row);
}
assert_eq!(grid.len(), grid[0].len());
let width = grid.len();
// Create a map of the cells we visited, and how long it took to get there
let visited: HashMap<(char, Pair), usize> = make_visited(start, end, &grid);
// Find the best answer for end
let ans = min_score(end, &visited);
// We will walk backward through the tiles to find all paths
let mut best_tiles: HashSet<Pair> = HashSet::new();
best_tiles.insert(end);
// Find all 'angles' of the starting pos which had the best score
let mut stack: Vec<(char, (usize, usize))> = vec![
('>', end),
('<', end),
('v', end),
('^', end),
]
.into_iter()
.filter(|(angle, pos)| *visited.get(&(*angle, *pos)).unwrap_or(&usize::MAX) == ans)
.collect();
// Loop through the stack
while let Some((old_angle, pos)) = stack.pop() {
if pos == start {
continue;
}
// Find the best score
let mut best_score = usize::MAX;
for angle in angles() {
let vel = mul_pair(vel(angle), -1);
if let Some(pos) = next(pos, vel, width) {
let mut score = *visited.get(&(angle, pos)).unwrap_or(&usize::MAX);
if angle != old_angle && score != usize::MAX {
if next_angle(angle).contains(&old_angle) {
score += 1000;
} else {
score += 2000;
}
}
if score < best_score {
best_score = score;
}
}
}
// Find the 'angles' of this tile that had the best score
for angle in angles() {
let vel = mul_pair(vel(angle), -1);
if let Some(pos) = next(pos, vel, width) {
let mut score = *visited.get(&(angle, pos)).unwrap_or(&usize::MAX);
if angle != old_angle && score != usize::MAX {
if next_angle(angle).contains(&old_angle) {
score += 1000;
} else {
score += 2000;
}
}
if score == best_score && !best_tiles.contains(&pos) {
stack.push((angle, pos));
best_tiles.insert(pos);
grid[pos.0][pos.1] = 'O';
}
}
}
}
Ok((ans, best_tiles.len()))
}
fn angles() -> [char; 4] {
['<', '>', '^', 'v']
}
fn min_score(end: Pair, visited: &HashMap<(char, Pair), usize>) -> usize {
*min(
visited.get(&('<', end)).unwrap_or(&usize::MAX),
min(
visited.get(&('>', end)).unwrap_or(&usize::MAX),
min(
visited.get(&('^', end)).unwrap_or(&usize::MAX),
visited.get(&('v', end)).unwrap_or(&usize::MAX),
),
),
)
}
fn make_visited(start: Pair, end: Pair, grid: &[Vec<char>]) -> HashMap<(char, (usize, usize)), usize> {
let width = grid.len();
let mut visited: HashMap<(char, Pair), usize> = HashMap::default();
let mut stack = vec![('>', 0, start)];
while let Some((angle, score, pos)) = stack.pop() {
if pos == end {
let entry = visited.entry((angle, pos)).or_insert(usize::MAX);
if *entry > score {
*entry = score;
}
continue;
}
// Try going forward
if let Some(next) = next(pos, vel(angle), width) {
let prev_score = visited.get(&(angle, next)).unwrap_or(&usize::MAX);
let new_score = score + 1;
if grid[next.0][next.1] != '#' && *prev_score >= new_score {
stack.push((angle, new_score, next));
visited.insert((angle, next), new_score);
}
}
// Try rotation left, right
for angle in next_angle(angle) {
let prev_score = visited.get(&(angle, pos)).unwrap_or(&usize::MAX);
let new_score = score + 1000;
if *prev_score >= new_score {
stack.push((angle, new_score, pos));
visited.insert((angle, pos), new_score);
}
}
}
visited
}
fn vel(m: char) -> Pair<i64> {
match m {
'>' => (0, 1),
'<' => (0, -1),
'^' => (-1, 0),
'v' => (1, 0),
c => panic!("not implemented: {}", c),
}
}
fn next_angle(m: char) -> [char; 2] {
match m {
'<' | '>' => ['^', 'v'],
'v' | '^' => ['<', '>'],
c => panic!("not implemented: {}", c),
}
}
fn print_grid(grid: &[Vec<char>]) {
println!("");
for i in 0..grid.len() {
for j in 0..grid[i].len() {
print!("{}", grid[i][j]);
}
println!("");
}
}
#[cfg(test)]
mod tests {
use advent_of_code_2024::input;
use super::*;
#[test]
fn d16i1() {
let strings: Vec<String> = input!("d16i1.txt");
let got = solve(strings).unwrap();
assert_eq!(got, (7036, 45));
}
#[test]
fn d16i2() {
let strings: Vec<String> = input!("d16i2.txt");
let got = solve(strings).unwrap();
assert_eq!(got, (11048, 64));
}
}
+5
View File
@@ -0,0 +1,5 @@
Register A: 2024
Register B: 0
Register C: 0
Program: 0,3,5,4,3,0
+5
View File
@@ -0,0 +1,5 @@
Register A: 729
Register B: 0
Register C: 0
Program: 0,1,5,4,3,0
+172
View File
@@ -0,0 +1,172 @@
use std::{collections::{HashMap, HashSet}, process::exit, thread, time::Duration};
use advent_of_code_2024::{make_main, SResult};
use regex::Regex;
use threadpool::ThreadPool;
make_main!();
struct State<'a> {
registers: [usize; 3],
pointer: usize,
program: &'a [usize],
}
impl<'a> State<'a> {
fn new(program: &'a [usize], registers: [usize; 3]) -> Self {
Self {
registers,
pointer: 0,
program,
}
}
fn run_to_end(&mut self) -> Vec<usize> {
let mut results = vec![];
let mut i = 0;
while self.pointer < self.program.len() {
if let Some(val) = self.opcode() {
if val != self.program[i] {
break;
}
results.push(val);
i += 1;
if i == self.program.len() {
break;
}
}
}
results
}
// Processes opcode and returns the program pointer
fn opcode(&mut self) -> Option<usize> {
let opcode = self.program[self.pointer];
let operand = self.program[self.pointer + 1];
match opcode {
0 => {
self.registers[0] = self.registers[0] / (usize::pow(2, self.combo(operand) as u32));
self.pointer += 2
}
1 => {
self.registers[1] = self.registers[1] ^ operand;
self.pointer += 2
}
2 => {
self.registers[1] = self.combo(operand) % 8;
self.pointer += 2
}
3 => {
if self.registers[0] == 0 {
self.pointer += 2
} else {
self.pointer = operand;
}
}
4 => {
self.registers[1] = self.registers[1] ^ self.registers[2];
self.pointer += 2
}
5 => {
self.pointer += 2;
return Some(self.combo(operand) % 8);
}
6 => {
self.registers[1] = self.registers[0] / (usize::pow(2, self.combo(operand) as u32));
self.pointer += 2
}
7 => {
self.registers[2] = self.registers[0] / (usize::pow(2, self.combo(operand) as u32));
self.pointer += 2
}
_ => unimplemented!(),
};
None
}
fn combo(&self, val: usize) -> usize {
match val {
0..4 => val,
4 => self.registers[0],
5 => self.registers[1],
6 => self.registers[2],
_ => unimplemented!(),
}
}
}
fn solve(lines: Vec<String>) -> SResult<(usize, usize)> {
let mut registers: HashMap<String, usize> = HashMap::default();
let regex = Regex::new(r"Register (\w+): (\d+)").unwrap();
let mut i = 0;
while i < lines.len() && lines[i].trim() != "" {
let caps = regex.captures(&lines[i]).unwrap();
i += 1;
registers.insert(caps[1].into(), caps[2].parse().unwrap());
}
i += 1;
let program: Vec<usize> = lines[i]
.strip_prefix("Program: ")
.unwrap()
.split(",")
.map(|s| s.parse().unwrap())
.collect();
let values =
State::new(&program, [registers["A"], registers["B"], registers["C"]]).run_to_end();
for (i, n) in values.iter().enumerate() {
if i > 0 {
print!(",");
}
print!("{}", n);
}
println!();
let pool = ThreadPool::new(20);
//let mut n = 3536000000;
let mut n = 0;
let program: &'static mut [usize] = program.leak();
loop {
{
let n = n;
let program: &'static [usize] = program;
pool.execute(move || {
let values = State::new(&program, [n, 0, 0]).run_to_end();
if values.len() > 4 {
println!("{} => {:?}", n, values);
}
while &values == program {
println!("finished at {}", n);
//exit(n as i32);
}
});
}
n += 1;
if n % 1000000 == 0 {
println!("n = {}", n);
}
while pool.queued_count() > 10000 {
thread::sleep(Duration::from_millis(10));
}
}
Ok((values.len(), n))
}
#[cfg(test)]
mod tests {
use advent_of_code_2024::input;
use super::*;
#[test]
fn d17i1() {
let strings: Vec<String> = input!("d17i1.txt");
let got = solve(strings).unwrap();
assert_eq!(got, (4, 117440));
}
#[test]
fn d17i2() {
return;
let strings: Vec<String> = input!("d17i2.txt");
let got = solve(strings).unwrap();
assert_eq!(got, (4, 117440));
}
}
+10
View File
@@ -42,6 +42,16 @@ pub fn next((x, y): Pair, (xvel, yvel): Pair<i64>, width: usize) -> Option<Pair>
} }
} }
pub fn next2((x, y): Pair, (xvel, yvel): Pair<i64>, (width, height): Pair) -> Option<Pair> {
let x = x as i64 + xvel;
let y = y as i64 + yvel;
if x < 0 || y < 0 || x >= width as i64 || y >= height as i64 {
None
} else {
Some((x as usize, y as usize))
}
}
pub fn nexti64((x, y): Pair<i64>, (xvel, yvel): Pair<i64>, width: usize) -> Option<Pair<i64>> { pub fn nexti64((x, y): Pair<i64>, (xvel, yvel): Pair<i64>, width: usize) -> Option<Pair<i64>> {
let x = x + xvel; let x = x + xvel;
let y = y + yvel; let y = y + yvel;