summaryrefslogtreecommitdiff
path: root/aoc/2024/08
diff options
context:
space:
mode:
Diffstat (limited to 'aoc/2024/08')
-rwxr-xr-xaoc/2024/08/python.py51
-rw-r--r--aoc/2024/08/rust/Cargo.lock7
-rw-r--r--aoc/2024/08/rust/Cargo.toml6
-rw-r--r--aoc/2024/08/rust/src/main.rs74
4 files changed, 138 insertions, 0 deletions
diff --git a/aoc/2024/08/python.py b/aoc/2024/08/python.py
new file mode 100755
index 0000000..783203b
--- /dev/null
+++ b/aoc/2024/08/python.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python3
+
+from collections import defaultdict
+from fileinput import input
+from itertools import product
+
+antennas = defaultdict(set)
+x_max, y_max = 0, 0
+
+for idy, line in enumerate(input()):
+ y_max = max(y_max, idy)
+ for idx, c in enumerate(line.strip()):
+ x_max = max(x_max, idx)
+ if c == ".":
+ continue
+
+ antennas[c].add(complex(idx, idy))
+
+nodes = set()
+for vs in antennas.values():
+ for v1, v2 in product(vs, vs):
+ if v1 == v2:
+ continue
+ vec = v2 - v1
+ nodes.add(v1 + 2 * vec)
+ nodes.add(v2 - 2 * vec)
+
+nodes = {n for n in nodes if 0 <= n.real <= x_max and 0 <= n.imag <= y_max}
+
+gold_nodes = set()
+for vs in antennas.values():
+ for v1, v2 in product(vs, vs):
+ if v1 == v2:
+ continue
+ vec = v2 - v1
+ start = v1
+ while 0 <= start.real <= x_max and 0 <= start.imag <= y_max:
+ gold_nodes.add(start)
+ start += vec
+
+ start = v2
+ while 0 <= start.real <= x_max and 0 <= start.imag <= y_max:
+ gold_nodes.add(start)
+ start -= vec
+
+
+silver = len(nodes)
+gold = len(gold_nodes)
+
+print("silver:", silver)
+print("gold:", gold)
diff --git a/aoc/2024/08/rust/Cargo.lock b/aoc/2024/08/rust/Cargo.lock
new file mode 100644
index 0000000..ac79b17
--- /dev/null
+++ b/aoc/2024/08/rust/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "puzzle"
+version = "0.1.0"
diff --git a/aoc/2024/08/rust/Cargo.toml b/aoc/2024/08/rust/Cargo.toml
new file mode 100644
index 0000000..88e7b42
--- /dev/null
+++ b/aoc/2024/08/rust/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "puzzle"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
diff --git a/aoc/2024/08/rust/src/main.rs b/aoc/2024/08/rust/src/main.rs
new file mode 100644
index 0000000..4fc3286
--- /dev/null
+++ b/aoc/2024/08/rust/src/main.rs
@@ -0,0 +1,74 @@
+use std::{
+ collections::{HashMap, HashSet},
+ io,
+};
+
+fn main() -> io::Result<()> {
+ let mut antennae: HashMap<char, Vec<(i32, i32)>> = HashMap::new();
+
+ let grid = io::stdin()
+ .lines()
+ .flatten()
+ .map(|s| s.chars().collect())
+ .collect::<Vec<Vec<char>>>();
+
+ let max = grid.first().unwrap().len() as i32;
+ let may = grid.len() as i32;
+ grid.iter()
+ .enumerate()
+ .flat_map(|(y, row)| {
+ row.iter()
+ .enumerate()
+ .filter(|(_, &c)| c != '.')
+ .map(move |(x, &c)| (c, (x as i32, y as i32)))
+ })
+ .for_each(|(c, p)| antennae.entry(c).or_default().push(p));
+
+ let mut silver = HashSet::new();
+ let mut gold = HashSet::new();
+ for ps in antennae.values() {
+ for (n, &p) in ps.iter().enumerate() {
+ for &t in &ps[n+1..] {
+ antinodes(p, t, (max, may), false).for_each(|n| {
+ silver.insert(n);
+ });
+ antinodes(p, t, (max, may), true).for_each(|n| {
+ gold.insert(n);
+ });
+ }
+ }
+ }
+
+ let silver = silver.len();
+ let gold = gold.len();
+ println!("silver: {silver}");
+ println!("gold: {gold}");
+
+ return Ok(());
+}
+
+fn antinodes(
+ a: (i32, i32),
+ b: (i32, i32),
+ max: (i32, i32),
+ gold: bool,
+) -> impl Iterator<Item = (i32, i32)> {
+ let dx = b.0 - a.0;
+ let dy = b.1 - a.1;
+ let in_range = move |(x, y)| (0..max.0).contains(&x) && (0..max.1).contains(&y);
+ if !gold {
+ vec![(a.0 - dx, a.1 - dy), (b.0 + dx, b.1 + dy)]
+ } else {
+ (0..)
+ .map(|n| (a.0 - n * dx, a.1 - n * dy))
+ .take_while(move |&p| in_range(p))
+ .chain(
+ (0..)
+ .map(|n| (b.0 + n * dx, b.1 + n * dy))
+ .take_while(move |&p| in_range(p)),
+ )
+ .collect()
+ }
+ .into_iter()
+ .filter(move |&p| in_range(p))
+}