mirror of
https://github.com/peter-tanner/advent-of-code-2022.git
synced 2024-11-30 06:10:22 +08:00
day 9
i learnt more about how memory safety in rust works and why we need to split a vector when mutating it in two locations to ensure they don't conflict. makes a lot of sense to me now. also learnt that tuples can be used in `match`, makes stuff really clean.
This commit is contained in:
parent
bb88b5b7ec
commit
dd3ec11462
|
@ -1,3 +1,123 @@
|
|||
use std::{collections::HashSet, fs::read_to_string};
|
||||
|
||||
const PATH: &str = "src/input";
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
println!("PART 1 {}", rope_sim(2));
|
||||
println!("PART 2 {}", rope_sim(10));
|
||||
}
|
||||
|
||||
fn rope_sim(rope_size: usize) -> usize {
|
||||
// FOR PART 1, THERE IS A SMARTER SOLUTION BUT WITH THE SIZE OF THE INPUT WE CAN DO IT WITH THE NAIVE SOLUTION.
|
||||
let binding = read_to_string(PATH).expect("Error reading file");
|
||||
assert!(binding.is_ascii());
|
||||
let data = binding.trim().split('\n').into_iter();
|
||||
|
||||
// WTF IS THIS???
|
||||
let mut rope = Vec::<(i32, i32)>::new();
|
||||
for _ in 0..rope_size {
|
||||
rope.push((0, 0));
|
||||
}
|
||||
|
||||
let mut tail_points = HashSet::<(i32, i32)>::new();
|
||||
tail_points.insert(*rope.last().unwrap());
|
||||
|
||||
for instruction in data {
|
||||
let mut tokens = instruction.split_ascii_whitespace().into_iter();
|
||||
let dir = tokens.next().unwrap();
|
||||
let mag = tokens.next().unwrap().parse::<usize>().unwrap();
|
||||
|
||||
for _ in 0..mag {
|
||||
// println!("({},{}), ({},{})", v_t.0, v_t.1, v_h.0, v_h.1);
|
||||
move_head(rope.get_mut(0).unwrap(), dir);
|
||||
for rope_part_i in 1..rope_size {
|
||||
// SEGMENT HEAD AND TAIL.
|
||||
let (part_1, part_2) = rope.split_at_mut(rope_part_i);
|
||||
let v_dh = part_1.get_mut(rope_part_i - 1).unwrap(); //rope.get_mut(rope_part_i - 1).unwrap()
|
||||
let v_dt = part_2.get_mut(0).unwrap(); //rope.get_mut(rope_part_i).unwrap()
|
||||
rule_1(&v_dh, v_dt);
|
||||
rule_2(&v_dh, v_dt);
|
||||
}
|
||||
tail_points.insert(*rope.last().unwrap());
|
||||
}
|
||||
// print_grid(12, &mut tail_points);
|
||||
}
|
||||
return tail_points.len();
|
||||
}
|
||||
|
||||
fn move_head(v_h: &mut (i32, i32), dir: &str) {
|
||||
let dir_p = dir.chars().nth(0).unwrap();
|
||||
match dir_p {
|
||||
'U' => v_h.1 -= 1,
|
||||
'D' => v_h.1 += 1,
|
||||
'L' => v_h.0 -= 1,
|
||||
'R' => v_h.0 += 1,
|
||||
_ => {
|
||||
panic!()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn rule_1(v_h: &(i32, i32), v_t: &mut (i32, i32)) {
|
||||
let di = v_h.0 - v_t.0;
|
||||
let dj = v_h.1 - v_t.1;
|
||||
|
||||
let change = match (di, dj) {
|
||||
(2, 0) => (1, 0),
|
||||
(0, 2) => (0, 1),
|
||||
(-2, 0) => (-1, 0),
|
||||
(0, -2) => (0, -1),
|
||||
_ => (0, 0),
|
||||
};
|
||||
v_t.0 += change.0;
|
||||
v_t.1 += change.1;
|
||||
}
|
||||
|
||||
fn rule_2(v_h: &(i32, i32), v_t: &mut (i32, i32)) {
|
||||
let di = v_h.0 - v_t.0;
|
||||
let dj = v_h.1 - v_t.1;
|
||||
|
||||
let change: (i32, i32) = match (di, dj) {
|
||||
(1, 2) => (1, 1),
|
||||
(2, 1) => (1, 1),
|
||||
(2, 2) => (1, 1),
|
||||
|
||||
(-2, -1) => (-1, -1),
|
||||
(-1, -2) => (-1, -1),
|
||||
(-2, -2) => (-1, -1),
|
||||
|
||||
(1, -2) => (1, -1),
|
||||
(2, -1) => (1, -1),
|
||||
(2, -2) => (1, -1),
|
||||
|
||||
(-1, 2) => (-1, 1),
|
||||
(-2, 1) => (-1, 1),
|
||||
(-2, 2) => (-1, 1),
|
||||
_ => (0, 0),
|
||||
};
|
||||
v_t.0 += change.0;
|
||||
v_t.1 += change.1;
|
||||
}
|
||||
|
||||
fn print_grid(
|
||||
r: i32,
|
||||
tail_points: &mut HashSet<(i32, i32)>,
|
||||
// v_h: &(i32, i32),
|
||||
// v_t: &mut (i32, i32),
|
||||
) {
|
||||
for j in -r..r {
|
||||
for i in -r..r {
|
||||
if i == 0 && j == 0 {
|
||||
print!("S");
|
||||
// } else if i == v_h.0 && j == v_h.1 {
|
||||
// print!("H")
|
||||
// } else if i == v_t.0 && j == v_t.1 {
|
||||
// print!("T")
|
||||
} else if tail_points.contains(&(i, j)) {
|
||||
print!("X");
|
||||
} else {
|
||||
print!("-");
|
||||
}
|
||||
}
|
||||
println!();
|
||||
}
|
||||
}
|
||||
|
|
121
day_9/src/main_pt1.rs
Normal file
121
day_9/src/main_pt1.rs
Normal file
|
@ -0,0 +1,121 @@
|
|||
use std::{collections::HashSet, fs::read_to_string};
|
||||
|
||||
fn parse_direction(dir: &str, mag: &str) -> (i32, i32) {
|
||||
let dir_p = dir.chars().nth(0).unwrap();
|
||||
let mag_p = mag.parse::<i32>().unwrap();
|
||||
let v = match dir_p {
|
||||
'U' => (0, -mag_p),
|
||||
'D' => (0, mag_p),
|
||||
'L' => (-mag_p, 0),
|
||||
'R' => (mag_p, 0),
|
||||
_ => {
|
||||
panic!()
|
||||
}
|
||||
};
|
||||
return v;
|
||||
}
|
||||
|
||||
fn move_head(v_h: &mut (i32, i32), dir: &str) {
|
||||
let dir_p = dir.chars().nth(0).unwrap();
|
||||
match dir_p {
|
||||
'U' => v_h.1 -= 1,
|
||||
'D' => v_h.1 += 1,
|
||||
'L' => v_h.0 -= 1,
|
||||
'R' => v_h.0 += 1,
|
||||
_ => {
|
||||
panic!()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn rule_1(v_h: &(i32, i32), v_t: &mut (i32, i32)) {
|
||||
let di = v_h.0 - v_t.0;
|
||||
let dj = v_h.1 - v_t.1;
|
||||
|
||||
let change = match (di, dj) {
|
||||
(2, 0) => (1, 0),
|
||||
(0, 2) => (0, 1),
|
||||
(-2, 0) => (-1, 0),
|
||||
(0, -2) => (0, -1),
|
||||
_ => (0, 0),
|
||||
};
|
||||
v_t.0 += change.0;
|
||||
v_t.1 += change.1;
|
||||
}
|
||||
|
||||
fn rule_2(v_h: &(i32, i32), v_t: &mut (i32, i32)) {
|
||||
let di = v_h.0 - v_t.0;
|
||||
let dj = v_h.1 - v_t.1;
|
||||
|
||||
let change: (i32, i32) = match (di, dj) {
|
||||
(1, 2) => (1, 1),
|
||||
(2, 1) => (1, 1),
|
||||
|
||||
(-2, -1) => (-1, -1),
|
||||
(-1, -2) => (-1, -1),
|
||||
|
||||
(1, -2) => (1, -1),
|
||||
(2, -1) => (1, -1),
|
||||
|
||||
(-1, 2) => (-1, 1),
|
||||
(-2, 1) => (-1, 1),
|
||||
_ => (0, 0),
|
||||
};
|
||||
v_t.0 += change.0;
|
||||
v_t.1 += change.1;
|
||||
}
|
||||
|
||||
fn print_grid(
|
||||
r: i32,
|
||||
tail_points: &mut HashSet<(i32, i32)>,
|
||||
v_h: &(i32, i32),
|
||||
v_t: &mut (i32, i32),
|
||||
) {
|
||||
for j in -r..r {
|
||||
for i in -r..r {
|
||||
if i == 0 && j == 0 {
|
||||
print!("S");
|
||||
// } else if i == v_h.0 && j == v_h.1 {
|
||||
// print!("H")
|
||||
// } else if i == v_t.0 && j == v_t.1 {
|
||||
// print!("T")
|
||||
} else if tail_points.contains(&(i, j)) {
|
||||
print!("X");
|
||||
} else {
|
||||
print!("-");
|
||||
}
|
||||
}
|
||||
println!();
|
||||
}
|
||||
}
|
||||
|
||||
const PATH: &str = "src/input";
|
||||
fn main() {
|
||||
// FOR PART 1, THERE IS A SMARTER SOLUTION BUT WITH THE SIZE OF THE INPUT WE CAN DO IT WITH THE NAIVE SOLUTION.
|
||||
let mut tail_points = HashSet::<(i32, i32)>::new();
|
||||
let binding = read_to_string(PATH).expect("Error reading file");
|
||||
assert!(binding.is_ascii());
|
||||
let data = binding.trim().split('\n').into_iter();
|
||||
|
||||
let v_h = &mut (0, 0);
|
||||
let v_t = &mut (0, 0);
|
||||
for instruction in data {
|
||||
let mut tokens = instruction.split_ascii_whitespace().into_iter();
|
||||
let dir = tokens.next().unwrap();
|
||||
let mag = tokens.next().unwrap().parse::<usize>().unwrap();
|
||||
|
||||
// println!("{} {}", dir, mag);
|
||||
|
||||
tail_points.insert(*v_t);
|
||||
|
||||
for i in 0..mag {
|
||||
// println!("({},{}), ({},{})", v_t.0, v_t.1, v_h.0, v_h.1);
|
||||
move_head(v_h, dir);
|
||||
rule_1(v_h, v_t);
|
||||
rule_2(v_h, v_t);
|
||||
tail_points.insert(*v_t);
|
||||
}
|
||||
}
|
||||
print_grid(5, &mut tail_points, v_h, v_t);
|
||||
println!("PART 1 {}", tail_points.len());
|
||||
}
|
Loading…
Reference in New Issue
Block a user