Completed day 3
This commit is contained in:
parent
4233663582
commit
3b06ca1c64
6
day3/Cargo.lock
generated
Normal file
6
day3/Cargo.lock
generated
Normal file
@ -0,0 +1,6 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "day3"
|
||||
version = "0.1.0"
|
||||
|
9
day3/Cargo.toml
Normal file
9
day3/Cargo.toml
Normal file
@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "day3"
|
||||
version = "0.1.0"
|
||||
authors = ["Tyler Hallada <tyler@hallada.net>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
2
day3/input/input.txt
Normal file
2
day3/input/input.txt
Normal file
@ -0,0 +1,2 @@
|
||||
R999,D467,L84,D619,L49,U380,R287,U80,R744,D642,L340,U738,R959,U710,R882,U861,L130,D354,L579,D586,R798,D735,L661,D453,L828,U953,R604,D834,R921,D348,R620,U775,R364,U552,L221,U119,R590,U29,L267,D745,L128,U468,L978,D717,R883,D227,R691,D330,L33,U520,L862,D132,R99,U400,L455,U737,L603,U220,L689,U131,R158,D674,R617,D287,R422,U734,L73,U327,L525,D245,R849,D692,R114,U136,R762,D5,R329,U429,L849,U748,R816,U556,R614,D412,R416,D306,R307,U826,R880,U936,L164,U984,L689,D934,R790,D14,R561,D736,L3,D442,R301,D520,L451,U76,R844,D307,L144,D800,L462,D138,R956,U225,L393,D186,L924,D445,L86,D640,L920,D877,L197,U191,L371,D701,R826,D282,R856,D412,L788,D417,R69,D678,R978,D268,L268,U112,L69,U164,L748,U191,R227,D227,R59,U749,R134,U779,R865,U247,R55,D567,R821,U799,R937,D942,L445,D571,R685,D111,R107,D769,R269,D968,R102,U335,R538,U125,L725,D654,R451,D242,R777,U813,R799,D786,L804,U313,L322,U771,R219,U316,L973,U963,R84,D289,R825,D299,L425,D49,R995,D486,R550,D789,R735,D501,R966,U955,R432,U635,L353,D600,R675,D236,R864,U322,R719,D418,L877,U833,R839,D634,L533,D438,L734,U130,L578,U498,L984,D413,L615,U40,L699,U656,L653,U419,R856,U882,R30,D266,R386,D692,L210,U802,L390,U753,L406,U338,R743,D320,L125,U204,R391,U537,R887,D194,L302,U400,R510,U92,L310,D382,R597,U498,R851,D357,L568,U800,R918,D106,R673,D735,L86,D67,R398,D677,R355,D501,L909,D133,R729,D293,L498,U222,R832,U671,R751,U36,R422,U840,L636,D476,L292,D105,L239,U199,R669,U736,L345,D911,L277,U452,L979,D153,R882,U604,R602,U495,L311,U453,L215,D713,R873
|
||||
L996,U773,L865,D472,L988,D570,L388,U458,L87,U885,L115,U55,R75,U582,R695,U883,R83,U285,R96,D244,L647,D359,R136,U107,R912,U871,L844,U395,L63,U899,L205,D137,R549,U221,L859,D429,L809,U127,R304,U679,L511,U144,R926,U95,L805,U811,R42,D248,L546,D644,L551,D897,R368,D391,L224,U164,L490,D991,L146,D615,R536,U247,R10,U998,L957,D233,R706,D926,R760,U438,R270,D983,R134,U738,L262,U301,L480,D635,L702,D715,R479,U500,R19,D291,R368,U203,R305,D999,R106,U355,L683,D298,R90,U968,L254,D936,R89,U496,R253,U688,R99,U637,L783,D451,R673,D762,R997,D50,L488,U551,L871,U388,R949,D371,R584,D908,L880,U523,R557,U436,R520,U587,L56,U18,R397,U541,R660,D444,R51,U187,R221,U902,R726,U303,R97,D817,R185,D218,L240,D67,L259,U334,R821,U629,R21,D970,R282,U155,R555,D678,L99,D570,R863,D405,R941,U584,L303,D109,L871,U180,R595,D226,L670,D943,L127,U647,R452,D570,R75,D284,R414,U404,R515,U993,R408,U488,R890,D318,L415,U969,R769,D976,L732,U1,R489,U655,R930,U638,R649,D254,R161,U287,L659,D26,L477,D821,L124,U538,R17,D711,L203,U888,R904,U648,L908,D65,L215,U283,R698,U28,R72,U214,R499,D89,R489,D58,R949,D91,L710,U960,L755,D402,L27,D873,R61,U607,R57,D548,R369,U622,L244,U19,R61,D606,R928,D968,R10,D988,R816,U500,R915,D400,R546,D283,L627,D919,L259,U337,R374,U795,L355,D989,L224,D77,L872,U901,R476,U765,L320,U768,L937,D437,R141,D822,L326,D324,L498,U994,L518,D857,R973,D681,L710,D590,L879,U499,R488,D151,L242,U988,L944,U683,L24,U491,R823,D246,R872,D654,R28,U581,L142,U31,R435,D686,L147,D102,R952,D607,L959,D929,L46
|
2
day3/input/test1.txt
Normal file
2
day3/input/test1.txt
Normal file
@ -0,0 +1,2 @@
|
||||
R8,U5,L5,D3
|
||||
U7,R6,D4,L4
|
2
day3/input/test2.txt
Normal file
2
day3/input/test2.txt
Normal file
@ -0,0 +1,2 @@
|
||||
R75,D30,R83,U83,L12,D49,R71,U7,L72
|
||||
U62,R66,U55,R34,D71,R55,D58,R83
|
2
day3/input/test3.txt
Normal file
2
day3/input/test3.txt
Normal file
@ -0,0 +1,2 @@
|
||||
R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51
|
||||
U98,R91,D20,R16,D67,R40,U7,R15,U6,R7
|
200
day3/src/main.rs
Normal file
200
day3/src/main.rs
Normal file
@ -0,0 +1,200 @@
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
use std::fs;
|
||||
use std::result;
|
||||
use std::str::FromStr;
|
||||
|
||||
const INPUT: &str = "input/input.txt";
|
||||
|
||||
type Result<T> = result::Result<T, Box<dyn Error>>;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct CrossedWires {
|
||||
wires: Vec<Vec<Move>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
struct Point {
|
||||
x: i32,
|
||||
y: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct Move {
|
||||
direction: Direction,
|
||||
distance: i32,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum Direction {
|
||||
Up,
|
||||
Down,
|
||||
Right,
|
||||
Left,
|
||||
}
|
||||
|
||||
impl CrossedWires {
|
||||
fn find_intersections(&self) -> HashMap<Point, u32> {
|
||||
let mut intersections: HashMap<Point, u32> = HashMap::new();
|
||||
|
||||
let mut occupied_points: HashMap<Point, u32> = HashMap::new();
|
||||
for (wire_index, wire) in self.wires.iter().enumerate() {
|
||||
let mut steps = 0;
|
||||
let mut end_point = Point { x: 0, y: 0 };
|
||||
for movement in wire.iter() {
|
||||
let mut point = end_point.clone();
|
||||
for _ in 0..movement.distance {
|
||||
match movement.direction {
|
||||
Direction::Up => point.y += 1,
|
||||
Direction::Down => point.y -= 1,
|
||||
Direction::Right => point.x += 1,
|
||||
Direction::Left => point.x -= 1,
|
||||
};
|
||||
steps += 1;
|
||||
if wire_index == 0 {
|
||||
occupied_points.insert(point, steps);
|
||||
} else {
|
||||
if let Some(first_wire_steps) = occupied_points.get(&point) {
|
||||
intersections.insert(point, first_wire_steps + steps);
|
||||
}
|
||||
}
|
||||
}
|
||||
end_point = point;
|
||||
}
|
||||
}
|
||||
|
||||
intersections
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for CrossedWires {
|
||||
type Err = Box<dyn Error>;
|
||||
|
||||
fn from_str(s: &str) -> Result<CrossedWires> {
|
||||
let mut wires = s.split("\n");
|
||||
let first_moves = wires.next().expect("First wire not found in input");
|
||||
let second_moves = wires.next().expect("Second wire not found in input");
|
||||
|
||||
Ok(CrossedWires {
|
||||
wires: vec![
|
||||
get_moves_from_string(first_moves)?,
|
||||
get_moves_from_string(second_moves)?,
|
||||
],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<char> for Direction {
|
||||
fn from(c: char) -> Direction {
|
||||
match c {
|
||||
'U' => Direction::Up,
|
||||
'D' => Direction::Down,
|
||||
'R' => Direction::Right,
|
||||
'L' => Direction::Left,
|
||||
_ => panic!("Could not parse direction: {}", c),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_moves_from_string(moves_string: &str) -> Result<Vec<Move>> {
|
||||
let moves_strings = moves_string.split(",");
|
||||
let mut moves = vec![];
|
||||
|
||||
for wire_move in moves_strings {
|
||||
let mut wire_move = wire_move.chars();
|
||||
let direction: Direction =
|
||||
Direction::from(wire_move.next().expect("Invalid empty wire move"));
|
||||
let distance: i32 = wire_move.collect::<String>().parse()?;
|
||||
|
||||
moves.push(Move {
|
||||
direction,
|
||||
distance,
|
||||
});
|
||||
}
|
||||
Ok(moves)
|
||||
}
|
||||
|
||||
fn read_wires(filename: &str) -> Result<CrossedWires> {
|
||||
let wires = fs::read_to_string(filename)?;
|
||||
Ok(wires.parse()?)
|
||||
}
|
||||
|
||||
fn solve_part1() -> Result<i32> {
|
||||
let wires = read_wires(INPUT)?;
|
||||
let intersections = wires.find_intersections();
|
||||
let intersect_points = intersections.keys();
|
||||
let distances = intersect_points.map(|point| point.x.abs() + point.y.abs());
|
||||
Ok(distances.min().expect("No intersections found"))
|
||||
}
|
||||
|
||||
fn solve_part2() -> Result<i32> {
|
||||
let wires = read_wires(INPUT)?;
|
||||
let intersections = wires.find_intersections();
|
||||
let min_intersection = intersections
|
||||
.iter()
|
||||
.min_by_key(|(_, steps)| steps.clone()).expect("No intersections found");
|
||||
Ok(*min_intersection.1 as i32)
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
println!("Part 1: {}", solve_part1()?);
|
||||
println!("Part 2: {}", solve_part2()?);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const TEST_INPUT1: &str = "input/test1.txt";
|
||||
// const TEST_INPUT2: &str = "input/test2.txt";
|
||||
// const TEST_INPUT3: &str = "input/test3.txt";
|
||||
|
||||
#[test]
|
||||
fn reads_wires() {
|
||||
assert_eq!(
|
||||
read_wires(TEST_INPUT1).unwrap(),
|
||||
CrossedWires {
|
||||
wires: vec![
|
||||
vec![
|
||||
Move {
|
||||
direction: Direction::Right,
|
||||
distance: 8
|
||||
},
|
||||
Move {
|
||||
direction: Direction::Up,
|
||||
distance: 5
|
||||
},
|
||||
Move {
|
||||
direction: Direction::Left,
|
||||
distance: 5
|
||||
},
|
||||
Move {
|
||||
direction: Direction::Down,
|
||||
distance: 3
|
||||
},
|
||||
],
|
||||
vec![
|
||||
Move {
|
||||
direction: Direction::Up,
|
||||
distance: 7
|
||||
},
|
||||
Move {
|
||||
direction: Direction::Right,
|
||||
distance: 6
|
||||
},
|
||||
Move {
|
||||
direction: Direction::Down,
|
||||
distance: 4
|
||||
},
|
||||
Move {
|
||||
direction: Direction::Left,
|
||||
distance: 4
|
||||
},
|
||||
],
|
||||
],
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user