added incomplete solutions

Dieser Commit ist enthalten in:
Sebastian Tobie 2024-12-14 11:48:20 +01:00
Ursprung f3339b38e1
Commit b24a6f52c0
5 geänderte Dateien mit 633 neuen und 0 gelöschten Zeilen

12
examples/2024/08.txt Normale Datei
Datei anzeigen

@ -0,0 +1,12 @@
............
........0...
.....0......
.......0....
....0.......
......A.....
............
............
........A...
.........A..
............
............

1
examples/2024/11.txt Normale Datei
Datei anzeigen

@ -0,0 +1 @@
125 17

120
src/bin/2024/08.rs Normale Datei
Datei anzeigen

@ -0,0 +1,120 @@
use std::collections::HashMap;
use advent_of_code::{
strings::{convert_to_array, line_to_char},
Kartesian, Table,
};
#[allow(unused_imports)]
use advent_of_code_macros::{include_data, include_example};
use log::*;
include_data!(DATA 2024 08);
const EMPTY: char = '.';
fn get_map(maximum: Kartesian<usize>) -> Vec<Vec<char>> {
let mut resomap = Vec::new();
let mut m = Vec::new();
m.resize(maximum.y, EMPTY);
resomap.resize(maximum.x, m);
resomap
}
fn find_antennas(map: Table) -> HashMap<char, Vec<Kartesian<usize>>> {
let mut positions = HashMap::new();
let mut x = 0;
let mut y;
let len = map[0].len();
for line in map.clone() {
y = 0;
for char in line {
if char != EMPTY {
if !positions.contains_key(&char) {
positions.insert(char, Vec::with_capacity(len));
}
positions.get_mut(&char).unwrap().push(Kartesian::new(x, y));
}
y += 1;
}
x += 1;
}
positions
}
fn get_resonance(points: Vec<Kartesian<usize>>, maximum: Kartesian<usize>, harmonic: bool) -> Vec<Kartesian<usize>> {
let mut resonances = Vec::new();
let mut diff;
let mut direction;
for outer in points.clone() {
for inner in points.clone() {
if outer == inner {
continue;
}
(diff, direction) = inner.diff(outer);
loop {
if let Some(reso) = outer.move_dir(diff, direction) {
if reso.x < maximum.x && reso.y < maximum.y {
debug!("Found Point: {}", reso);
resonances.push(reso);
if !harmonic {
break;
}
} else {
break;
}
} else {
break;
}
}
}
}
resonances
}
fn main() {
let map = convert_to_array::<_, _, '\n'>(DATA, line_to_char);
let maximum = Kartesian::new(map.len(), map[0].len());
let positions = find_antennas(map.clone());
let mut tmp;
let mut resonating_points = Vec::new();
for (group, points) in positions.clone() {
tmp = get_resonance(points.clone(), maximum, false);
println!("Found {} resonances for {} antennas in group {}", tmp.len(), points.len(), group,);
resonating_points.append(&mut tmp);
}
println!("Found {} points before dedup", resonating_points.len());
resonating_points.dedup();
println!("{} after simple dedup", resonating_points.len());
resonating_points = resonating_points
.iter()
.filter(|x| {
for (group, positions) in positions.clone() {
if positions.contains(*x) {
println!("Discarded point {} because it is over an point of group {}", *x, group);
return false;
}
}
true
})
.cloned()
.collect();
let mut resomap = map.clone();
println!("There are {} Resonating points on the map after dedup.", resonating_points.len());
if resonating_points.len() != 305 {
println!("Wrong solution");
}
for point in resonating_points {
resomap[point.x][point.y] = '~';
}
for line in 0..resomap.len() {
print!("{:02}. ", line + 1);
for char in map[line].clone() {
print!("{}", char);
}
print!("|");
for char in resomap[line].clone() {
print!("{}", char);
}
println!();
}
}

193
src/bin/2024/11.rs Normale Datei
Datei anzeigen

@ -0,0 +1,193 @@
#![allow(unused)]
use std::collections::HashMap;
use advent_of_code::{
numberlength,
strings::{convert_to_array, parsenumber},
ExtendedOption,
};
#[allow(unused_imports)]
use advent_of_code_macros::{include_data, include_example};
use num::Integer;
include_data!(DATA 2024 11);
const BILLIONS: u64 = 1000_000_000;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
struct Stone {
number: u64,
left: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
struct MapSkip {
newnumber_a: u64,
newnumber_b: u64,
skipped_steps: usize,
}
#[derive(Debug, Clone)]
struct StoneCounter {
cache: Vec<Stone>,
map: HashMap<u64, ExtendedOption<MapSkip>>,
stones: u64,
start: usize,
stones_billions: u64,
}
impl StoneCounter {
fn new(start_values: Vec<u64>, rounds: usize) -> StoneCounter {
let mut cache = Vec::with_capacity(start_values.len());
for v in start_values.iter() {
cache.push(Stone { number: *v, left: rounds });
}
StoneCounter {
cache: cache,
map: HashMap::with_capacity(10_000),
stones: 0,
start: rounds,
stones_billions: 0,
}
}
fn blink(&mut self) -> u64 {
let mut stone: Stone;
let mut copy: Stone;
let (mut next, mut second);
while self.cache.len() > 0 {
stone = self.cache.pop().unwrap();
copy = stone.clone();
while stone.left > 0 {
if self.map.contains_key(&stone.number) {
match self.map.get(&stone.number).unwrap() {
ExtendedOption::None => {
self.stones += 1;
break;
},
ExtendedOption::Some(skip) => {
if stone.left < skip.skipped_steps {
stone.left = 0
} else {
stone.left -= skip.skipped_steps;
}
stone.number = skip.newnumber_a;
self.cache.push(Stone { number: skip.newnumber_b, left: stone.left });
continue;
},
ExtendedOption::Unset => {},
}
}
if stone.left == 1 {
self.map = self
.map
.iter()
.filter_map(|x| {
Some(if *x.1 == ExtendedOption::Unset {
(*x.0, ExtendedOption::None)
} else {
(*x.0, *x.1)
})
})
.collect();
break;
} else {
self.map.insert(stone.number, ExtendedOption::Unset);
}
stone.left -= 1;
(next, second) = blink(stone.number);
match second {
None => {
self.map.insert(stone.number, ExtendedOption::Unset);
stone.number = next;
},
Some(sec) => {
self.map.insert(
stone.number,
ExtendedOption::Some(MapSkip {
newnumber_a: next,
newnumber_b: sec,
skipped_steps: copy.left - stone.left,
}),
);
},
}
}
}
self.stones_billions * BILLIONS + self.stones
}
}
fn combine_number(p: &[u64]) -> u64 {
let mut o = 0;
for i in p {
o = o * 10 + i;
}
o
}
fn splitnumber(i: u64) -> (u64, u64) {
let len = numberlength(i) as usize;
let mut array = Vec::with_capacity(len);
let (mut quot, mut remainder);
quot = i;
loop {
(quot, remainder) = quot.div_rem(&10);
array.insert(0, remainder);
if quot == 0 {
break;
}
}
let (a, b) = array.split_at(len / 2);
(combine_number(a), combine_number(b))
}
fn blink(stone: u64) -> (u64, Option<u64>) {
if stone == 0 {
(1, None)
} else if numberlength(stone) % 2 == 0 {
let (stone, t) = splitnumber(stone);
(stone, Some(t))
} else {
(stone * 2024, None)
}
}
fn main() {
let stoneline = convert_to_array::<_, _, ' '>(DATA, parsenumber);
let mut counter = StoneCounter::new(stoneline.clone(), 25);
let stones = counter.blink();
debug_assert!(stones == 235850, "{} != {}", stones, 235850);
println!("{:?} Stones after 25 blinks", stones);
counter = StoneCounter::new(stoneline, 75);
println!("{:?} Stones after 75 blinks", counter.blink());
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_blink() {
let mut res = blink(8);
assert_eq!(res, (16192, None));
res = blink(res.0);
assert_eq!(res, (32772608, None));
res = blink(res.0);
assert_eq!(res, (3277, Some(2608)));
}
#[test]
fn test_stones() {
let testvalues = vec![
125, 17,
];
let mut counter = StoneCounter::new(testvalues.clone(), 6);
assert_eq!(counter.blink(), 22);
counter = StoneCounter::new(testvalues.clone(), 25);
assert_eq!(counter.blink(), 55312);
}
}

307
src/bin/2024/12.rs Normale Datei
Datei anzeigen

@ -0,0 +1,307 @@
#![allow(unused)]
use std::ops::{Mul, Not};
use advent_of_code::{strings::convert_to_array, ExtendedOption, Kartesian, KartesianDirection, KartesianIterator, MaximumFromMap, Table, KD};
#[allow(unused_imports)]
use advent_of_code_macros::{include_data, include_example};
use log::*;
use num::{iter, Integer};
include_data!(DATA 2024 12);
type Minimap = Vec<Vec<bool>>;
#[inline]
fn mul<T: Integer + Mul>(v: (T, T)) -> T {
v.0 * v.1
}
fn calc_perimeter_and_area(minimap: &Minimap) -> (u32, u32) {
//print_minimap(minimap);
let mut rectangle = true;
let length = minimap[0].len();
for line in minimap.clone() {
rectangle = rectangle && line.len() == length && line.iter().all(|x| *x);
}
if rectangle {
let height = minimap.len() as u32;
(height * length as u32, 2 * (length as u32 + height))
} else {
let (mut area, mut perimeter) = (0, 0);
for (x, line) in minimap.iter().enumerate() {
debug!("Row: {}", x + 1);
for (y, cell) in line.iter().cloned().enumerate() {
if cell {
area += 1;
}
if cell {
if x == 0 {
debug!(" Top Border in column {}", y + 1);
perimeter += 1;
}
if x == minimap.len() - 1 {
debug!(" Bottom Border");
perimeter += 1;
}
if y == 0 {
debug!(" Left border on line {}", x + 1);
perimeter += 1
}
if y == line.len() - 1 {
debug!(" Right border on line {}", x + 1);
perimeter += 1;
}
if x != 0 {
if minimap[x - 1].len() <= y || minimap[x - 1].len() > y && !minimap[x - 1][y] {
debug!(" Top Border on line {} and column {}", x + 1, y + 1);
perimeter += 1;
}
}
if x != minimap.len() - 1 {
if minimap[x + 1].len() <= y || minimap[x + 1].len() > y && !minimap[x + 1][y] {
debug!(" Bottom Border on line {} and column {}", x + 1, y + 1);
perimeter += 1;
}
}
if y != 0 && !minimap[x][y - 1] {
debug!(" Left Border on line {} and column {}", x + 1, y + 1);
perimeter += 1;
}
if y != line.len() - 1 && !minimap[x][y + 1] {
debug!(" Right Border on line {} and column {}", x + 1, y + 1);
perimeter += 1;
}
}
}
}
debug!("Area is {} and perimeter {}", area, perimeter);
(area, perimeter)
}
}
fn check_side(minimap: &Minimap, position: Kartesian<usize>, dir: KD) -> Option<Kartesian<usize>> {
match position.move_dir(dir.vector(), dir) {
None => None,
Some(new) => {
if minimap.len() == new.x || minimap[new.x].len() < new.y {
return Some(new);
}
None
},
}
}
fn calc_sides_and_area(minimap: &Minimap) -> (u32, u32) {
print_minimap(&minimap);
let maximum: Kartesian<usize> = Kartesian::maximum(&minimap);
let area = minimap.iter().map(|l| l.iter().filter(|x| **x == true).count()).sum::<usize>() as u32;
let mut sides = 0;
let mut lines = Vec::with_capacity(minimap.len().max(minimap[0].len()));
let mut position = Kartesian::default();
let mut innerdir;
let mut innerposition;
let mut emptys;
let mut map;
for dir in KD::iter(false, false, true) {
map = minimap.clone();
innerdir = dir.clockwise(false);
loop {
emptys = 0;
innerposition = position;
loop {
if innerposition.get_value(&map) == Some(true) {
break;
}
emptys += 1;
innerposition = match innerposition.move_dir_max(innerdir.vector(), innerdir, maximum) {
None => break,
Some(new) => new,
}
}
lines.push(emptys);
if let Some(newpos) = position.move_dir_max(dir.vector(), dir, maximum) {
position = newpos;
} else {
break;
}
}
let mut iter = lines.iter().cloned();
let mut last = iter.next().unwrap();
for i in iter {
if last != i {
sides += 1;
}
last = i;
}
sides += 1;
lines.clear();
}
println!("Prossesing done, found {} sides with and area of {}", sides, area);
(area, sides)
}
fn print_minimap(map: &Minimap) {
for row in map {
for column in row {
print!(
"{}",
match column {
false => ".",
true => "X",
}
)
}
println!()
}
}
#[inline]
fn move_content_left(minimap: &mut Minimap, columns: usize) {
for line in minimap.iter_mut() {
for _ in 0..columns {
if line.len() == 0 {
line.push(false);
} else {
line.insert(0, false);
}
}
}
}
fn ensure_size(minimap: &mut Minimap, x: usize, y: usize) {
if minimap.len() <= x + 1 {
let mut minimal_v = Vec::new();
minimal_v.resize(y + 1, false);
minimap.resize(x + 1, minimal_v);
}
if minimap[x].len() <= y + 1 {
minimap[x].resize(y + 1, false);
}
}
fn find_connected_i(position: Kartesian<u32>, minimap: &mut Minimap, visited: &mut Vec<Kartesian<u32>>, max: Kartesian<u32>, map: &Table, plant: char, startpos: &mut Kartesian<u32>) {
for direction in KD::iter(false, false, true) {
match position.move_dir_max(direction.vector(), direction, max) {
None => continue,
Some(new) => {
if map[new.x as usize][new.y as usize] != plant {
continue;
}
if !visited.contains(&new) {
visited.push(new);
}
let (mut diff, dir) = startpos.diff(new);
let mut movedir = KD::None;
match dir {
KD::Left | KD::BottomLeft => {
debug!("Moving {} from {}, because {} is {}", dir, startpos, new, dir);
*startpos = startpos.move_dir(KD::Left.vector(), KD::Left).unwrap();
move_content_left(minimap, diff.y as usize);
(diff, _) = startpos.diff(new);
},
KD::TopLeft => {
debug!("Moving {} from {}, because {} is {}", dir, startpos, new, dir);
*startpos = startpos.move_dir(KD::TopLeft.vector(), KD::TopLeft).unwrap();
minimap.insert(0, Vec::new());
move_content_left(minimap, diff.y as usize);
(diff, _) = startpos.diff(new);
},
KD::Top => {
debug!("Moving {} from {}, because {} is {}", dir, startpos, new, dir);
*startpos = startpos.move_dir(KD::Top.vector(), KD::Top).unwrap();
minimap.insert(0, Vec::new());
(diff, _) = startpos.diff(new);
},
_ => {},
}
ensure_size(minimap, diff.x as usize, diff.y as usize);
if minimap[diff.x as usize][diff.y as usize] {
continue;
}
minimap[diff.x as usize][diff.y as usize] = true;
find_connected_i(new, minimap, visited, max, map, plant, startpos);
},
}
}
}
fn find_connected<F: Fn(&Minimap) -> (u32, u32) + Copy>(position: Kartesian<u32>, map: &Table, visited: &mut Vec<Kartesian<u32>>, func: F) -> u32 {
if visited.contains(&position) {
return 0;
}
let max = Kartesian::maximum(map);
let plant = map[position.x as usize][position.y as usize];
let mut fences = 2;
let mut newposition = position;
let mut startposition = position;
let mut minimap = vec![vec![true]];
find_connected_i(position, &mut minimap, visited, max, map, plant, &mut startposition);
let max_length = minimap.iter().map(|line| line.len()).max().unwrap_or(0);
for line in minimap.iter_mut() {
if line.len() < max_length {
line.resize(max_length, false);
}
}
let price = mul(func(&minimap));
debug!("price for region {}: {}", plant, price);
price
}
fn calculate_fence_price<F: Fn(&Minimap) -> (u32, u32) + Copy>(map: Table, func: F) -> u32 {
let mut visited = Vec::with_capacity(map.len() * map[0].len());
let mut fences = 0;
let mut position = Kartesian::new(0, 0);
for (x, row) in map.iter().enumerate() {
for (y, column) in row.iter().enumerate() {
position = Kartesian::new(x as u32, y as u32);
if !visited.contains(&position) {
fences += find_connected(position, &map, &mut visited, func);
}
}
}
fences
}
fn main() {
let map: Table = convert_to_array::<_, _, '\n'>(DATA, |l| l.chars().collect());
println!("The Price for the fences is {}", calculate_fence_price(map.clone(), calc_perimeter_and_area));
println!("The Price with bulk discount is {}", calculate_fence_price(map, calc_sides_and_area));
}
#[cfg(test)]
mod test {
use super::*;
include_example!(MAP_A 2024 12a);
include_example!(MAP_B 2024 12b);
include_example!(MAP_C 2024 12c);
include_example!(MAP_D 2024 12d);
include_example!(MAP_E 2024 12f);
#[test]
fn test_fence_a_perimeter() {
assert_eq!(calculate_fence_price(convert_to_array::<_, _, '\n'>(MAP_A, |l| l.chars().collect()), calc_perimeter_and_area), 140);
}
#[test]
fn test_fence_b_perimeter() {
assert_eq!(calculate_fence_price(convert_to_array::<_, _, '\n'>(MAP_B, |l| l.chars().collect()), calc_perimeter_and_area), 772);
}
#[test]
fn test_fence_c_perimeter() {
assert_eq!(calculate_fence_price(convert_to_array::<_, _, '\n'>(MAP_C, |l| l.chars().collect()), calc_perimeter_and_area), 1930);
}
#[test]
fn test_fence_a_sides() {
assert_eq!(calculate_fence_price(convert_to_array::<_, _, '\n'>(MAP_A, |l| l.chars().collect()), calc_sides_and_area), 80);
}
#[test]
fn test_fence_d_sides() {
assert_eq!(calculate_fence_price(convert_to_array::<_, _, '\n'>(MAP_D, |l| l.chars().collect()), calc_sides_and_area), 236);
}
#[test]
fn test_fence_e_sides() {
assert_eq!(calculate_fence_price(convert_to_array::<_, _, '\n'>(MAP_E, |l| l.chars().collect()), calc_sides_and_area), 368);
}
}