Compare commits
1 Commits
main
...
c9e45c4685
Author | SHA1 | Date | |
---|---|---|---|
c9e45c4685 |
@@ -28,10 +28,7 @@ fn part2(input: &Vec<u32>) -> i64 {
|
||||
let mut ans = HashMap::new();
|
||||
ans.insert(0, 1);
|
||||
for adapter in input.iter().cloned().map(|x| x as i32) {
|
||||
let to_insert = ans.get(&(adapter as i32 - 1)).unwrap_or(&0)
|
||||
+ ans.get(&(adapter as i32 - 2)).unwrap_or(&0)
|
||||
+ ans.get(&(adapter as i32 - 3)).unwrap_or(&0);
|
||||
|
||||
let to_insert = ans.get(&(adapter as i32 - 1)).unwrap_or(&0) + ans.get(&(adapter as i32 - 2)).unwrap_or(&0) + ans.get(&(adapter as i32 - 3)).unwrap_or(&0);
|
||||
ans.insert(adapter, to_insert.clone());
|
||||
}
|
||||
|
||||
|
137
src/day12.rs
137
src/day12.rs
@@ -1,137 +0,0 @@
|
||||
use aoc_runner_derive::{aoc, aoc_generator};
|
||||
|
||||
use Instruction::*;
|
||||
use itertools::Itertools;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Instruction {
|
||||
MoveNorth(i32),
|
||||
MoveSouth(i32),
|
||||
MoveEast(i32),
|
||||
MoveWest(i32),
|
||||
TurnLeft(i32),
|
||||
TurnRight(i32),
|
||||
MoveForward(i32)
|
||||
}
|
||||
|
||||
impl From<(char, i32)> for Instruction {
|
||||
fn from(value: (char, i32)) -> Self {
|
||||
match value {
|
||||
(i, v) if i == 'N' => MoveNorth(v),
|
||||
(i, v) if i == 'S' => MoveSouth(v),
|
||||
(i, v) if i == 'E' => MoveEast(v),
|
||||
(i, v) if i == 'W' => MoveWest(v),
|
||||
(i, v) if i == 'L' => TurnLeft(v),
|
||||
(i, v) if i == 'R' => TurnRight(v),
|
||||
(i, v) if i == 'F' => MoveForward(v),
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[aoc_generator(day12)]
|
||||
fn parse(input: &str) -> Vec<Instruction> {
|
||||
input
|
||||
.lines()
|
||||
.map(|line| {
|
||||
(line.chars().next().unwrap(), line[1..].parse::<i32>().unwrap()).into()
|
||||
})
|
||||
.collect_vec()
|
||||
}
|
||||
|
||||
const DIR_POS_MODIFIER: [(i32, i32); 4] = [(1, 0), (0, -1), (-1, 0), (0, 1)];
|
||||
|
||||
#[aoc(day12, part1)]
|
||||
fn part1(input: &Vec<Instruction>) -> i32 {
|
||||
let mut x = 0;
|
||||
let mut y = 0;
|
||||
let mut direction = 0; // 0 is east, thus 90 is south, 180 is west, and 270 is north
|
||||
|
||||
for instr in input {
|
||||
match instr {
|
||||
MoveNorth(val) => y += val,
|
||||
MoveSouth(val) => y -= val,
|
||||
MoveEast(val) => x += val,
|
||||
MoveWest(val) => x -= val,
|
||||
TurnLeft(val) => {
|
||||
direction -= val;
|
||||
if direction < 0 {
|
||||
direction += 360;
|
||||
}
|
||||
},
|
||||
TurnRight(val) => {
|
||||
direction += val;
|
||||
if direction >= 360 {
|
||||
direction -= 360
|
||||
}
|
||||
},
|
||||
MoveForward(val) => {
|
||||
let (xmod, ymod) = DIR_POS_MODIFIER[(direction / 90) as usize];
|
||||
x += xmod * val;
|
||||
y += ymod * val;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
x.abs() + y.abs()
|
||||
}
|
||||
|
||||
#[aoc(day12, part2)]
|
||||
fn part2(input: &Vec<Instruction>) -> i32 {
|
||||
let mut way_x = 10;
|
||||
let mut way_y = 1;
|
||||
|
||||
let mut ship_x: i32 = 0;
|
||||
let mut ship_y: i32 = 0;
|
||||
|
||||
for instr in input {
|
||||
match instr {
|
||||
MoveNorth(val) => way_y += val,
|
||||
MoveSouth(val) => way_y -= val,
|
||||
MoveEast(val) => way_x += val,
|
||||
MoveWest(val) => way_x -= val,
|
||||
TurnLeft(val) => {
|
||||
for _ in 0..(val / 90) {
|
||||
let tmp = way_y;
|
||||
way_y = way_x;
|
||||
way_x = -tmp;
|
||||
}
|
||||
},
|
||||
TurnRight(val) => {
|
||||
for _ in 0..(val / 90) {
|
||||
let tmp = way_y;
|
||||
way_y = -way_x;
|
||||
way_x = tmp;
|
||||
}
|
||||
},
|
||||
MoveForward(val) => {
|
||||
ship_x += way_x * val;
|
||||
ship_y += way_y * val;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
ship_x.abs() + ship_y.abs()
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const EX: &str = r"F10
|
||||
N3
|
||||
F7
|
||||
R90
|
||||
F11";
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
assert_eq!(part1(&parse(EX)), 25);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
assert_eq!(part2(&parse(EX)), 286);
|
||||
}
|
||||
}
|
76
src/day13.rs
76
src/day13.rs
@@ -1,76 +0,0 @@
|
||||
use aoc_runner_derive::{aoc, aoc_generator};
|
||||
use itertools::Itertools;
|
||||
#[aoc_generator(day13, part1)]
|
||||
fn parse(input: &str) -> (i32, Vec<i32>) {
|
||||
let (start, buses) = input
|
||||
.lines()
|
||||
.collect_tuple()
|
||||
.unwrap();
|
||||
|
||||
let buses = buses
|
||||
.split(',')
|
||||
.filter_map(|num| num.parse::<i32>().ok())
|
||||
.collect_vec();
|
||||
|
||||
(start.parse::<i32>().unwrap(), buses)
|
||||
}
|
||||
|
||||
#[aoc(day13, part1)]
|
||||
fn part1((start, buses): &(i32, Vec<i32>)) -> i32 {
|
||||
let mut cur = 0;
|
||||
loop {
|
||||
if let Some(bus) = buses.iter().find(|x| (cur + start) % *x == 0) {
|
||||
return bus * cur;
|
||||
}
|
||||
cur += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#[aoc_generator(day13, part2)]
|
||||
fn parse2(input: &str) -> Vec<Option<i64>> {
|
||||
let buses = input
|
||||
.lines().skip(1).next().unwrap();
|
||||
|
||||
let buses = buses
|
||||
.split(',')
|
||||
.map(|num| num.parse::<i64>().ok())
|
||||
.collect_vec();
|
||||
|
||||
buses
|
||||
}
|
||||
|
||||
#[aoc(day13, part2)]
|
||||
fn part2(input: &Vec<Option<i64>>) -> i64 {
|
||||
let mut min_value = 0;
|
||||
let mut running_product = 1;
|
||||
|
||||
for (index, bus) in input.iter().enumerate() {
|
||||
if let Some(bus) = bus {
|
||||
while (min_value + index as i64) % bus != 0 {
|
||||
min_value += running_product;
|
||||
}
|
||||
running_product *= bus;
|
||||
}
|
||||
}
|
||||
|
||||
min_value
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const EX: &str = r"939
|
||||
7,13,x,x,59,x,31,19";
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
assert_eq!(part1(&parse(EX)), 295);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
assert_eq!(part2(&parse2(EX)), 1068781);
|
||||
}
|
||||
}
|
149
src/day14.rs
149
src/day14.rs
@@ -1,149 +0,0 @@
|
||||
use std::{collections::HashMap, iter::zip};
|
||||
|
||||
use aoc_runner_derive::{aoc, aoc_generator};
|
||||
use itertools::{Itertools, iproduct};
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ProgramStep {
|
||||
Mask(String),
|
||||
Mem(u64, u64)
|
||||
}
|
||||
|
||||
impl From<&str> for ProgramStep {
|
||||
fn from(value: &str) -> Self {
|
||||
let (name, value) = value.split(" = ").collect_tuple().unwrap();
|
||||
|
||||
return match name {
|
||||
"mask" => Self::Mask(value.to_string()),
|
||||
name if name.starts_with("mem") => {
|
||||
Self::Mem(name[4..name.len() - 1].parse::<u64>().unwrap(), value.parse::<u64>().unwrap())
|
||||
}
|
||||
_ => unreachable!()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[aoc_generator(day14)]
|
||||
fn parse(input: &str) -> Vec<ProgramStep> {
|
||||
input.lines().map(ProgramStep::from).collect_vec()
|
||||
}
|
||||
|
||||
fn apply_mask(mask: &str, val: u64) -> u64 {
|
||||
let mut val = val;
|
||||
for (i, char) in mask.chars().enumerate() {
|
||||
match char {
|
||||
'X' => continue,
|
||||
'1' => val = val | (2_u64.pow((36 - i - 1).try_into().unwrap())),
|
||||
'0' => val = val & !(2_u64.pow((36 - i - 1).try_into().unwrap())),
|
||||
_ => unreachable!()
|
||||
};
|
||||
}
|
||||
|
||||
val
|
||||
}
|
||||
|
||||
#[aoc(day14, part1)]
|
||||
fn part1(program: &Vec<ProgramStep>) -> u64 {
|
||||
let mut mem: HashMap<u64, u64> = HashMap::new();
|
||||
let mut mask = "";
|
||||
|
||||
for step in program {
|
||||
match step {
|
||||
ProgramStep::Mask(val) => mask = val,
|
||||
ProgramStep::Mem(addr, val) => {
|
||||
let val = apply_mask(mask, *val);
|
||||
mem.insert(*addr, val);
|
||||
},
|
||||
}
|
||||
}
|
||||
mem.values().sum()
|
||||
}
|
||||
|
||||
fn permute_masks(mask: &str) -> Vec<String> {
|
||||
let mut masks: Vec<String> = vec![];
|
||||
let bits = mask.chars().enumerate().filter(|(_, v)| *v == 'X').map(|(i, _)| i).collect_vec();
|
||||
let perms = kproduct("21".to_string(), bits.len() as u32);
|
||||
|
||||
let mut new_mask = mask.to_string();
|
||||
for perm in perms {
|
||||
let bit_vals = zip(bits.clone(), perm.chars()).collect::<HashMap<usize, char>>();
|
||||
for (k, val) in bit_vals {
|
||||
new_mask = new_mask[0..k].to_string() + &val.to_string() + &new_mask[k+1..];
|
||||
}
|
||||
masks.push(new_mask.clone());
|
||||
}
|
||||
masks
|
||||
}
|
||||
|
||||
fn kproduct(seq: String, k: u32) -> Vec<String> {
|
||||
match k {
|
||||
0 => vec![],
|
||||
1 => seq.chars().map(|c| c.to_string()).collect(),
|
||||
2 => iproduct!(seq.chars(), seq.chars()).map(|(a, b)| format!("{}{}", a, b)).collect(),
|
||||
_ => iproduct!(kproduct(seq.clone(), k - 1), seq.chars()).map(|(a, b)| format!("{}{}", a, b)).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_addrs(addr: u64, mask: &str) -> Vec<u64> {
|
||||
let mut addrs = vec![];
|
||||
let masks = permute_masks(mask);
|
||||
for mask in masks {
|
||||
let mut addr = addr;
|
||||
for (i, char) in mask.chars().enumerate() {
|
||||
match char {
|
||||
'1' => addr = addr | (2_u64.pow((36 - i - 1).try_into().unwrap())),
|
||||
'2' => addr = addr & !(2_u64.pow((36 - i - 1).try_into().unwrap())),
|
||||
'0' => continue,
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
addrs.push(addr)
|
||||
}
|
||||
addrs
|
||||
}
|
||||
|
||||
#[aoc(day14, part2)]
|
||||
fn part2(program: &Vec<ProgramStep>) -> u64 {
|
||||
let mut mem: HashMap<u64, u64> = HashMap::new();
|
||||
let mut mask = "";
|
||||
|
||||
for step in program {
|
||||
match step {
|
||||
ProgramStep::Mask(val) => mask = val,
|
||||
ProgramStep::Mem(addr, val) => {
|
||||
let addrs = get_addrs(*addr, mask);
|
||||
for addr in addrs {
|
||||
mem.insert(addr, *val);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
mem.values().sum()
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const EX: &str = r"mask = XXXXXXXXXXXXXXXXXXXXXXXXXXXXX1XXXX0X
|
||||
mem[8] = 11
|
||||
mem[7] = 101
|
||||
mem[8] = 0";
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
assert_eq!(part1(&parse(EX)), 165);
|
||||
}
|
||||
|
||||
const EX_2: &str = r"mask = 000000000000000000000000000000X1001X
|
||||
mem[42] = 100
|
||||
mask = 00000000000000000000000000000000X0XX
|
||||
mem[26] = 1";
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
assert_eq!(part2(&parse(EX_2)), 208);
|
||||
}
|
||||
}
|
60
src/day15.rs
60
src/day15.rs
@@ -1,60 +0,0 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use aoc_runner_derive::{aoc, aoc_generator};
|
||||
use itertools::Itertools;
|
||||
|
||||
|
||||
#[aoc_generator(day15)]
|
||||
fn parse(input: &str) -> Vec<u64> {
|
||||
input.split(',').map(str::parse::<u64>).map(Result::unwrap).collect_vec()
|
||||
}
|
||||
|
||||
#[aoc(day15, part1)]
|
||||
fn part1(input: &Vec<u64>) -> u64 {
|
||||
let mut list = input.iter().take(input.len() - 1).cloned().enumerate().map(|(i,v)| (v,i)).collect::<HashMap<_, _>>();
|
||||
let mut cur = *input.last().unwrap();
|
||||
|
||||
for turn in input.len() - 1..2020 - 1 {
|
||||
let mut next = 0;
|
||||
if let Some(last_turn) = list.get_mut(&cur) {
|
||||
next = (turn - *last_turn) as u64;
|
||||
}
|
||||
list.insert(cur, turn);
|
||||
cur = next;
|
||||
}
|
||||
cur
|
||||
}
|
||||
|
||||
#[aoc(day15, part2)]
|
||||
fn part2(input: &Vec<u64>) -> u64 {
|
||||
let mut list = input.iter().take(input.len() - 1).cloned().enumerate().map(|(i,v)| (v,i)).collect::<HashMap<_, _>>();
|
||||
let mut cur = *input.last().unwrap();
|
||||
|
||||
for turn in input.len() - 1..30000000 - 1 {
|
||||
let mut next = 0;
|
||||
if let Some(last_turn) = list.get_mut(&cur) {
|
||||
next = (turn - *last_turn) as u64;
|
||||
}
|
||||
list.insert(cur, turn);
|
||||
cur = next;
|
||||
}
|
||||
cur
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const EX: &str = r"0,3,6";
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
assert_eq!(part1(&parse(EX)), 436);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
assert_eq!(part2(&parse(EX)), 175594);
|
||||
}
|
||||
}
|
145
src/day16.rs
145
src/day16.rs
@@ -1,145 +0,0 @@
|
||||
use std::{ops::RangeInclusive, collections::HashSet};
|
||||
|
||||
use aoc_runner_derive::{aoc, aoc_generator};
|
||||
use itertools::Itertools;
|
||||
use regex::Regex;
|
||||
|
||||
lazy_static!(
|
||||
static ref RULE_RE: Regex = Regex::new(r"(.*): (\d+)-(\d+) or (\d+)-(\d+)").unwrap();
|
||||
);
|
||||
|
||||
#[aoc_generator(day16)]
|
||||
fn parse(input: &str) -> (Vec<(String, RangeInclusive<usize>, RangeInclusive<usize>)>, Vec<usize>, Vec<Vec<usize>>) {
|
||||
let (rules, my_ticket, tickets) = input
|
||||
.split("\n\n")
|
||||
.collect_tuple()
|
||||
.unwrap();
|
||||
|
||||
let rules = RULE_RE
|
||||
.captures_iter(rules)
|
||||
.filter_map(|captures| {
|
||||
Some((
|
||||
captures.get(1)?.as_str().to_string(),
|
||||
captures.get(2)?.as_str().parse::<usize>().ok()?..=captures.get(3)?.as_str().parse::<usize>().ok()?,
|
||||
captures.get(4)?.as_str().parse::<usize>().ok()?..=captures.get(5)?.as_str().parse::<usize>().ok()?,
|
||||
))
|
||||
}).collect_vec();
|
||||
|
||||
let my_ticket = my_ticket
|
||||
.lines()
|
||||
.last()
|
||||
.unwrap()
|
||||
.split(',')
|
||||
.filter_map(|num| num.parse::<usize>().ok())
|
||||
.collect_vec();
|
||||
|
||||
let tickets = tickets
|
||||
.lines()
|
||||
.skip(1)
|
||||
.map(|line| {
|
||||
line
|
||||
.split(',')
|
||||
.filter_map(|num| num.parse::<usize>().ok())
|
||||
.collect_vec()
|
||||
}).collect_vec();
|
||||
|
||||
(rules, my_ticket, tickets)
|
||||
}
|
||||
|
||||
#[aoc(day16, part1)]
|
||||
fn part1((rules, _, tickets): &(Vec<(String, RangeInclusive<usize>, RangeInclusive<usize>)>, Vec<usize>, Vec<Vec<usize>>)) -> usize {
|
||||
let mut invalid = 0;
|
||||
for ticket in tickets {
|
||||
for item in ticket {
|
||||
if !rules.iter().any(|rule| {
|
||||
rule.1.contains(item) || rule.2.contains(item)
|
||||
}) {
|
||||
invalid += item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
invalid
|
||||
}
|
||||
|
||||
#[aoc(day16, part2)]
|
||||
fn part2((rules, my_ticket, tickets): &(Vec<(String, RangeInclusive<usize>, RangeInclusive<usize>)>, Vec<usize>, Vec<Vec<usize>>)) -> usize {
|
||||
let mut tickets = tickets.clone();
|
||||
let mut rem = 0;
|
||||
for (i, ticket) in tickets.clone().iter().enumerate() {
|
||||
for item in ticket {
|
||||
if !rules.iter().any(|rule| {
|
||||
rule.1.contains(item) || rule.2.contains(item)
|
||||
}) {
|
||||
tickets.remove(i - rem);
|
||||
rem += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut possible_rules = get_possible_rules(&tickets, rules);
|
||||
let mut assigned_rules = [0; 20];
|
||||
while let Some(i) = possible_rules.iter().position(|s| s.len() == 1) {
|
||||
let v = *possible_rules[i].iter().next().unwrap();
|
||||
assigned_rules[i] = v;
|
||||
for s in &mut possible_rules { s.remove(&v); }
|
||||
}
|
||||
assigned_rules.iter()
|
||||
.enumerate()
|
||||
.filter(|(_,&rule)| rule < 6)
|
||||
.map(|(i,_)| my_ticket[i])
|
||||
.product()
|
||||
}
|
||||
|
||||
fn get_possible_rules(tickets: &Vec<Vec<usize>>, rules: &Vec<(String, RangeInclusive<usize>, RangeInclusive<usize>)>) -> Vec<HashSet<usize>> {
|
||||
(0..20).map(|i|
|
||||
(0..20).filter(|&j|
|
||||
tickets.iter().all(|t| fits_rule(&rules[j], t[i]))
|
||||
).collect()
|
||||
).collect()
|
||||
}
|
||||
|
||||
fn fits_rule((_, r1,r2): &(String, RangeInclusive<usize>, RangeInclusive<usize>), v: usize) -> bool {
|
||||
r1.contains(&v) || r2.contains(&v)
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const EX: &str = r"class: 1-3 or 5-7
|
||||
row: 6-11 or 33-44
|
||||
seat: 13-40 or 45-50
|
||||
|
||||
your ticket:
|
||||
7,1,14
|
||||
|
||||
nearby tickets:
|
||||
7,3,47
|
||||
40,4,50
|
||||
55,2,20
|
||||
38,6,12";
|
||||
|
||||
#[test]
|
||||
fn part1_example() {
|
||||
assert_eq!(part1(&parse(EX)), 71);
|
||||
}
|
||||
|
||||
const EX2: &str = r"class: 0-1 or 4-19
|
||||
row: 0-5 or 8-19
|
||||
seat: 0-13 or 16-19
|
||||
|
||||
your ticket:
|
||||
11,12,13
|
||||
|
||||
nearby tickets:
|
||||
3,9,18
|
||||
15,1,5
|
||||
5,14,9";
|
||||
|
||||
#[test]
|
||||
fn part2_example() {
|
||||
assert_eq!(part2(&parse(EX2)), 1716);
|
||||
}
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
use aoc_runner_derive::{aoc, aoc_generator};
|
||||
use itertools::Itertools;
|
||||
|
||||
const PREAMBLE_LEN: usize = 5;
|
||||
const PREAMBLE_LEN: usize = 25;
|
||||
|
||||
#[aoc_generator(day9)]
|
||||
fn parse(input: &str) -> Vec<u64> {
|
||||
|
@@ -1,8 +1,3 @@
|
||||
mod day16;
|
||||
mod day15;
|
||||
mod day14;
|
||||
mod day13;
|
||||
mod day12;
|
||||
mod day10;
|
||||
mod day9;
|
||||
mod day8;
|
||||
|
Reference in New Issue
Block a user