Compare commits
5 Commits
f951932c2c
...
main
Author | SHA1 | Date | |
---|---|---|---|
195ef4651f
|
|||
a264e1e6d3
|
|||
47a7381575
|
|||
e0900ec2ed
|
|||
d34dcb5957
|
28
Cargo.toml
28
Cargo.toml
@ -65,4 +65,32 @@ path = "src/day13/main.rs"
|
||||
name = "day14"
|
||||
path = "src/day14/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "day15"
|
||||
path = "src/day15/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "day16"
|
||||
path = "src/day16/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "day17"
|
||||
path = "src/day17/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "day18"
|
||||
path = "src/day18/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "day19"
|
||||
path = "src/day19/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "day20"
|
||||
path = "src/day20/main.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "day21"
|
||||
path = "src/day21/main.rs"
|
||||
|
||||
[dependencies]
|
||||
|
26
day15.txt
Normal file
26
day15.txt
Normal file
@ -0,0 +1,26 @@
|
||||
Sensor at x=3772068, y=2853720: closest beacon is at x=4068389, y=2345925
|
||||
Sensor at x=78607, y=2544104: closest beacon is at x=-152196, y=4183739
|
||||
Sensor at x=3239531, y=3939220: closest beacon is at x=3568548, y=4206192
|
||||
Sensor at x=339124, y=989831: closest beacon is at x=570292, y=1048239
|
||||
Sensor at x=3957534, y=2132743: closest beacon is at x=3897332, y=2000000
|
||||
Sensor at x=1882965, y=3426126: closest beacon is at x=2580484, y=3654136
|
||||
Sensor at x=1159443, y=3861139: closest beacon is at x=2580484, y=3654136
|
||||
Sensor at x=2433461, y=287013: closest beacon is at x=2088099, y=-190228
|
||||
Sensor at x=3004122, y=3483833: closest beacon is at x=2580484, y=3654136
|
||||
Sensor at x=3571821, y=799602: closest beacon is at x=3897332, y=2000000
|
||||
Sensor at x=2376562, y=1539540: closest beacon is at x=2700909, y=2519581
|
||||
Sensor at x=785113, y=1273008: closest beacon is at x=570292, y=1048239
|
||||
Sensor at x=1990787, y=38164: closest beacon is at x=2088099, y=-190228
|
||||
Sensor at x=3993778, y=3482849: closest beacon is at x=4247709, y=3561264
|
||||
Sensor at x=3821391, y=3986080: closest beacon is at x=3568548, y=4206192
|
||||
Sensor at x=2703294, y=3999015: closest beacon is at x=2580484, y=3654136
|
||||
Sensor at x=1448314, y=2210094: closest beacon is at x=2700909, y=2519581
|
||||
Sensor at x=3351224, y=2364892: closest beacon is at x=4068389, y=2345925
|
||||
Sensor at x=196419, y=3491556: closest beacon is at x=-152196, y=4183739
|
||||
Sensor at x=175004, y=138614: closest beacon is at x=570292, y=1048239
|
||||
Sensor at x=1618460, y=806488: closest beacon is at x=570292, y=1048239
|
||||
Sensor at x=3974730, y=1940193: closest beacon is at x=3897332, y=2000000
|
||||
Sensor at x=2995314, y=2961775: closest beacon is at x=2700909, y=2519581
|
||||
Sensor at x=105378, y=1513086: closest beacon is at x=570292, y=1048239
|
||||
Sensor at x=3576958, y=3665667: closest beacon is at x=3568548, y=4206192
|
||||
Sensor at x=2712265, y=2155055: closest beacon is at x=2700909, y=2519581
|
14
day15_test.txt
Normal file
14
day15_test.txt
Normal file
@ -0,0 +1,14 @@
|
||||
Sensor at x=2, y=18: closest beacon is at x=-2, y=15
|
||||
Sensor at x=9, y=16: closest beacon is at x=10, y=16
|
||||
Sensor at x=13, y=2: closest beacon is at x=15, y=3
|
||||
Sensor at x=12, y=14: closest beacon is at x=10, y=16
|
||||
Sensor at x=10, y=20: closest beacon is at x=10, y=16
|
||||
Sensor at x=14, y=17: closest beacon is at x=10, y=16
|
||||
Sensor at x=8, y=7: closest beacon is at x=2, y=10
|
||||
Sensor at x=2, y=0: closest beacon is at x=2, y=10
|
||||
Sensor at x=0, y=11: closest beacon is at x=2, y=10
|
||||
Sensor at x=20, y=14: closest beacon is at x=25, y=17
|
||||
Sensor at x=17, y=20: closest beacon is at x=21, y=22
|
||||
Sensor at x=16, y=7: closest beacon is at x=15, y=3
|
||||
Sensor at x=14, y=3: closest beacon is at x=15, y=3
|
||||
Sensor at x=20, y=1: closest beacon is at x=15, y=3
|
10
day16_test.txt
Normal file
10
day16_test.txt
Normal file
@ -0,0 +1,10 @@
|
||||
Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
|
||||
Valve BB has flow rate=13; tunnels lead to valves CC, AA
|
||||
Valve CC has flow rate=2; tunnels lead to valves DD, BB
|
||||
Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
|
||||
Valve EE has flow rate=3; tunnels lead to valves FF, DD
|
||||
Valve FF has flow rate=0; tunnels lead to valves EE, GG
|
||||
Valve GG has flow rate=0; tunnels lead to valves FF, HH
|
||||
Valve HH has flow rate=22; tunnel leads to valve GG
|
||||
Valve II has flow rate=0; tunnels lead to valves AA, JJ
|
||||
Valve JJ has flow rate=21; tunnel leads to valve II
|
0
day18_test.txt
Normal file
0
day18_test.txt
Normal file
7
day20_test.txt
Normal file
7
day20_test.txt
Normal file
@ -0,0 +1,7 @@
|
||||
1
|
||||
2
|
||||
-3
|
||||
3
|
||||
-2
|
||||
0
|
||||
4
|
15
day21_test.txt
Normal file
15
day21_test.txt
Normal file
@ -0,0 +1,15 @@
|
||||
root: pppw + sjmn
|
||||
dbpl: 5
|
||||
cczh: sllz + lgvd
|
||||
zczc: 2
|
||||
ptdq: humn - dvpt
|
||||
dvpt: 3
|
||||
lfqf: 4
|
||||
humn: 5
|
||||
ljgn: 2
|
||||
sjmn: drzm * dbpl
|
||||
sllz: 4
|
||||
pppw: cczh / lfqf
|
||||
lgvd: ljgn * ptdq
|
||||
drzm: hmdt - zczc
|
||||
hmdt: 32
|
145
src/day15/main.rs
Normal file
145
src/day15/main.rs
Normal file
@ -0,0 +1,145 @@
|
||||
use std::cmp::max;
|
||||
use std::collections::HashSet;
|
||||
use base::read_file;
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
|
||||
struct Pos(i32, i32);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Beacon {
|
||||
pos: Pos,
|
||||
beacon: Pos,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
struct Range {
|
||||
start: i32,
|
||||
end: i32,
|
||||
}
|
||||
|
||||
impl Range {
|
||||
fn new(start: i32, end: i32) -> Self {
|
||||
Range { start, end }
|
||||
}
|
||||
|
||||
fn contains(&self, number: i32) -> bool {
|
||||
number >= self.start && number <= self.end
|
||||
}
|
||||
|
||||
fn fully_overlap(&self, other: &Range) -> bool {
|
||||
self.contains(other.start) && self.contains(other.end)
|
||||
}
|
||||
|
||||
fn partly_overlap(&self, other: &Range) -> bool {
|
||||
self.contains(other.start) || self.contains(other.end)
|
||||
}
|
||||
}
|
||||
|
||||
struct YLine {
|
||||
y: i32,
|
||||
start_x: i32,
|
||||
start_y: i32,
|
||||
}
|
||||
|
||||
impl Beacon {
|
||||
fn possible_positions_into_of(&self, positions: &mut HashSet<Pos>, y: i32) {
|
||||
let distance = self.get_distance();
|
||||
for x in -distance..=distance {
|
||||
if x.abs() + (self.pos.1 - y).abs() <= distance {
|
||||
positions.insert(Pos(self.pos.0 + x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_distance(&self) -> i32 {
|
||||
let Pos(px, py) = self.pos;
|
||||
let Pos(bx, by) = self.beacon;
|
||||
(px - bx).abs() + (py - by).abs()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let lines = read_file("day15.txt");
|
||||
let mut beacons = vec![];
|
||||
|
||||
for line in lines {
|
||||
beacons.push(
|
||||
line.split([' ', '=', ':', ','])
|
||||
.filter_map(|tok| tok.parse::<i32>().ok())
|
||||
.collect::<Vec<_>>()
|
||||
.chunks_exact(4)
|
||||
.map(|positions| Beacon { pos: Pos(positions[0], positions[1]), beacon: Pos(positions[2], positions[3]) })
|
||||
.next()
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
let mut possible_positions = HashSet::new();
|
||||
|
||||
println!("Found {} beacons", beacons.len());
|
||||
|
||||
println!("Inserting possible positions");
|
||||
let y = 2000000;
|
||||
|
||||
for (idx, beacon) in beacons.iter().enumerate() {
|
||||
println!("Generating positions for beacon {}", idx);
|
||||
beacon.possible_positions_into_of(&mut possible_positions, y);
|
||||
}
|
||||
|
||||
println!("Inserting beacons");
|
||||
|
||||
for beacon in &beacons {
|
||||
possible_positions.remove(&beacon.pos);
|
||||
possible_positions.remove(&beacon.beacon);
|
||||
}
|
||||
|
||||
|
||||
println!("Searching for possible positions");
|
||||
|
||||
let count = possible_positions.iter().filter(|pos| pos.1 == y).count();
|
||||
|
||||
println!("Found {} at {}", count, y);
|
||||
|
||||
let max = 4000001;
|
||||
for y in 0..max {
|
||||
if y % 1000 == 0 {
|
||||
println!("Y is {}/{}", y, max);
|
||||
}
|
||||
let mut beacon_radiation = vec![];
|
||||
for beacon in &beacons {
|
||||
let distance = (beacon.pos.1 - y as i32).abs();
|
||||
let max_distance = beacon.get_distance();
|
||||
if distance <= max_distance {
|
||||
let start_x = beacon.pos.0 - (max_distance - distance);
|
||||
let end_x = beacon.pos.0 + (max_distance - distance);
|
||||
beacon_radiation.push(Range::new(start_x, end_x));
|
||||
}
|
||||
}
|
||||
|
||||
beacon_radiation.sort_by(|r1, r2| r1.start.cmp(&r2.start));
|
||||
|
||||
let mut start: Option<Range> = None;
|
||||
for range in beacon_radiation {
|
||||
match start {
|
||||
None => {
|
||||
start = Some(range);
|
||||
}
|
||||
Some(before) => {
|
||||
if range.partly_overlap(&before) || (range.start - before.end) == 1 {
|
||||
if range.end > before.end {
|
||||
start = Some(Range::new(before.start, range.end));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(sol) = start {
|
||||
if sol.end < max {
|
||||
let x = sol.end + 1;
|
||||
println!("Possible solution: {}/{} Distress: {}", x, y, (x as i64) * 4000000 + (y as i64));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
71
src/day16/main.rs
Normal file
71
src/day16/main.rs
Normal file
@ -0,0 +1,71 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use base::read_file;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ScanEntry {
|
||||
id: usize,
|
||||
flow_rate: u32,
|
||||
next: Vec<usize>,
|
||||
}
|
||||
|
||||
fn find_path(graph: &HashMap<usize, ScanEntry>, start_id: usize, visited: &mut HashSet<usize>) {
|
||||
if let Some(current) = graph.get(&start_id) {
|
||||
visited.insert(current.id);
|
||||
for next_id in ¤t.next {
|
||||
if !visited.contains(next_id) {
|
||||
println!("Found {}", next_id);
|
||||
find_path(graph, *next_id, visited);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let lines = read_file("day16_test.txt");
|
||||
let mut ids = HashMap::new();
|
||||
let mut next_id = 0;
|
||||
let mut entries = HashMap::new();
|
||||
let mut start_id = None;
|
||||
for line in lines {
|
||||
let mut my_id = None;
|
||||
let mut flow = None;
|
||||
let mut next_ids = vec![];
|
||||
for x in line.split([' ', ',']) {
|
||||
if x.len() > 0 {
|
||||
let mut uppercase = true;
|
||||
for char in x.chars() {
|
||||
uppercase = char.is_uppercase();
|
||||
if !uppercase { break; };
|
||||
}
|
||||
if uppercase {
|
||||
let id = *ids.entry(x.to_owned()).or_insert_with(|| {
|
||||
next_id += 1;
|
||||
next_id
|
||||
});
|
||||
match my_id {
|
||||
None => my_id = Some(id),
|
||||
Some(_) => next_ids.push(id),
|
||||
}
|
||||
match start_id {
|
||||
None => start_id = Some(id),
|
||||
_ => {}
|
||||
}
|
||||
} else if x.contains('=') {
|
||||
let flow_value = x.split(['=', ';']).filter_map(|s| s.parse::<u32>().ok()).next().unwrap();
|
||||
flow = Some(flow_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
let entry = ScanEntry {
|
||||
id: my_id.unwrap(),
|
||||
flow_rate: flow.unwrap(),
|
||||
next: next_ids,
|
||||
};
|
||||
entries.insert(entry.id, entry);
|
||||
}
|
||||
|
||||
let mut visited = HashSet::new();
|
||||
|
||||
dbg!(&entries);
|
||||
find_path(&entries, start_id.unwrap(), &mut visited);
|
||||
}
|
3
src/day17/main.rs
Normal file
3
src/day17/main.rs
Normal file
@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
println!("Not ready");
|
||||
}
|
3
src/day18/main.rs
Normal file
3
src/day18/main.rs
Normal file
@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
println!("Not ready");
|
||||
}
|
3
src/day19/main.rs
Normal file
3
src/day19/main.rs
Normal file
@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
println!("Not ready");
|
||||
}
|
52
src/day20/main.rs
Normal file
52
src/day20/main.rs
Normal file
@ -0,0 +1,52 @@
|
||||
use base::read_file;
|
||||
|
||||
fn do_encryption(key: &Vec<(usize, i64)>, data: &mut Vec<(usize, i64)>) {
|
||||
let wrap_size = data.len() - 1;
|
||||
for (index_to_find, enc_datum) in key {
|
||||
let index = data.iter().position(|(org_index, _)| org_index == index_to_find).unwrap();
|
||||
if *enc_datum == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let element = data.remove(index);
|
||||
|
||||
if *enc_datum > 0 {
|
||||
let enc_datum = *enc_datum as usize;
|
||||
data.rotate_left((enc_datum % wrap_size) as usize);
|
||||
} else {
|
||||
let enc_datum = enc_datum.abs() as usize;
|
||||
data.rotate_right((enc_datum % wrap_size) as usize);
|
||||
}
|
||||
|
||||
data.insert(index, element);
|
||||
}
|
||||
}
|
||||
|
||||
fn calc_result(data: Vec<(usize, i64)>) -> i64 {
|
||||
let zero_index = data.iter().position(|(_, value)| *value == 0).unwrap();
|
||||
println!("Found zero at {}", zero_index);
|
||||
let wrap_size = data.len();
|
||||
let number_1 = data[(zero_index + 1000) % wrap_size].1;
|
||||
let number_2 = data[(zero_index + 2000) % wrap_size].1;
|
||||
let number_3 = data[(zero_index + 3000) % wrap_size].1;
|
||||
|
||||
number_1 + number_2 + number_3
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let enc_data = read_file("day20.txt").iter().filter_map(|line| line.parse().ok()).enumerate().collect::<Vec<(usize, i64)>>();
|
||||
|
||||
let mut result = enc_data.clone();
|
||||
do_encryption(&enc_data, &mut result);
|
||||
|
||||
|
||||
println!("Task 1: {}", calc_result(result));
|
||||
|
||||
let enc_data = enc_data.iter().map(|(idx, value)| (*idx, value * 811589153)).collect::<Vec<_>>();
|
||||
let mut result = enc_data.clone();
|
||||
for _ in 0..10 {
|
||||
do_encryption(&enc_data, &mut result);
|
||||
}
|
||||
|
||||
println!("Task 2: {}", calc_result(result));
|
||||
}
|
90
src/day21/main.rs
Normal file
90
src/day21/main.rs
Normal file
@ -0,0 +1,90 @@
|
||||
use std::collections::HashMap;
|
||||
use base::read_file;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum UnparsedOp {
|
||||
Constant(i64),
|
||||
Add(String, String),
|
||||
Sub(String, String),
|
||||
Mul(String, String),
|
||||
Div(String, String),
|
||||
}
|
||||
|
||||
fn solve_op(op: &UnparsedOp, data: &HashMap<String, UnparsedOp>) -> i64 {
|
||||
return match op {
|
||||
UnparsedOp::Constant(number) => *number,
|
||||
UnparsedOp::Add(f, s) => solve_op(&data[f], data) + solve_op(&data[s], data),
|
||||
UnparsedOp::Sub(f, s) => solve_op(&data[f], data) - solve_op(&data[s], data),
|
||||
UnparsedOp::Mul(f, s) => solve_op(&data[f], data) * solve_op(&data[s], data),
|
||||
UnparsedOp::Div(f, s) => solve_op(&data[f], data) / solve_op(&data[s], data),
|
||||
};
|
||||
}
|
||||
|
||||
fn solve(data: &HashMap<String, UnparsedOp>) -> i64 {
|
||||
let root = &data["root"];
|
||||
|
||||
solve_op(root, data)
|
||||
}
|
||||
|
||||
fn solve_eq(data: &mut HashMap<String, UnparsedOp>) -> i64 {
|
||||
let root = data["root"].clone();
|
||||
|
||||
|
||||
if let UnparsedOp::Add(f, s) = root {
|
||||
let mut guess = 0;
|
||||
let mut add = 100000000000;
|
||||
|
||||
loop {
|
||||
let new_guess = guess + add;
|
||||
data.insert("humn".to_owned(), UnparsedOp::Constant(new_guess));
|
||||
let left = solve_op(&data[&f], data);
|
||||
let right = solve_op(&data[&s], data);
|
||||
if left < right {
|
||||
add /= 10;
|
||||
} else {
|
||||
guess = new_guess;
|
||||
}
|
||||
|
||||
if left == right {
|
||||
return guess;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
panic!("Can't handle this");
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let lines = read_file("day21.txt");
|
||||
let mut data = HashMap::new();
|
||||
|
||||
for line in lines {
|
||||
let splits = line.split(": ").collect::<Vec<_>>();
|
||||
let name = splits[0];
|
||||
if let Ok(number) = splits[1].parse::<i64>() {
|
||||
data.insert(name.to_owned(), UnparsedOp::Constant(number));
|
||||
} else {
|
||||
let split_op = splits[1].split_whitespace().collect::<Vec<_>>();
|
||||
let first = split_op[0].to_owned();
|
||||
let second = split_op[2].to_owned();
|
||||
|
||||
data.insert(name.to_owned(), match split_op[1].chars().next().unwrap() {
|
||||
'+' => UnparsedOp::Add(first, second),
|
||||
'-' => UnparsedOp::Sub(first, second),
|
||||
'*' => UnparsedOp::Mul(first, second),
|
||||
'/' => UnparsedOp::Div(first, second),
|
||||
_ => {
|
||||
panic!("Unknown operation");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let result = solve(&data);
|
||||
println!("Task1: {}", result);
|
||||
|
||||
|
||||
let result = solve_eq(&mut data);
|
||||
println!("Task2: {}", result);
|
||||
}
|
Reference in New Issue
Block a user