mirror of
https://github.com/Findus23/AdventOfCode2019.git
synced 2024-08-27 19:52:12 +02:00
add day 3
This commit is contained in:
parent
38f37f755c
commit
62bc48fd96
6 changed files with 227 additions and 0 deletions
|
@ -8,6 +8,7 @@ jobs:
|
|||
- cd python
|
||||
script:
|
||||
- pytest
|
||||
- mypy 1 2 3
|
||||
|
||||
- language: rust
|
||||
rust: stable
|
||||
|
|
|
@ -49,6 +49,8 @@ def part2() -> int:
|
|||
if cl[0] == 19690720:
|
||||
return 100 * noun + verb
|
||||
|
||||
return -1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(part1())
|
||||
|
|
80
python/3/day3.py
Normal file
80
python/3/day3.py
Normal file
|
@ -0,0 +1,80 @@
|
|||
from typing import Tuple, List
|
||||
|
||||
|
||||
def parse_path(path: str):
|
||||
commands = path.split(",")
|
||||
|
||||
return [(c[0], int(c[1:])) for c in commands]
|
||||
|
||||
|
||||
def record_path(path) -> List[Tuple[int, int]]:
|
||||
pos = [0, 0]
|
||||
poslist = []
|
||||
for direction, length in path:
|
||||
while length > 0:
|
||||
if direction == "U":
|
||||
pos[1] += 1
|
||||
elif direction == "D":
|
||||
pos[1] -= 1
|
||||
elif direction == "R":
|
||||
pos[0] += 1
|
||||
elif direction == "L":
|
||||
pos[0] -= 1
|
||||
else:
|
||||
raise ValueError(f"invalid direction: {direction}")
|
||||
poslist.append((pos[0], pos[1]))
|
||||
length -= 1
|
||||
return poslist
|
||||
|
||||
|
||||
def manhatten_distance(point: Tuple[int, int]) -> int:
|
||||
return abs(point[0]) + abs(point[1])
|
||||
|
||||
|
||||
def closest_crossing(first_path, second_path) -> int:
|
||||
p1 = record_path(first_path)
|
||||
p2 = record_path(second_path)
|
||||
commons = set(p1).intersection(set(p2))
|
||||
min_dist = 100000
|
||||
for crossing in commons:
|
||||
dist = manhatten_distance(crossing)
|
||||
if dist < min_dist:
|
||||
min_dist = dist
|
||||
return min_dist
|
||||
|
||||
|
||||
def shortest_signal(first_path, second_path) -> int:
|
||||
p1 = record_path(first_path)
|
||||
p2 = record_path(second_path)
|
||||
commons = set(p1).intersection(set(p2))
|
||||
shortest = 10000000
|
||||
for crossing in commons:
|
||||
total = 0
|
||||
for path in [p1, p2]:
|
||||
i = 0
|
||||
for segment in path:
|
||||
i += 1
|
||||
if segment == crossing:
|
||||
total += i
|
||||
break
|
||||
if total < shortest:
|
||||
shortest = total
|
||||
|
||||
return shortest
|
||||
|
||||
|
||||
def part1() -> int:
|
||||
with open("3/input.txt") as f:
|
||||
w1, w2 = f.readlines()
|
||||
return closest_crossing(parse_path(w1), parse_path(w2))
|
||||
|
||||
|
||||
def part2() -> int:
|
||||
with open("3/input.txt") as f:
|
||||
w1, w2 = f.readlines()
|
||||
return shortest_signal(parse_path(w1), parse_path(w2))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(part1())
|
||||
print(part2())
|
2
python/3/input.txt
Normal file
2
python/3/input.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
R990,U796,R784,U604,R6,U437,L96,U285,L361,U285,L339,D512,L389,D840,L425,U444,L485,D528,L262,U178,L80,U2,R952,U459,L361,D985,R56,U135,R953,D913,L361,U120,L329,U965,L294,U890,L126,U214,R232,D444,L714,U791,R888,U923,R378,U233,L654,D703,R902,D715,R469,D60,R990,U238,R755,U413,L409,D601,R452,U504,R472,D874,L766,D594,R696,U398,R593,D889,R609,D405,L962,U176,L237,U642,L393,D91,L463,U936,R199,D136,R601,D8,R359,D863,L410,U598,L444,D34,R664,D323,R72,D98,L565,D476,L197,D132,R510,U665,R936,U3,R385,U144,L284,D713,L605,U106,R543,D112,R528,D117,R762,U330,R722,U459,L229,U375,L870,D81,R623,U95,L148,D530,L622,D62,R644,D365,L214,U847,R31,D832,L648,D293,R79,D748,L270,U159,L8,U83,R195,U912,L409,D649,L750,D286,L623,D956,R81,U775,R44,D437,L199,U698,L42,U419,L883,U636,L323,U89,L246,D269,L992,U739,R62,U47,R63,U17,L234,U135,R126,D208,L69,U550,L123,D66,R463,U992,R411,D276,L851,U520,R805,D300,L894,U171,L922,D901,R637,U907,R328,U433,L316,D644,L398,U10,L648,D190,R884,U474,R397,D718,L925,D578,R249,U959,L697,D836,R231,U806,R982,U827,R579,U830,L135,D666,R818,D502,L898,D585,R91,D190,L255,U535,R56,U390,R619,D815,L300,D81,R432,D70,L940,D587,L259,D196,R241,U4,R440,U678,R185,U451,R733,D984,R464,D298,L738,U600,R353,D44,L458,U559,L726,D786,L307,D333,L226,D463,R138,D142,L521,D201,R51,D202,L204,U130,L333,U597,R298,U42,L951,U66,R312,U707,L555,D225,L360,D12,L956,D361,L989,D625,L944,D398,L171,D982,L377,U114,L339,U164,R39,D793,R992,U834,R675,U958,R334,D697,L734,D40,L149,U394,R976
|
||||
L1005,D52,L125,U787,L761,U262,L466,D966,R895,U789,R6,U2,R870,U971,R238,D946,L752,D240,R721,U349,L679,D518,L104,U417,L462,U544,L519,U797,R873,U70,R298,U45,L779,D921,R468,D421,R803,U108,L812,D498,R226,D309,R766,U724,L961,U472,R940,U944,R418,D682,R328,U55,R737,U961,L343,U397,R112,D292,L155,U162,R398,U445,L524,U256,R323,D587,L862,D726,R624,D230,R460,U539,R723,U93,L507,U608,L150,U159,R35,U458,R208,U546,L495,D835,L636,U960,L322,U408,L78,D250,L994,U818,R107,U978,R401,D147,R574,D549,R983,U698,L99,D63,L772,U409,R975,U990,L893,U467,L860,D721,R504,U102,R678,D672,L406,D933,R743,D788,R142,D44,R208,D424,R28,D674,R331,D968,L154,U206,R222,D354,R687,D331,L539,D390,L373,D514,L622,U673,R345,U943,L508,D337,R265,D785,L189,U429,R344,D719,R622,U199,L765,U350,R833,U309,R95,U911,R548,U746,R107,D867,L648,D680,R28,U596,L891,U168,R933,U571,R365,U267,R916,D130,L149,D898,L513,D167,R587,U799,R134,D328,R562,D929,L399,U568,R565,U241,L395,U822,L624,D145,L995,U516,R474,D609,R153,U52,R561,D15,R283,U321,L850,U218,L225,D635,L630,U102,L84,D672,L128,D885,L506,U911,R355,D132,R155,D120,L110,U368,R149,D343,L708,U378,R591,D585,L381,D517,R852,U432,R342,U273,R893,D277,L548,U859,L891,U311,L901,U255,R421,U90,L72,D474,L654,U12,L146,D867,L485,D663,R123,D82,L21,U408,L38,D864,L114,D645,R936,U765,L832,D668,L482,U79,L594,U276,L559,D469,R314,D162,R621,U230,L688,U82,R605,U191,L381,D327,L91,D217,R714,D942,R851,U358,R22,U952,R279,D897,R485,D867,L940,U891,L223,D264,L634,D560,R645,D705,L289,U584,R97,U920,R41
|
33
python/3/test_day3.py
Normal file
33
python/3/test_day3.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
from day3 import parse_path, manhatten_distance, closest_crossing, part1, shortest_signal, part2
|
||||
|
||||
|
||||
def test_parse_path():
|
||||
assert parse_path("R8,U5,L5,D3") == [('R', 8), ('U', 5), ('L', 5), ('D', 3)]
|
||||
|
||||
|
||||
def test_manhatten_distance():
|
||||
assert manhatten_distance((1, 4)) == 5
|
||||
|
||||
|
||||
def test_closest_crossing():
|
||||
assert closest_crossing(parse_path("R8,U5,L5,D3"), parse_path("U7,R6,D4,L4")) == 6
|
||||
assert closest_crossing(parse_path("R75,D30,R83,U83,L12,D49,R71,U7,L72"),
|
||||
parse_path("U62,R66,U55,R34,D71,R55,D58,R83")) == 159
|
||||
assert closest_crossing(parse_path("R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51"),
|
||||
parse_path("U98,R91,D20,R16,D67,R40,U7,R15,U6,R7")) == 135
|
||||
|
||||
|
||||
def test_shortest_signal():
|
||||
assert shortest_signal(parse_path("R8,U5,L5,D3"), parse_path("U7,R6,D4,L4")) == 30
|
||||
assert shortest_signal(parse_path("R75,D30,R83,U83,L12,D49,R71,U7,L72"),
|
||||
parse_path("U62,R66,U55,R34,D71,R55,D58,R83")) == 610
|
||||
assert shortest_signal(parse_path("R98,U47,R26,D63,R33,U87,L62,D20,R33,U53,R51"),
|
||||
parse_path("U98,R91,D20,R16,D67,R40,U7,R15,U6,R7")) == 410
|
||||
|
||||
|
||||
def test_part1():
|
||||
assert part1() == 316
|
||||
|
||||
|
||||
def test_part2():
|
||||
assert part2() == 16368
|
109
rust/src/day2.rs
Normal file
109
rust/src/day2.rs
Normal file
|
@ -0,0 +1,109 @@
|
|||
use std::fs;
|
||||
|
||||
type IntCode = Vec<i32>;
|
||||
|
||||
fn parse_intcode(codestr: &str) -> IntCode {
|
||||
let split: IntCode = codestr
|
||||
.split(",")
|
||||
.map(|codestr| codestr.parse::<i32>().expect("can't parse intcode"))
|
||||
.collect();
|
||||
return split;
|
||||
}
|
||||
|
||||
fn run_intcode(mut cl: IntCode) -> IntCode {
|
||||
let mut p = 0; // pointer,
|
||||
loop {
|
||||
let code = cl[p];
|
||||
if code == 99 {
|
||||
break;
|
||||
}
|
||||
let from1 = cl[p + 1] as usize;
|
||||
let from2 = cl[p + 2] as usize;
|
||||
let to = cl[p + 3] as usize;
|
||||
cl[to] = match code {
|
||||
1 => cl[from1] + cl[from2],
|
||||
2 => cl[from1] * cl[from2],
|
||||
_ => panic!("invalid intcode: {}", code),
|
||||
};
|
||||
p += 4
|
||||
}
|
||||
|
||||
return cl;
|
||||
}
|
||||
|
||||
pub fn part1() -> i32 {
|
||||
let mut data = fs::read_to_string("../python/2/input.txt").expect("Unable to read file");
|
||||
data.pop();
|
||||
let mut cl = parse_intcode(data.as_str());
|
||||
cl[1] = 12;
|
||||
cl[2] = 2;
|
||||
|
||||
cl = run_intcode(cl);
|
||||
return cl[0];
|
||||
}
|
||||
pub fn part2() -> i32 {
|
||||
let mut data = fs::read_to_string("../python/2/input.txt").expect("Unable to read file");
|
||||
data.pop();
|
||||
let inital_cl = parse_intcode(data.as_str());
|
||||
let mut cl: IntCode;
|
||||
for noun in 0..99 {
|
||||
for verb in 0..99 {
|
||||
cl = inital_cl.clone();
|
||||
cl[1] = noun;
|
||||
cl[2] = verb;
|
||||
cl = run_intcode(cl);
|
||||
if cl[0] == 19690720 {
|
||||
return 100 * noun + verb;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn test_parse_intcode() {
|
||||
assert_eq!(parse_intcode("2,2,3,45,5"), [2, 2, 3, 45, 5])
|
||||
}
|
||||
#[test]
|
||||
#[should_panic(expected = "invalid intcode: 123")]
|
||||
fn test_opcode_panics() {
|
||||
let cl = vec![123, 123, 123, 123];
|
||||
run_intcode(cl);
|
||||
}
|
||||
#[test]
|
||||
fn test_run_intcode1() {
|
||||
let mut cl: IntCode = vec![1, 0, 0, 0, 99];
|
||||
cl = run_intcode(cl);
|
||||
assert_eq!(cl, vec![2, 0, 0, 0, 99])
|
||||
}
|
||||
#[test]
|
||||
fn test_run_intcode2() {
|
||||
let mut cl: IntCode = vec![2, 3, 0, 3, 99];
|
||||
cl = run_intcode(cl);
|
||||
assert_eq!(cl, vec![2, 3, 0, 6, 99])
|
||||
}
|
||||
#[test]
|
||||
fn test_run_intcode3() {
|
||||
let mut cl: IntCode = vec![2, 4, 4, 5, 99, 0];
|
||||
cl = run_intcode(cl);
|
||||
assert_eq!(cl, vec![2, 4, 4, 5, 99, 9801])
|
||||
}
|
||||
#[test]
|
||||
fn test_run_intcode4() {
|
||||
let mut cl: IntCode = vec![1, 1, 1, 4, 99, 5, 6, 0, 99];
|
||||
cl = run_intcode(cl);
|
||||
assert_eq!(cl, vec![30, 1, 1, 4, 2, 5, 6, 0, 99])
|
||||
}
|
||||
#[test]
|
||||
fn test_part1() {
|
||||
assert_eq!(part1(), 4714701)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part2() {
|
||||
assert_eq!(part2(), 5121)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue