From 5cc33ed979946b1d86240cb07494b6cf0331a33c Mon Sep 17 00:00:00 2001 From: Dominic Date: Fri, 8 Dec 2023 08:23:22 +0100 Subject: [PATCH 1/4] day 8 part 1 --- inputs/day8.txt | 668 ++++++++++++++++++++++++++++++++++++++++++++++++ src/bin/day8.rs | 104 ++++++++ 2 files changed, 772 insertions(+) create mode 100644 inputs/day8.txt create mode 100644 src/bin/day8.rs diff --git a/inputs/day8.txt b/inputs/day8.txt new file mode 100644 index 0000000..51929da --- /dev/null +++ b/inputs/day8.txt @@ -0,0 +1,668 @@ +LRRLRRRLRRLLLRLLRRLRRLLRRRLRRLLRLRRRLRLRRLRLRRRLRLRLRRLLRLRLRRLRRRLRRRLRRRLRLRRLLLLRLLRLLRRLRRRLLLRLRRRLRLRRRLRLRRLRRRLRRRLRLRLLRRRLLRLLRLRLRLRLLRRLRRLRRRLRRLRLRLRLRLRRLRRRLLRRRLLRLLLRRRLLRRRLRRRLRRLRLRRLRLLRRLLRRLRLRLRRLRLRRLLRRRLLRRRLLRLRRRLRLRRRLRLRRRLRRRLRRLRRLRRLLRRRLRRRLLLRRRR + +RGT = (HDG, QJV) +QDM = (GPB, SXG) +DJN = (TQD, BQN) +QGG = (GGS, PTC) +FJP = (MPB, HFP) +KNB = (QHC, XBQ) +RGR = (LSQ, LJV) +HDP = (RLT, LRK) +DBQ = (KTM, MPJ) +QSG = (QVF, QVF) +JKR = (XTK, RQB) +BJH = (VKC, SML) +LRF = (NPJ, HKK) +JRD = (BQX, LGK) +HVD = (CJP, TLM) +VCG = (JMS, RJB) +PCT = (KJC, RCQ) +DRK = (PTR, FSH) +BJN = (GVD, XXN) +CXL = (FMB, NKM) +TVM = (TTX, RCG) +PTP = (KQQ, XLR) +CKX = (VKR, RDH) +TCP = (TPX, BSB) +KSC = (JFL, CHL) +DTF = (BTQ, TTQ) +GFQ = (HKK, NPJ) +BKD = (CXB, JSB) +DJB = (TMG, DDQ) +CQV = (SSX, DFT) +BPC = (KNR, CGF) +KLT = (BMF, XQC) +NLB = (DBD, VCL) +HJS = (FXK, FLB) +PSL = (PBC, XFX) +LVL = (JFD, RJD) +JMX = (CGG, RRL) +TTQ = (XVC, RCT) +NLG = (FXK, FLB) +LCD = (JSB, CXB) +HVR = (CRV, HHM) +HGV = (VCG, JDT) +LND = (TTL, QCH) +CSX = (DHS, JLB) +BRJ = (BCT, XFS) +XVN = (RDH, VKR) +HQB = (BVD, GPC) +PGP = (CFB, HQL) +NFB = (BDX, JDK) +HJK = (VVX, HTP) +KKB = (NSF, GPP) +JDV = (XJG, FDR) +VGC = (HFV, JMT) +BBG = (GTF, KTP) +HTB = (BTC, KKC) +KPL = (MXJ, MBN) +NHD = (GCT, TGP) +DMP = (KRH, SPM) +LRB = (GNP, GGB) +BGA = (MPB, HFP) +PBZ = (KXQ, CKP) +BQF = (LJC, VGC) +KKC = (DJB, MCS) +RRL = (QCK, RKN) +PDZ = (RGF, BHL) +SLA = (BCD, VJK) +XRC = (SKL, VBP) +HHM = (HSJ, NTR) +BNP = (GPP, NSF) +GHM = (HLC, KQK) +LMV = (VTS, NFQ) +QKF = (JNG, THN) +PCG = (HSQ, DMP) +CKG = (XSX, RDF) +RMV = (FQL, HJL) +LPG = (RJD, JFD) +HFJ = (VQX, LQZ) +QRF = (BCR, VSV) +JSR = (BJJ, DVJ) +TKS = (KTP, GTF) +JNG = (DJD, XLM) +XDG = (JKR, MRR) +PFB = (QLT, PBD) +NTR = (HBV, NRX) +NMN = (BDX, JDK) +MGP = (QMT, VLG) +PTA = (LSP, TXX) +CRK = (CJP, TLM) +NVL = (STQ, QFH) +VCL = (XFD, MGN) +LJM = (VJH, NXV) +GCJ = (RFS, QLN) +NSF = (TKV, LKQ) +PQN = (QHC, XBQ) +GHK = (FNT, LCX) +SFK = (FQL, HJL) +FNX = (VXK, BJN) +SSX = (MGK, KRX) +FSH = (FNB, QFL) +XFS = (BCK, CKG) +VLQ = (XJV, HLM) +JLB = (MMR, HMQ) +GXX = (HLN, SGX) +PKX = (QKF, SHQ) +VND = (CDN, VVH) +HJG = (FXR, VDR) +GGR = (QRF, JMB) +BQG = (CRV, HHM) +RFS = (BHN, MNL) +CSK = (DCX, VXG) +RSL = (XCG, JGV) +KRH = (CKX, XVN) +VBP = (NLF, TVM) +AAA = (MQQ, VHH) +BVX = (LPG, LVL) +QCG = (JKJ, CDR) +JMQ = (HLR, GGT) +NLF = (RCG, TTX) +CXB = (NLG, HJS) +VXG = (SDN, FCJ) +XFT = (GNP, GGB) +SST = (GGS, PTC) +NNK = (PTD, HPF) +RKN = (XVF, MMX) +TGP = (SSN, MRT) +TSR = (SFK, RMV) +GBL = (NKQ, KVH) +NKJ = (CGM, TCP) +KVH = (VTK, GKV) +VBB = (DXX, JVB) +KGC = (HMK, TFL) +PNL = (QLT, PBD) +TNG = (QSG, TPL) +HCV = (KVR, PKK) +RBB = (TKG, CQK) +BJJ = (GCN, PLQ) +JRF = (DHC, XCQ) +FLJ = (CKP, KXQ) +KVR = (DJS, NKJ) +HGT = (KVX, LTP) +MGN = (JDS, LNS) +FRC = (QLM, FHJ) +MBN = (TRQ, MRD) +TMG = (CTD, SFH) +TNT = (JDG, HGV) +DXP = (SSX, DFT) +VVD = (JXJ, PGP) +CHL = (XSL, SNZ) +CGS = (GFQ, LRF) +BHL = (FNQ, HFD) +XHF = (NHD, PQC) +PMH = (CNS, SVM) +VKR = (TBT, TLT) +LLK = (TQD, BQN) +LVJ = (PDD, LML) +JPB = (PRK, VCV) +HSJ = (HBV, NRX) +VJH = (DTL, BRL) +SNJ = (DXP, CQV) +HQL = (KDL, QFN) +XHM = (HVG, ZZZ) +RDX = (KTM, MPJ) +MQQ = (LSC, DGG) +TMM = (GMQ, RTL) +JKP = (LRF, GFQ) +TKG = (BDN, BDN) +FBJ = (HLR, GGT) +PTD = (LMV, QBR) +FMB = (DQT, RRH) +TTX = (LVJ, FXX) +BXL = (BTQ, TTQ) +QMV = (GND, FGG) +HFD = (TBQ, VVD) +NFQ = (PMH, DMM) +RTH = (TPG, VDP) +VHH = (DGG, LSC) +HLN = (SPP, SPP) +XQD = (PNL, PFB) +GVD = (BPC, JJG) +XRN = (DHJ, LBD) +GNP = (NRC, NRC) +JLC = (JHB, DRK) +LGK = (BSK, BRV) +BSB = (MBM, XHF) +PBJ = (FRC, RFH) +DRH = (VMR, XVK) +RDF = (BHV, NGM) +MMR = (HGD, PBJ) +RGF = (HFD, FNQ) +HTR = (RCQ, KJC) +NGM = (FJP, LCZ) +PJF = (QKF, SHQ) +BCK = (XSX, XSX) +PBD = (SXM, HTT) +VCV = (GRD, VVT) +TFL = (CCX, HQB) +THT = (NXX, TSR) +JMS = (RCF, XRC) +FKG = (XRN, PHG) +TBQ = (PGP, JXJ) +SML = (TCH, DPF) +RJB = (RCF, XRC) +KJC = (LND, JNR) +HPT = (DLM, MVH) +NKM = (DQT, RRH) +JSJ = (QFH, STQ) +KJJ = (XXT, DBC) +FGG = (HPT, GMM) +RFH = (QLM, FHJ) +TLM = (DKN, QGH) +MJV = (QSG, TPL) +DHG = (RGT, CVS) +BVB = (QLJ, SNR) +RMH = (JKR, MRR) +XFX = (SNJ, QBD) +LNS = (SFQ, GGR) +QJV = (LRB, XFT) +BHV = (FJP, FJP) +JMT = (BJM, NPC) +BDN = (JFL, JFL) +CHC = (CXL, SXC) +VBN = (VBB, CFM) +SFQ = (QRF, JMB) +XXN = (JJG, BPC) +MCS = (TMG, DDQ) +CFV = (DHG, NKS) +FXK = (JSR, GLR) +JMB = (VSV, BCR) +VVT = (LST, GCJ) +VRL = (DJN, LLK) +XLB = (FGJ, PGB) +JVC = (XXT, DBC) +VQX = (BCD, VJK) +DVJ = (GCN, PLQ) +BTQ = (RCT, XVC) +LCX = (JHK, KPL) +FSD = (NNC, XLX) +TSQ = (FKM, HFJ) +HGD = (RFH, FRC) +HJL = (JDV, LNV) +FSB = (DBD, VCL) +DCX = (SDN, FCJ) +BHH = (JPK, GVQ) +JHB = (PTR, FSH) +THP = (SXC, CXL) +LRK = (QCT, FPT) +PTC = (LMF, DLF) +DHS = (HMQ, MMR) +GDK = (SNR, QLJ) +CNJ = (JKJ, CDR) +SBM = (BCT, XFS) +GJP = (RJK, DDX) +DFT = (KRX, MGK) +XBQ = (BNP, KKB) +FGJ = (VRL, CKV) +QVF = (XTM, XTM) +VJK = (BFB, CKT) +VJX = (BKD, LCD) +KQK = (GBL, HPK) +KKX = (BDC, SKC) +CRV = (HSJ, NTR) +JNR = (QCH, TTL) +HTG = (NQK, GJP) +QLN = (MNL, BHN) +GMB = (VVX, HTP) +JDG = (JDT, VCG) +QLT = (HTT, SXM) +CLK = (VJB, SRH) +GSX = (XKX, RSL) +MQX = (RTH, LPL) +ZZZ = (VHH, MQQ) +PKK = (DJS, NKJ) +MJT = (MQX, HTF) +GLT = (TCD, HXV) +PQX = (TGQ, JBF) +VSX = (LTP, KVX) +FSV = (FKG, NLC) +FKR = (CQD, JPR) +CKT = (RDX, DBQ) +JFD = (TKS, BBG) +CNM = (TBH, XRF) +PBC = (SNJ, QBD) +MRT = (QCG, CNJ) +RCQ = (JNR, LND) +JJG = (KNR, CGF) +CFP = (JVT, GSX) +BTG = (SBM, BRJ) +BJM = (CRK, HVD) +XVK = (CDS, BQF) +BCT = (BCK, CKG) +LST = (RFS, QLN) +DNM = (VMR, XVK) +GPB = (GNX, DJV) +FDR = (FTG, LFQ) +LCZ = (HFP, MPB) +XJV = (FCP, JHV) +HQC = (TRG, SCP) +RMD = (QMV, NNH) +SRH = (FLL, QKV) +QBD = (CQV, DXP) +RRH = (NCB, TSQ) +XVF = (NFB, NMN) +QMT = (GLT, NTS) +GBX = (TKG, CQK) +MFP = (TLH, QXD) +XKG = (MHN, NLR) +HQH = (HPF, PTD) +LLR = (CNR, CRF) +LSP = (SVQ, VJX) +HSH = (LRK, RLT) +TTL = (FKR, QMF) +CFB = (KDL, QFN) +SXG = (GNX, DJV) +LTP = (KJJ, JVC) +HSQ = (SPM, KRH) +SHG = (DRH, DNM) +DHJ = (QXR, GHK) +GGK = (PRK, VCV) +TRG = (PJN, CFV) +TTF = (LJV, LSQ) +VVH = (HSH, HDP) +QXR = (FNT, LCX) +DTL = (FSV, VQV) +KVX = (JVC, KJJ) +HLR = (BTG, MKN) +XCG = (QTJ, HTQ) +LML = (JMQ, FBJ) +FMS = (XTM, VXJ) +CTD = (JHQ, XLB) +TCD = (CSK, GLS) +MRR = (RQB, XTK) +SSN = (CNJ, QCG) +VLG = (NTS, GLT) +JDT = (JMS, RJB) +TPJ = (XFX, PBC) +PDD = (FBJ, JMQ) +QLJ = (NVL, JSJ) +TVX = (JPB, GGK) +QCT = (GBX, RBB) +GMM = (DLM, MVH) +RLT = (QCT, FPT) +PFH = (HTG, DNF) +DQN = (XCQ, DHC) +XQC = (QJQ, JLC) +QCH = (FKR, QMF) +GMQ = (KPJ, RTF) +HVJ = (QMV, NNH) +VDP = (TVX, VFB) +NXV = (DTL, BRL) +JHK = (MXJ, MBN) +JPK = (GQN, MFP) +SSH = (KQK, HLC) +FNB = (GPS, LLR) +HTP = (SPG, CSX) +HHN = (DNF, HTG) +QJQ = (JHB, DRK) +PFC = (KRJ, JLV) +HFP = (JRD, MMT) +HGC = (QCJ, CXG) +KLG = (BVX, QSM) +LHG = (HLM, XJV) +CGG = (QCK, RKN) +XVC = (CGS, JKP) +FCJ = (TMM, MBL) +KLC = (CDN, VVH) +CRF = (LVG, FNX) +PBP = (GSX, JVT) +GLS = (DCX, VXG) +DJD = (QGG, SST) +BJV = (DMP, HSQ) +MNL = (JSG, LNC) +DNF = (NQK, GJP) +NLR = (SSH, GHM) +HSP = (JBF, TGQ) +NRX = (DTX, CJK) +VVX = (CSX, SPG) +LSC = (DCL, QBB) +VXJ = (FLJ, PBZ) +CDR = (NXN, NMT) +SGM = (NXV, VJH) +XSX = (BHV, BHV) +MGK = (FXG, XTG) +VPC = (SKC, BDC) +HBV = (CJK, DTX) +RQB = (PCT, HTR) +FXR = (HKP, LVP) +BRL = (FSV, VQV) +VXK = (GVD, XXN) +SDN = (MBL, TMM) +FCP = (HXD, SHG) +XTG = (KLT, SPX) +LBD = (GHK, QXR) +JHQ = (FGJ, PGB) +XXT = (KNB, PQN) +VKC = (TCH, DPF) +GQN = (QXD, TLH) +HLM = (JHV, FCP) +JDK = (TTF, RGR) +VTS = (PMH, DMM) +VMR = (CDS, BQF) +XJA = (BHL, RGF) +MMS = (NLR, MHN) +DPF = (PQX, HSP) +NNH = (FGG, GND) +JSB = (NLG, HJS) +XLR = (GMB, HJK) +RCF = (VBP, SKL) +JPD = (HTF, MQX) +CJP = (DKN, QGH) +BLC = (HGV, JDG) +FTG = (PSL, TPJ) +JDS = (SFQ, GGR) +FQL = (JDV, LNV) +JBF = (CHC, THP) +HVG = (MQQ, VHH) +LKQ = (NLX, HHX) +KRX = (FXG, XTG) +JNA = (CKP, KXQ) +JPR = (CGD, BJH) +CJK = (MSQ, HCV) +QSM = (LVL, LPG) +BQN = (PCG, BJV) +SFH = (XLB, JHQ) +XLD = (QNN, LVC) +GTF = (HTB, RQV) +BMF = (QJQ, JLC) +THN = (XLM, DJD) +VPB = (FXR, VDR) +RQX = (XQD, JDL) +LNV = (XJG, FDR) +NXN = (DSS, KMF) +QTJ = (DKR, KLG) +VSV = (KHH, FSD) +DBD = (MGN, XFD) +DHC = (PHH, HQC) +QGH = (VBN, DPJ) +NTS = (TCD, HXV) +BSK = (BQG, HVR) +MRD = (VPB, HJG) +BQX = (BSK, BRV) +BRV = (BQG, HVR) +SVM = (PKX, PJF) +KRJ = (NMC, TBX) +GTH = (HVG, HVG) +SCP = (PJN, CFV) +CGF = (VFD, GXX) +SHQ = (THN, JNG) +JVT = (XKX, RSL) +RJK = (RVD, CLK) +MKN = (SBM, BRJ) +JHV = (HXD, SHG) +TLT = (JRF, DQN) +QBR = (NFQ, VTS) +CNR = (FNX, LVG) +LVG = (BJN, VXK) +FCQ = (BHL, RGF) +JXJ = (CFB, HQL) +DJV = (BXL, DTF) +DTX = (HCV, MSQ) +JLV = (NMC, TBX) +STQ = (RMH, XDG) +NQK = (DDX, RJK) +KTP = (RQV, HTB) +RLP = (JDL, XQD) +TQD = (PCG, BJV) +GGT = (MKN, BTG) +VJB = (FLL, QKV) +JVB = (MJT, JPD) +VQV = (FKG, NLC) +FXG = (KLT, SPX) +XFD = (LNS, JDS) +NKS = (CVS, RGT) +QFL = (GPS, LLR) +CDN = (HSH, HDP) +RTL = (RTF, KPJ) +CCX = (GPC, BVD) +CXG = (THT, VVN) +GRC = (CGG, RRL) +MXJ = (TRQ, MRD) +SXM = (HQH, NNK) +LJV = (SMP, VRJ) +RJD = (TKS, BBG) +HMQ = (PBJ, HGD) +MSQ = (KVR, PKK) +GPS = (CNR, CRF) +FNT = (KPL, JHK) +HDG = (LRB, XFT) +LFQ = (PSL, TPJ) +VFD = (HLN, SGX) +SKC = (CFP, PBP) +TKV = (HHX, NLX) +GPP = (TKV, LKQ) +JSG = (PFH, HHN) +BCD = (CKT, BFB) +MPJ = (HVJ, RMD) +GCT = (MRT, SSN) +XTM = (FLJ, FLJ) +DKN = (DPJ, VBN) +SVN = (VLG, QMT) +LQZ = (VJK, BCD) +PHS = (GPB, SXG) +XCQ = (HQC, PHH) +QNN = (FCQ, FCQ) +DMM = (CNS, SVM) +DBC = (PQN, KNB) +JFL = (XSL, XSL) +MBL = (RTL, GMQ) +VTK = (MGP, SVN) +SKL = (TVM, NLF) +HXD = (DRH, DNM) +GNX = (DTF, BXL) +XLM = (SST, QGG) +QMF = (CQD, JPR) +HMK = (HQB, CCX) +MMT = (BQX, LGK) +PJN = (DHG, NKS) +DGG = (DCL, QBB) +SPX = (XQC, BMF) +MHN = (SSH, GHM) +RDH = (TLT, TBT) +NMC = (KKX, VPC) +GKV = (SVN, MGP) +XSL = (LSP, TXX) +TGQ = (THP, CHC) +TRQ = (HJG, VPB) +VHK = (KRJ, JLV) +TPX = (MBM, XHF) +QXD = (QDM, PHS) +VRJ = (GDK, BVB) +KXQ = (RLP, RQX) +CNS = (PKX, PJF) +TPG = (TVX, VFB) +PTR = (QFL, FNB) +QHC = (KKB, BNP) +CDS = (VGC, LJC) +BTC = (MCS, DJB) +NLC = (PHG, XRN) +BDC = (CFP, PBP) +FPT = (GBX, RBB) +CQD = (BJH, CGD) +XKX = (JGV, XCG) +TXX = (VJX, SVQ) +SPP = (GTH, GTH) +KTM = (HVJ, RMD) +JGV = (HTQ, QTJ) +HKP = (KLC, VND) +GLR = (DVJ, BJJ) +LMF = (LHG, VLQ) +CLG = (TFL, HMK) +KHH = (NNC, XLX) +HTQ = (KLG, DKR) +QFN = (CNM, TCT) +FLL = (TNG, MJV) +HFV = (NPC, BJM) +NPC = (HVD, CRK) +HKK = (KGC, CLG) +XRF = (PFC, VHK) +GGS = (DLF, LMF) +LVC = (FCQ, PDZ) +DXX = (MJT, JPD) +DCL = (HGT, VSX) +LNC = (HHN, PFH) +TBT = (JRF, DQN) +DKR = (QSM, BVX) +KNL = (QCJ, CXG) +TLH = (PHS, QDM) +NMT = (DSS, KMF) +HLC = (GBL, HPK) +BDX = (TTF, RGR) +HXV = (GLS, CSK) +TBH = (VHK, PFC) +QBB = (HGT, VSX) +TCH = (PQX, HSP) +QFH = (XDG, RMH) +GND = (HPT, GMM) +CVS = (QJV, HDG) +FNQ = (VVD, TBQ) +NCB = (FKM, FKM) +FHJ = (MMS, XKG) +VFB = (GGK, JPB) +RQV = (KKC, BTC) +NLX = (KNL, HGC) +TCT = (XRF, TBH) +GGB = (NRC, XLD) +JKJ = (NXN, NMT) +SPG = (DHS, JLB) +LVP = (VND, KLC) +NPJ = (KGC, CLG) +RVD = (SRH, VJB) +HTT = (NNK, HQH) +PQC = (TGP, GCT) +MPB = (MMT, JRD) +BCR = (FSD, KHH) +BHN = (LNC, JSG) +SMP = (BVB, GDK) +GPC = (NLB, FSB) +NMD = (GTH, XHM) +CGD = (SML, VKC) +CKP = (RQX, RLP) +DQT = (NCB, NCB) +KDL = (CNM, TCT) +CQK = (BDN, KSC) +NXX = (SFK, RMV) +RTF = (LJM, SGM) +KQQ = (HJK, GMB) +KMF = (BVK, BHH) +HPK = (KVH, NKQ) +PLQ = (MLH, PTP) +RCG = (LVJ, FXX) +HPF = (LMV, QBR) +TBX = (VPC, KKX) +NKQ = (VTK, GKV) +PRK = (GRD, VVT) +TPL = (QVF, FMS) +CFM = (DXX, JVB) +SGX = (SPP, NMD) +MLH = (KQQ, XLR) +NNC = (TNT, BLC) +XLX = (TNT, BLC) +MBM = (NHD, PQC) +PHH = (TRG, SCP) +QKV = (TNG, MJV) +XJG = (FTG, LFQ) +QCK = (XVF, MMX) +SVQ = (LCD, BKD) +SXC = (FMB, NKM) +RCT = (CGS, JKP) +KNR = (VFD, GXX) +FKM = (VQX, VQX) +CKV = (DJN, LLK) +DDX = (CLK, RVD) +GCN = (PTP, MLH) +BFB = (DBQ, RDX) +SNZ = (TXX, LSP) +MVH = (JMX, GRC) +HHX = (HGC, KNL) +GRD = (GCJ, LST) +SPM = (CKX, XVN) +LPL = (VDP, TPG) +CGM = (BSB, TPX) +FXX = (LML, PDD) +PGB = (CKV, VRL) +MMX = (NMN, NFB) +DJS = (TCP, CGM) +HTF = (LPL, RTH) +DSS = (BVK, BHH) +KPJ = (SGM, LJM) +DLM = (GRC, JMX) +LSQ = (SMP, VRJ) +SNR = (NVL, JSJ) +DPJ = (CFM, VBB) +DDQ = (SFH, CTD) +VVN = (NXX, TSR) +QLM = (XKG, MMS) +QCJ = (VVN, THT) +JDL = (PFB, PNL) +DLF = (LHG, VLQ) +LJC = (JMT, HFV) +GVQ = (GQN, MFP) +XTK = (HTR, PCT) +NRC = (QNN, QNN) +PHG = (DHJ, LBD) +BVD = (NLB, FSB) +VDR = (HKP, LVP) +BVK = (GVQ, JPK) +FLB = (JSR, GLR) diff --git a/src/bin/day8.rs b/src/bin/day8.rs new file mode 100644 index 0000000..1049b88 --- /dev/null +++ b/src/bin/day8.rs @@ -0,0 +1,104 @@ +#![forbid(elided_lifetimes_in_paths, unsafe_code)] + +use aoc23::read; +use chumsky::prelude::*; +use std::collections::HashMap; + +enum Instruction { + Left, + Right +} + +impl Instruction { + fn parser() -> impl Parser> { + choice(( + just('L').map(|_| Self::Left), + just('R').map(|_| Self::Right) + )) + } +} + +#[derive(Debug)] +struct Node { + left: String, + right: String +} + +fn parse_node_name() -> impl Parser> { + none_of([',', ')', ' ']) + .repeated() + .at_least(1) + .map(|chars| chars.into_iter().collect()) +} + +impl Node { + fn parser() -> impl Parser> { + just("(") + .ignore_then(parse_node_name()) + .then_ignore(just(", ")) + .then(parse_node_name()) + .then_ignore(just(")")) + .map(|(left, right)| Self { left, right }) + } +} + +#[derive(Debug)] +struct Network { + nodes: HashMap +} + +impl Network { + fn parser() -> impl Parser> { + parse_node_name() + .then_ignore(just(" = ")) + .then(Node::parser()) + .then_ignore(just("\n")) + .repeated() + .map(|nodes| Self { + nodes: nodes.into_iter().collect() + }) + } + + fn node(&self, node: &str) -> &Node { + self.nodes + .get(node) + .unwrap_or_else(|| panic!("Failed to get node {node:?}")) + } + + fn left(&self, node: &str) -> &str { + &self.node(node).left + } + + fn right(&self, node: &str) -> &str { + &self.node(node).right + } +} + +fn parser() -> impl Parser, Network), Error = Simple> { + Instruction::parser() + .repeated() + .at_least(1) + .then_ignore(just("\n\n")) + .then(Network::parser()) + .then_ignore(end()) +} + +fn main() -> anyhow::Result<()> { + let (instructions, network) = read("inputs/day8.txt", parser())?; + // eprintln!("{network:?}"); + + let mut curr_node = "AAA"; + let mut i = 0; + let mut steps = 0; + while curr_node != "ZZZ" { + curr_node = match instructions[i] { + Instruction::Left => network.left(curr_node), + Instruction::Right => network.right(curr_node) + }; + i = (i + 1) % instructions.len(); + steps += 1; + } + println!("{steps}"); + + Ok(()) +} From 1c8b2b3179dfc4b2f2b353e3df1f3d6983ec4a2a Mon Sep 17 00:00:00 2001 From: Dominic Date: Fri, 8 Dec 2023 21:28:36 +0100 Subject: [PATCH 2/4] day 8 part 2 bruteforce attempt --- src/bin/day8.rs | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/bin/day8.rs b/src/bin/day8.rs index 1049b88..5423e2c 100644 --- a/src/bin/day8.rs +++ b/src/bin/day8.rs @@ -2,7 +2,7 @@ use aoc23::read; use chumsky::prelude::*; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; enum Instruction { Left, @@ -85,7 +85,6 @@ fn parser() -> impl Parser, Network), Error = Simple anyhow::Result<()> { let (instructions, network) = read("inputs/day8.txt", parser())?; - // eprintln!("{network:?}"); let mut curr_node = "AAA"; let mut i = 0; @@ -100,5 +99,30 @@ fn main() -> anyhow::Result<()> { } println!("{steps}"); + let mut curr_nodes: HashSet<&str> = network + .nodes + .keys() + .map(|node| node.as_str()) + .filter(|node| node.ends_with('A')) + .collect(); + dbg!(curr_nodes.len()); + let mut i = 0; + let mut steps = 0; + while curr_nodes.iter().any(|node| !node.ends_with('Z')) { + curr_nodes = curr_nodes + .into_iter() + .map(|node| match instructions[i] { + Instruction::Left => network.left(node), + Instruction::Right => network.right(node) + }) + .collect(); + i = (i + 1) % instructions.len(); + steps += 1; + if steps % 10000 == 0 { + dbg!(steps); + } + } + println!("{steps}"); + Ok(()) } From 40b252e3934d423dacb78b55df866be5efb5addb Mon Sep 17 00:00:00 2001 From: Dominic Date: Fri, 8 Dec 2023 21:28:48 +0100 Subject: [PATCH 3/4] day 8 part 2 multi-threaded bruteforce attempt --- src/bin/day8.rs | 130 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 98 insertions(+), 32 deletions(-) diff --git a/src/bin/day8.rs b/src/bin/day8.rs index 5423e2c..bc36ec3 100644 --- a/src/bin/day8.rs +++ b/src/bin/day8.rs @@ -1,9 +1,18 @@ -#![forbid(elided_lifetimes_in_paths, unsafe_code)] +#![forbid(elided_lifetimes_in_paths)] use aoc23::read; use chumsky::prelude::*; -use std::collections::{HashMap, HashSet}; +use std::{ + collections::{HashMap, HashSet}, + sync::{ + atomic::{AtomicBool, Ordering}, + Mutex + }, + thread, + time::Duration +}; +#[derive(Clone, Copy, Debug)] enum Instruction { Left, Right @@ -18,7 +27,7 @@ impl Instruction { } } -#[derive(Debug)] +#[derive(Clone, Debug)] struct Node { left: String, right: String @@ -42,7 +51,7 @@ impl Node { } } -#[derive(Debug)] +#[derive(Clone, Debug)] struct Network { nodes: HashMap } @@ -83,46 +92,103 @@ fn parser() -> impl Parser, Network), Error = Simple>> = Vec::new(); + fn main() -> anyhow::Result<()> { let (instructions, network) = read("inputs/day8.txt", parser())?; - let mut curr_node = "AAA"; - let mut i = 0; - let mut steps = 0; - while curr_node != "ZZZ" { - curr_node = match instructions[i] { - Instruction::Left => network.left(curr_node), - Instruction::Right => network.right(curr_node) - }; - i = (i + 1) % instructions.len(); - steps += 1; - } - println!("{steps}"); + // let mut curr_node = "AAA"; + // let mut i = 0; + // let mut steps = 0; + // while curr_node != "ZZZ" { + // curr_node = match instructions[i] { + // Instruction::Left => network.left(curr_node), + // Instruction::Right => network.right(curr_node) + // }; + // i = (i + 1) % instructions.len(); + // steps += 1; + // } + // println!("{steps}"); - let mut curr_nodes: HashSet<&str> = network + let curr_nodes: HashSet<&str> = network .nodes .keys() .map(|node| node.as_str()) .filter(|node| node.ends_with('A')) .collect(); dbg!(curr_nodes.len()); - let mut i = 0; - let mut steps = 0; - while curr_nodes.iter().any(|node| !node.ends_with('Z')) { - curr_nodes = curr_nodes - .into_iter() - .map(|node| match instructions[i] { - Instruction::Left => network.left(node), - Instruction::Right => network.right(node) - }) - .collect(); - i = (i + 1) % instructions.len(); - steps += 1; - if steps % 10000 == 0 { - dbg!(steps); + + for (thread_index, node) in curr_nodes + .iter() + .map(|node| String::from(*node)) + .enumerate() + { + unsafe { + RESULTS.push(Mutex::new(Vec::new())); + } + let network = network.clone(); + let instructions = instructions.clone(); + thread::spawn(move || { + let mut curr_node = node.as_str(); + let mut i = 0; + let mut steps = 0; + while !STOP.load(Ordering::Relaxed) { + curr_node = match instructions[i] { + Instruction::Left => network.left(curr_node), + Instruction::Right => network.right(curr_node) + }; + i = (i + 1) % instructions.len(); + steps += 1; + if steps % 1_000_000 == 0 { + dbg!(steps); + } + if curr_node.ends_with('Z') { + unsafe { + RESULTS[thread_index].lock().unwrap().push(steps); + } + } + } + }); + } + 'outer: loop { + thread::sleep(Duration::from_secs(1)); + unsafe { + let res0 = RESULTS[0].lock().unwrap(); + 'i: for i in 0 .. res0.len() { + 't: for t in 1 .. RESULTS.len() { + let rest = RESULTS[t].lock().unwrap(); + for j in 0 .. rest.len() { + if res0[i] == rest[j] { + continue 't; + } + } + continue 'i; + } + println!("{}", res0[i]); + STOP.store(true, Ordering::Relaxed); + break 'outer; + } } } - println!("{steps}"); + + // let mut i = 0; + // let mut steps = 0; + // while curr_nodes.iter().any(|node| !node.ends_with('Z')) { + // curr_nodes = curr_nodes + // .into_iter() + // .map(|node| match instructions[i] { + // Instruction::Left => network.left(node), + // Instruction::Right => network.right(node) + // }) + // .collect(); + // i = (i + 1) % instructions.len(); + // steps += 1; + // if steps % 10000 == 0 { + // dbg!(steps); + // } + // } + // println!("{steps}"); Ok(()) } From 094d48df8468cbe93fe3e9fda4d046377a42d2c7 Mon Sep 17 00:00:00 2001 From: Dominic Date: Fri, 8 Dec 2023 22:15:07 +0100 Subject: [PATCH 4/4] day 8 part 2 dp --- src/bin/day8.rs | 200 +++++++++++++++++++++++++++--------------------- 1 file changed, 112 insertions(+), 88 deletions(-) diff --git a/src/bin/day8.rs b/src/bin/day8.rs index bc36ec3..f96f690 100644 --- a/src/bin/day8.rs +++ b/src/bin/day8.rs @@ -1,18 +1,9 @@ -#![forbid(elided_lifetimes_in_paths)] +#![forbid(elided_lifetimes_in_paths, unsafe_code)] use aoc23::read; use chumsky::prelude::*; -use std::{ - collections::{HashMap, HashSet}, - sync::{ - atomic::{AtomicBool, Ordering}, - Mutex - }, - thread, - time::Duration -}; +use std::collections::{HashMap, HashSet, VecDeque}; -#[derive(Clone, Copy, Debug)] enum Instruction { Left, Right @@ -27,7 +18,7 @@ impl Instruction { } } -#[derive(Clone, Debug)] +#[derive(Debug)] struct Node { left: String, right: String @@ -51,7 +42,7 @@ impl Node { } } -#[derive(Clone, Debug)] +#[derive(Debug)] struct Network { nodes: HashMap } @@ -92,15 +83,93 @@ fn parser() -> impl Parser, Network), Error = Simple>> = Vec::new(); +#[derive(Copy, Clone, Debug)] +struct Ghost<'a> { + node: &'a str, + i: usize, + steps: u128 +} + +impl<'a> Ghost<'a> { + fn new(node: &'a str) -> Self { + Self { + node, + i: 0, + steps: 0 + } + } + + fn advance(&mut self, ghost: Ghost<'a>) { + self.node = ghost.node; + self.i = ghost.i; + self.steps += ghost.steps; + } +} fn main() -> anyhow::Result<()> { let (instructions, network) = read("inputs/day8.txt", parser())?; + // build a lookup map of left/right predecessors + let mut left_pred: HashMap<&str, Vec<&str>> = HashMap::new(); + let mut right_pred: HashMap<&str, Vec<&str>> = HashMap::new(); + for (node, next) in &network.nodes { + left_pred.entry(&next.left).or_default().push(node); + right_pred.entry(&next.right).or_default().push(node); + } + eprintln!("Built pred lookup map"); + + // build a lookup map from instruction position and node with the length to the next + // finish node + let mut dp: HashMap<(&str, usize), Ghost<'_>> = HashMap::new(); + let mut q: VecDeque<(&str, usize)> = VecDeque::new(); + for node in network + .nodes + .keys() + .map(|node| node.as_str()) + .filter(|node| node.ends_with('Z')) + { + for i in 0 .. instructions.len() { + dp.insert((node, i), Ghost { node, i, steps: 0 }); + q.push_back((node, i)); + } + } + while let Some((node, i)) = q.pop_front() { + let ghost = dp[&(node, i)]; + let i_pred = match i { + 0 => instructions.len() - 1, + i => i - 1 + }; + let pred = match instructions[i_pred] { + Instruction::Left => left_pred.get(node), + Instruction::Right => right_pred.get(node) + }; + for node_pred in pred.into_iter().flatten() { + let new = (*node_pred, i_pred); + #[allow(clippy::map_entry)] // lint is opinionated garbage + if !dp.contains_key(&new) { + dp.insert(new, Ghost { + node: ghost.node, + i: ghost.i, + steps: ghost.steps + 1 + }); + q.push_back(new); + if dp.len() % 1_000_000 == 0 { + dbg!(dp.len()); + } + } + } + if ghost.steps == 0 { + dp.remove(&(node, i)); + } + } + eprintln!("Built ghost lookup map"); + // for (key, value) in &dp { + // eprintln!("\t{key:?}\t = \t{value:?}"); + // } + // let mut curr_node = "AAA"; // let mut i = 0; - // let mut steps = 0; + // let mut steps = 0_u128; // while curr_node != "ZZZ" { // curr_node = match instructions[i] { // Instruction::Left => network.left(curr_node), @@ -111,84 +180,39 @@ fn main() -> anyhow::Result<()> { // } // println!("{steps}"); - let curr_nodes: HashSet<&str> = network + let mut ghosts: Vec> = network .nodes .keys() - .map(|node| node.as_str()) .filter(|node| node.ends_with('A')) + .map(|node| Ghost::new(node)) .collect(); - dbg!(curr_nodes.len()); - - for (thread_index, node) in curr_nodes - .iter() - .map(|node| String::from(*node)) - .enumerate() - { - unsafe { - RESULTS.push(Mutex::new(Vec::new())); + let mut progress = 0; + loop { + if ghosts[0].steps > 0 + && ghosts + .iter() + .skip(1) + .all(|ghost| ghost.steps == ghosts[0].steps) + { + println!("{}", ghosts[0].steps); + break; } - let network = network.clone(); - let instructions = instructions.clone(); - thread::spawn(move || { - let mut curr_node = node.as_str(); - let mut i = 0; - let mut steps = 0; - while !STOP.load(Ordering::Relaxed) { - curr_node = match instructions[i] { - Instruction::Left => network.left(curr_node), - Instruction::Right => network.right(curr_node) - }; - i = (i + 1) % instructions.len(); - steps += 1; - if steps % 1_000_000 == 0 { - dbg!(steps); - } - if curr_node.ends_with('Z') { - unsafe { - RESULTS[thread_index].lock().unwrap().push(steps); - } - } - } - }); - } - 'outer: loop { - thread::sleep(Duration::from_secs(1)); - unsafe { - let res0 = RESULTS[0].lock().unwrap(); - 'i: for i in 0 .. res0.len() { - 't: for t in 1 .. RESULTS.len() { - let rest = RESULTS[t].lock().unwrap(); - for j in 0 .. rest.len() { - if res0[i] == rest[j] { - continue 't; - } - } - continue 'i; - } - println!("{}", res0[i]); - STOP.store(true, Ordering::Relaxed); - break 'outer; - } - } - } - // let mut i = 0; - // let mut steps = 0; - // while curr_nodes.iter().any(|node| !node.ends_with('Z')) { - // curr_nodes = curr_nodes - // .into_iter() - // .map(|node| match instructions[i] { - // Instruction::Left => network.left(node), - // Instruction::Right => network.right(node) - // }) - // .collect(); - // i = (i + 1) % instructions.len(); - // steps += 1; - // if steps % 10000 == 0 { - // dbg!(steps); - // } - // } - // println!("{steps}"); + let (ghost_index, ghost) = ghosts + .iter() + .enumerate() + .min_by_key(|(_, ghost)| ghost.steps) + .unwrap(); + if ghost.steps - progress >= 1_000_000_000_000 { + progress = ghost.steps; + eprintln!("progress: {progress}"); + } + + // eprint!("{ghost:?}\t -> \t"); + let ghost = dp[&(ghost.node, ghost.i)]; + // eprintln!("{ghost:?}"); + ghosts[ghost_index].advance(ghost); + } Ok(()) }