From b9d6d9ad9c3bfe66604362a022214f2deeb08d81 Mon Sep 17 00:00:00 2001 From: Kienan Stewart Date: Mon, 6 Dec 2021 20:54:37 -0500 Subject: [PATCH] Day 3 --- day3/Cargo.lock | 7 ++ day3/Cargo.toml | 8 +++ day3/input | 2 + day3/src/main.rs | 178 +++++++++++++++++++++++++++++++++++++++++++++++ day3/testinput | 2 + 5 files changed, 197 insertions(+) create mode 100644 day3/Cargo.lock create mode 100644 day3/Cargo.toml create mode 100644 day3/input create mode 100644 day3/src/main.rs create mode 100644 day3/testinput diff --git a/day3/Cargo.lock b/day3/Cargo.lock new file mode 100644 index 0000000..4104d70 --- /dev/null +++ b/day3/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "day3" +version = "0.1.0" diff --git a/day3/Cargo.toml b/day3/Cargo.toml new file mode 100644 index 0000000..898e70d --- /dev/null +++ b/day3/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "day3" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/day3/input b/day3/input new file mode 100644 index 0000000..ae753a6 --- /dev/null +++ b/day3/input @@ -0,0 +1,2 @@ +R990,U944,L921,U993,L64,U29,R899,D406,R841,U716,L32,U658,L830,D481,L441,U491,L687,D847,L459,U920,R165,U224,L896,D868,L191,U877,L909,U467,R798,U132,R234,U49,R484,U911,R108,D308,R867,U350,L404,U107,L84,U668,R850,U470,L182,U93,R284,U999,L664,U110,R650,D189,R540,D112,R794,U999,R871,D829,L549,U988,R654,D411,R323,D774,R529,U275,L909,U936,R122,D922,L331,U813,L748,U770,R511,D892,L770,U318,R661,U823,R210,D393,L694,U929,L76,D619,R395,U651,R526,U145,R851,U112,R73,D89,R17,U929,R807,U87,R764,D158,L820,U803,L785,D205,L828,D271,L839,D482,L797,U338,R322,D633,L292,U16,R627,U19,R548,U516,L384,U83,R256,U937,R404,U322,R671,D543,L412,U446,R238,U246,L794,D750,L34,U317,L994,U874,L247,D20,R491,U834,L498,D987,R2,U175,R452,U168,R495,D183,R201,U532,L192,U984,L566,D471,L704,D2,L776,U5,R911,U308,R763,D555,R458,D439,L968,D78,R549,D583,R289,D355,L503,D871,L881,U516,L507,D551,R711,U702,L308,D905,L408,U932,L884,U218,L158,D562,L200,D114,R673,U448,R887,U181,R247,U329,L965,U495,L329,D162,L265,D389,R419,U435,R258,U146,R208,D184,R730,D19,L78,D886,R472,D350,R484,U392,L542,U601,L202,U974,L310,U52,L537,U597,L163,D655,R928,U269,L926,D790,L513,U441,L90,U581,L211,U871,R603,D130,L220,U459,L933,U648,R721,U642,R301,U537,L858,D777,R823,U14,R820,D218,L96,D318,L206,U280,R887,D241,L752,U828,R354,U864,R844,D872,L728,D298,L234,U695,R434,D94,R905,D592,L32,D860,R680,D197,R886,U760,L232,U916,L452,U248,R715,D773,R867,U77,R751,D36,R565,U897,R782,U931,R546,U261,R920,D296,R451,U258,L394,U965,R912,D593,L990 +L994,U515,R163,U863,L343,U162,L875,D92,L483,D601,R79,D761,L389,U167,L145,U145,L247,U886,R61,U820,L584,D239,R402,U805,R956,U126,R615,D322,R431,D460,R397,D511,R805,D177,L778,U296,R599,U759,R40,U1,L422,U751,R94,U401,R504,U940,L564,U24,R595,U944,R815,U672,R787,D854,R579,D604,L62,U670,L516,U199,L639,D919,L485,U655,R391,U669,R772,D34,R868,D12,L108,U295,R701,D603,R493,U927,R29,D34,R499,U111,L87,U190,R884,D658,R474,D166,R921,U698,R592,U25,R710,D398,L26,U696,L432,D887,R469,U656,L428,D188,L543,D150,R160,U543,R743,U692,R618,D148,R956,U753,L175,D789,R897,U305,L137,D914,R330,D780,R744,D473,L754,U482,L975,D413,L698,U656,L177,U419,R13,D827,L67,D800,R369,U97,L34,D588,L41,D760,L164,U224,L921,D311,R489,U956,R277,U180,R724,U748,R785,U826,L426,D957,R303,U16,L729,U224,L712,U43,L280,D648,R987,D941,R154,D581,R876,U615,L480,D103,R636,D276,R948,U89,R434,D212,R837,D295,R532,D390,R374,D926,R911,D110,R258,U83,L955,U747,L925,D366,R571,U241,R628,D344,R919,U117,R337,D683,L720,U261,L124,D545,R979,D601,L906,D324,R441,U678,L978,U744,L472,D217,R799,U740,L77,U964,L278,U497,R441,U21,L37,U319,L24,D211,L44,U459,R35,D609,R900,D538,R397,D776,R629,D860,R519,D340,R168,U603,R46,U889,R897,D442,R997,U705,L82,D963,R941,U701,L347,D824,R269,U891,L569,D558,L867,U145,R121,D369,R542,U227,L198,U863,L755,U273,L734,D233,R578,U67,L821,U600,L203,D234,R695,U819,L639,D700,R295,D129,L612,U157,R212,U536,L968,U562,L999,D391,L231,U262,R334,D967,R463,U748,R842,D500,R860,U856,R263,D633,R460,D337,L880,U146,R910 diff --git a/day3/src/main.rs b/day3/src/main.rs new file mode 100644 index 0000000..5d07d56 --- /dev/null +++ b/day3/src/main.rs @@ -0,0 +1,178 @@ +use std::collections::HashSet; +use std::collections::HashMap; + +fn main() { + let mut contents = std::fs::read_to_string("input") + .expect("Failed to read file 'input'"); + let mut it = contents.split("\n"); + let mut line_a: HashSet = HashSet::new(); + let mut line_b: HashSet = HashSet::new(); + match it.next() { + Some(v) => get_line_points_from_str(&mut line_a, &v), + None => panic!(), + } + match it.next() { + Some(v) => { + let s = String::from(v); + get_line_points_from_str(&mut line_b, &s); + }, + None => panic!(), + } + + // Some possible approaches + // my first thought was to do the following + // 1) collect all points for line_a and line_b + // 2) create a pool of intersecting points + // 3) for all the intersecting points, which is + // closest to the origin in manhattan distance + // + // this is pretty easy, but seems like it would be + // memory hungry and doesn't scale to large lines + // bonus: rust HashSets (wrappers around HashMap) + // a union method to facilitate this task. + // + // another thought I had was to find and use some + // sort of math things to compare to pair of line + // segments to see if they intersect, and if so - where. + + let mut closest_point: Point = Point {x: 0, y: 0}; + let mut closest_distance = i32::MAX; + let mut intersects: HashSet = HashSet::new(); + for p in line_a.intersection(&line_b) { + if p.x == 0 && p.y == 0 { + continue; + } + intersects.insert(Point {x: p.x, y: p.y}); + let distance = p.x.abs() + p.y.abs(); + //println!("Intersection: {},{} distance {}", + // p.x, p.y, distance); + if distance < closest_distance { + closest_point = Point {x: p.x, y: p.y}; + closest_distance = distance; + } + } + println!("[Part 1] Closest intersection {} away at {},{}", + closest_distance, closest_point.x, closest_point.y); + + // We replay the get_line_poionts_from_str, but instead + // when we reach one of the intersections we can add + // Point, steps into a result set. + let mut line_a_steps_to_intersect: HashMap = HashMap::new(); + let mut line_b_steps_to_intersect: HashMap = HashMap::new(); + contents = std::fs::read_to_string("input") + .expect("Failed to read file 'input'"); + it = contents.split("\n"); + match it.next() { + Some(v) => get_steps_to_intersections(&intersects, v, + &mut line_a_steps_to_intersect), + None => panic!(), + } + match it.next() { + Some(v) => get_steps_to_intersections(&intersects, v, + &mut line_b_steps_to_intersect), + None => panic!(), + } + let mut step_sum = u64::MAX; + let iit = intersects.iter(); + for p in iit { + let new_sum = line_a_steps_to_intersect.get(&p).unwrap() + + line_b_steps_to_intersect.get(&p).unwrap(); + if new_sum < step_sum { + step_sum = new_sum; + closest_point = Point {x: p.x, y: p.y}; + } + } + println!("[Part 2] Intersection {},{} is {} steps away", + closest_point.x, closest_point.y, step_sum); +} + +fn get_steps_to_intersections(points: &HashSet, source: &str, map: &mut HashMap) { + let mut x = 0; + let mut y = 0; + let mut total_steps = 0; + let lit = source.split(","); + for val in lit { + let dir = val.chars().nth(0).unwrap(); + let mut dx = 0; + let mut dy = 0; + let v = val[1..].parse::().unwrap(); + match dir { + 'U' => dy = 1, + 'D' => dy = -1, + 'L' => dx = -1, + 'R' => dx = 1, + _ => panic!(), + } + let mut needed_steps = 0; + if dx != 0 { + needed_steps = v; + needed_steps = needed_steps.abs(); + } + if dy != 0 { + needed_steps = v; + needed_steps = needed_steps.abs(); + } + let mut step = 0; + while step < needed_steps { + x += dx; + y += dy; + total_steps += 1; + let p = Point {x: x, y: y}; + if points.contains(&p) { + //println!("Inserting intersection {},{} at {} steps", + //p.x, p.y, total_steps); + map.insert(p, total_steps); + } + step += 1; + } + } +} + +fn get_line_points_from_str(points: &mut HashSet, source: &str) { + let mut x = 0; + let mut y = 0; + points.insert(Point { x: x, y: y }); + let lit = source.split(","); + for val in lit { + let dir = val.chars().nth(0).unwrap(); + let mut dx = 0; + let mut dy = 0; + let v = val[1..].parse::().unwrap(); + match dir { + 'U' => dy = 1, + 'D' => dy = -1, + 'L' => dx = -1, + 'R' => dx = 1, + _ => panic!(), + } + let mut needed_steps = 0; + if dx != 0 { + needed_steps = v; + needed_steps = needed_steps.abs(); + } + if dy != 0 { + needed_steps = v; + needed_steps = needed_steps.abs(); + } + //println!("Walking from {},{} {}{} (step {},{} {} times)", + //x, y, dir, v, dx, dy, needed_steps); + let mut step = 0; + while step < needed_steps { + x += dx; + y += dy; + //println!("Adding {},{}", x, y); + points.insert(Point {x: x, y: y}); + step += 1; + } + } +} + +#[derive(PartialEq, Eq, Hash)] +struct Point { + x: i32, + y: i32, +} +#[cfg(test)] +mod tests { + +} diff --git a/day3/testinput b/day3/testinput new file mode 100644 index 0000000..73b95a1 --- /dev/null +++ b/day3/testinput @@ -0,0 +1,2 @@ +R8,U5,L5,D3 +U7,R6,D4,L4