[TASK] Solved Day 20 Pt 1
This commit is contained in:
157
src/day20.rs
Normal file
157
src/day20.rs
Normal file
@@ -0,0 +1,157 @@
|
||||
use super::util;
|
||||
use std::collections::HashMap;
|
||||
|
||||
const PIECE_SIZE: u16 = 10;
|
||||
// const POSSIBLE_EDGE_COUNT: u16 = 1 << (PIECE_SIZE + 1);
|
||||
|
||||
pub fn solve() {
|
||||
let lines = util::read_file("input/day20.txt");
|
||||
let mut piece_id = 0u32;
|
||||
let mut piece_lines: Vec<PieceLine> = Vec::new();
|
||||
let mut pieces = Vec::new();
|
||||
for line in &lines {
|
||||
|
||||
if line == &"" {
|
||||
pieces.push(Piece::from(piece_id, piece_lines));
|
||||
piece_lines = Vec::new();
|
||||
} else if line.starts_with("Tile") {
|
||||
piece_id = line[5..(line.len() - 1)].parse::<u32>().unwrap();
|
||||
} else {
|
||||
piece_lines.push(PieceLine::parse(&line));
|
||||
}
|
||||
}
|
||||
if !piece_lines.is_empty() {
|
||||
pieces.push(Piece::from(piece_id, piece_lines));
|
||||
}
|
||||
pieces.sort_by_key(|p| p.id);
|
||||
|
||||
// Let's create an array containing for each puzzle piece side, in which pieces it appears:
|
||||
let mut piece_matches = HashMap::new();
|
||||
for piece in &pieces {
|
||||
add_to_piece_matches(piece.id, &piece.top_edge, &piece.flipped_top_edge, &mut piece_matches);
|
||||
add_to_piece_matches(piece.id, &piece.bottom_edge, &piece.flipped_bottom_edge, &mut piece_matches);
|
||||
add_to_piece_matches(piece.id, &piece.left_edge, &piece.flipped_left_edge, &mut piece_matches);
|
||||
add_to_piece_matches(piece.id, &piece.right_edge, &piece.flipped_right_edge, &mut piece_matches);
|
||||
}
|
||||
|
||||
// println!("{:?}", piece_matches);
|
||||
|
||||
// And now we find which pieces are adjacent (same edge) to which other pieces (not caring about orientation at all)
|
||||
let mut edge_matches: HashMap<u32, usize> = HashMap::new();
|
||||
for piece_match in piece_matches {
|
||||
if piece_match.1.len() == 1 {
|
||||
continue;
|
||||
}
|
||||
piece_match.1.iter().for_each(|m| { edge_matches.entry(m.clone()).and_modify(|c| *c += 1 ).or_insert(1); })
|
||||
}
|
||||
|
||||
println!("{:?}", edge_matches);
|
||||
let corner_pieces: Vec<u32> = edge_matches.iter().filter(|e| e.1 == &2).map(|e| e.0.clone()).collect::<Vec<_>>();
|
||||
|
||||
assert_eq!(corner_pieces.len(), 4);
|
||||
|
||||
let part1 = corner_pieces.iter().fold(1u64, |a, b| a as u64 * b.clone() as u64);
|
||||
println!("Day X Part 1: {}", part1);
|
||||
|
||||
|
||||
let part2 = 0;
|
||||
println!("Day X Part 2: {}", part2);
|
||||
}
|
||||
|
||||
fn add_to_piece_matches(piece_id: u32, edge: &PieceLine, flipped_edge: &PieceLine, piece_matches: &mut HashMap<u16, Vec<u32>>) {
|
||||
|
||||
let use_flipped = flipped_edge.data < edge.data;
|
||||
let bookkeeping_edge = if use_flipped { flipped_edge } else { edge };
|
||||
|
||||
piece_matches.entry(bookkeeping_edge.data).and_modify(|d| d.push(piece_id)).or_insert(vec![ piece_id ]);
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Piece {
|
||||
|
||||
id: u32,
|
||||
piece_lines: Vec<PieceLine>,
|
||||
|
||||
// left to right top edge
|
||||
top_edge: PieceLine,
|
||||
// left to right bottom edge
|
||||
bottom_edge: PieceLine,
|
||||
// Left edge (from top to bottom)
|
||||
left_edge: PieceLine,
|
||||
// Right edge (from to to bottom)
|
||||
right_edge: PieceLine,
|
||||
// Right to left top edge
|
||||
flipped_top_edge: PieceLine,
|
||||
// Right to left bottom edge
|
||||
flipped_bottom_edge: PieceLine,
|
||||
// Bottom to top left edge
|
||||
flipped_left_edge: PieceLine,
|
||||
// Bottom to top right edge
|
||||
flipped_right_edge: PieceLine,
|
||||
|
||||
}
|
||||
|
||||
impl Piece {
|
||||
|
||||
fn from(id: u32, piece_lines: Vec<PieceLine>) -> Piece {
|
||||
|
||||
let top_edge = piece_lines[0].clone();
|
||||
let bottom_edge = piece_lines[(PIECE_SIZE - 1) as usize].clone();
|
||||
let left_edge = Piece::get_vertical(0, &piece_lines);
|
||||
let right_edge = Piece::get_vertical(PIECE_SIZE - 1, &piece_lines);
|
||||
|
||||
return Piece {
|
||||
id, piece_lines,
|
||||
flipped_top_edge: top_edge.flipped(), flipped_bottom_edge: bottom_edge.flipped(),
|
||||
flipped_left_edge: left_edge.flipped(), flipped_right_edge: right_edge.flipped(),
|
||||
top_edge, bottom_edge, left_edge, right_edge,
|
||||
};
|
||||
}
|
||||
|
||||
fn get_vertical(x: u16, piece_lines: &Vec<PieceLine>) -> PieceLine {
|
||||
let mut vert = 0;
|
||||
for i in 0..PIECE_SIZE {
|
||||
if piece_lines[i as usize].get(x as usize) {
|
||||
vert |= 1 << i;
|
||||
}
|
||||
}
|
||||
return PieceLine { data: vert };
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
struct PieceLine {
|
||||
data: u16,
|
||||
}
|
||||
|
||||
impl PieceLine {
|
||||
fn parse(line: &String) -> PieceLine {
|
||||
|
||||
let mut data = 0u16;
|
||||
let mut i = 0;
|
||||
for char in line.chars() {
|
||||
if char == '#' {
|
||||
data |= 1 << i;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return PieceLine { data };
|
||||
}
|
||||
|
||||
fn get(&self, i: usize) -> bool {
|
||||
|
||||
let mask = 1u16 << i;
|
||||
return self.data & mask == mask;
|
||||
}
|
||||
|
||||
fn flipped(&self) -> PieceLine {
|
||||
let mut res = 0u16;
|
||||
for i in 0..PIECE_SIZE {
|
||||
if self.get(i as usize) {
|
||||
res |= 1 << (PIECE_SIZE - i - 1)
|
||||
}
|
||||
}
|
||||
return PieceLine { data: res };
|
||||
}
|
||||
}
|
||||
@@ -21,8 +21,9 @@ mod day16;
|
||||
mod day17;
|
||||
mod day18;
|
||||
mod day19;
|
||||
mod day20;
|
||||
|
||||
const MAX_DAY: u8 = 19;
|
||||
const MAX_DAY: u8 = 20;
|
||||
const BENCHMARK_AMOUNT: u32 = 100;
|
||||
|
||||
fn solve(day: u8) {
|
||||
@@ -46,6 +47,7 @@ fn solve(day: u8) {
|
||||
17 => day17::solve(),
|
||||
18 => day18::solve(),
|
||||
19 => day19::solve(),
|
||||
20 => day20::solve(),
|
||||
_ => println!("This day is not yet implemented")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user