Day 1, day 2, day 3

This commit is contained in:
Armin Friedl 2019-12-04 20:18:15 +01:00
parent 1b1e13b523
commit 8117741f48
Signed by: armin
GPG key ID: 48C726EEE7FBCBC8
20 changed files with 1349 additions and 1 deletions

View file

@ -1,3 +1,17 @@
# AoC-2019
Advent Of Code 2019
[Advent Of Code 2019][1]
## Days
## License
I don't expect this to be used in any relevant capacity. Hence, this code is
under the most serious copyleft license I could find - the [EPL 2.0][2]. This is
a rather fun license for people who really mean it. It virtually checks _all_
the boxes on (choosealicense.com)[https://choosealicense.com/appendix/].
Beware when cloning! I might take ownership of your favorite pet :)
[1]: https://adventofcode.com/2019/
[2]: https://eupl.eu/1.2/en/

6
day1/1/day1.py Normal file
View file

@ -0,0 +1,6 @@
from functools import reduce
from operator import add
with open('input', 'r') as f:
result = reduce(add, [(int(line)//3)-2 for line in f])
print(f"{result}")

100
day1/1/input Normal file
View file

@ -0,0 +1,100 @@
119341
141179
104964
90174
106547
78708
128438
84980
66768
106894
82394
95489
52669
95631
66849
135461
88795
77228
123981
72391
103823
63982
64997
145184
69311
117874
106314
101353
114745
88889
83875
85051
101949
118449
65252
135144
68497
132390
105856
121098
144838
87829
141579
140516
126377
55911
89261
76610
135578
110154
147648
106639
143854
91637
84297
117449
75041
58141
132983
114681
75817
116453
56544
65230
90622
133929
92089
134197
104271
127204
149761
128253
132253
109273
88734
136243
122128
119246
121118
128448
137797
66767
67488
90616
97823
51642
98789
94130
128350
101600
85570
145174
127257
141772
144415
82959
58548
129474
125838
68864

13
day1/2/day2.py Normal file
View file

@ -0,0 +1,13 @@
from functools import reduce
from operator import add
def converge(fuel):
ff = (fuel//3)-2
if ff <= 0:
return 0
else:
return ff + converge(ff)
with open('input', 'r') as f:
result = reduce(add, [converge(int(line)) for line in f])
print(f"{result}")

100
day1/2/input Normal file
View file

@ -0,0 +1,100 @@
119341
141179
104964
90174
106547
78708
128438
84980
66768
106894
82394
95489
52669
95631
66849
135461
88795
77228
123981
72391
103823
63982
64997
145184
69311
117874
106314
101353
114745
88889
83875
85051
101949
118449
65252
135144
68497
132390
105856
121098
144838
87829
141579
140516
126377
55911
89261
76610
135578
110154
147648
106639
143854
91637
84297
117449
75041
58141
132983
114681
75817
116453
56544
65230
90622
133929
92089
134197
104271
127204
149761
128253
132253
109273
88734
136243
122128
119246
121118
128448
137797
66767
67488
90616
97823
51642
98789
94130
128350
101600
85570
145174
127257
141772
144415
82959
58548
129474
125838
68864

153
day2/1/input Normal file
View file

@ -0,0 +1,153 @@
1
0
0
3
1
1
2
3
1
3
4
3
1
5
0
3
2
9
1
19
1
19
5
23
1
9
23
27
2
27
6
31
1
5
31
35
2
9
35
39
2
6
39
43
2
43
13
47
2
13
47
51
1
10
51
55
1
9
55
59
1
6
59
63
2
63
9
67
1
67
6
71
1
71
13
75
1
6
75
79
1
9
79
83
2
9
83
87
1
87
6
91
1
91
13
95
2
6
95
99
1
10
99
103
2
103
9
107
1
6
107
111
1
10
111
115
2
6
115
119
1
5
119
123
1
123
13
127
1
127
5
131
1
6
131
135
2
135
13
139
1
139
2
143
1
143
10
0
99
2
0
14
0

View file

@ -0,0 +1,9 @@
[package]
name = "intcode"
version = "0.1.0"
authors = ["Armin Friedl <dev@friedl.net>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

153
day2/1/intcode/input Normal file
View file

@ -0,0 +1,153 @@
1
0
0
3
1
1
2
3
1
3
4
3
1
5
0
3
2
9
1
19
1
19
5
23
1
9
23
27
2
27
6
31
1
5
31
35
2
9
35
39
2
6
39
43
2
43
13
47
2
13
47
51
1
10
51
55
1
9
55
59
1
6
59
63
2
63
9
67
1
67
6
71
1
71
13
75
1
6
75
79
1
9
79
83
2
9
83
87
1
87
6
91
1
91
13
95
2
6
95
99
1
10
99
103
2
103
9
107
1
6
107
111
1
10
111
115
2
6
115
119
1
5
119
123
1
123
13
127
1
127
5
131
1
6
131
135
2
135
13
139
1
139
2
143
1
143
10
0
99
2
0
14
0

148
day2/1/intcode/src/main.rs Normal file
View file

@ -0,0 +1,148 @@
use std::fs::File;
use std::io::{BufReader, BufRead};
use std::error::Error;
use std::result::Result;
struct Computer {
mem: Vec<u32>,
intp: *mut u32, // here will be dragons
}
impl Computer {
fn new() -> Self {
let mut mem = vec![0];
let intp = &mut mem[0] as *mut u32;
Computer {mem, intp}
}
fn push(&mut self, val: u32) {
if self.mem[0] == 0 { // we are in init state
self.mem[0] = val
} else {
self.mem.push(val);
}
}
fn set(&mut self, pos: usize, val: u32) {
self.mem[pos] = val;
}
fn get(&self, pos: usize) -> u32 {
self.mem[pos]
}
fn compute(mut self) -> u32 {
// first reset the pointer just to be sure
self.intp = &mut self.mem[0] as *mut u32;
loop {
match self._next() {
Some(1) => self._add(),
Some(2) => self._mul(),
Some(99) => break,
Some(x) => panic!{"Invalid opcode {}", x},
None => panic!{"No halt"}
}
}
self.mem[0]
}
fn _add(&mut self) {
let op1 = self._expect_next() as usize;
let op2 = self._expect_next() as usize;
let pos = self._expect_next() as usize;
println!{"Summing {} and {} to {}", self.mem[op1], self.mem[op2], pos}
self.mem[pos] = self.mem[op1]+self.mem[op2];
}
fn _mul(&mut self) {
let op1 = self._expect_next() as usize;
let op2 = self._expect_next() as usize;
let pos = self._expect_next() as usize;
println!{"Mulling {} and {} to {}", self.mem[op1], self.mem[op2], pos}
self.mem[pos] = self.mem[op1]*self.mem[op2];
}
fn _next(&mut self) -> Option<u32> {
unsafe{ // Dragons
// overflow check, smart cpu
let lstp = self.mem.last_mut().unwrap() as *mut u32;
if self.intp == lstp.offset(1) {
return None;
}
let op = *self.intp;
println!{"Intp at {}", *self.intp}
self.intp = self.intp.offset(1);
Some(op)
}
}
fn _expect_next(&mut self) -> u32 {
self._next().expect("Exhausted")
}
}
fn main() -> Result<(), Box<dyn Error>>{
let input = File::open("input")?;
let reader = BufReader::new(input);
let mut computer = Computer::new();
reader.lines()
.filter_map(Result::ok) // transform into Option and filter
.filter_map(|l| l.parse().ok()) // parse String to i32 transform to Option and filter
.for_each(|i| computer.push(i)); // push instruction to computer
computer.set(1, 12);
computer.set(2, 2);
let res = computer.compute();
println!{"Result: {}", res}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
fn compute(inst: Vec<u32>) -> u32 {
let mut computer = Computer::new();
inst.iter().for_each(|i| computer.push(*i));
computer.compute()
}
#[test]
fn tc0() {
let inst = vec!{1,9,10,3,2,3,11,0,99,30,40,50};
println!{"Fixture {:?}", inst}
assert_eq!{compute(inst), 3500}
}
#[test]
fn tc1() {
let inst = vec!{1,0,0,0,99};
println!{"Fixture {:?}", inst}
assert_eq!{compute(inst), 2}
}
#[test]
fn tc4() {
let inst = vec!{1,1,1,4,99,5,6,0,99};
println!{"Fixture {:?}", inst}
assert_eq!{compute(inst), 30}
}
}

9
day2/2/Cargo.toml Normal file
View file

@ -0,0 +1,9 @@
[package]
name = "intcode"
version = "0.1.0"
authors = ["Armin Friedl <dev@friedl.net>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

153
day2/2/input Normal file
View file

@ -0,0 +1,153 @@
1
0
0
3
1
1
2
3
1
3
4
3
1
5
0
3
2
9
1
19
1
19
5
23
1
9
23
27
2
27
6
31
1
5
31
35
2
9
35
39
2
6
39
43
2
43
13
47
2
13
47
51
1
10
51
55
1
9
55
59
1
6
59
63
2
63
9
67
1
67
6
71
1
71
13
75
1
6
75
79
1
9
79
83
2
9
83
87
1
87
6
91
1
91
13
95
2
6
95
99
1
10
99
103
2
103
9
107
1
6
107
111
1
10
111
115
2
6
115
119
1
5
119
123
1
123
13
127
1
127
5
131
1
6
131
135
2
135
13
139
1
139
2
143
1
143
10
0
99
2
0
14
0

119
day2/2/src/main.rs Normal file
View file

@ -0,0 +1,119 @@
use std::fs::File;
use std::io::{BufReader, BufRead};
use std::error::Error;
use std::result::Result;
#[derive(Debug)]
struct Computer {
mem: Vec<u32>,
intp: *mut u32, // here will be dragons
}
impl Computer {
fn new() -> Self {
let mut mem = vec![0];
let intp = &mut mem[0] as *mut u32;
Computer {mem, intp}
}
fn push(&mut self, val: u32) {
if self.mem[0] == 0 { // we are in init state
self.mem[0] = val
} else {
self.mem.push(val);
}
}
fn set(&mut self, pos: usize, val: u32) {
self.mem[pos] = val;
}
fn compute(&mut self) -> u32 {
// first reset the pointer just to be sure
self.intp = &mut self.mem[0] as *mut u32;
loop {
match self._next() {
Some(1) => self._add(),
Some(2) => self._mul(),
Some(99) => break,
Some(x) => panic!{"Invalid opcode {}", x},
None => panic!{"No halt"}
}
}
self.mem[0]
}
fn _add(&mut self) {
let op1 = self._expect_next() as usize;
let op2 = self._expect_next() as usize;
let pos = self._expect_next() as usize;
self.mem[pos] = self.mem[op1]+self.mem[op2];
}
fn _mul(&mut self) {
let op1 = self._expect_next() as usize;
let op2 = self._expect_next() as usize;
let pos = self._expect_next() as usize;
self.mem[pos] = self.mem[op1]*self.mem[op2];
}
fn _next(&mut self) -> Option<u32> {
unsafe{ // Dragons
// overflow check, smart cpu
let lstp = self.mem.last_mut().unwrap() as *mut u32;
if self.intp == lstp.offset(1) {
return None;
}
let op = *self.intp;
self.intp = self.intp.offset(1);
Some(op)
}
}
fn _expect_next(&mut self) -> u32 {
self._next().expect("Exhausted")
}
}
impl Clone for Computer {
fn clone(&self) -> Self {
let mut mem = self.mem.clone();
let intp = &mut mem[0] as *mut u32;
Computer { mem, intp }
}
}
fn main() -> Result<(), Box<dyn Error>>{
let input = File::open("input")?;
let reader = BufReader::new(input);
let mut computer = Computer::new();
reader.lines()
.filter_map(Result::ok) // transform into Option and filter
.filter_map(|l| l.parse().ok()) // parse String to i32 transform to Option and filter
.for_each(|i| computer.push(i)); // push instruction to computer
for i in 0..100 {
for j in 0..100 {
let mut ncomp = computer.clone();
ncomp.set(1, i);
ncomp.set(2, j);
if 19690720 == ncomp.compute() {
println!{"Result: a={}, b={}", i, j}
}
}
}
Ok(())
}

View file

@ -0,0 +1,9 @@
[package]
name = "crossed_wires"
version = "0.1.0"
authors = ["Armin Friedl <dev@friedl.net>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View file

@ -0,0 +1,2 @@
R1003,U756,L776,U308,R718,D577,R902,D776,R760,U638,R289,D70,L885,U161,R807,D842,R175,D955,R643,U380,R329,U573,L944,D2,L807,D886,L549,U592,R152,D884,L761,D915,L726,D677,L417,D651,L108,D377,L699,D938,R555,D222,L689,D196,L454,U309,L470,D234,R198,U689,L996,U117,R208,D310,R572,D562,L207,U244,L769,U186,R153,D756,R97,D625,R686,U244,R348,U586,L385,D466,R483,U718,L892,D39,R692,U756,L724,U148,R70,U224,L837,D370,L309,U235,R382,D579,R404,D146,R6,U584,L840,D863,R942,U646,R146,D618,L12,U210,R126,U163,R931,D661,L710,D883,L686,D688,L148,D19,R703,U530,R889,U186,R779,D503,R417,U272,R541,U21,L562,D10,L349,U998,R69,D65,R560,D585,L949,D372,L110,D865,R212,U56,L936,U957,L88,U612,R927,U642,R416,U348,L541,D416,L808,D759,R449,D6,L517,D4,R494,D143,L536,U341,R394,U179,L22,D680,L138,U249,L285,U879,L717,U756,L313,U222,R823,D208,L134,U984,R282,U635,R207,D63,L416,U511,L179,D582,L651,U932,R646,U378,R263,U138,L920,U523,L859,D556,L277,D518,R489,U561,L457,D297,R72,U920,L583,U23,L395,D844,R776,D552,L55,D500,R111,U409,R685,D427,R275,U739,R181,U333,L215,U808,R341,D537,R336,U230,R247,U748,R846,U404,R850,D493,R891,U176,L744,U585,L987,D849,R271,D848,L555,U801,R316,U753,L390,U97,L128,U45,R706,U35,L928,U913,R537,D512,R152,D410,R76,D209,R183,U941,R289,U632,L923,D190,R488,D934,R442,D303,R178,D250,R204,U247,R707,U77,R428,D701,R386,U110,R641,U925,R703,D387,L946,U415,R461,D123,L214,U236,L959,U517,R957,D524,R812,D668,R369,U340,L606,D503,R755,U390,R142,D921,L976,D36,L965,D450,L722,D224,L303,U705,L584
L993,U810,L931,D139,R114,D77,L75,U715,R540,D994,L866,U461,R340,D179,R314,D423,R629,D8,L692,U446,L88,D132,L128,U934,L465,D58,L696,D883,L955,D565,R424,U286,R403,U57,L627,D930,R887,D941,L306,D951,R918,U587,R939,U821,L65,D18,L987,D707,L360,D54,L932,U366,R625,U609,R173,D637,R661,U888,L68,U962,R270,U369,R780,U845,L813,U481,R66,D182,R420,U605,R880,D276,L6,D529,R883,U189,R380,D472,R30,U35,L510,D844,L146,U875,R152,U545,R274,U920,R432,U814,R583,D559,L820,U135,L353,U975,L103,U615,R401,U692,L676,D781,R551,D985,L317,U836,R115,D216,L967,U286,R681,U144,L354,U678,L893,D487,R664,D185,R787,D909,L582,D283,L519,D893,L56,U768,L345,D992,L248,U439,R573,D98,L390,D43,L470,D435,R176,U468,R688,U388,L377,U800,R187,U641,L268,U857,L716,D179,R212,U196,L342,U731,R261,D92,R183,D623,L589,D215,L966,U878,L784,U740,R823,D99,L167,D992,R414,U22,L27,U390,R286,D744,L360,U554,L756,U715,R939,D806,R279,U292,L960,U633,L428,U949,R90,D321,R749,U395,L392,U348,L33,D757,R289,D367,L562,D668,L79,D193,L991,D705,L562,U25,R146,D34,R325,U203,R403,D714,R607,U72,L444,D76,R267,U924,R289,U962,L159,U726,L57,D540,R299,U343,R936,U90,L311,U243,L415,D426,L936,D570,L539,D731,R367,D374,L56,D251,L265,U65,L14,D882,L956,U88,R688,D34,R866,U777,R342,D270,L344,D953,L438,D855,L587,U320,L953,D945,L473,U559,L487,D602,R255,U871,L854,U45,R705,D247,R955,U885,R657,D664,L360,D764,L549,D676,R85,U189,L951,D922,R511,D429,R37,U11,R821,U984,R825,U874,R753,D524,L537,U618,L919,D597,L364,D231,L258,U818,R406,D208,R214,U530,R261

View file

@ -0,0 +1,2 @@
R1003,U756,L776,U308,R718,D577,R902,D776,R760,U638,R289,D70,L885,U161,R807,D842,R175,D955,R643,U380,R329,U573,L944,D2,L807,D886,L549,U592,R152,D884,L761,D915,L726,D677,L417,D651,L108,D377,L699,D938,R555,D222,L689,D196,L454,U309,L470,D234,R198,U689,L996,U117,R208,D310,R572,D562,L207,U244,L769,U186,R153,D756,R97,D625,R686,U244,R348,U586,L385,D466,R483,U718,L892,D39,R692,U756,L724,U148,R70,U224,L837,D370,L309,U235,R382,D579,R404,D146,R6,U584,L840,D863,R942,U646,R146,D618,L12,U210,R126,U163,R931,D661,L710,D883,L686,D688,L148,D19,R703,U530,R889,U186,R779,D503,R417,U272,R541,U21,L562,D10,L349,U998,R69,D65,R560,D585,L949,D372,L110,D865,R212,U56,L936,U957,L88,U612,R927,U642,R416,U348,L541,D416,L808,D759,R449,D6,L517,D4,R494,D143,L536,U341,R394,U179,L22,D680,L138,U249,L285,U879,L717,U756,L313,U222,R823,D208,L134,U984,R282,U635,R207,D63,L416,U511,L179,D582,L651,U932,R646,U378,R263,U138,L920,U523,L859,D556,L277,D518,R489,U561,L457,D297,R72,U920,L583,U23,L395,D844,R776,D552,L55,D500,R111,U409,R685,D427,R275,U739,R181,U333,L215,U808,R341,D537,R336,U230,R247,U748,R846,U404,R850,D493,R891,U176,L744,U585,L987,D849,R271,D848,L555,U801,R316,U753,L390,U97,L128,U45,R706,U35,L928,U913,R537,D512,R152,D410,R76,D209,R183,U941,R289,U632,L923,D190,R488,D934,R442,D303,R178,D250,R204,U247,R707,U77,R428,D701,R386,U110,R641,U925,R703,D387,L946,U415,R461,D123,L214,U236,L959,U517,R957,D524,R812,D668,R369,U340,L606,D503,R755,U390,R142,D921,L976,D36,L965,D450,L722,D224,L303,U705,L584
L993,U810,L931,D139,R114,D77,L75,U715,R540,D994,L866,U461,R340,D179,R314,D423,R629,D8,L692,U446,L88,D132,L128,U934,L465,D58,L696,D883,L955,D565,R424,U286,R403,U57,L627,D930,R887,D941,L306,D951,R918,U587,R939,U821,L65,D18,L987,D707,L360,D54,L932,U366,R625,U609,R173,D637,R661,U888,L68,U962,R270,U369,R780,U845,L813,U481,R66,D182,R420,U605,R880,D276,L6,D529,R883,U189,R380,D472,R30,U35,L510,D844,L146,U875,R152,U545,R274,U920,R432,U814,R583,D559,L820,U135,L353,U975,L103,U615,R401,U692,L676,D781,R551,D985,L317,U836,R115,D216,L967,U286,R681,U144,L354,U678,L893,D487,R664,D185,R787,D909,L582,D283,L519,D893,L56,U768,L345,D992,L248,U439,R573,D98,L390,D43,L470,D435,R176,U468,R688,U388,L377,U800,R187,U641,L268,U857,L716,D179,R212,U196,L342,U731,R261,D92,R183,D623,L589,D215,L966,U878,L784,U740,R823,D99,L167,D992,R414,U22,L27,U390,R286,D744,L360,U554,L756,U715,R939,D806,R279,U292,L960,U633,L428,U949,R90,D321,R749,U395,L392,U348,L33,D757,R289,D367,L562,D668,L79,D193,L991,D705,L562,U25,R146,D34,R325,U203,R403,D714,R607,U72,L444,D76,R267,U924,R289,U962,L159,U726,L57,D540,R299,U343,R936,U90,L311,U243,L415,D426,L936,D570,L539,D731,R367,D374,L56,D251,L265,U65,L14,D882,L956,U88,R688,D34,R866,U777,R342,D270,L344,D953,L438,D855,L587,U320,L953,D945,L473,U559,L487,D602,R255,U871,L854,U45,R705,D247,R955,U885,R657,D664,L360,D764,L549,D676,R85,U189,L951,D922,R511,D429,R37,U11,R821,U984,R825,U874,R753,D524,L537,U618,L919,D597,L364,D231,L258,U818,R406,D208,R214,U530,R261

View file

@ -0,0 +1,161 @@
use std::io::BufRead;
use std::collections::HashSet;
use std::collections::LinkedList;
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
struct Point(i32, i32);
#[derive(Copy, Clone)]
enum Direction {
Up,
Down,
Left,
Right
}
#[derive(Debug)]
struct Cable {
points: HashSet<Point>,
path: LinkedList<Point>,
}
impl Cable {
fn new(origin: Point) -> Cable {
let mut cable = Cable {
points: HashSet::new(),
path: LinkedList::new()
};
cable.add_point(origin);
cable
}
fn add_point(&mut self, point: Point) {
self.path.push_back(point);
self.points.insert(point);
}
fn step(&mut self, direction: Direction) {
let curp = self.path.back().unwrap().clone();
match direction {
Direction::Up => self.add_point(Point (curp.0, curp.1+1)),
Direction::Down => self.add_point(Point (curp.0, curp.1-1)),
Direction::Left => self.add_point(Point (curp.0-1, curp.1)),
Direction::Right => self.add_point(Point (curp.0+1, curp.1))
}
}
fn walk(&mut self, direction: Direction, steps: u32) {
for _i in 0..steps {
self.step(direction);
}
}
fn intersections(&self, other: &Self) -> Vec<Point> {
let mut v = vec!{};
let s = if self.path.len() > other.path.len() {self} else {other};
let o = if self.path.len() > other.path.len() {other} else {self};
for p in s.points.iter() {
if o.points.contains(p) {
v.push(*p);
}
}
v
}
}
fn parse(line: &str) -> Cable {
let mut cable = Cable::new(Point(0,0));
line.split(',').for_each(|s| {
let ss = s.split_at(1);
match ss.0 {
"R" => cable.walk(Direction::Right, ss.1.parse().unwrap()),
"L" => cable.walk(Direction::Left, ss.1.parse().unwrap()),
"U" => cable.walk(Direction::Up, ss.1.parse().unwrap()),
"D" => cable.walk(Direction::Down, ss.1.parse().unwrap()),
_ => panic! {"Unknown direction"}
}});
cable
}
fn nearest_point(origin: Point, points: &[Point]) -> Point {
let mut min: Point = Point(std::i32::MAX/2-1, std::i32::MAX/2-1);
let dist = |p: Point| {(origin.0 - p.0).abs() + (origin.1 - p.1).abs()};
for p in points {
if dist(*p) < dist(min) {
min = p.clone();
}
}
min
}
fn distance(origin: Point, point: Point) -> i32 {
(origin.0 - point.0).abs() + (origin.1 - point.1).abs()
}
fn main() {
let f = std::fs::File::open("input").unwrap();
let r = std::io::BufReader::new(f);
let mut l = r.lines();
let c1line = l.next().unwrap().unwrap();
let cable1 = parse(&c1line);
let c2line = l.next().unwrap().unwrap();
let cable2 = parse(&c2line);
println!{"Intersecting"}
let mut inter = cable1.intersections(&cable2);
println!{"Intersections: {:?}", inter}
let origin = inter.iter().position(|x| *x == Point(0,0)).unwrap();
inter.remove(origin);
let np = nearest_point(Point(0,0), &inter);
println!("Min point: {:?}", np);
let np_dist = distance(Point(0,0), np);
println!("Distance: {}", np_dist)
}
#[cfg(test)]
mod test {
use super::*;
fn run_with(l1: &str, l2: &str) -> i32 {
let cable1 = parse(&l1);
let cable2 = parse(&l2);
println!{"hi"};
let mut inter = cable1.intersections(&cable2);
let origin = inter.iter().position(|x| *x == Point(0,0)).unwrap();
inter.remove(origin);
let np = nearest_point(Point(0,0), &inter);
println!("Min point: {:?}", np);
distance(Point(0,0), np)
}
#[test]
fn tc1 () {
let l1 = "R75,D30,R83,U83,L12,D49,R71,U7,L72";
let l2 = "U62,R66,U55,R34,D71,R55,D58,R83";
assert_eq!{159, run_with(l1,l2)}
}
#[test]
fn tc2 () {
let l1 = "R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51";
let l2 = "U98,R91,D20,R16,D67,R40,U7,R15,U6,R7";
assert_eq!{135, run_with(l1,l2)}
}
}

View file

@ -0,0 +1,9 @@
[package]
name = "crossed_wires"
version = "0.1.0"
authors = ["Armin Friedl <dev@friedl.net>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View file

@ -0,0 +1,2 @@
R1003,U756,L776,U308,R718,D577,R902,D776,R760,U638,R289,D70,L885,U161,R807,D842,R175,D955,R643,U380,R329,U573,L944,D2,L807,D886,L549,U592,R152,D884,L761,D915,L726,D677,L417,D651,L108,D377,L699,D938,R555,D222,L689,D196,L454,U309,L470,D234,R198,U689,L996,U117,R208,D310,R572,D562,L207,U244,L769,U186,R153,D756,R97,D625,R686,U244,R348,U586,L385,D466,R483,U718,L892,D39,R692,U756,L724,U148,R70,U224,L837,D370,L309,U235,R382,D579,R404,D146,R6,U584,L840,D863,R942,U646,R146,D618,L12,U210,R126,U163,R931,D661,L710,D883,L686,D688,L148,D19,R703,U530,R889,U186,R779,D503,R417,U272,R541,U21,L562,D10,L349,U998,R69,D65,R560,D585,L949,D372,L110,D865,R212,U56,L936,U957,L88,U612,R927,U642,R416,U348,L541,D416,L808,D759,R449,D6,L517,D4,R494,D143,L536,U341,R394,U179,L22,D680,L138,U249,L285,U879,L717,U756,L313,U222,R823,D208,L134,U984,R282,U635,R207,D63,L416,U511,L179,D582,L651,U932,R646,U378,R263,U138,L920,U523,L859,D556,L277,D518,R489,U561,L457,D297,R72,U920,L583,U23,L395,D844,R776,D552,L55,D500,R111,U409,R685,D427,R275,U739,R181,U333,L215,U808,R341,D537,R336,U230,R247,U748,R846,U404,R850,D493,R891,U176,L744,U585,L987,D849,R271,D848,L555,U801,R316,U753,L390,U97,L128,U45,R706,U35,L928,U913,R537,D512,R152,D410,R76,D209,R183,U941,R289,U632,L923,D190,R488,D934,R442,D303,R178,D250,R204,U247,R707,U77,R428,D701,R386,U110,R641,U925,R703,D387,L946,U415,R461,D123,L214,U236,L959,U517,R957,D524,R812,D668,R369,U340,L606,D503,R755,U390,R142,D921,L976,D36,L965,D450,L722,D224,L303,U705,L584
L993,U810,L931,D139,R114,D77,L75,U715,R540,D994,L866,U461,R340,D179,R314,D423,R629,D8,L692,U446,L88,D132,L128,U934,L465,D58,L696,D883,L955,D565,R424,U286,R403,U57,L627,D930,R887,D941,L306,D951,R918,U587,R939,U821,L65,D18,L987,D707,L360,D54,L932,U366,R625,U609,R173,D637,R661,U888,L68,U962,R270,U369,R780,U845,L813,U481,R66,D182,R420,U605,R880,D276,L6,D529,R883,U189,R380,D472,R30,U35,L510,D844,L146,U875,R152,U545,R274,U920,R432,U814,R583,D559,L820,U135,L353,U975,L103,U615,R401,U692,L676,D781,R551,D985,L317,U836,R115,D216,L967,U286,R681,U144,L354,U678,L893,D487,R664,D185,R787,D909,L582,D283,L519,D893,L56,U768,L345,D992,L248,U439,R573,D98,L390,D43,L470,D435,R176,U468,R688,U388,L377,U800,R187,U641,L268,U857,L716,D179,R212,U196,L342,U731,R261,D92,R183,D623,L589,D215,L966,U878,L784,U740,R823,D99,L167,D992,R414,U22,L27,U390,R286,D744,L360,U554,L756,U715,R939,D806,R279,U292,L960,U633,L428,U949,R90,D321,R749,U395,L392,U348,L33,D757,R289,D367,L562,D668,L79,D193,L991,D705,L562,U25,R146,D34,R325,U203,R403,D714,R607,U72,L444,D76,R267,U924,R289,U962,L159,U726,L57,D540,R299,U343,R936,U90,L311,U243,L415,D426,L936,D570,L539,D731,R367,D374,L56,D251,L265,U65,L14,D882,L956,U88,R688,D34,R866,U777,R342,D270,L344,D953,L438,D855,L587,U320,L953,D945,L473,U559,L487,D602,R255,U871,L854,U45,R705,D247,R955,U885,R657,D664,L360,D764,L549,D676,R85,U189,L951,D922,R511,D429,R37,U11,R821,U984,R825,U874,R753,D524,L537,U618,L919,D597,L364,D231,L258,U818,R406,D208,R214,U530,R261

View file

@ -0,0 +1,2 @@
R1003,U756,L776,U308,R718,D577,R902,D776,R760,U638,R289,D70,L885,U161,R807,D842,R175,D955,R643,U380,R329,U573,L944,D2,L807,D886,L549,U592,R152,D884,L761,D915,L726,D677,L417,D651,L108,D377,L699,D938,R555,D222,L689,D196,L454,U309,L470,D234,R198,U689,L996,U117,R208,D310,R572,D562,L207,U244,L769,U186,R153,D756,R97,D625,R686,U244,R348,U586,L385,D466,R483,U718,L892,D39,R692,U756,L724,U148,R70,U224,L837,D370,L309,U235,R382,D579,R404,D146,R6,U584,L840,D863,R942,U646,R146,D618,L12,U210,R126,U163,R931,D661,L710,D883,L686,D688,L148,D19,R703,U530,R889,U186,R779,D503,R417,U272,R541,U21,L562,D10,L349,U998,R69,D65,R560,D585,L949,D372,L110,D865,R212,U56,L936,U957,L88,U612,R927,U642,R416,U348,L541,D416,L808,D759,R449,D6,L517,D4,R494,D143,L536,U341,R394,U179,L22,D680,L138,U249,L285,U879,L717,U756,L313,U222,R823,D208,L134,U984,R282,U635,R207,D63,L416,U511,L179,D582,L651,U932,R646,U378,R263,U138,L920,U523,L859,D556,L277,D518,R489,U561,L457,D297,R72,U920,L583,U23,L395,D844,R776,D552,L55,D500,R111,U409,R685,D427,R275,U739,R181,U333,L215,U808,R341,D537,R336,U230,R247,U748,R846,U404,R850,D493,R891,U176,L744,U585,L987,D849,R271,D848,L555,U801,R316,U753,L390,U97,L128,U45,R706,U35,L928,U913,R537,D512,R152,D410,R76,D209,R183,U941,R289,U632,L923,D190,R488,D934,R442,D303,R178,D250,R204,U247,R707,U77,R428,D701,R386,U110,R641,U925,R703,D387,L946,U415,R461,D123,L214,U236,L959,U517,R957,D524,R812,D668,R369,U340,L606,D503,R755,U390,R142,D921,L976,D36,L965,D450,L722,D224,L303,U705,L584
L993,U810,L931,D139,R114,D77,L75,U715,R540,D994,L866,U461,R340,D179,R314,D423,R629,D8,L692,U446,L88,D132,L128,U934,L465,D58,L696,D883,L955,D565,R424,U286,R403,U57,L627,D930,R887,D941,L306,D951,R918,U587,R939,U821,L65,D18,L987,D707,L360,D54,L932,U366,R625,U609,R173,D637,R661,U888,L68,U962,R270,U369,R780,U845,L813,U481,R66,D182,R420,U605,R880,D276,L6,D529,R883,U189,R380,D472,R30,U35,L510,D844,L146,U875,R152,U545,R274,U920,R432,U814,R583,D559,L820,U135,L353,U975,L103,U615,R401,U692,L676,D781,R551,D985,L317,U836,R115,D216,L967,U286,R681,U144,L354,U678,L893,D487,R664,D185,R787,D909,L582,D283,L519,D893,L56,U768,L345,D992,L248,U439,R573,D98,L390,D43,L470,D435,R176,U468,R688,U388,L377,U800,R187,U641,L268,U857,L716,D179,R212,U196,L342,U731,R261,D92,R183,D623,L589,D215,L966,U878,L784,U740,R823,D99,L167,D992,R414,U22,L27,U390,R286,D744,L360,U554,L756,U715,R939,D806,R279,U292,L960,U633,L428,U949,R90,D321,R749,U395,L392,U348,L33,D757,R289,D367,L562,D668,L79,D193,L991,D705,L562,U25,R146,D34,R325,U203,R403,D714,R607,U72,L444,D76,R267,U924,R289,U962,L159,U726,L57,D540,R299,U343,R936,U90,L311,U243,L415,D426,L936,D570,L539,D731,R367,D374,L56,D251,L265,U65,L14,D882,L956,U88,R688,D34,R866,U777,R342,D270,L344,D953,L438,D855,L587,U320,L953,D945,L473,U559,L487,D602,R255,U871,L854,U45,R705,D247,R955,U885,R657,D664,L360,D764,L549,D676,R85,U189,L951,D922,R511,D429,R37,U11,R821,U984,R825,U874,R753,D524,L537,U618,L919,D597,L364,D231,L258,U818,R406,D208,R214,U530,R261

View file

@ -0,0 +1,184 @@
use std::io::BufRead;
use std::collections::HashSet;
use std::collections::LinkedList;
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
struct Point(i32, i32);
#[derive(Copy, Clone)]
enum Direction {
Up,
Down,
Left,
Right
}
#[derive(Debug)]
struct Cable {
points: HashSet<Point>,
path: LinkedList<Point>,
}
impl Cable {
fn new(origin: Point) -> Cable {
let mut cable = Cable {
points: HashSet::new(),
path: LinkedList::new()
};
cable.add_point(origin);
cable
}
fn add_point(&mut self, point: Point) {
self.path.push_back(point);
self.points.insert(point);
}
fn step(&mut self, direction: Direction) {
let curp = self.path.back().unwrap().clone();
match direction {
Direction::Up => self.add_point(Point (curp.0, curp.1+1)),
Direction::Down => self.add_point(Point (curp.0, curp.1-1)),
Direction::Left => self.add_point(Point (curp.0-1, curp.1)),
Direction::Right => self.add_point(Point (curp.0+1, curp.1))
}
}
fn walk(&mut self, direction: Direction, steps: u32) {
for _i in 0..steps {
self.step(direction);
}
}
fn min_steps_to(&self, point: &Point) -> u32 {
let mut steps = 0;
for &p in self.path.iter() {
if p == *point {
return steps;
}
steps+=1;
}
std::u32::MAX/2
}
fn intersections(&self, other: &Self) -> Vec<Point> {
let mut v = vec!{};
let s = if self.path.len() > other.path.len() {self} else {other};
let o = if self.path.len() > other.path.len() {other} else {self};
for p in s.points.iter() {
if o.points.contains(p) {
v.push(*p);
}
}
v
}
}
fn parse(line: &str) -> Cable {
let mut cable = Cable::new(Point(0,0));
line.split(',').for_each(|s| {
let ss = s.split_at(1);
match ss.0 {
"R" => cable.walk(Direction::Right, ss.1.parse().unwrap()),
"L" => cable.walk(Direction::Left, ss.1.parse().unwrap()),
"U" => cable.walk(Direction::Up, ss.1.parse().unwrap()),
"D" => cable.walk(Direction::Down, ss.1.parse().unwrap()),
_ => panic! {"Unknown direction"}
}});
cable
}
fn nearest_point(origin: Point, points: &[Point]) -> Point {
let mut min: Point = Point(std::i32::MAX/2-1, std::i32::MAX/2-1);
let dist = |p: Point| {(origin.0 - p.0).abs() + (origin.1 - p.1).abs()};
for p in points {
if dist(*p) < dist(min) {
min = p.clone();
}
}
min
}
fn nearest_point_by_steps(cable1: &Cable, cable2: &Cable, points: &[Point]) -> (Point,u32) {
let mut min: Point = Point(std::i32::MAX/2-1, std::i32::MAX/2-1);
let combined_steps = |p: &Point| {cable1.min_steps_to(p) + cable2.min_steps_to(p)};
for p in points {
if combined_steps(p) < combined_steps(&min) {
min = p.clone();
}
}
(min, combined_steps(&min))
}
fn main() {
let f = std::fs::File::open("input").unwrap();
let r = std::io::BufReader::new(f);
let mut l = r.lines();
let c1line = l.next().unwrap().unwrap();
let cable1 = parse(&c1line);
let c2line = l.next().unwrap().unwrap();
let cable2 = parse(&c2line);
println!{"Intersecting"}
let mut inter = cable1.intersections(&cable2);
println!{"Intersections: {:?}", inter}
let origin = inter.iter().position(|x| *x == Point(0,0)).unwrap();
inter.remove(origin);
let (np,stps) = nearest_point_by_steps(&cable1, &cable2, &inter);
println!("Min point: {:?}", np);
println!("Steps: {}", stps);
}
#[cfg(test)]
mod test {
use super::*;
fn run_with(l1: &str, l2: &str) -> (Point, u32) {
let cable1 = parse(&l1);
let cable2 = parse(&l2);
println!{"hi"};
let mut inter = cable1.intersections(&cable2);
let origin = inter.iter().position(|x| *x == Point(0,0)).unwrap();
inter.remove(origin);
let (np,stps) = nearest_point_by_steps(&cable1, &cable2, &inter);
println!("Min point: {:?}", np);
println!("Steps: {:?}", stps);
(np,stps)
}
#[test]
fn tc1 () {
let l1 = "R75,D30,R83,U83,L12,D49,R71,U7,L72";
let l2 = "U62,R66,U55,R34,D71,R55,D58,R83";
assert_eq!{610, run_with(l1,l2).1}
}
#[test]
fn tc2 () {
let l1 = "R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51";
let l2 = "U98,R91,D20,R16,D67,R40,U7,R15,U6,R7";
assert_eq!{410, run_with(l1,l2).1}
}
}