Day 8.1, 9 and 10, plus formatting and optimization
This commit is contained in:
parent
54700e121b
commit
21fcc07f3c
10 changed files with 788 additions and 471 deletions
230
src/day02.rs
230
src/day02.rs
|
@ -1,115 +1,115 @@
|
||||||
use aoc_runner_derive::{aoc, aoc_generator};
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
use std::{error::Error, str::FromStr};
|
use std::{error::Error, str::FromStr};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
enum Direction {
|
enum Direction {
|
||||||
Forward,
|
Forward,
|
||||||
Down,
|
Down,
|
||||||
Up,
|
Up,
|
||||||
}
|
}
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Instruction {
|
pub struct Instruction {
|
||||||
direction: Direction,
|
direction: Direction,
|
||||||
amount: usize,
|
amount: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Default)]
|
#[derive(Debug, Copy, Clone, Default)]
|
||||||
pub struct Submarine{
|
pub struct Submarine {
|
||||||
depth: i64,
|
depth: i64,
|
||||||
pos: i64,
|
pos: i64,
|
||||||
aim: i64
|
aim: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Submarine {
|
impl Submarine {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
fn run_p1(&mut self, inst: &Instruction) {
|
fn run_p1(&mut self, inst: &Instruction) {
|
||||||
let d = inst.direction;
|
let d = inst.direction;
|
||||||
let a = inst.amount as i64;
|
let a = inst.amount as i64;
|
||||||
match d {
|
match d {
|
||||||
Direction::Forward => {
|
Direction::Forward => {
|
||||||
self.pos += a;
|
self.pos += a;
|
||||||
}
|
}
|
||||||
Direction::Down => {
|
Direction::Down => {
|
||||||
self.depth += a;
|
self.depth += a;
|
||||||
}
|
}
|
||||||
Direction::Up => {
|
Direction::Up => {
|
||||||
self.depth -= a;
|
self.depth -= a;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
fn run_p2(&mut self, inst: &Instruction) {
|
fn run_p2(&mut self, inst: &Instruction) {
|
||||||
let d = inst.direction;
|
let d = inst.direction;
|
||||||
let a = inst.amount as i64;
|
let a = inst.amount as i64;
|
||||||
match d {
|
match d {
|
||||||
Direction::Forward => {
|
Direction::Forward => {
|
||||||
self.pos += a;
|
self.pos += a;
|
||||||
self.depth += self.aim*a;
|
self.depth += self.aim * a;
|
||||||
}
|
}
|
||||||
Direction::Down => {
|
Direction::Down => {
|
||||||
self.aim += a;
|
self.aim += a;
|
||||||
}
|
}
|
||||||
Direction::Up => {
|
Direction::Up => {
|
||||||
self.aim -= a;
|
self.aim -= a;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for Instruction {
|
impl FromStr for Instruction {
|
||||||
type Err = Box<dyn Error>;
|
type Err = Box<dyn Error>;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
let mut s = s.split_ascii_whitespace();
|
let mut s = s.split_ascii_whitespace();
|
||||||
let inst = s.next().unwrap();
|
let inst = s.next().unwrap();
|
||||||
let amount: usize = s.next().unwrap().parse().unwrap();
|
let amount: usize = s.next().unwrap().parse().unwrap();
|
||||||
let ret = match inst {
|
let ret = match inst {
|
||||||
"forward" => Self {
|
"forward" => Self {
|
||||||
direction: Direction::Forward,
|
direction: Direction::Forward,
|
||||||
amount,
|
amount,
|
||||||
},
|
},
|
||||||
"up" => Self {
|
"up" => Self {
|
||||||
direction: Direction::Up,
|
direction: Direction::Up,
|
||||||
amount,
|
amount,
|
||||||
},
|
},
|
||||||
"down" => Self {
|
"down" => Self {
|
||||||
direction: Direction::Down,
|
direction: Direction::Down,
|
||||||
amount,
|
amount,
|
||||||
},
|
},
|
||||||
other => {
|
other => {
|
||||||
panic!("Invalid instruction: {}", other)
|
panic!("Invalid instruction: {}", other)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(ret)
|
Ok(ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Data = Vec<Instruction>;
|
pub type Data = Vec<Instruction>;
|
||||||
|
|
||||||
#[aoc_generator(day02)]
|
#[aoc_generator(day02)]
|
||||||
pub fn input_generator(input: &str) -> Data {
|
pub fn input_generator(input: &str) -> Data {
|
||||||
input
|
input
|
||||||
.lines()
|
.lines()
|
||||||
.map(Instruction::from_str)
|
.map(Instruction::from_str)
|
||||||
.collect::<Result<Vec<_>, _>>()
|
.collect::<Result<Vec<_>, _>>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[aoc(day02, part1)]
|
#[aoc(day02, part1)]
|
||||||
pub fn solve_part1(input: &Data) -> usize {
|
pub fn solve_part1(input: &Data) -> usize {
|
||||||
let mut sm = Submarine::new();
|
let mut sm = Submarine::new();
|
||||||
for inst in input {
|
for inst in input {
|
||||||
sm.run_p1(inst);
|
sm.run_p1(inst);
|
||||||
}
|
}
|
||||||
(sm.pos * sm.depth) as usize
|
(sm.pos * sm.depth) as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
#[aoc(day02, part2)]
|
#[aoc(day02, part2)]
|
||||||
pub fn solve_part2(input: &Data) -> usize {
|
pub fn solve_part2(input: &Data) -> usize {
|
||||||
let mut sm = Submarine::new();
|
let mut sm = Submarine::new();
|
||||||
for inst in input {
|
for inst in input {
|
||||||
sm.run_p2(inst);
|
sm.run_p2(inst);
|
||||||
}
|
}
|
||||||
(sm.pos * sm.depth) as usize
|
(sm.pos * sm.depth) as usize
|
||||||
}
|
}
|
||||||
|
|
173
src/day03.rs
173
src/day03.rs
|
@ -1,91 +1,82 @@
|
||||||
use aoc_runner_derive::{aoc, aoc_generator};
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
|
type Data = Vec<u16>;
|
||||||
type Data = Vec<u16>;
|
fn make_histogram(input: &[u16]) -> Vec<(usize, i64)> {
|
||||||
|
let counts: &mut [Option<i64>] = &mut [None; 64];
|
||||||
fn make_histogram(input: &[u16]) -> Vec<(usize, i64)> {
|
input.iter().for_each(|val| {
|
||||||
let counts: &mut [Option<i64>] = &mut [None; 64];
|
for (n, count) in counts.iter_mut().enumerate().take(12) {
|
||||||
input.iter().for_each(|val| {
|
let v = count.get_or_insert(0);
|
||||||
for (n, count) in counts.iter_mut().enumerate().take(12) {
|
if ((val >> n) & 1) == 1 {
|
||||||
let v = count.get_or_insert(0);
|
*v += 1;
|
||||||
if ((val >> n) & 1) == 1 {
|
} else {
|
||||||
*v += 1;
|
*v -= 1;
|
||||||
} else {
|
}
|
||||||
*v -= 1;
|
}
|
||||||
}
|
});
|
||||||
}
|
counts.reverse();
|
||||||
});
|
counts
|
||||||
counts.reverse();
|
.iter()
|
||||||
counts
|
.enumerate()
|
||||||
.iter()
|
.filter_map(|(a, b)| b.map(|b| (a, b)))
|
||||||
.enumerate()
|
.collect::<Vec<_>>()
|
||||||
.filter_map(|(a, b)| b.map(|b| (a, b)))
|
}
|
||||||
.collect::<Vec<_>>()
|
#[aoc_generator(day03)]
|
||||||
}
|
pub fn input_generator(input: &str) -> Vec<u16> {
|
||||||
|
input
|
||||||
#[aoc_generator(day03)]
|
.lines()
|
||||||
pub fn input_generator(input: &str) -> Vec<u16> {
|
.map(|l| u16::from_str_radix(l, 2).unwrap())
|
||||||
input
|
.collect()
|
||||||
.lines()
|
}
|
||||||
.map(|l| u16::from_str_radix(l, 2).unwrap())
|
#[derive(Debug)]
|
||||||
.collect()
|
enum Mode {
|
||||||
}
|
MostCommon,
|
||||||
|
LeastCommon,
|
||||||
|
}
|
||||||
#[derive(Debug)]
|
fn tree_filter(data: &[u16], mut pos: usize, mode: Mode) -> u16 {
|
||||||
enum Mode {
|
let (zero, one) = data
|
||||||
MostCommon,
|
.iter()
|
||||||
LeastCommon,
|
.partition::<Vec<u16>, _>(|&v| ((v >> pos) & 1) == 0);
|
||||||
}
|
if data.is_empty() {
|
||||||
|
panic!("Uh Oh!");
|
||||||
fn tree_filter(data: &[u16], pos: usize, mode: Mode) -> u16 {
|
}
|
||||||
let (zero, one) = data
|
if data.len() == 1 {
|
||||||
.iter()
|
return data[0];
|
||||||
.partition::<Vec<u16>, _>(|&v| ((v >> pos) & 1) == 0);
|
}
|
||||||
if data.is_empty() {
|
pos=pos.wrapping_sub(1);
|
||||||
panic!("Uh Oh!");
|
if zero.len() == one.len() {
|
||||||
}
|
match mode {
|
||||||
if data.len() == 1 {
|
Mode::MostCommon => tree_filter(&one, pos, mode),
|
||||||
return data[0];
|
Mode::LeastCommon => tree_filter(&zero, pos, mode),
|
||||||
}
|
}
|
||||||
if zero.len() == one.len() {
|
} else {
|
||||||
match mode {
|
let mut srt = vec![zero, one];
|
||||||
Mode::MostCommon => tree_filter(&one, pos - 1, mode),
|
srt.sort_by_key(|v| v.len());
|
||||||
Mode::LeastCommon => tree_filter(&zero, pos - 1, mode),
|
match mode {
|
||||||
}
|
Mode::MostCommon => tree_filter(&srt[1], pos, mode),
|
||||||
} else {
|
Mode::LeastCommon => tree_filter(&srt[0], pos, mode),
|
||||||
let mut srt = vec![zero, one];
|
}
|
||||||
srt.sort_by_key(|v| v.len());
|
}
|
||||||
match mode {
|
}
|
||||||
Mode::MostCommon => tree_filter(&srt[1], pos - 1, mode),
|
const ASCII_ZERO: u8 = 0x30;
|
||||||
Mode::LeastCommon => tree_filter(&srt[0], pos - 1, mode),
|
#[aoc(day03, part1)] // 1997414
|
||||||
}
|
pub fn solve_part1(input: &Data) -> usize {
|
||||||
}
|
let counts = make_histogram(input);
|
||||||
}
|
let (gamma, epsilon): (String, String) = counts
|
||||||
|
.iter()
|
||||||
|
.map(|(_, v)| {
|
||||||
const ASCII_ZERO: u8 = 0x30;
|
(
|
||||||
|
(ASCII_ZERO + (*v >= 0) as u8) as char,
|
||||||
#[aoc(day03, part1)] // 1997414
|
(ASCII_ZERO + (*v < 0) as u8) as char,
|
||||||
pub fn solve_part1(input: &Data) -> usize {
|
)
|
||||||
let counts = make_histogram(input);
|
})
|
||||||
let (gamma, epsilon): (String, String) = counts
|
.unzip();
|
||||||
.iter()
|
let gamma = usize::from_str_radix(&gamma, 2).unwrap();
|
||||||
.map(|(_, v)| {
|
let epsilon = usize::from_str_radix(&epsilon, 2).unwrap();
|
||||||
(
|
gamma * epsilon
|
||||||
(ASCII_ZERO + (*v >= 0) as u8) as char,
|
}
|
||||||
(ASCII_ZERO + (*v < 0) as u8) as char,
|
#[aoc(day03, part2)] // 1032597
|
||||||
)
|
pub fn solve_part2(input: &[u16]) -> usize {
|
||||||
})
|
// let input: Vec<bool> = input.iter().for_each(|v| v[0]).collect();
|
||||||
.unzip();
|
let a = tree_filter(input, 11, Mode::MostCommon) as usize;
|
||||||
let gamma = usize::from_str_radix(&gamma, 2).unwrap();
|
let b = tree_filter(input, 11, Mode::LeastCommon) as usize;
|
||||||
let epsilon = usize::from_str_radix(&epsilon, 2).unwrap();
|
a * b
|
||||||
gamma * epsilon
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[aoc(day03, part2)]
|
|
||||||
pub fn solve_part2(input: &[u16]) -> usize {
|
|
||||||
// let input: Vec<bool> = input.iter().for_each(|v| v[0]).collect();
|
|
||||||
let a = tree_filter(input, 11, Mode::MostCommon) as usize;
|
|
||||||
let b = tree_filter(input, 11, Mode::LeastCommon) as usize;
|
|
||||||
a * b
|
|
||||||
}
|
|
239
src/day04.rs
239
src/day04.rs
|
@ -1,92 +1,147 @@
|
||||||
use aoc_runner_derive::{aoc, aoc_generator};
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
|
|
||||||
#[derive(Debug,Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Data {
|
pub struct Data {
|
||||||
pub numbers: Vec<u8>,
|
pub numbers: Vec<u8>,
|
||||||
pub boards: Vec<[[(u8,bool); 5]; 5]>,
|
pub boards: Vec<[[(u8, bool); 5]; 5]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[aoc_generator(day04)]
|
#[aoc_generator(day04)]
|
||||||
pub fn input_generator(input: &str) -> Data {
|
pub fn input_generator(input: &str) -> Data {
|
||||||
let mut lines = input.lines();
|
let mut lines = input.lines();
|
||||||
let mut boards = vec![];
|
let mut boards = vec![];
|
||||||
let numbers = lines
|
let numbers = lines
|
||||||
.next()
|
.next()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.split(',')
|
.split(',')
|
||||||
.map(|s| s.parse())
|
.map(|s| s.parse())
|
||||||
.collect::<Result<Vec<u8>, _>>()
|
.collect::<Result<Vec<u8>, _>>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut row = 0;
|
let mut row = 0;
|
||||||
let mut board = [[(0u8,false); 5]; 5];
|
let mut board = [[(0u8, false); 5]; 5];
|
||||||
for line in lines {
|
for line in lines {
|
||||||
if line.is_empty() {
|
if line.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let line = line
|
let line = line
|
||||||
.split_ascii_whitespace()
|
.split_ascii_whitespace()
|
||||||
.map(|s| s.parse())
|
.map(|s| s.parse())
|
||||||
.collect::<Result<Vec<u8>, _>>()
|
.collect::<Result<Vec<u8>, _>>()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
line.iter().enumerate().for_each(|(i, v)| {
|
line.iter().enumerate().for_each(|(i, v)| {
|
||||||
board[row][i] = (*v,false);
|
board[row][i] = (*v, false);
|
||||||
});
|
});
|
||||||
row = (row + 1) % 5;
|
row = (row + 1) % 5;
|
||||||
if row == 0 {
|
if row == 0 {
|
||||||
boards.push(board);
|
boards.push(board);
|
||||||
board = [[(0u8,false); 5]; 5];
|
board = [[(0u8, false); 5]; 5];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Data { numbers, boards }
|
Data { numbers, boards }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[aoc(day04, part1)]
|
#[aoc(day04, part1)]
|
||||||
pub fn solve_part1(input: &Data) -> usize {
|
pub fn solve_part1(input: &Data) -> usize {
|
||||||
let Data {numbers,mut boards} =input.clone();
|
let Data {
|
||||||
for number in numbers.iter() {
|
numbers,
|
||||||
for board in &mut boards {
|
mut boards,
|
||||||
for row in board.iter_mut() {
|
} = input.clone();
|
||||||
for (n,b) in row {
|
for number in numbers.iter() {
|
||||||
if n==number {
|
for board in &mut boards {
|
||||||
*b=true;
|
for row in board.iter_mut() {
|
||||||
}
|
for (n, b) in row {
|
||||||
}
|
if n == number {
|
||||||
}
|
*b = true;
|
||||||
let win=(0..5).map(|v| {
|
}
|
||||||
[board[v][0],board[v][1],board[v][2],board[v][3],board[v][4]].iter().all(|v| v.1)|
|
}
|
||||||
[board[0][v],board[1][v],board[2][v],board[3][v],board[4][v]].iter().all(|v| v.1)
|
}
|
||||||
}).any(|v| v);
|
let win = (0..5)
|
||||||
if win {
|
.map(|v| {
|
||||||
return board.iter().flatten().filter_map(|(v,b)| (!*b).then(|| *v as usize)).sum::<usize>()*(*number as usize)
|
[
|
||||||
}
|
board[v][0],
|
||||||
}
|
board[v][1],
|
||||||
}
|
board[v][2],
|
||||||
unreachable!()
|
board[v][3],
|
||||||
}
|
board[v][4],
|
||||||
|
]
|
||||||
#[aoc(day04, part2)]
|
.iter()
|
||||||
pub fn solve_part2(input: &Data) -> usize {
|
.all(|v| v.1)
|
||||||
let mut ret=None;
|
| [
|
||||||
let Data {numbers,mut boards} =input.clone();
|
board[0][v],
|
||||||
let mut board_wins: Vec<bool> = vec![false;boards.len()];
|
board[1][v],
|
||||||
for number in numbers.iter() {
|
board[2][v],
|
||||||
for (board_n,board) in boards.iter_mut().enumerate() {
|
board[3][v],
|
||||||
for row in board.iter_mut() {
|
board[4][v],
|
||||||
for (n,b) in row {
|
]
|
||||||
if n==number {
|
.iter()
|
||||||
*b=true;
|
.all(|v| v.1)
|
||||||
}
|
})
|
||||||
}
|
.any(|v| v);
|
||||||
}
|
if win {
|
||||||
let win=(0..5).map(|v| {
|
return board
|
||||||
[board[v][0],board[v][1],board[v][2],board[v][3],board[v][4]].iter().all(|v| v.1)|
|
.iter()
|
||||||
[board[0][v],board[1][v],board[2][v],board[3][v],board[4][v]].iter().all(|v| v.1)
|
.flatten()
|
||||||
}).any(|v| v);
|
.filter_map(|(v, b)| (!*b).then(|| *v as usize))
|
||||||
if win && !board_wins[board_n] {
|
.sum::<usize>()
|
||||||
ret=Some(board.iter().flatten().filter(|(_,b)| !*b).map(|(v,_)| *v as usize).sum::<usize>()*(*number as usize));
|
* (*number as usize);
|
||||||
board_wins[board_n]=true;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
unreachable!()
|
||||||
return ret.unwrap();
|
}
|
||||||
}
|
|
||||||
|
#[aoc(day04, part2)]
|
||||||
|
pub fn solve_part2(input: &Data) -> usize {
|
||||||
|
let mut ret = None;
|
||||||
|
let Data {
|
||||||
|
numbers,
|
||||||
|
mut boards,
|
||||||
|
} = input.clone();
|
||||||
|
let mut board_wins: Vec<bool> = vec![false; boards.len()];
|
||||||
|
for number in numbers.iter() {
|
||||||
|
for (board_n, board) in boards.iter_mut().enumerate() {
|
||||||
|
for row in board.iter_mut() {
|
||||||
|
for (n, b) in row {
|
||||||
|
if n == number {
|
||||||
|
*b = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let win = (0..5)
|
||||||
|
.map(|v| {
|
||||||
|
[
|
||||||
|
board[v][0],
|
||||||
|
board[v][1],
|
||||||
|
board[v][2],
|
||||||
|
board[v][3],
|
||||||
|
board[v][4],
|
||||||
|
]
|
||||||
|
.iter()
|
||||||
|
.all(|v| v.1)
|
||||||
|
| [
|
||||||
|
board[0][v],
|
||||||
|
board[1][v],
|
||||||
|
board[2][v],
|
||||||
|
board[3][v],
|
||||||
|
board[4][v],
|
||||||
|
]
|
||||||
|
.iter()
|
||||||
|
.all(|v| v.1)
|
||||||
|
})
|
||||||
|
.any(|v| v);
|
||||||
|
if win && !board_wins[board_n] {
|
||||||
|
ret = Some(
|
||||||
|
board
|
||||||
|
.iter()
|
||||||
|
.flatten()
|
||||||
|
.filter(|(_, b)| !*b)
|
||||||
|
.map(|(v, _)| *v as usize)
|
||||||
|
.sum::<usize>()
|
||||||
|
* (*number as usize),
|
||||||
|
);
|
||||||
|
board_wins[board_n] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret.unwrap();
|
||||||
|
}
|
||||||
|
|
216
src/day05.rs
216
src/day05.rs
|
@ -1,106 +1,110 @@
|
||||||
use aoc_runner_derive::{aoc, aoc_generator};
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Line {
|
pub struct Line {
|
||||||
x: (i64, i64),
|
x: (i64, i64),
|
||||||
y: (i64, i64),
|
y: (i64, i64),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Line {
|
impl Line {
|
||||||
fn iter(&self) -> LineIterator {
|
fn iter(&self) -> LineIterator {
|
||||||
let ret= LineIterator {
|
let ret = LineIterator {
|
||||||
line: self,
|
line: self,
|
||||||
px: self.x.0,
|
px: self.x.0,
|
||||||
py: self.y.0,
|
py: self.y.0,
|
||||||
sx: match self.x.0.cmp(&self.x.1) {
|
sx: match self.x.0.cmp(&self.x.1) {
|
||||||
std::cmp::Ordering::Less => 1,
|
std::cmp::Ordering::Less => 1,
|
||||||
std::cmp::Ordering::Equal => 0,
|
std::cmp::Ordering::Equal => 0,
|
||||||
std::cmp::Ordering::Greater => -1,
|
std::cmp::Ordering::Greater => -1,
|
||||||
},
|
},
|
||||||
sy: match self.y.0.cmp(&self.y.1) {
|
sy: match self.y.0.cmp(&self.y.1) {
|
||||||
std::cmp::Ordering::Less => 1,
|
std::cmp::Ordering::Less => 1,
|
||||||
std::cmp::Ordering::Equal => 0,
|
std::cmp::Ordering::Equal => 0,
|
||||||
std::cmp::Ordering::Greater => -1,
|
std::cmp::Ordering::Greater => -1,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
assert!(ret.sx!=0||ret.sy!=0);
|
assert!(ret.sx != 0 || ret.sy != 0);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct LineIterator<'a> {
|
struct LineIterator<'a> {
|
||||||
line: &'a Line,
|
line: &'a Line,
|
||||||
px: i64,
|
px: i64,
|
||||||
py: i64,
|
py: i64,
|
||||||
sx: i64,
|
sx: i64,
|
||||||
sy: i64,
|
sy: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for LineIterator<'a> {
|
impl<'a> Iterator for LineIterator<'a> {
|
||||||
type Item = (i64, i64);
|
type Item = (i64, i64);
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let ret = (self.px,self.py);
|
let ret = (self.px, self.py);
|
||||||
if self.sx>0 && self.px>self.line.x.1 {
|
if self.sx > 0 && self.px > self.line.x.1 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
if self.sx<0 && self.px<self.line.x.1 {
|
if self.sx < 0 && self.px < self.line.x.1 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
if self.sy>0 && self.py>self.line.y.1 {
|
if self.sy > 0 && self.py > self.line.y.1 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
if self.sy<0 && self.py<self.line.y.1 {
|
if self.sy < 0 && self.py < self.line.y.1 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
self.px+=self.sx;
|
self.px += self.sx;
|
||||||
self.py+=self.sy;
|
self.py += self.sy;
|
||||||
Some(ret)
|
Some(ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Data = Vec<Line>;
|
type Data = Vec<Line>;
|
||||||
|
|
||||||
#[aoc_generator(day05)]
|
#[aoc_generator(day05)]
|
||||||
pub fn input_generator(input: &str) -> Data {
|
pub fn input_generator(input: &str) -> Data {
|
||||||
input
|
input
|
||||||
.lines()
|
.lines()
|
||||||
.map(|line| {
|
.map(|line| {
|
||||||
let parts= line.split(" -> ").collect::<Vec<_>>();
|
let parts = line.split(" -> ").collect::<Vec<_>>();
|
||||||
let start = parts[0]
|
let start = parts[0]
|
||||||
.split(',')
|
.split(',')
|
||||||
.map(|v| v.parse().unwrap())
|
.map(|v| v.parse().unwrap())
|
||||||
.collect::<Vec<i64>>();
|
.collect::<Vec<i64>>();
|
||||||
let end = parts[1]
|
let end = parts[1]
|
||||||
.split(',')
|
.split(',')
|
||||||
.map(|v| v.parse().unwrap())
|
.map(|v| v.parse().unwrap())
|
||||||
.collect::<Vec<i64>>();
|
.collect::<Vec<i64>>();
|
||||||
Line {
|
Line {
|
||||||
x: (start[0], end[0]),
|
x: (start[0], end[0]),
|
||||||
y: (start[1], end[1]),
|
y: (start[1], end[1]),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[aoc(day05, part1)]
|
#[aoc(day05, part1)]
|
||||||
pub fn solve_part1(input: &Data) -> usize {
|
pub fn solve_part1(input: &Data) -> usize {
|
||||||
let mut grid = vec![vec![0u8; 1000]; 1000];
|
let mut grid = vec![vec![0u8; 1000]; 1000];
|
||||||
for (x,y) in input.iter().filter(|l| l.x.0==l.x.1||l.y.0==l.y.1).flat_map(|v| v.iter()) {
|
for (x, y) in input
|
||||||
let x: usize=x.try_into().unwrap();
|
.iter()
|
||||||
let y: usize=y.try_into().unwrap();
|
.filter(|l| l.x.0 == l.x.1 || l.y.0 == l.y.1)
|
||||||
grid[x][y] += 1;
|
.flat_map(|v| v.iter())
|
||||||
}
|
{
|
||||||
return grid.iter().flatten().filter(|&v| *v > 1).count();
|
let x: usize = x.try_into().unwrap();
|
||||||
}
|
let y: usize = y.try_into().unwrap();
|
||||||
|
grid[x][y] += 1;
|
||||||
#[aoc(day05, part2)]
|
}
|
||||||
pub fn solve_part2(input: &Data) -> usize {
|
return grid.iter().flatten().filter(|&v| *v > 1).count();
|
||||||
let mut grid = vec![vec![0u8; 1000]; 1000];
|
}
|
||||||
for (x,y) in input.iter().flat_map(|v| v.iter()) {
|
|
||||||
let x: usize=x.try_into().unwrap();
|
#[aoc(day05, part2)]
|
||||||
let y: usize=y.try_into().unwrap();
|
pub fn solve_part2(input: &Data) -> usize {
|
||||||
grid[x][y] += 1;
|
let mut grid = vec![vec![0u8; 1000]; 1000];
|
||||||
}
|
for (x, y) in input.iter().flat_map(|v| v.iter()) {
|
||||||
return grid.iter().flatten().filter(|&v| *v > 1).count();
|
let x: usize = x.try_into().unwrap();
|
||||||
}
|
let y: usize = y.try_into().unwrap();
|
||||||
|
grid[x][y] += 1;
|
||||||
|
}
|
||||||
|
return grid.iter().flatten().filter(|&v| *v > 1).count();
|
||||||
|
}
|
||||||
|
|
64
src/day06.rs
64
src/day06.rs
|
@ -1,33 +1,31 @@
|
||||||
use aoc_runner_derive::{aoc, aoc_generator};
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
|
|
||||||
type Data = [usize;9];
|
type Data = [usize; 9];
|
||||||
|
|
||||||
#[aoc_generator(day06)]
|
#[aoc_generator(day06)]
|
||||||
pub fn input_generator(input: &str) -> [usize;9] {
|
pub fn input_generator(input: &str) -> [usize; 9] {
|
||||||
let mut state: [usize;9] = [0;9];
|
let mut state: [usize; 9] = [0; 9];
|
||||||
let input = input.trim().split(',').map(|v| v.parse::<usize>().unwrap());
|
let input = input.trim().split(',').map(|v| v.parse::<usize>().unwrap());
|
||||||
for v in input {
|
for v in input {
|
||||||
state[v]+=1;
|
state[v] += 1;
|
||||||
}
|
}
|
||||||
state
|
state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn simulate(input: &Data, n: usize) -> usize {
|
||||||
fn simulate(input: &Data,n: usize) -> usize {
|
let mut state = *input;
|
||||||
let mut state=*input;
|
for i in 0..n {
|
||||||
for i in 0..n {
|
state[(7 + i) % 9] += state[i % 9];
|
||||||
state[(7+i)%9]+=state[i%9];
|
}
|
||||||
}
|
state.iter().sum()
|
||||||
state.iter().sum()
|
}
|
||||||
|
|
||||||
}
|
#[aoc(day06, part1)] // 353274
|
||||||
|
pub fn solve_part1(input: &Data) -> usize {
|
||||||
#[aoc(day06, part1)] // 353274
|
simulate(input, 80)
|
||||||
pub fn solve_part1(input: &Data) -> usize {
|
}
|
||||||
simulate(input,80)
|
|
||||||
}
|
#[aoc(day06, part2)] // 1609314870967
|
||||||
|
pub fn solve_part2(input: &Data) -> usize {
|
||||||
#[aoc(day06, part2)] // 1609314870967
|
simulate(input, 256)
|
||||||
pub fn solve_part2(input: &Data) -> usize {
|
}
|
||||||
simulate(input,256)
|
|
||||||
}
|
|
||||||
|
|
71
src/day07.rs
71
src/day07.rs
|
@ -1,33 +1,38 @@
|
||||||
use aoc_runner_derive::{aoc, aoc_generator};
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
|
|
||||||
type Data = Vec<i64>;
|
type Data = Vec<i64>;
|
||||||
|
|
||||||
#[aoc_generator(day07)]
|
#[aoc_generator(day07)]
|
||||||
pub fn input_generator(input: &str) -> Data {
|
pub fn input_generator(input: &str) -> Data {
|
||||||
let mut input: Vec<_> = input.split(',').map(|v| v.parse().unwrap()).collect();
|
let mut input: Vec<_> = input.split(',').map(|v| v.parse().unwrap()).collect();
|
||||||
input.sort_unstable();
|
input.sort_unstable();
|
||||||
input
|
input
|
||||||
}
|
}
|
||||||
|
|
||||||
#[aoc(day07, part1)] // 336040
|
#[aoc(day07, part1)] // 336040
|
||||||
pub fn solve_part1(input: &Data) -> i64 {
|
pub fn solve_part1(input: &Data) -> i64 {
|
||||||
let start = *input.first().unwrap();
|
let start = *input.first().unwrap();
|
||||||
let end = *input.last().unwrap();
|
let end = *input.last().unwrap();
|
||||||
(start..=end).map(|n| {
|
(start..=end)
|
||||||
input.iter().map(|v| {
|
.map(|n| input.iter().map(|v| (v - n).abs()).sum())
|
||||||
(v-n).abs()
|
.min()
|
||||||
}).sum()
|
.unwrap()
|
||||||
}).min().unwrap()
|
}
|
||||||
}
|
|
||||||
|
#[aoc(day07, part2)] // 94813675
|
||||||
#[aoc(day07, part2)] // 94813675
|
pub fn solve_part2(input: &Data) -> i64 {
|
||||||
pub fn solve_part2(input: &Data) -> i64 {
|
let start = *input.first().unwrap();
|
||||||
let start = *input.first().unwrap();
|
let end = *input.last().unwrap();
|
||||||
let end = *input.last().unwrap();
|
(start..=end)
|
||||||
(start..=end).map(|n| {
|
.map(|n| {
|
||||||
input.iter().map(|v| {
|
input
|
||||||
let diff=(v-n).abs();
|
.iter()
|
||||||
(diff*(diff+1))>>1 // Gauss
|
.map(|v| {
|
||||||
}).sum()
|
let diff = (v - n).abs();
|
||||||
}).min().unwrap()
|
(diff * (diff + 1)) >> 1 // Gauss
|
||||||
}
|
})
|
||||||
|
.sum()
|
||||||
|
})
|
||||||
|
.min()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
93
src/day08.rs
Normal file
93
src/day08.rs
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||||
|
|
||||||
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
type Data = HashMap<Vec<String>, Vec<String>>;
|
||||||
|
|
||||||
|
#[aoc_generator(day08)]
|
||||||
|
pub fn input_generator(input: &str) -> Data {
|
||||||
|
// let input =
|
||||||
|
// "acedgfb cdfbe gcdfa fbcad dab cefabd cdfgeb eafb cagedb ab | cdfeb fcadb cdfeb cdbaf";
|
||||||
|
let mut ret = HashMap::new();
|
||||||
|
for line in input.lines() {
|
||||||
|
let mut line = line.split(" | ").map(|v| {
|
||||||
|
v.split(' ')
|
||||||
|
.map(|v| v.chars().sorted().collect::<String>())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
});
|
||||||
|
ret.insert(line.next().unwrap(), line.next().unwrap());
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resolve_overlaps(digits: &HashMap<BTreeSet<char>, HashSet<u8>>) -> HashMap<BTreeSet<char>, u8> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unshuffle(input: &[String], output: &[String]) -> usize {
|
||||||
|
let mut results: HashMap<BTreeSet<char>, u8> = HashMap::new();
|
||||||
|
// segments -> candidate digits
|
||||||
|
let mut digits: HashMap<BTreeSet<char>, HashSet<u8>> = HashMap::new();
|
||||||
|
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 digits
|
||||||
|
// 6, 2, 5, 5, 4, 5, 6, 3, 7, 6 segments
|
||||||
|
// println!("Unshuffling: {:?} -> {:?}", input, output);
|
||||||
|
// LHS is sub-pattern of RHS
|
||||||
|
let overlap: HashMap<u8,Vec<u8>> = HashMap::from([
|
||||||
|
(0,vec![8]),
|
||||||
|
(1,vec![3,4,7,8,9]),
|
||||||
|
(2,vec![8]),
|
||||||
|
]);
|
||||||
|
for val in input {
|
||||||
|
let candidates: Vec<u8> = match val.len() {
|
||||||
|
2 => vec![1],
|
||||||
|
3 => vec![7],
|
||||||
|
4 => vec![4],
|
||||||
|
5 => vec![2, 5, 3],
|
||||||
|
6 => vec![6, 9],
|
||||||
|
7 => vec![8],
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
digits
|
||||||
|
.entry(val.chars().collect())
|
||||||
|
.or_default()
|
||||||
|
.extend(&candidates);
|
||||||
|
}
|
||||||
|
for _ in 0..10 {
|
||||||
|
// println!("===================");
|
||||||
|
// println!("D: {:?}", digits);
|
||||||
|
// println!("R: {:?}", results);
|
||||||
|
if results.len() == 10 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (k, v) in &digits {
|
||||||
|
if v.len() == 1 {
|
||||||
|
let c = v.iter().copied().next().unwrap();
|
||||||
|
results.insert(k.clone(), c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
digits.values_mut().for_each(|v| {
|
||||||
|
for c in results.values() {
|
||||||
|
v.remove(c);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
digits = digits.drain().filter(|(_, v)| !v.is_empty()).collect();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day08, part1)] // 310
|
||||||
|
pub fn solve_part1(input: &Data) -> usize {
|
||||||
|
input
|
||||||
|
.values()
|
||||||
|
.flatten()
|
||||||
|
.filter(|v| {
|
||||||
|
[2, 4, 3, 7].contains(&v.len())
|
||||||
|
})
|
||||||
|
.count()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day08, part2)]
|
||||||
|
pub fn solve_part2(input: &Data) -> usize {
|
||||||
|
input.iter().map(|(k, v)| unshuffle(k, v)).sum()
|
||||||
|
}
|
103
src/day09.rs
Normal file
103
src/day09.rs
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
use std::collections::{BTreeSet, VecDeque};
|
||||||
|
|
||||||
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
|
|
||||||
|
pub struct Data(Vec<Vec<u8>>);
|
||||||
|
|
||||||
|
impl Data {
|
||||||
|
fn shape(&self) -> (usize, usize) {
|
||||||
|
if !self.0.iter().all(|v| v.len() == self.0[0].len()) {
|
||||||
|
panic!("Not rectangular!");
|
||||||
|
}
|
||||||
|
(self.0.len(), self.0[0].len())
|
||||||
|
}
|
||||||
|
fn get(&self, x: i64, y: i64) -> Option<u8> {
|
||||||
|
if x < 0 || y < 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
self.0
|
||||||
|
.get(x as usize)
|
||||||
|
.map(|v| v.get(y as usize).copied())
|
||||||
|
.flatten()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc_generator(day09)]
|
||||||
|
pub fn input_generator(input: &str) -> Data {
|
||||||
|
Data(
|
||||||
|
input
|
||||||
|
.lines()
|
||||||
|
.map(|l| {
|
||||||
|
l.chars()
|
||||||
|
.map(|c| c.to_digit(10).unwrap().try_into().unwrap())
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_low_points(input: &Data) -> Vec<(i64, i64, u8)> {
|
||||||
|
let mut ret = vec![];
|
||||||
|
let (sx, sy) = input.shape();
|
||||||
|
let sx = sx as i64;
|
||||||
|
let sy = sy as i64;
|
||||||
|
for x in 0..sx {
|
||||||
|
for y in 0..sy {
|
||||||
|
let c = input.get(x, y);
|
||||||
|
if c.is_none() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let c = c.unwrap();
|
||||||
|
let low_point = input
|
||||||
|
.get(x + 1, y)
|
||||||
|
.iter()
|
||||||
|
.chain(input.get(x - 1, y).iter())
|
||||||
|
.chain(input.get(x, y + 1).iter())
|
||||||
|
.chain(input.get(x, y - 1).iter())
|
||||||
|
.all(|v| v > &c);
|
||||||
|
if low_point {
|
||||||
|
ret.push((x, y, c))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day09, part1)] // 468
|
||||||
|
pub fn solve_part1(input: &Data) -> usize {
|
||||||
|
get_low_points(input)
|
||||||
|
.iter()
|
||||||
|
.map(|(_, _, v)| (*v as usize) + 1)
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day09, part2)]
|
||||||
|
pub fn solve_part2(input: &Data) -> usize {
|
||||||
|
let mut basins: BTreeSet<usize> = BTreeSet::new();
|
||||||
|
let mut q = VecDeque::new();
|
||||||
|
let mut visited = BTreeSet::<(i64, i64)>::new();
|
||||||
|
for (x, y, c) in &get_low_points(input) {
|
||||||
|
visited.clear();
|
||||||
|
q.clear();
|
||||||
|
q.push_back((*x, *y, *c));
|
||||||
|
while let Some((x, y, c)) = q.pop_front() {
|
||||||
|
if c == 9 || !visited.insert((x, y)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for d in [-1, 1] {
|
||||||
|
if let Some(v) = input.get(x + d, y) {
|
||||||
|
if v > c {
|
||||||
|
q.push_back((x + d, y, v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(v) = input.get(x, y + d) {
|
||||||
|
if v > c {
|
||||||
|
q.push_back((x, y + d, v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
basins.insert(visited.len());
|
||||||
|
}
|
||||||
|
return basins.iter().rev().take(3).product();
|
||||||
|
}
|
66
src/day10.rs
Normal file
66
src/day10.rs
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
use aoc_runner_derive::{aoc, aoc_generator};
|
||||||
|
type Data = Vec<Vec<char>>;
|
||||||
|
|
||||||
|
#[aoc_generator(day10)]
|
||||||
|
pub fn input_generator(input: &str) -> Data {
|
||||||
|
input.lines().map(|l| l.chars().collect()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn error_score(line: &Vec<char>) -> (usize,Vec<char>) {
|
||||||
|
let mut score=0;
|
||||||
|
let mut stack=vec![];
|
||||||
|
for c in line {
|
||||||
|
match c {
|
||||||
|
'(' => {stack.push(')')},
|
||||||
|
'[' => {stack.push(']')},
|
||||||
|
'{' => {stack.push('}')},
|
||||||
|
'<' => {stack.push('>')},
|
||||||
|
')'|']'|'}'|'>' => {
|
||||||
|
if let Some(ex) = stack.pop() {
|
||||||
|
if ex!=*c {
|
||||||
|
score+=match c {
|
||||||
|
')' => 3,
|
||||||
|
']' => 57,
|
||||||
|
'}' => 1197,
|
||||||
|
'>' => 25137,
|
||||||
|
c => unreachable!("Unexpected character {:?}!",c)
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
c => unreachable!("Unexpected character {:?}!",c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(score,stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day10, part1)]
|
||||||
|
pub fn solve_part1(input: &Data) -> usize {
|
||||||
|
input.iter().map(|v| error_score(v).0).sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[aoc(day10, part2)]
|
||||||
|
pub fn solve_part2(input: &Data) -> usize {
|
||||||
|
let mut scores=vec![];
|
||||||
|
for line in input {
|
||||||
|
let mut line_score=0;
|
||||||
|
let (error_score,mut stack) = error_score(line);
|
||||||
|
stack.reverse();
|
||||||
|
if error_score==0 && !stack.is_empty() {
|
||||||
|
for c in stack {
|
||||||
|
line_score*=5;
|
||||||
|
line_score+=match c {
|
||||||
|
')' => 1,
|
||||||
|
']' => 2,
|
||||||
|
'}' => 3,
|
||||||
|
'>' => 4,
|
||||||
|
c => unreachable!("Unexpected character {:?}!",c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scores.push(line_score);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scores.sort_unstable();
|
||||||
|
scores[scores.len()/2]
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
#![allow(clippy::clippy::needless_return)]
|
#![allow(clippy::clippy::needless_return)]
|
||||||
#![feature(int_abs_diff)]
|
#![feature(int_abs_diff)]
|
||||||
|
|
||||||
use aoc_runner_derive::aoc_lib;
|
use aoc_runner_derive::aoc_lib;
|
||||||
pub mod day01;
|
pub mod day01;
|
||||||
pub mod day02;
|
pub mod day02;
|
||||||
|
@ -9,4 +8,7 @@ pub mod day04;
|
||||||
pub mod day05;
|
pub mod day05;
|
||||||
pub mod day06;
|
pub mod day06;
|
||||||
pub mod day07;
|
pub mod day07;
|
||||||
|
pub mod day08;
|
||||||
|
pub mod day09;
|
||||||
|
pub mod day10;
|
||||||
aoc_lib! { year = 2021 }
|
aoc_lib! { year = 2021 }
|
||||||
|
|
Loading…
Reference in a new issue