Skip to content

Commit b8094b4

Browse files
committed
Solve Rust for 17/1,2 and 16/1
1 parent f7b8a1e commit b8094b4

File tree

8 files changed

+256
-8
lines changed

8 files changed

+256
-8
lines changed

native/aoc/src/lib.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
pub mod util {
22
pub mod io_helpers;
33
pub mod parsers;
4-
pub mod runner;
54
pub mod result;
5+
pub mod runner;
66
}
77

88
// All modules for year 2015
@@ -15,13 +15,16 @@ pub mod year_2015 {
1515

1616
// All modules for year 2016
1717
pub mod year_2016 {
18+
mod day_16_01;
1819
mod day_16_02;
1920
mod day_16_04;
2021
pub mod solver;
2122
}
2223

2324
// All modules for year 2017
2425
pub mod year_2017 {
26+
mod day_17_01;
27+
mod day_17_02;
2528
mod day_17_04;
2629
pub mod solver;
2730
}
@@ -64,10 +67,10 @@ pub mod year_2023 {
6467
pub mod solver;
6568
}
6669

70+
use rustler::Error;
6771
use util::io_helpers::read_input_from_resources;
6872
use util::result::Solution;
6973
use util::runner::Runner;
70-
use rustler::Error;
7174

7275
#[rustler::nif]
7376
fn solve(year: i16, day: i8) -> Result<Solution, Error> {

native/aoc/src/util/io_helpers.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@ pub fn validate_input(year: i16, day: i8) -> (bool, bool) {
2828
}
2929

3030
(year_ok, day_ok)
31-
}
31+
}

native/aoc/src/util/result.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use rustler::NifTaggedEnum;
22

3-
43
#[derive(NifTaggedEnum)]
54
pub enum Solution {
6-
BothString((String, String)),
7-
BothInt32((i32, i32)),
8-
BothUSize((usize, usize)),
9-
}
5+
BothString((String, String)),
6+
BothInt32((i32, i32)),
7+
BothUSize((usize, usize)),
8+
}

native/aoc/src/year_2016/day_16_01.rs

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
use std::collections::HashSet;
2+
3+
pub fn solve_16_01(raw_input: String) -> (i32, i32) {
4+
let input = process_input(&raw_input);
5+
6+
let mut position = Position::new();
7+
input.iter().for_each(|instruction| {
8+
position.step(instruction);
9+
});
10+
11+
let part_1 = position.location.manhattan_distance();
12+
let part_2 = position.repeat.unwrap().manhattan_distance();
13+
14+
(part_1, part_2)
15+
}
16+
17+
fn process_input(raw_input: &str) -> Vec<(Direction, i32)> {
18+
raw_input
19+
.trim()
20+
.split(", ")
21+
.map(|i| {
22+
let direction = match &i[0..=0] {
23+
"R" => Direction::Right,
24+
"L" => Direction::Left,
25+
value => panic!("Invalid instruction {value}"),
26+
};
27+
let steps: i32 = i[1..].parse::<i32>().unwrap();
28+
29+
(direction, steps)
30+
})
31+
.collect()
32+
}
33+
34+
enum Facing {
35+
North,
36+
East,
37+
South,
38+
West,
39+
}
40+
41+
enum Direction {
42+
Left,
43+
Right,
44+
}
45+
46+
#[derive(Debug)]
47+
struct Point {
48+
pub x: i32,
49+
pub y: i32,
50+
}
51+
52+
impl Point {
53+
pub fn manhattan_distance(&self) -> i32 {
54+
self.x.abs() + self.y.abs()
55+
}
56+
}
57+
58+
struct Position {
59+
facing: Facing,
60+
location: Point,
61+
visits: HashSet<(i32, i32)>,
62+
repeat: Option<Point>,
63+
}
64+
65+
impl Position {
66+
pub fn new() -> Position {
67+
Position {
68+
facing: Facing::North,
69+
location: Point { x: 0, y: 0 },
70+
visits: vec![(0, 0)].into_iter().collect(),
71+
repeat: Option::None,
72+
}
73+
}
74+
75+
pub fn step(&mut self, instruction: &(Direction, i32)) {
76+
let (direction, steps) = instruction;
77+
78+
match (direction, &self.facing) {
79+
(Direction::Left, Facing::North) => self.move_to((-1, 0), *steps),
80+
(Direction::Left, Facing::East) => self.move_to((0, 1), *steps),
81+
(Direction::Left, Facing::South) => self.move_to((1, 0), *steps),
82+
(Direction::Left, Facing::West) => self.move_to((0, -1), *steps),
83+
(Direction::Right, Facing::North) => self.move_to((1, 0), *steps),
84+
(Direction::Right, Facing::East) => self.move_to((0, -1), *steps),
85+
(Direction::Right, Facing::South) => self.move_to((-1, 0), *steps),
86+
(Direction::Right, Facing::West) => self.move_to((0, 1), *steps),
87+
}
88+
}
89+
90+
fn move_to(&mut self, delta: (i32, i32), steps: i32) {
91+
let (x_diff, y_diff) = delta;
92+
93+
self.facing = Self::facing_for_delta(delta);
94+
95+
for _ in 0..steps {
96+
let Point { x, y } = self.location;
97+
self.location = match x_diff {
98+
0 => Point { x, y: y + y_diff },
99+
_ => Point { x: x + x_diff, y },
100+
};
101+
102+
self.update_visits();
103+
}
104+
}
105+
106+
fn facing_for_delta(delta: (i32, i32)) -> Facing {
107+
match delta {
108+
(-1, 0) => Facing::West,
109+
(0, 1) => Facing::North,
110+
(1, 0) => Facing::East,
111+
(0, -1) => Facing::South,
112+
_ => unreachable!(),
113+
}
114+
}
115+
116+
fn update_visits(&mut self) {
117+
if self.repeat.is_none() {
118+
let Point { x, y } = self.location;
119+
if self.visits.contains(&(x, y)) {
120+
self.repeat = Some(Point { x, y });
121+
}
122+
self.visits.insert((x, y));
123+
}
124+
}
125+
}
126+
127+
#[cfg(test)]
128+
mod tests {
129+
use super::*;
130+
use crate::util::io_helpers::read_input_from_resources;
131+
132+
#[test]
133+
fn test_result_16_01() {
134+
let (year, day) = (2016, 1);
135+
let expected_result = (253, 126);
136+
137+
let raw_input = read_input_from_resources(year, day, false);
138+
assert_eq!(solve_16_01(raw_input), expected_result);
139+
}
140+
}

native/aoc/src/year_2016/solver.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
use crate::util::result::Solution;
22

3+
use super::day_16_01::solve_16_01;
34
use super::day_16_02::solve_16_02;
45
use super::day_16_04::solve_16_04;
56

67
const YEAR: i16 = 2016;
78

89
pub fn run(day: i8, input_data: String) -> Solution {
910
match day {
11+
1 => Solution::BothInt32(solve_16_01(input_data)),
1012
2 => Solution::BothString(solve_16_02(input_data)),
1113
4 => Solution::BothUSize(solve_16_04(input_data)),
1214
_ => panic!("Year {YEAR} day {day} has not been solved."),

native/aoc/src/year_2017/day_17_01.rs

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
pub fn solve_17_01(raw_input: String) -> (i32, i32) {
2+
let processed_input = process(raw_input);
3+
4+
(part_1(&processed_input), part_2(&processed_input))
5+
}
6+
7+
fn process(raw_input: String) -> Vec<i32> {
8+
raw_input
9+
.trim()
10+
.chars()
11+
.map(|c| (c as i32) - 0x30)
12+
.collect()
13+
}
14+
15+
fn part_1(input: &[i32]) -> i32 {
16+
captcha(input, 1)
17+
}
18+
19+
fn part_2(input: &[i32]) -> i32 {
20+
captcha(input, input.len() / 2)
21+
}
22+
23+
fn captcha(input: &[i32], by: usize) -> i32 {
24+
let mut rotated = input.to_owned();
25+
rotated.rotate_left(by);
26+
input
27+
.iter()
28+
.zip(rotated.iter())
29+
.filter_map(|(a, b)| (a == b).then_some(*a))
30+
.sum()
31+
}
32+
33+
#[cfg(test)]
34+
mod tests {
35+
use super::*;
36+
use crate::util::io_helpers::read_input_from_resources;
37+
38+
#[test]
39+
fn test_result_17_01() {
40+
let (year, day) = (2017, 1);
41+
let expected_result = (1089, 1156);
42+
43+
let raw_input = read_input_from_resources(year, day, false);
44+
assert_eq!(solve_17_01(raw_input), expected_result);
45+
}
46+
}

native/aoc/src/year_2017/day_17_02.rs

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use itertools::Itertools;
2+
3+
pub fn solve_17_02(raw_input: String) -> (i32, i32) {
4+
let input = process(&raw_input);
5+
(part_1(&input), part_2(&input))
6+
}
7+
8+
fn process(input_data: &str) -> Vec<Vec<i32>> {
9+
input_data.trim().split('\n').map(parse_row).collect()
10+
}
11+
12+
fn parse_row(line: &str) -> Vec<i32> {
13+
line.split('\t')
14+
.map(|cell| cell.parse::<i32>().unwrap())
15+
.sorted()
16+
.collect()
17+
}
18+
19+
fn part_1(input_data: &[Vec<i32>]) -> i32 {
20+
input_data
21+
.iter()
22+
.map(|row| row.last().unwrap() - row.first().unwrap())
23+
.sum()
24+
}
25+
26+
fn part_2(input_data: &[Vec<i32>]) -> i32 {
27+
input_data
28+
.iter()
29+
.map(|values| {
30+
for i in 0..values.len() {
31+
for j in i + 1..values.len() {
32+
if values[j] % values[i] == 0 {
33+
return values[j] / values[i];
34+
}
35+
}
36+
}
37+
unreachable!()
38+
})
39+
.sum()
40+
}
41+
42+
#[cfg(test)]
43+
mod tests {
44+
use super::*;
45+
use crate::util::io_helpers::read_input_from_resources;
46+
47+
#[test]
48+
fn test_result_17_02() {
49+
let raw_input = read_input_from_resources(2017, 2, false);
50+
let expected_result = (32020, 236);
51+
52+
assert_eq!(solve_17_02(raw_input), expected_result);
53+
}
54+
}

native/aoc/src/year_2017/solver.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
use crate::util::result::Solution;
22

3+
use super::day_17_01::solve_17_01;
4+
use super::day_17_02::solve_17_02;
35
use super::day_17_04::solve_17_04;
46

57
const YEAR: i16 = 2017;
68

79
pub fn run(day: i8, input_data: String) -> Solution {
810
match day {
11+
1 => Solution::BothInt32(solve_17_01(input_data)),
12+
2 => Solution::BothInt32(solve_17_02(input_data)),
913
4 => Solution::BothUSize(solve_17_04(input_data)),
1014
_ => panic!("Year {YEAR} day {day} has not been solved."),
1115
}

0 commit comments

Comments
 (0)