2020: day20: part 1

This commit is contained in:
Antoine Martin 2020-12-20 22:33:42 +01:00
parent 0dbae9bffb
commit fda311a7ee
6 changed files with 1974 additions and 0 deletions

View file

@ -19,6 +19,7 @@ use aoc2020::day16;
use aoc2020::day17; use aoc2020::day17;
use aoc2020::day18; use aoc2020::day18;
use aoc2020::day19; use aoc2020::day19;
use aoc2020::day20;
use aoc2020::day21; use aoc2020::day21;
use aoc2020::day22; use aoc2020::day22;
use aoc2020::day23; use aoc2020::day23;
@ -44,6 +45,7 @@ fn aoc2020_all(c: &mut Criterion) {
c.bench_function("day17", |b| b.iter(|| day17::run().unwrap())); c.bench_function("day17", |b| b.iter(|| day17::run().unwrap()));
c.bench_function("day18", |b| b.iter(|| day18::run().unwrap())); c.bench_function("day18", |b| b.iter(|| day18::run().unwrap()));
c.bench_function("day19", |b| b.iter(|| day19::run().unwrap())); c.bench_function("day19", |b| b.iter(|| day19::run().unwrap()));
c.bench_function("day20", |b| b.iter(|| day20::run().unwrap()));
c.bench_function("day21", |b| b.iter(|| day21::run().unwrap())); c.bench_function("day21", |b| b.iter(|| day21::run().unwrap()));
c.bench_function("day22", |b| b.iter(|| day22::run().unwrap())); c.bench_function("day22", |b| b.iter(|| day22::run().unwrap()));
c.bench_function("day23", |b| b.iter(|| day23::run().unwrap())); c.bench_function("day23", |b| b.iter(|| day23::run().unwrap()));

1727
aoc2020/input/day20.txt Normal file

File diff suppressed because it is too large Load diff

View file

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

135
aoc2020/src/day20.rs Normal file
View file

@ -0,0 +1,135 @@
use std::fmt::Write;
use anyhow::{anyhow, Context, Result};
const INPUT: &str = include_str!("../input/day20.txt");
pub fn run() -> Result<String> {
let mut res = String::with_capacity(128);
writeln!(res, "part 1: {}", part1(INPUT)?)?;
Ok(res)
}
fn part1(input: &str) -> Result<u64> {
let tiles: Vec<Tile> = input.split("\n\n").map(str::parse).collect::<Result<_>>()?;
Ok(tiles
.iter()
.filter_map(|tile| {
let mut count = 0;
for other in &tiles {
if tile == other {
continue;
}
count += tile
.edges
.iter()
.filter(|e| other.edges.contains(e))
.count();
count += tile
.reversed_edges
.iter()
.filter(|e| other.edges.contains(e))
.count();
}
// corners have 2 edges in common
if count == 2 {
Some(tile.id)
} else {
None
}
})
.product())
}
#[derive(Debug)]
struct Tile {
id: u64,
edges: [Vec<bool>; 4],
reversed_edges: [Vec<bool>; 4],
}
impl std::cmp::PartialEq for Tile {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl std::str::FromStr for Tile {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self> {
const LINE_LENGTH: usize = 10;
let mut lines = s.lines();
let title = lines.next().context("couldn't find line with tile ID")?;
let space = title.find(' ').unwrap();
let colon = title.find(':').unwrap();
let id = title[(space + 1)..colon].parse()?;
let mut edges = [vec![], vec![], vec![], vec![]];
lines
.enumerate()
.try_for_each::<_, Result<()>>(|(i, line)| {
line.chars().enumerate().try_for_each(|(j, c)| {
let c = match c {
'#' => true,
'.' => false,
_ => return Err(anyhow!("unknown char `{}` while parsing tile", c)),
};
if i == 0 {
edges[0].push(c);
}
if j == 0 {
edges[1].push(c);
}
if i == (LINE_LENGTH - 1) {
edges[2].push(c);
}
if j == (LINE_LENGTH - 1) {
edges[3].push(c);
}
Ok(())
})?;
Ok(())
})?;
let mut reversed_edges = [vec![], vec![], vec![], vec![]];
for (i, edge) in edges.iter().enumerate() {
reversed_edges[i] = edge.iter().copied().rev().collect();
}
Ok(Tile {
id,
edges,
reversed_edges,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
const PROVIDED: &str = include_str!("../input/day20_provided.txt");
#[test]
fn part1_provided() {
assert_eq!(part1(PROVIDED).unwrap(), 20_899_048_083_289);
}
#[test]
fn part1_real() {
assert_eq!(part1(INPUT).unwrap(), 5_775_714_912_743);
}
}

View file

@ -19,6 +19,7 @@ pub mod day16;
pub mod day17; pub mod day17;
pub mod day18; pub mod day18;
pub mod day19; pub mod day19;
pub mod day20;
pub mod day21; pub mod day21;
pub mod day22; pub mod day22;
pub mod day23; pub mod day23;

View file

@ -21,6 +21,7 @@ use aoc2020::day16;
use aoc2020::day17; use aoc2020::day17;
use aoc2020::day18; use aoc2020::day18;
use aoc2020::day19; use aoc2020::day19;
use aoc2020::day20;
use aoc2020::day21; use aoc2020::day21;
use aoc2020::day22; use aoc2020::day22;
use aoc2020::day23; use aoc2020::day23;
@ -47,6 +48,7 @@ fn main() -> Result<()> {
day17::run, day17::run,
day18::run, day18::run,
day19::run, day19::run,
day20::run,
day21::run, day21::run,
day22::run, day22::run,
day23::run, day23::run,