[TASK] Solved Day 20 Pt 1

This commit is contained in:
2020-12-21 13:57:35 +01:00
parent 006eb5f19e
commit acaf136814
4 changed files with 1994 additions and 1 deletions

1727
input/day20.txt Normal file

File diff suppressed because it is too large Load Diff

107
input/day20_example.txt Normal file
View File

@@ -0,0 +1,107 @@
Tile 2311:
..##.#..#.
##..#.....
#...##..#.
####.#...#
##.##.###.
##...#.###
.#.#.#..##
..#....#..
###...#.#.
..###..###
Tile 1951:
#.##...##.
#.####...#
.....#..##
#...######
.##.#....#
.###.#####
###.##.##.
.###....#.
..#.#..#.#
#...##.#..
Tile 1171:
####...##.
#..##.#..#
##.#..#.#.
.###.####.
..###.####
.##....##.
.#...####.
#.##.####.
####..#...
.....##...
Tile 1427:
###.##.#..
.#..#.##..
.#.##.#..#
#.#.#.##.#
....#...##
...##..##.
...#.#####
.#.####.#.
..#..###.#
..##.#..#.
Tile 1489:
##.#.#....
..##...#..
.##..##...
..#...#...
#####...#.
#..#.#.#.#
...#.#.#..
##.#...##.
..##.##.##
###.##.#..
Tile 2473:
#....####.
#..#.##...
#.##..#...
######.#.#
.#...#.#.#
.#########
.###.#..#.
########.#
##...##.#.
..###.#.#.
Tile 2971:
..#.#....#
#...###...
#.#.###...
##.##..#..
.#####..##
.#..####.#
#..#.#..#.
..####.###
..#.#.###.
...#.#.#.#
Tile 2729:
...#.#.#.#
####.#....
..#.#.....
....#..#.#
.##..##.#.
.#.####...
####.#.#..
##.####...
##..#.##..
#.##...##.
Tile 3079:
#.#.#####.
.#..######
..#.......
######....
####.#..#.
.#...#.##.
#.#####.##
..#.###...
..#.......
..#.###...

157
src/day20.rs Normal file
View 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 };
}
}

View File

@@ -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")
}
}