do day20 for 2020

This commit is contained in:
Adam Jeniski 2022-09-25 23:43:24 -04:00
parent 81acc2d472
commit 8deb5610a0
37 changed files with 2141 additions and 10 deletions

12
.gitignore vendored
View File

@ -1,2 +1,10 @@
/target */target/
.vscode/ */.vscode/
# Added by cargo
#
# already existing elements were commented out
#/target
*/Cargo.lock

View File

@ -25,5 +25,9 @@ image: "rust:latest"
# Use cargo to test the project # Use cargo to test the project
test:cargo: test:cargo:
script: script:
- cd 2021
- rustc --version && cargo --version # Print version info for debugging - rustc --version && cargo --version # Print version info for debugging
- cargo test --workspace --verbose - cargo test --workspace --verbose -j 8
- cd ../2020
- rustc --version && cargo --version # Print version info for debugging
- cargo test --workspace --verbose -j 8

34
2020/Cargo.lock generated Normal file
View File

@ -0,0 +1,34 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aoc-2020"
version = "0.1.0"
dependencies = [
"rpds",
]
[[package]]
name = "archery"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a8da9bc4c4053ee067669762bcaeea6e241841295a2b6c948312dad6ef4cc02"
dependencies = [
"static_assertions",
]
[[package]]
name = "rpds"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66262ea963eff99163e6b741fbc3417a52cc13074728c1047e9911789df9b000"
dependencies = [
"archery",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"

9
2020/Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "aoc-2020"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
rpds = "0.12.0"

1728
2020/inputs/day20.txt Normal file

File diff suppressed because it is too large Load Diff

View File

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

201
2020/src/day20.rs Normal file
View File

@ -0,0 +1,201 @@
use std::{collections::HashSet, fmt::Display};
#[derive(Clone, Debug, Eq)]
struct Tile {
id: u128,
grid: Vec<Vec<char>>,
}
impl Tile {
fn rotate(&mut self) {
let n = self.grid.len();
// reverse rows
for row in &mut self.grid {
row.reverse();
}
// perform matrix transpose
for i in 0..n {
for j in i..n {
let temp = self.grid[i][j];
self.grid[i][j] = self.grid[j][i];
self.grid[j][i] = temp;
}
}
}
fn flip(&mut self) {
for row in &mut self.grid {
row.reverse();
}
}
fn fits_with_right_border_of(&self, left_tile: &Self) -> bool {
let n = self.grid[0].len();
for i in 0..n {
if self.grid[i][0] != left_tile.grid[i][n - 1] {
return false;
}
}
true
}
fn fits_with_bottom_border_of(&self, above_tile: &Self) -> bool {
let n = self.grid[0].len();
for i in 0..n {
if self.grid[0][i] != above_tile.grid[n - 1][i] {
return false;
}
}
true
}
}
fn configure_board(
board: &mut Vec<Vec<Option<Tile>>>,
tiles_left: &mut HashSet<Tile>,
x: usize,
y: usize,
n: usize,
) -> Option<Vec<Vec<Tile>>> {
if x == n {
return Some(
board
.iter()
.map(|row| {
row.iter()
.map(|cell| cell.as_ref().unwrap().clone())
.collect()
})
.collect(),
);
}
let new_y = if y + 1 == n { 0 } else { y + 1 };
let new_x = if new_y == 0 { x + 1 } else { x };
for mut tile in tiles_left.clone() {
tiles_left.remove(&tile);
for _ in 0..4 {
for _ in 0..2 {
if (x == 0 && y == 0)
|| (x != 0
&& tile.fits_with_bottom_border_of(board[x - 1][y].as_ref().unwrap()))
|| (y != 0 && tile.fits_with_right_border_of(board[x][y - 1].as_ref().unwrap()))
{
board[x][y] = Some(tile.clone());
// println!("found match for {x}, {y}, {tile}");
if let Some(ans) = configure_board(board, tiles_left, new_x, new_y, n) {
return Some(ans);
}
} else {
// println!("no match found for {x}, {y}, {tile}");
}
tile.flip();
}
tile.rotate();
}
tiles_left.insert(tile);
}
None
}
fn part_one(mut input: HashSet<Tile>) -> u128 {
let n2 = input.len();
let n = (n2 as f64).sqrt() as usize;
let mut board = vec![vec![None; n]; n];
let value = configure_board(&mut board, &mut input, 0, 0, n);
let board = value.unwrap();
board[0][0].id * board[0][n - 1].id * board[n - 1][0].id * board[n - 1][n - 1].id
}
fn part_two(mut input: HashSet<Tile>) -> u128 {
let n2 = input.len();
let n = (n2 as f64).sqrt() as usize;
let mut board = vec![vec![None; n]; n];
let board = configure_board(&mut board, &mut input, 0, 0, n).unwrap();
let tile_size = board[0][0].grid.len();
let _picture = {
let mut pic = vec![vec![]; n];
for (x, board_row) in board.iter().enumerate() {
for tile in board_row {
for (i, tile_row) in tile.grid.iter().enumerate() {
for c in tile_row {
pic[x * (tile_size - 2) + i].push(*c);
}
}
}
}
pic
};
// turn board into picture
// flip/rotate pitctures
// traverse each image for sea monsters
todo!()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn day20_part_one_sample() {
let input = parse_inputs(include_str!("../inputs/day20_sample.txt"));
assert_eq!(part_one(input), 20899048083289);
}
#[test]
fn day20_part_one() {
let input = parse_inputs(include_str!("../inputs/day20.txt"));
assert_eq!(part_one(input), 66020135789767);
}
#[test]
fn day20_part_two_sample() {
let _input = parse_inputs(include_str!("../inputs/day20_sample.txt"));
// assert_eq!(part_two(input), 273);
}
fn parse_inputs(input: &str) -> HashSet<Tile> {
let mut tiles = HashSet::new();
let chunks: Vec<&str> = input.split("\n\n").collect();
for chunk in &chunks[0..chunks.len() - 1] {
let mut line_it = chunk.split('\n');
let tile_id_line = line_it.next().unwrap();
let id = tile_id_line[5..tile_id_line.chars().count() - 1]
.parse()
.unwrap();
let mut grid = vec![];
for line in line_it {
grid.push(line.chars().collect());
}
tiles.insert(Tile { id, grid });
}
tiles
}
}
// utility traits for data structures and debugging
impl PartialEq for Tile {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl std::hash::Hash for Tile {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.id.hash(state);
}
}
impl Display for Tile {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "tile: {}", self.id)?;
let n = self.grid.len();
for i in 0..n {
writeln!(f, "{}", self.grid[i].iter().collect::<String>())?;
}
writeln!(f)?;
Ok(())
}
}

4
2020/src/lib.rs Normal file
View File

@ -0,0 +1,4 @@
#[allow(dead_code)]
mod day20;

35
2020/temp.txt Normal file
View File

@ -0,0 +1,35 @@
running 2 tests
test day20::tests::day20_part_one_sample ... ok
test day20::tests::day20_part_one ... FAILED
failures:
---- day20::tests::day20_part_one stdout ----
n is 12, n squared is 144
num: 250
num: 500
num: 750
num: 1000
num: 1250
num: 1500
num: 1750
num: 2000
num: 2250
num: 2500
num: 2750
num: 3000
num: 3250
num: 3500
num iterations: 3721
thread 'day20::tests::day20_part_one' panicked at 'assertion failed: `(left == right)`
left: `66020135789767`,
right: `20899048083289`', src/day20.rs:149:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
day20::tests::day20_part_one
test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 37.51s

View File

@ -3,5 +3,5 @@
version = 3 version = 3
[[package]] [[package]]
name = "abc" name = "aoc-2021"
version = "0.1.0" version = "0.1.0"

View File

@ -1,5 +1,5 @@
[package] [package]
name = "abc" name = "aoc-2021"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"

View File

@ -1,12 +1,12 @@
#![allow(dead_code)] #![allow(dead_code)]
/** /**
* File: lib.rs * File: lib.rs
* Author: Adam Jeniski; @Ajetski * Author: Adam Jeniski; @Ajetski
*/ */
pub(crate) mod day1; pub(crate) mod day1;
pub(crate) mod day10;
pub(crate) mod day9; pub(crate) mod day9;
pub(crate) mod day10;
pub(crate) mod day11; pub(crate) mod day11;
pub(crate) mod day13; pub(crate) mod day13;
pub(crate) mod day14; pub(crate) mod day14;

View File

@ -1,4 +1,4 @@
## Advent of Code 2021 ## Advent of Code
My rust solutions for Advent of Code 2021. My rust solutions for Advent of Code
Use `cargo test` to run each test case. Navigate to one of the folder for a given year, then use `cargo test` to run it's test cases.