day15: problem 1 & 2 solutions

This commit is contained in:
ktims committed 2023-12-14 22:07:49 -08:00
1 parent 24c534ff88
commit eac460417c
4 files changed
+181

No files matched your search

Generated
+7
View File
@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "day15"
version = "0.1.0"
+8
View File
@@ -0,0 +1,8 @@
[package]
name = "day15"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+1
View File
@@ -0,0 +1 @@
dcf=3,hp=9,kjfhxf-,hpmvrg-,pnb=7,zxz-,vrmt=4,ghrx=7,fz-,vdx-,pbft-,sxlz=7,pdh-,bdm=3,tp=1,bpf=6,ftx-,vc-,bc-,jcm=9,kfgm-,jlfmd=4,bgc-,fs=4,bsqpf-,hsk=5,cr=9,dn=1,xs=8,qdht=1,gtd=6,ccd=4,ngk=1,fp=8,vhf-,hvd-,kxssfz=5,ks=2,llnh=9,rv=8,mj=8,bf-,jrdv=5,jf=9,lpkjx=6,bnf=8,fz-,zxz-,nxsx-,rz-,mkt=1,db=2,lmvv=5,hgnj-,xlh-,mz-,ghcf-,fm=3,lsz-,mqgk-,ldxvr=9,kqkxm=8,gkc=3,rkl-,jxv-,fmgd-,dmbgc=2,sdp-,xv-,zsf=6,gbfp=6,tjbpt-,cs-,ks=1,nct=4,qlv-,jrdkpm=1,nm=3,pncdx=6,xg-,zq=9,kmxnp-,lfqd=5,vp=1,rdl-,fz=3,mbt-,sdp-,vhx-,jcm=5,skz=1,fzq-,fvzbl-,kbtbvk=6,tpv-,gbfp=9,gbfp=3,xnz-,djl-,nb-,nzh=1,zgcr=5,fmgxs=8,tk-,skh-,fvqx-,jsbjs-,cc-,fvf-,mqgk-,mjrkp-,qz=3,db=1,gm-,vckn-,bf=2,cp-,qnjf-,fm-,kzt-,kdt=5,nm-,bnf=8,xnt-,rtf=5,qsvbm-,ngj=5,vp-,mxnm-,kgg-,btd=1,ghcf-,mrm-,nct-,hpj=8,ntrxnc-,dbh-,jld-,nclb-,mkt-,vckn=1,hpmvrg-,rsn=3,jzr=8,gf=9,sff-,jlfmd=1,fc=8,bnl-,jrdv=1,cr-,bj-,zl-,vv-,qkdghh=3,rdl=2,fthhk-,btbbbg=2,qsvbm=3,jfjn-,qsvbm-,vc-,cn=4,zdjz=5,tjbpt-,xj=1,qhzp-,gnknqg-,rvcl-,kz-,xzbk=9,vqs-,zlss=3,rld=5,rtf=7,qp=5,gtp=4,chsk-,mr=4,tp=2,dcb-,zcm-,jnr=7,pld-,czlvx=9,mlgj=6,bm-,grn=5,gct=9,xd-,ks-,mlgj-,jxv=1,gbfp=9,vckn-,cqn=6,jjfth-,hksq-,lpkjx-,rl-,cl-,br=8,jpm-,pg=1,czlvx=3,qdssh-,cx=5,sdp-,hr-,pg-,brn-,xr=7,qd-,hpgq-,nbvjjn-,qkdghh=4,fvzbl=1,sjd=7,qm-,nz-,jcm-,dk=5,bgj-,cnspxc=9,ls-,zhbz-,rsnmqs-,bhv=6,sp-,csr=8,fvqx=3,lmvv=2,bzqbb-,qzf-,tx-,gpl-,xlh-,pg=2,xcc-,rl=2,kbtbvk-,xg-,sp-,sz-,mz=9,bp-,rtf-,bsvql=6,pncdx-,lr=7,gpd=6,srtdk=9,kgtg-,mhz=6,dh-,gkc-,tvhg-,gxx-,tt=3,dj-,rhj-,zcm=4,nq-,xr=9,rtxm=5,br=4,hg-,rv-,ppt=5,df-,jn-,ks=7,qgg=1,zgsvvh-,hpmvrg-,hsk=5,cx=4,dlc-,jpm=4,jm=2,tt=6,mz=7,vf=3,jpm=2,jlkf-,lr-,sjd-,jxjns-,fpj=6,qlv-,jnr=6,dd-,rp-,xf-,npvb=2,qxm=8,br-,sp-,fm-,mf-,rsn=1,pclz-,qxm-,mj-,chsk=5,zq-,lsz-,jfnt-,bpf-,jgkvdq=4,pz=4,rv-,bsvql-,rhj=8,ppm=7,fz=5,fkg=3,cr=3,mvbgm-,xlh=9,frszb=5,sff-,qv=2,mhz-,hv-,xlh-,grn=2,hnqsn-,rsn-,hds-,sjkxq-,pld=7,qlt-,grn-,rc-,tft=7,nztgd=6,fhxq=4,jbn=1,fc=1,fmgd=7,mbnpqk-,mlg=4,ls=8,zmj=1,txvfx=8,gxp-,mjbcps=4,rz=4,qv-,fp=8,hxr-,lhd=1,rhj-,lhd=5,hm=8,njg-,btbbbg=5,sdp-,lnkkl-,jrk=3,sjvs-,btd=8,hgx-,gjtq=1,tk=1,vj=7,tnf-,ck=5,dprj-,lr=9,ngvmt=5,jk=2,sff=9,frszb-,dkhv=4,xq-,dlc=6,hp=6,psh=4,nlmjb-,hfr=2,zcz=5,xcbsp=6,jlhx=5,txc-,tn=6,lpkjx-,bj=4,nhzcjt-,bzqbb=2,brh=1,drdn=7,vhx-,lfz=8,dkhv=1,gxx=5,zlc=5,qz=7,kzt=5,dsxdt=2,gbfp-,fmg-,gjtq=2,jn-,lmbhsl=5,qm=8,ccd-,ldxvr-,mbnpqk-,vg-,dn-,bj-,bp=8,qhzp-,mqgk-,btvq=8,fzq-,htf-,nnfmq-,ck-,bzqbb-,bshcdm=2,dsxdt=6,lhc-,rvcl-,jgvk-,cc-,tvc=2,fs-,qcn=9,qff=6,dmz=5,kqmx-,qgg=3,mr=3,jgknh=2,gknp-,rpq=1,hksq=6,tsg-,bf=8,dcb-,qdht=5,fc-,mfjf=9,qdssh=3,htf-,qgp=8,rf-,kk=3,sn-,bshcdm=7,nclb-,hgnj-,xtd=6,jk-,jtkj=9,nhzcjt=6,xt-,hsk=5,bf-,zl-,cc=1,phxt=8,bj=4,lhd=9,zgcr=6,qf-,bj=8,bhb-,ks-,cx-,czlvx=9,lvh=7,jrdkpm=7,rv-,rkl-,jrdkpm=7,gf-,bgj=4,qdssh-,hd=3,kc=8,jzr=7,cl=7,gtd=8,fc=2,rpq=6,jkh-,zxz-,fksj=4,sxlz-,xj-,vckn-,dj=5,zb-,hds-,bgn-,ngk=6,hfr-,vrmt-,knv=6,pncdx=9,kbtbvk=1,lj=1,zkj=7,jpv-,rv-,smk=6,gndr=8,thddd=9,kp-,rsnmqs-,mj=6,fthhk-,bjgh=3,xj-,vnqslq=9,npvb-,pvn=7,kdj=8,lclv-,pclz=1,skh=5,xd=2,rld=1,bj=9,lqbq=9,vzm=5,srtdk-,kc=2,xdhk=2,kdj=3,lmvv=1,plc-,gknp=9,xbddc=1,jrdkpm=9,vm=6,xv=6,hksq=7,djl=2,hg=9,hk-,khcq-,zlc=7,tvc=4,qf-,qnjf-,nq=7,vm-,frszb=8,jqx=6,jtm=7,bsqpf=2,rdl=6,gtd-,sxlz=7,ls=5,hr-,th-,vbt-,bpf-,xv-,pd-,kgtg-,xtd=7,kkt=5,skz=4,vhx-,dcb-,rzk=4,dcf-,pbft=8,zd-,mqgk-,rvcl-,rv-,nclb=9,mjbcps=1,pclz=4,psh=4,jgkvdq=3,bhps=8,bjgh-,jtm=1,csr-,mlg=7,vdkm=2,jcm=4,smk=6,bdm-,gknp=7,rg-,gxqs=8,rl=1,hsk=9,kt-,jbn-,zcm=8,rhr-,fmgxs-,bhv-,hzh-,vt=9,txvfx-,mf-,rg=8,fmg-,cl=2,hd-,fz-,lv-,xgsr-,fp-,hp=1,rg=1,gtd-,gknp-,hpmvrg=9,tzdg=6,rpq=4,htf-,tq=3,dcf-,dk-,hlrzf=3,vdx-,hpgq=5,kc=8,fhxq=7,cr-,gpd-,snf=7,tqt-,vbt-,hlrzf-,hzrv-,ck=1,jf-,zcz-,fh-,zcm-,rvcl=1,gbv=2,cfx=5,ndhh=8,xks=6,tx-,zm-,dk=7,dbtq-,qlt=9,kcgg=6,mbnpqk=1,qhzp-,vs-,tqt=2,lnkkl-,cx-,jsbjs-,nbvjjn=7,dk=2,jf-,rg=3,rhj-,jdvx-,bpg=7,mbt-,phxt=7,lqbq=2,kkt=9,ldxvr=2,pd-,jgvk=3,hzh=4,dmbgc=4,jrk=5,nm=8,rzk=1,zq-,jsbjs=4,jlfmd-,gpb-,lsz=1,kpz-,rtf-,mjrkp=7,zg=7,xm-,sjvs=3,lnkkl=4,gxqs-,xcc-,tq=9,dndnrr=7,qsvbm-,qsvbm=8,zg=4,ppt-,lv-,gnknqg-,br=9,rtf=2,kjfhxf-,fc=2,jrk=7,bzqbb=4,xpt-,qff-,rp-,bnf=2,dlh-,zcm-,zmj=1,bshcdm-,fmg=6,nkbb=2,bn=7,zdjz-,snf-,ldxvr=2,tzdg=1,lhc=1,xv-,pvn-,dh-,mqrr=8,hpmvrg-,bh=5,jk=4,mvbgm-,zdn-,xnt-,rtf-,tzdg-,vzm=6,lhd-,nz-,mf=1,bgn=7,txvfx=2,nm=6,nq-,pvn=6,jxjns-,zmj=3,kpz=4,kpz-,xcbsp-,nrfpf-,lv-,dj-,jn-,btbbbg=4,cf-,nm=1,mqrr-,nb-,gbp-,bj=6,xdv-,bh-,jzr=7,gkc=6,zhbz-,hx=6,lr-,bz-,bfhqb=6,kfgm-,xf-,tzdg-,xf=5,csr-,xzbk=6,hnqsn-,djl-,jf=1,mbnpqk=1,jt-,zmj=3,kkt-,cs-,ngj=1,lgc-,jf-,lhd=6,llr-,nct-,kxssfz=1,xr=9,gnknqg-,zg=9,lfz-,jk-,rxc-,sjd=8,bzq-,tpv=9,pvs-,vch-,fmgxs-,mlgj=7,qr=8,rl-,zgcr-,nrfpf=9,nhzcjt=5,dcb-,mr=1,kgg-,srtdk-,xlh=5,btd=8,vp=6,xv=2,vnqslq-,xcg=8,rz-,mv-,sjd=9,czlvx-,hx-,gknp=8,zcz=7,jdvx-,pclz-,hsk-,sl-,vg-,lv-,gpb=4,zcm=4,zlj=6,db-,dd-,nlmjb-,fc=1,jtkj-,qgp=9,vm=2,ntrxnc-,hds-,qdht-,rldfx=4,lvh=1,dlc=8,sn=6,gjtq-,cf=1,fvzbl-,jkh=9,snh-,jms-,xpv=6,mvbgm-,lt-,jbn-,rx-,lvh=1,lsz=4,zb=2,ftx=8,fgbjn-,qm-,btbbbg=1,xm=6,hqzl=2,xj-,hvd-Line truncated
+165
View File
@@ -0,0 +1,165 @@
use std::collections::HashMap;
use std::fs::File;
use std::io::{BufRead, BufReader, Lines};
use std::time::{Duration, Instant};
// BOILERPLATE
type InputIter = Lines<BufReader<File>>;
fn get_input() -> InputIter {
let f = File::open("input").unwrap();
let br = BufReader::new(f);
br.lines()
}
fn main() {
let start = Instant::now();
let ans1 = problem1(get_input());
let duration = start.elapsed();
println!("Problem 1 solution: {} [{}s]", ans1, duration.as_secs_f64());
let start = Instant::now();
let ans2 = problem2(get_input());
let duration = start.elapsed();
println!("Problem 2 solution: {} [{}s]", ans2, duration.as_secs_f64());
}
// COMMON
fn hash_string(s: &str) -> u64 {
let mut val = 0u64;
for c in s.bytes() {
val += c as u64;
val *= 17;
val %= 256;
}
val
}
// PROBLEM 1 solution
fn problem1<T: BufRead>(mut input: Lines<T>) -> u64 {
let line = input.next().unwrap().unwrap();
line.split(',').map(|s| hash_string(s)).sum()
}
// PROBLEM 2 solution
#[derive(Clone, Default)]
struct LensBox {
// lenses k: lens label v: focal length
lenses: HashMap<String, u8>,
// order is the lens stack, values are labels into lenses
order: Vec<String>,
}
impl LensBox {
fn add_lens(&mut self, label: &str, focal_length: u8) {
// If there is not already a lens in the box with the same label, add
// the lens to the box immediately behind any lenses already in the box.
// Don't move any of the other lenses when you do this. If there aren't
// any lenses in the box, the new lens goes all the way to the front of
// the box.
if self.lenses.insert(label.to_owned(), focal_length).is_none() {
self.order.push(label.to_owned());
}
}
//If the operation character is a dash (-), go to the relevant box and
//remove the lens with the given label if it is present in the box. Then,
//move any remaining lenses as far forward in the box as they can go without
//changing their order, filling any space made by removing the indicated
//lens. (If no lens in that box has the given label, nothing happens.)
fn remove_lens_if_present(&mut self, label: &str) {
if let Some(_) = self.lenses.remove(label) {
self.order.remove(
self.order
.iter()
.position(|s| s == label)
.expect("We had the lens in lenses but not in order?!"),
);
}
}
fn total_lens_power(&self) -> u64{
self.order.iter().enumerate().map(|(lens_idx, label)| (lens_idx+1) as u64 * self.lenses[label] as u64).sum()
}
}
enum Instruction {
Replace(String, u8),
Remove(String),
}
impl From<&str> for Instruction {
fn from(s: &str) -> Self {
let op_pos = s.find(|c| c == '-' || c == '=').expect("No operation?!");
let op = s.chars().nth(op_pos).unwrap();
let (label, op_focal) = s.split_once(|c| c == '-' || c == '=').unwrap();
match op {
'-' => Self::Remove(label.to_owned()),
'=' => Self::Replace(label.to_owned(), op_focal.parse().unwrap()),
_ => panic!("unexpected op {}", op),
}
}
}
impl Instruction {
fn execute(&self, boxes: &mut [LensBox; 256]) {
match self {
Self::Remove(label) => boxes[hash_string(label) as usize].remove_lens_if_present(label),
Self::Replace(label, focal) => {
boxes[hash_string(label) as usize].add_lens(label, *focal)
}
}
}
}
fn print_boxes(boxes: &[LensBox; 256]) {
for (idx, b) in boxes.iter().enumerate() {
if !b.order.is_empty() {
print!("Box {}:", idx);
for label in &b.order {
print!(" [{} {}]", label, b.lenses[label]);
}
println!();
}
}
}
fn problem2<T: BufRead>(mut input: Lines<T>) -> u64 {
let line = input.next().unwrap().unwrap();
let instructions: Vec<_> = line.split(',').map(|s| Instruction::from(s)).collect();
let mut boxes: [LensBox; 256] = std::array::from_fn(|_| LensBox::default());
for inst in instructions {
inst.execute(&mut boxes);
}
boxes.iter().enumerate().map(|(box_idx, b)| (box_idx + 1) as u64 * b.total_lens_power()).sum()
}
#[cfg(test)]
mod tests {
use crate::*;
use std::io::Cursor;
const EXAMPLE: &str = &"rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7";
#[test]
fn problem1_test_hash() {
assert_eq!(hash_string(&"HASH"), 52);
}
#[test]
fn problem1_example() {
let c = Cursor::new(EXAMPLE);
assert_eq!(problem1(c.lines()), 1320);
}
#[test]
fn problem2_example() {
let c = Cursor::new(EXAMPLE);
assert_eq!(problem2(c.lines()), 145);
}
}