-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f7b8a1e
commit b8094b4
Showing
8 changed files
with
256 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,4 +28,4 @@ pub fn validate_input(year: i16, day: i8) -> (bool, bool) { | |
} | ||
|
||
(year_ok, day_ok) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,8 @@ | ||
use rustler::NifTaggedEnum; | ||
|
||
|
||
#[derive(NifTaggedEnum)] | ||
pub enum Solution { | ||
BothString((String, String)), | ||
BothInt32((i32, i32)), | ||
BothUSize((usize, usize)), | ||
} | ||
BothString((String, String)), | ||
BothInt32((i32, i32)), | ||
BothUSize((usize, usize)), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
use std::collections::HashSet; | ||
|
||
pub fn solve_16_01(raw_input: String) -> (i32, i32) { | ||
let input = process_input(&raw_input); | ||
|
||
let mut position = Position::new(); | ||
input.iter().for_each(|instruction| { | ||
position.step(instruction); | ||
}); | ||
|
||
let part_1 = position.location.manhattan_distance(); | ||
let part_2 = position.repeat.unwrap().manhattan_distance(); | ||
|
||
(part_1, part_2) | ||
} | ||
|
||
fn process_input(raw_input: &str) -> Vec<(Direction, i32)> { | ||
raw_input | ||
.trim() | ||
.split(", ") | ||
.map(|i| { | ||
let direction = match &i[0..=0] { | ||
"R" => Direction::Right, | ||
"L" => Direction::Left, | ||
value => panic!("Invalid instruction {value}"), | ||
}; | ||
let steps: i32 = i[1..].parse::<i32>().unwrap(); | ||
|
||
(direction, steps) | ||
}) | ||
.collect() | ||
} | ||
|
||
enum Facing { | ||
North, | ||
East, | ||
South, | ||
West, | ||
} | ||
|
||
enum Direction { | ||
Left, | ||
Right, | ||
} | ||
|
||
#[derive(Debug)] | ||
struct Point { | ||
pub x: i32, | ||
pub y: i32, | ||
} | ||
|
||
impl Point { | ||
pub fn manhattan_distance(&self) -> i32 { | ||
self.x.abs() + self.y.abs() | ||
} | ||
} | ||
|
||
struct Position { | ||
facing: Facing, | ||
location: Point, | ||
visits: HashSet<(i32, i32)>, | ||
repeat: Option<Point>, | ||
} | ||
|
||
impl Position { | ||
pub fn new() -> Position { | ||
Position { | ||
facing: Facing::North, | ||
location: Point { x: 0, y: 0 }, | ||
visits: vec![(0, 0)].into_iter().collect(), | ||
repeat: Option::None, | ||
} | ||
} | ||
|
||
pub fn step(&mut self, instruction: &(Direction, i32)) { | ||
let (direction, steps) = instruction; | ||
|
||
match (direction, &self.facing) { | ||
(Direction::Left, Facing::North) => self.move_to((-1, 0), *steps), | ||
(Direction::Left, Facing::East) => self.move_to((0, 1), *steps), | ||
(Direction::Left, Facing::South) => self.move_to((1, 0), *steps), | ||
(Direction::Left, Facing::West) => self.move_to((0, -1), *steps), | ||
(Direction::Right, Facing::North) => self.move_to((1, 0), *steps), | ||
(Direction::Right, Facing::East) => self.move_to((0, -1), *steps), | ||
(Direction::Right, Facing::South) => self.move_to((-1, 0), *steps), | ||
(Direction::Right, Facing::West) => self.move_to((0, 1), *steps), | ||
} | ||
} | ||
|
||
fn move_to(&mut self, delta: (i32, i32), steps: i32) { | ||
let (x_diff, y_diff) = delta; | ||
|
||
self.facing = Self::facing_for_delta(delta); | ||
|
||
for _ in 0..steps { | ||
let Point { x, y } = self.location; | ||
self.location = match x_diff { | ||
0 => Point { x, y: y + y_diff }, | ||
_ => Point { x: x + x_diff, y }, | ||
}; | ||
|
||
self.update_visits(); | ||
} | ||
} | ||
|
||
fn facing_for_delta(delta: (i32, i32)) -> Facing { | ||
match delta { | ||
(-1, 0) => Facing::West, | ||
(0, 1) => Facing::North, | ||
(1, 0) => Facing::East, | ||
(0, -1) => Facing::South, | ||
_ => unreachable!(), | ||
} | ||
} | ||
|
||
fn update_visits(&mut self) { | ||
if self.repeat.is_none() { | ||
let Point { x, y } = self.location; | ||
if self.visits.contains(&(x, y)) { | ||
self.repeat = Some(Point { x, y }); | ||
} | ||
self.visits.insert((x, y)); | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use crate::util::io_helpers::read_input_from_resources; | ||
|
||
#[test] | ||
fn test_result_16_01() { | ||
let (year, day) = (2016, 1); | ||
let expected_result = (253, 126); | ||
|
||
let raw_input = read_input_from_resources(year, day, false); | ||
assert_eq!(solve_16_01(raw_input), expected_result); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
pub fn solve_17_01(raw_input: String) -> (i32, i32) { | ||
let processed_input = process(raw_input); | ||
|
||
(part_1(&processed_input), part_2(&processed_input)) | ||
} | ||
|
||
fn process(raw_input: String) -> Vec<i32> { | ||
raw_input | ||
.trim() | ||
.chars() | ||
.map(|c| (c as i32) - 0x30) | ||
.collect() | ||
} | ||
|
||
fn part_1(input: &[i32]) -> i32 { | ||
captcha(input, 1) | ||
} | ||
|
||
fn part_2(input: &[i32]) -> i32 { | ||
captcha(input, input.len() / 2) | ||
} | ||
|
||
fn captcha(input: &[i32], by: usize) -> i32 { | ||
let mut rotated = input.to_owned(); | ||
rotated.rotate_left(by); | ||
input | ||
.iter() | ||
.zip(rotated.iter()) | ||
.filter_map(|(a, b)| (a == b).then_some(*a)) | ||
.sum() | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use crate::util::io_helpers::read_input_from_resources; | ||
|
||
#[test] | ||
fn test_result_17_01() { | ||
let (year, day) = (2017, 1); | ||
let expected_result = (1089, 1156); | ||
|
||
let raw_input = read_input_from_resources(year, day, false); | ||
assert_eq!(solve_17_01(raw_input), expected_result); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
use itertools::Itertools; | ||
|
||
pub fn solve_17_02(raw_input: String) -> (i32, i32) { | ||
let input = process(&raw_input); | ||
(part_1(&input), part_2(&input)) | ||
} | ||
|
||
fn process(input_data: &str) -> Vec<Vec<i32>> { | ||
input_data.trim().split('\n').map(parse_row).collect() | ||
} | ||
|
||
fn parse_row(line: &str) -> Vec<i32> { | ||
line.split('\t') | ||
.map(|cell| cell.parse::<i32>().unwrap()) | ||
.sorted() | ||
.collect() | ||
} | ||
|
||
fn part_1(input_data: &[Vec<i32>]) -> i32 { | ||
input_data | ||
.iter() | ||
.map(|row| row.last().unwrap() - row.first().unwrap()) | ||
.sum() | ||
} | ||
|
||
fn part_2(input_data: &[Vec<i32>]) -> i32 { | ||
input_data | ||
.iter() | ||
.map(|values| { | ||
for i in 0..values.len() { | ||
for j in i + 1..values.len() { | ||
if values[j] % values[i] == 0 { | ||
return values[j] / values[i]; | ||
} | ||
} | ||
} | ||
unreachable!() | ||
}) | ||
.sum() | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use crate::util::io_helpers::read_input_from_resources; | ||
|
||
#[test] | ||
fn test_result_17_02() { | ||
let raw_input = read_input_from_resources(2017, 2, false); | ||
let expected_result = (32020, 236); | ||
|
||
assert_eq!(solve_17_02(raw_input), expected_result); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters