Day 3
This commit is contained in:
parent
176bef0c0c
commit
b9d6d9ad9c
|
@ -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"
|
|
@ -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]
|
|
@ -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
|
|
@ -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<Point> = HashSet::new();
|
||||
let mut line_b: HashSet<Point> = 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<Point> = 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<Point, u64> = HashMap::new();
|
||||
let mut line_b_steps_to_intersect: HashMap<Point, u64> = 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<Point>, source: &str, map: &mut HashMap<Point, u64>) {
|
||||
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::<i32>().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<Point>, 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::<i32>().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 {
|
||||
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
R8,U5,L5,D3
|
||||
U7,R6,D4,L4
|
Reference in New Issue