diff --git a/aoc2022/input/day03.txt b/aoc2022/input/day03.txt new file mode 100644 index 0000000..a29ec79 --- /dev/null +++ b/aoc2022/input/day03.txt @@ -0,0 +1,300 @@ +vvMQnwwvrwWNfrtZJfppmSfJSmSg +BzGqjlBqBBmztHNFzDHg +llRCPlTPPqBjPhqhlBRBClhqWcTWrWNcMbQbdrdLccccrnvM +wMhwbTWpQjbpWHMQppzTHhjtlCjPSSJCCtlqRlJVFJFt +ggdvvnvDgdDmNcBrrcDntFRFqHJJtSJqvlVSRlJq +fggNNffGmcBrmBfcDzzzpHbsGTpszwwTbp +BPdPPBggrPtrpbtvPBBdgrFmhhQThGGlbbTZnzZQzZfn +ccjWRJVNcTGmnWWFmh +DMNmsMHwRNBrggdPDPdt +TfsfHLQbBtBFQbQsBmPwwlnPGZFwwdwWFZZw +MRpcvJMJVSMrVMpVSvhhnclwgWwDZgWgWgWglwcG +GCzjRJjVjSSrvfNQtLmQNsQbjB +FrSPFjtVvwsqSwcG +hDHdWDngpgZTDgHzzHwNNqlwNvZJlGqcQGsl +wDzLTDHgFffLtRft +CnCJNVqvCBJBNZmfPcPMcFLVcwmd +HgzjHFghSFtrLfwPchPM +QDpjgDSQlHHlDQQRzRzsBRRvWnWvJvZnqWBJNF +mGHcFPFqzPtcfPwDGVVpgLgSlgBl +rCvddTrnsbDLVSDwjSjd +QWhWQThswssMQMMMvhTzPqJzmzftHccJfHFhFm +cPbNpLVFTPbbFrpTLQBzqqmgnnBhgLMM +vvSwWCZCRZCDZtGwzdgWdQmzqgnQddJn +vCltGltCGmRRmCvDjjtHFpbcFfbbfssbpNPpHFpH +WLLQMWZLSPMPWmrwhnjhZZhpHJHljBDB +csbtCfFgCftGljHwHcBnpnJR +tsvgszNtfMwPzWqPrS +NbDZrbrFQQqqQtQqQDtTcBvCLBLswsZhscCGBZ +ljmWRzVRpbndMWmmfdsTsCBsGwTVVVCGCGws +ffRpnllHRMfdWzdnmRNQNNSFQQFNbrFHHrNH +LccGzWNjcvNLGTmHNsNLMlMwMpMPGlMCwFwDDGCw +fZZtfrZgrfQSnnnSnJRCglHpCwwHwpglDClFMw +SqJQnffJRnfQQVRhrQtrhnThcLhzNzHdTjhsTWzjdmcm +QJQwJMSbtbRgMQMQVZpCZsrrhpZBwrLLvs +qCNPGWdqhpphsWrB +DcNPNnqjdGDqjmPGGJRFMQmgtlQmQJCSgb +blTRbDnHRGGBwnGPCtFPWzVCDvFWtL +pdSJprqhhZSdqSdZNhVzZWtzLVgVPvzjLzWv +rrsqsmrMpPHlwTsRHn +mbNhgbRSLmTwswFm +vHjHBWMHBzMqWZVZBzHzcwwwdcFLcpLspdzwpwQd +HfMWMfvjWtZHqWDlhSnnnJNnbhslDb +lwsvPPnqlwwwsPcHTgqcRcSccmgQ +CVWBWCFpFzWfFjWjhNSQJJmcVcHRZJNTSc +zdhfzBtfLLtfFClbrDvsPvtPbnmv +PntVQbDnQHcDVvhtbtDhcbPcFTrrNfjqmmPTTZqMLZZMjFZm +lgJCpCFCSCGCpllWMfZqTNNZrMjrJTTM +CSzSwgFlzsGBzQcQhsnnDbVdtc +THzqvrVrWzhqhWwqhTbNNDRtFRmmpFDDVsFLLsdddF +MbZSSScZSGCJCjZlCjdPmpRmFLDtctdmFRsp +GfJQlnZjSMnllbJCQbClnZQrhNwwqhBzTNhrffqhqWhTqz +BdBdmDZHFFbrHHStPSRtPCzSRNDS +JGGpwqLJGMTLpLlMpqLhJtzCCSGQSPzNNczVVPVzSV +WwpllfslqfhffLwhfJpJlqlwdBmZnrdFHBFBBmNHFsFmdZmn +jZfQZnZfnbRfjCnfbSSmVpqmNmVpCqlhCqqPpP +MdJMwMvvLDssLtFMsMtLDsvvDRmmmPhWzWzphpmqDVzPDWNp +TsLdMrvRtLJtGdtGRRtFTBjSBrScnSZjnbcgQgHfnB +RZfmlRlWJmWLLRscrslJqvvMdVwmddvPddQPVDdDwz +GStFbFCbntbjNnjFhFvdHfhzHfzzQdMHwPdD +BSGpFbbjbNjnNNFSbRsLlWqgrZrfRgsBlg +ztHczmrmcNNzHsPSTwsPHSQPQT +CFCRjlvbClCjBdPDFQdwBsqn +llbRgjClJCVVMMCssfmNZWszrNgzGL +mmFldllVlmtdWFvPPFBcSSBW +DZzZGzZswQZHwQZjZzWWTSSvjSdvPvvWjJTS +DpQQggwzZGdmbCldgVgf +PJJvhqzVGbTFqzqbbGTlLmrtrZMnnZnntlJnrD +fNwRcQBCRNddNgLtgDnttqrMMtlr +RfRdNWQHcqHscdfRdGPFbFPpvpVWWzPzVS +DRgjZRRDggTfjfRvwWzHGGHPWDswvv +dhbmpcCmchgCpsGzWPdVGvWHwP +hpMMMpCQMnChFgNRQffTRrSN +gfqPCHWtPMMjCtffgjQWGLvGdZcdLLGZcLFGZBWG +pJTDsnnnvBjnFwvj +zJRpTbNrTSppRVblgbljMgMfCfbC +fGrGwqggtbVmtzbf +CTMjNQcJjJTBNCjMNZFNBcCZHbmWZHVLZDDWVtDzzbVmlV +hMvTcNMFMhQjTTBFBNMhwpspwgnGtvtnSgdwrRpG +RfFdqPdMMGPVgWmNVN +QwrTsbnSsSQpwlSSbNNWDmGLVjjmLWwNVB +rpcclTCprmZQSbprSTpRRRfqMfHHCHfhMhvFJM +LnJJsMtLbzsPPVPJbrTBlTWlfRfqnTrrlr +VDHVQNFGgNTrSjSBjq +CHFHGmvDGdZZGCQZVDgDHVbwLLwtMwwmJLJbLPPMbczt +qNNNBllFBzFjjzwGqGgLrWgrtQjdmmtQmQpp +ZMHJCPhMZRsRCsCPsSJZLmQdQgrtQwQwQZwdWg +CnMPbbRbsPhCnbfhMPRPllnFGqwTTFzTzNvBGBGc +wZWlBFZQgBzTzpZwBlVpzWBWnNMmnMvMcMJMmLGnVmqLqGMq +PdSDfJbCHsHHdJjsRRhjjPjmLqnnrLMLcrnLvdLMNccvGn +tSJtSCtbJhDhtzlFQZlTZTFp +TNqZDqmMDZNMFSGHjSGBRBdN +CrrwVwsPjjBHddPf +rpWggQVspQWcgtLwcHZZzDDMLDvvnnMzDM +lWrWmPwmGlZwZjdLZLzV +cFcDJhJnmqBqDCRpZzVLNsFLjLzdds +qJchTDCBHDWglmrfWPHH +RgLRnTJWnfHDcQQBfg +bZpNwdwbdMvVPsHHJMQfSSfP +mVbdNNdrbCzZbdZvbWTGrhqjTJtRWttRjq +TMtqqBJLrwqrZPlHHGhGnlBhzv +bFgNcpDRnpgggjCzvWDWhQhQWQHHvz +jnnVgjcgcTZMJqJVtT +dVSjmdHrfGPddrQgstFgzsQfsMFQ +hvJJCCJDcCtwBVFQzzBD +RWCnTvWTLRnJJLJllWhTLSprVdNZVGHGNGGnrdGSZH +gvMSHFZtBBMBMFZHzjnqLsLGMCzRWWMn +QJmDrhbNDbJfPQhDmQPRLszRlnjCzzWqrRnlsL +PcJVhJbJJNcNDmfDmjJmbhTfBvpwVSdggtgvgSFZwgvtgpdZ +PBClRHHClRlFljllZSBBBllppVGDLpZVVVsGpmGcNDpGLL +MvNwnbMwccVsswDG +MqnNbzMMrQfnqtttqfQWQQnRdCSHgHPglRFBRWlHjWRlCW +lldwdfSBWphHBggZghFs +DjDbDVRzDmLRzRLGJjPssrLZPhdshFHrssTZ +mvddMzvmmDDvvwQqWftCfqWqfM +gpTTwNWGWMSMgJjnvpvvJbJppn +lQvmLFdfrQzRFctlrLdRLVPnhPPbVDPDfjnVbfhJjV +FLFqccvmmtcQtrmQccRFLlRLSSWBSgTWNwsggqMBsqWGHMNG +PjPtVQrPVjrVPLLDQVFLTTWWqbSZwRwzqwSbSbbbwFSq +lBnGJBnfflRRNZwbqb +HJMGgmfpRMHGGdgncJHLDjjtVDQctLCvQCjTtr +VvmvjRGwRwvhmhRvvvVCCTTJjfWqfDMMcJlcCD +NpNbPfpSnngZbbLMFJWTMlLFqJJDMD +bNSfdSHQZgVQzwhhvRmQ +MhmHcDhChhcPVMDPDPQdFhQHnbNpZbZnprnrmNnjNbsllbnp +WWqGCWSCzsGbbGNgjN +LzwqBLSvwJCLPVMVDLdhMP +mNVLLffSLVWdZCcFZCZrSbGr +glvcwszTlsRDrHQCZFCvGH +gTBRlJnwhzgTgsTnggslsJRTpLNmjmNNcdVLdhfpLpdLVmLc +pCgfDrDrgccfppmDnhHMGqGbpHHSqzGLlqHS +tFtjQRPFFZRVNRcQGbLzLFMSGzSbWLqH +QRNTZjvjTTwtwNfmcTgfnCgnnBhm +hcPBhqPzqWPccHWHHWqnPdssPVfFFmZDnVDDms +NSLNCTRQZndRmDfnRD +QSGTGbjTSTJHBlbZZBbh +dgcWgVgWdvZSbbRtjLRZZZ +MMDPPfTnPTQrFDMpHzmmLztLnsszRtwbtS +rDfDqfHTpCSJqlCCGq +bjsgllstBbpNpslBpdBgqljgGwzJzDzwLGGrwLQQdJDwGhQh +nncmnmHHnmWRWmPfJCnvPRMrzvDhZZLGQwhDLhhMzZZZ +mffccVHRRPTTNlpNbNjJVslJ +DgPstgPtgPNNcjQQrtPJJCRSZTwSGJZZCZCJGD +dHVvpzdBBhVqzWqvhvHdzGSZlTRCSRJrwSSCwJCWGT +zpvVVqMBrzqrhFBvjbNPcPLnjcQtMcnj +gBcmTCFghhCCBnBhWWwFbwLdwHFMLMdp +LVzlZzPPMMzWWrwH +ljqjsGlZPPqqlVsPqDVqjQQctNTnRcNLtCNmmnRTRthBGG +LPRrrBNNjLBRJNdrGPRBfBrLwFqmDbdbTbTgmmgwmttFwtmH +QQcVvnQphlWsCQCCVpnvptTJgbtqwHDwbJtJHFsTHw +ppcJVQvpvMVMCvQZQVVZCCSRZPSjNRRZBPPPPzLjSLGf +MLtRnjQsRMJcDQJnSrsfqVVvGwbbbqgggg +WBFCNlFFFhFBlCHbplFWdpWZfVqPPwqTGdqTGvwrPVvTqvTr +HClCHzFzFBhmnjtQzMMSMnbD +sVnMCsdlMRcMFBGz +JvwwgrJDfgDmmggQrhNfhQQftjFrGRRtZFGBRZFHzjGcjrcj +PBJJvgDPNllPddVCPl +fmmRSnfnMnFSmMmmzTDSBFHtlJJqHJJqdHQdTCdtCCdt +WggGpNVVgWdwwHQtlGlC +hjbWppbLbLZLjVPPjPLSRRMvDlmSzDzBSnBFZf +nVttMPnPLjnJLjcnPVCjJJLcssfggBNlffgcNsWTcGcgNsBF +HQbwhmDrRrgFsWlQGNls +pZdbGzGrGpVttPLttv +LLbMrMHLDdWhmgbqqt +jGSQZQTpQGVVRSlQMQRljZmgmJBSvggvBWhJmJWvddmt +VjlQFGMVrFFrDrPw +DZVDwGZlJlVlwZVDzNdqfjMDnjqzNnWf +pmtpLRQFhSFpmpRgRtHNFznNdqWBjzWfnBjMWf +rHRrhStppHdJcGJrrssCsV +pgQqHwgPcPCddCjdWtdp +VfZGVFfNVhZhzjjjLz +fNNBBnGVNfBfRSRjBRQHJQTwJcJTgHPwTngr +MZdlzWzthMgrwmGmqZNqNs +VvJQJPVDBJQThwwNsRqsvRsHHm +BDQQPTnDDBQQBVfTBQPdFctzzdtztMMtnhcWcd +LjWjDShflZRRcZzfHH +srNwQPBsrVRhNmRGHzmM +rBdgQTrhdPndQTrsQQsrPwnTpLLCWDpSCLtCnvtSWpJjDCvl +gSlvDwCvcmcTQTFtRMjWHFVVHwtj +rbsphZZzBshGZssMffTVRFfFpWpfTH +GZNhZBhPBzTPNLDcDlCDCJNmlg +smZjGfvjbWWffQtf +dwRrdlVdDdgDbNtgcgQSNStQ +FdFVwdblFlzVrlwrTlndZHHZGhmLhhssjHhMjnjq +QFvQVFLLgVrFLBVgGhTtllPvmHRRGbTm +hDCCNCNCJNzWDZnqJDzSNCTnbRttHGRnccbPRtmmlmHc +qJshNMCNdVFVfsLB +FcLZZPFjdZcZMPcRjcRTgbpJlwbbTlmdTlGlwD +nrrNrHWBNSWvBqvvrhBqzStrgGnnmbwsbbJbwwJnmwmgJTlD +BCrrNvqWvSQPcCGZZRQQ +vPwcJblJzJbJcJFcwBSvJNdWRLtdsddGWWddWRWsMF +mDZmmDZDHVhfmjZgjVDfhTZHtsNptRsMntnWdsMnGtRntG +mhQrQDDhgqTTNfhmVQVBrPlBczSJbbCbCCPPvb +ZjbjLlbZjGqsgJTfHggrVvlB +tFDRFRnMFnnWtDdMdDRhzHfTJhJhffHvHTBHTgcfJV +nztDtdWzCCMSptSdFRRswZjsLbjwZmwqwGqpQV +vnvmmVnmVbrBJlzgWQWVNFzNHV +MwSjZhSwPjMwfDRzgWlNpWvHlgNNNP +CfSZjSfftwZDChDRSnccnrvBbbGrtBvctr +LCBRQRBQwRrCVLVWSrCSwCptzvhthvGGhdHzwppTTddv +mFnJJmnmFFFfPLNNmqqNJDpGnGtbHTtHvhnHbzvHvpGv +lMMPLqDmNMVSjjgMCS +zzPzbLjHLjfQPQHwwjddFNsNSJjDMsdNMFsC +BqqtmgDhcqdSFCdsqddF +GtcmrvhgcZlvZtBhtVgrvrvtnWzDnQbfnwlfWWRHWbbwzHRL +JfWHWZcMMdDLMPjRnCJjRbFgnblF +ShtBTSmBhTtqtfmqSTNvmjVjnFbFnnlrlqgCnrFnVg +vfzTTthppmdzPLHLWdGZ +tdvrvGgGTSScnHcjcg +zLLVfzPPcDZnPjSPpD +LfffNFLNlNbJwrctthWqNdNq +NdjJtfVNZnnFFdtfGfFNcvpbMDbzdcTbbzpvmcDR +PHMSHCHHWrRCvzDzDChT +BqPWSHwllSQWrLHQHPqlBBNfttZMjFQfjGtZtNjJJjnN +CpZtMCMQQpCVWjMDVjPVQsWWqJJhbTcddPlfhTRqchcJblhh +NwDSGNmGRccqNJfT +SBSSmgrrgGHnvSzwGVWDCzMCpLZtMsstLM +sbjHQsBlBQrrGjQjBqCRSnSCpnfngLnFhJngFfSP +zHVctHDcZtdJffnPpcSpFn +ZdwNMztdvzVdrqblvWsqHvBR +jPdjFPSbVDMMbqZzQWzQ +hFRrJlpprGhtlJGQzmCRmZBWQCHRQR +vThNplJpNhltNNlvcGDvwVFgnPwvSgPSSfjS +DhDTPQpTDmQbDQrrrWtWPJNNrrsJ +qqGjgwCgVRjMSRwMMGRGqjwvsNJJBZtrstvNBvHWHJvL +VqqgfjzfgfFGVjRggCGznhlbTpQchcshpdFlnDbn +DpTQTBbCZQVJQZJjrFllGdlvMPlMLqGBGvLl +hmnWHWWNzzmHsmWRlGGpdLgLHGlqvgqg +RzcWRhRnRnfmswfwtzzRWrDTrrFCQTCpQpcCrjjQCp +HLvpHvGcBTDFznvfqT +hCPQbPZPbjSbwwjCPChSClJJfzqTggTFDfsJngDg +StqmmZbdqrQmhQrrhZWcRcGBpBHWVcLctMWp +dNnRNbRdbRJMBMBVVThn +rNrsLNscFsCDjpwTMgBGWMGjJjWBVJ +wNcLpqHNsCprsfLFsHwRvPSSPRZRtRQSqtQPmP +PPhGfbthhBDVsTDtDqRR +mCmSNmqpcqjjrCScWRsZDpHsDQRZQDZDss +CcWzNmccrjjvqBGzzdPGnv +SDRmCSFfcSFFcfDmDBFSCfdVJhpzZjNJTNzRTvjzjhzNjTtZ +ngGsltrMWrblNpNTJJplJN +PGGnGsWngrGLQHHtHHHgWsHSBLqqfLcqBdVdcCDDBFdCDm +VPjGwhwVPhrnqhzJmQvQTQvmzBzw +ZBDBRbLLdtfRLlddLlCLCZMgmFJQFDcvzMQmgMzzJJFJ +LHLWltHlRZCtBVhVVHPjGSpphp +JqhlhdnnmfRVVSpzWLjzVLGpvB +stQtFTTrsZQPFQNNDtQgLzzSLvjvLGLBGSZGGWJv +DDDFFgDPbTwbTTJMCMcbCqqmmRRCnb +JbDWPDPPJJDMDjHPZHGbHGVZTBhrzBpdzszdTTphdNdWdrpv +RmRRqllqffwFtqwLCsqTNvpCsqCNqvdN +fmfLmStlnnfnRtfcnQbbjPjPPggZGVsMQMbb +WJggvGDJSwWgSfgvfSMGqqQHBcPjcHChcQBCssDHCTTQ +mlRnbrnbnltblwdnnpbLRdCCjCTHTjPTTsQcTrHHhCcj +bFLbdmzRpvSwfFFNWN +BHnDnQHnHMWLwzWPzD +dmlZCrdqLZzZVZJM +tRRtdlLCjLmqCRsrSLrvvRQNFQnbgRTQQNHTBbGQQh +ZrQPQWCrJnPdQSNTmBJNTHGHJN +zhFRfswjwhhsFttfsfvQftRtLTzmBTHGTBmzMLHHLmGHNTTS +hQhwqVjQwsdggrZZCWVl +VjfnQgVQjblChfjVJlbzLtrSLlTGtztHTtsTGH +DDqWQDQMWmDwWNwcqdWvpSrtLpLsptMprMStstMz +vQcddRdRvWcwWRmmmmddZmmfVnnngJJbZnCBnBhhFbhCgJ +gVgDnnmJdQVdJJgtgDjBsBhsBSPRSRRSSwccSbSqwPcCPcSC +HrQHlHFpQfTHzzWzwScPPCRfLbPSfCSR +TTQlZNTzlZNMWvrZMlpnhnVtnDDnVNtVJnjmhg +MCmmssFnZJcNNszfpvvrpvJzvwpp +BRRRWQWbSRGGRTTtZHWSqTrvDfgfdfrrwrDgfbvfzfrd +jRBhWRWTSRttQBZMNchNCsmFMchP +GBDncllqcSlNFZWBFWPjHVbw +LQphJlJzLCwPjHbpHZvV +hzCMJLMzTsrdrszQCCCTCQCDlqqnNmggqfGmgdmGgcmSNt +hFVVbqJsqhcnBRTRGBTh +lwdDpmzdNznzZBgGRRjR +HdmvNvSCmDmwNDFrMJMqJFCRfsbq +ctnbTcFTnbwSSfrrMLRhpJLMRdpwdJJR +vdGCVBmGVHPLBRWhpRLJJZ +VmQPHqvsPdlQsVHDftnlFTbffnbttfTF +LBJZHrhLThHddcMLVtcMcL +CPMNFDDMpGqFjjSPDPDqdvmdtQgVQQcQWcQgQQsj +DzFDFMRSFPSGTJJTJBwwRhBw +dpldqlqlRppFTHpbjbnLRLVnnGfjtG +NNJTcmhzvJQNgMJBwcGtjtGbttfhtsGGnhnt +rzcwmgvcvrBNvvmMgvcBzwHPCTWWprqPHqTFWdPCWDTF +BNllDRTNqDNvNDDLBcDvBCLVJrVdJdtrnrCHggtrdd +mppFMFjpMFZQZQGjFCdgrCrCdrvVGtJJCC +PZsQmfPphvPjSsjmPjfZllBwcNRDNcDqNNWbTclS +fjqZBSDSDwwsQwCDND +rrdMdjVWtTTPslsslFLTLCsJ +rvPWbvcmHjmdPbHvrvBHgqRRgqHGgfZGfHRS +ggTQgsgwFrTrggbMTvSdmjfCmmQDcmqjDjmc +nLZnRhNZnnNHZhZVStCcDqjcqmjSjH +RWGNnhzBnJJRRWNRBNZNLZhFMTFPvrTrTlsggPwSlFMWTw +RNmnPRnLGcQmzBQpHHjTltjtlfgspbsq +CZvCJwZMMCCMdFVcwJJsgTTHfsTlbfbgbT +SSVFhWCZdSCcWCcWdrvhzmnnnLNGDRDNzzLNGz +jPwfPwNfFpFNQpDjdMcjcrdddDHD +tzsRsGRLzhLhvqvhHMlqqV +LRBnRBGSnBSGsGSGmGtBJCmnNWZpPpTNPMwQMPNJFZTTNwWT +PCrStRPSPvZQcZPvqvfjSRWFFNFJFLZTTJTTVZFFGLFF +DlpBzBntHDzhlpGJVHLwTMFLVLTL +gptBBdgzpsBbpQvvPQPRqrdcCC diff --git a/aoc2022/input/day03_provided.txt b/aoc2022/input/day03_provided.txt new file mode 100644 index 0000000..f17e726 --- /dev/null +++ b/aoc2022/input/day03_provided.txt @@ -0,0 +1,6 @@ +vJrwpWtwJgWrhcsFMMfFFhFp +jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL +PmmdzqPrVvPwwTWBwg +wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn +ttgJtRGJQctTZtZT +CrZsJsPPZsGzwwsLwLmpwMDw diff --git a/aoc2022/src/day03.rs b/aoc2022/src/day03.rs new file mode 100644 index 0000000..1270cfa --- /dev/null +++ b/aoc2022/src/day03.rs @@ -0,0 +1,164 @@ +use std::{collections::BTreeSet, fmt::Write, str::FromStr}; + +use anyhow::{bail, Context, Result}; + +const INPUT: &str = include_str!("../input/day03.txt"); + +pub fn run() -> Result { + let mut res = String::with_capacity(128); + + writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; + + Ok(res) +} + +fn part1(input: &str) -> Result { + let mut priorities = 0; + for line in input.lines() { + let rucksack = RucksackSplit::from_str(line)?; + let item = rucksack + .find_duplicate() + .context("rucksack didn't have any duplicate!")?; + priorities += item.priority(); + } + + Ok(priorities) +} + +fn part2(input: &str) -> Result { + let mut priorities = 0; + let mut lines = input.lines(); + while let (Some(first), Some(second), Some(third)) = (lines.next(), lines.next(), lines.next()) + { + let first = Rucksack::from_str(first)?; + let second = Rucksack::from_str(second)?; + let third = Rucksack::from_str(third)?; + + let priority = first + .items + .intersection(&second.items) + .copied() + .collect::>() + .intersection(&third.items) + .next() + .context("the three elves didn't have any item in common!")? + .priority(); + + priorities += priority; + } + + Ok(priorities) +} + +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] +struct Item(u8); + +impl TryFrom for Item { + type Error = anyhow::Error; + + fn try_from(value: u8) -> Result { + match value { + b'A'..=b'Z' | b'a'..=b'z' => Ok(Self(value)), + _ => bail!("unsupported item kind: `{}'", value), + } + } +} + +impl Item { + fn priority(self) -> u64 { + match self.0 { + b'A'..=b'Z' => (self.0 - b'A' + 27).into(), + b'a'..=b'z' => (self.0 - b'a' + 1).into(), + _ => unreachable!("shouldn't happen if Item is constructed from TryFrom"), + } + } +} + +struct RucksackSplit { + first_half: BTreeSet, + second_half: BTreeSet, +} + +impl std::str::FromStr for RucksackSplit { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + if s.len() % 2 != 0 { + bail!( + "rucksack should contain an even number of items, this one contained {}", + s.len() + ); + } + + let half = s.len() / 2; + let mut bytes = s.bytes(); + let first_half = (&mut bytes) + .take(half) + .map(Item::try_from) + .collect::>()?; + + let second_half = (&mut bytes) + .take(half) + .map(Item::try_from) + .collect::>()?; + + debug_assert!(bytes.count() == 0, "something went terribly wrong!"); + + Ok(Self { + first_half, + second_half, + }) + } +} + +impl RucksackSplit { + fn find_duplicate(&self) -> Option { + self.first_half + .intersection(&self.second_half) + .next() + .copied() + } +} + +struct Rucksack { + items: BTreeSet, +} + +impl std::str::FromStr for Rucksack { + type Err = anyhow::Error; + + fn from_str(s: &str) -> Result { + let mut bytes = s.bytes(); + let items = (&mut bytes).map(Item::try_from).collect::>()?; + + Ok(Self { items }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const PROVIDED: &str = include_str!("../input/day03_provided.txt"); + + #[test] + fn part1_provided() { + assert_eq!(part1(PROVIDED).unwrap(), 157); + } + + #[test] + fn part1_real() { + assert_eq!(part1(INPUT).unwrap(), 8018); + } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 70); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 2518); + } +} diff --git a/aoc2022/src/lib.rs b/aoc2022/src/lib.rs index c10d8ec..eef213c 100644 --- a/aoc2022/src/lib.rs +++ b/aoc2022/src/lib.rs @@ -2,3 +2,4 @@ pub mod day01; pub mod day02; +pub mod day03; diff --git a/aoc2022/src/main.rs b/aoc2022/src/main.rs index 6f39647..fefc61d 100644 --- a/aoc2022/src/main.rs +++ b/aoc2022/src/main.rs @@ -4,9 +4,10 @@ use aoc::DayFunc; use aoc2022::day01; use aoc2022::day02; +use aoc2022::day03; fn main() -> Result<()> { - let days: &[DayFunc] = &[day01::run, day02::run]; + let days: &[DayFunc] = &[day01::run, day02::run, day03::run]; aoc::run(days) }