diff --git a/.run/Run-aoc2022-bench-dayX.run.xml b/.run/Run-aoc2022-bench-dayX.run.xml
new file mode 100644
index 0000000..5f016a3
--- /dev/null
+++ b/.run/Run-aoc2022-bench-dayX.run.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/Run-aoc2022-bench.run.xml b/.run/Run-aoc2022-bench.run.xml
index 279cbed..4b0c949 100644
--- a/.run/Run-aoc2022-bench.run.xml
+++ b/.run/Run-aoc2022-bench.run.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/.run/run-day-3.run.xml b/.run/run-day-3.run.xml
new file mode 100644
index 0000000..e35ed6d
--- /dev/null
+++ b/.run/run-day-3.run.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/input/day3.txt b/input/day3.txt
new file mode 100644
index 0000000..9af14f3
--- /dev/null
+++ b/input/day3.txt
@@ -0,0 +1,300 @@
+BzRmmzZHzVBzgVQmZLPtqqffPqWqJmPLlL
+hpvvTDcrCjhpcrvcGGhfLHMlLtMCqflNlWPJlJ
+hGjhncHhGnhbTHczBBZVVSbRwgSgRV
+rWVQjPQQjGRWNSrWrPjcptwBpqqJBtJBBcZgMdtq
+zzmmpzfTCFpTlMlJJwBgMlqMBt
+TvLszpbhhTLmsnRQPDQGWDWRvQSR
+zGzvLlGlQHLGBQZlhBWhdjRdmdWRcjPj
+fTJNfTfNSRWPhjdjfj
+pbsbVVnpSnbVTprnbqqrzvLLgQlGLPLHll
+ZCCCsWvNvmsCsCmZLZmgMLRpQMhwQRpQRfphfprpTfpM
+tlncPjzlndctbzcPPBcjwDphwrfGGDffbDRpDTGG
+cdqnddwzqjNVWVLZZLZq
+DTLbDbRrlQbwhhNrmmfwdt
+zzMJMzjCjJJjvLjMPJpcgPpzfhHdfqWcqddwtwfqdttcNtdN
+pJCzVpCvDZBLsVRQ
+STzBBbJzRRBZBRTqCCsfZLtNNLClCsfh
+jsQnnQjjHcvQFrcPwCmtLCNlvDfftfff
+sGFscMQQMMpqzqbMbd
+QlNDWGsjQjgQllWQsbtzqTJczTJcbFmmFJJP
+MhLrhgLVndRmzJFzVqqJqP
+pSLnMdwhwdRZRSwhLZwLhdGWQjlsgWjNQWWSvgBsWDlj
+THjSRFSddTjdBTcPLcVVvVBw
+GzWnWfndWfznDfsnsBsPVwVwPPLL
+zNflzJWqqzQDdSStHNZNpFFtbj
+FSzDmsFSFlDlBzqVjqHHjHHpVgHLbp
+rTrTtTQQntRQnQJQgggHZttVgHLBLhZL
+WTJJRRQCRRJTRdBCRdvRNDFSWFMPmDlPPSsNPSzS
+WQldlMtMVQgVMQHnDGbHGGnRnQmD
+rqcZPrCFjmHlbGjZ
+zSScchqwchBzTzFzhhSlcCwNtdVWWJgsVdMtWNgNVWTJTd
+lMZqjMWllrTTspjprWWSSwgWNSVNDmWGVwFwgN
+cdCCdLHcnndHJnmCRntLBnRzDvFNtNDVzgSgwDgFNVzFVv
+BRLcCCJCmJdcRhfjPPZphrlrPqlZ
+GdGqcrrZGDrvDJJqJHcBvmFFgmFMMgMgBtMLTssLmF
+NbPVPDlljPmTmsTj
+VfQDhflCCRWdcrQwJvvnJv
+RLcWgLCqqPQLcqZwzHgwmmrmmtgwTw
+DhbhNrMpnJSDJwVTHmmTVnTTVj
+lrsvblMDlcWcfQPQ
+PVldlphHwGwJJGdjZZWsRbbsGsNWrWQbNbQR
+SqcDvTmDLtfmSmtqppfqzTgTQBrRQsbCFWbNNFQFBBrRbLNb
+MgtmTgtfpqVlnVddZMwV
+BdmfmPBPSbSNdGSdvWrwcZrccZPPcZnH
+jzzLsjsMRlQQVHwswvvZrCHrrT
+VqhzVFzplFlpLwpMphLRQQVRmSqgbdGtNJBmNSmgGbtggSgt
+DHVpNZjdZjFZWVFHpvFvzmlRzPnlfznFRz
+lrTBTsBwwMbrrwLPPfwGmGzvRf
+scrtMhMCtJBBBclbHdHttWZWDSqDSjHj
+wzqsPmqsbsfqBwPMNRMMZcZmFFNtZM
+CgCnhlvvLJgcRFNNBdCpWM
+QnQrVgHSvVHjbjTGBbbTHb
+HdrVrdqFDdZVmHgRmDRFHMnTdTssMGnLnPJLbPTbCs
+SczlScjwcNzplNzQSSfjwQSrTGGsbTsnTCnGTMCMLMGGbN
+wQlfjrhfhQFHqZhRZRtD
+RsfJDGJvzPNcjpddSWJWMd
+LLCbBCwCrCmVVnrmhQFmbVhdcdlWpjZzSpMdWSpcWczSBj
+rrLCbTwnHTvzvNGT
+wPhPhbCqqSCrtJDlqvlrJr
+RVVZddLFRZZcQLvJJtzptlgPJp
+TVQRZGVncFdTGWZdCNShHhfPNwwsWPwb
+dzLVzPSgrgDDDCMSMLLPwFmdTTcsvmwNwjNsHcFF
+nWBGntQfGNGBflWBBqlpRQGbWFvjwsbsFswbvTHjjbmHTc
+tBNJBnGBflQnDPJrPhDgrPVg
+VtWztWtqpqzWpWzqjNRjNpWTmrrmrSbnmJwSJwnMPrCSJVwM
+sDHsBDhBdsBZGcHvLHDLhhCSnRSwCJMZrPbmnMbJSCSR
+ccLRhgsLBdRsdHNTFFNNgqTglqzF
+hztlmDhPhgPlPNNgmZMCbmwwQjcwjjwMjVCd
+RSJRrRqnqQJFqvnTGrHCcHHCCHHbHHMcMvdM
+qGJsnQTRsStsftPlhPNl
+BFFBLPRCwsLwhlPlRmhcGGrbmmGjfNTTnp
+VJMVpzgqggJnrjmjNcMjmT
+VqdSZtQgZvtdzqHqHtVZdVQpCDWWFdwlRPDpWPPBCswlWD
+fCWCsjPzcbzwRSzVTzhhDLqvdg
+TmJtrNJrBLSLJqgS
+ptNTQFHrZlnpFPwsWMbRjCpcjR
+nJmQNCmbmlllmbClbfMLjMFqbGBsdLFq
+ZcgTWcTnMqqMTBqF
+tPgctSnPctZZgDWzZgQHwNmHlhlmzlQhlJlw
+ZpTCwpffdslvgShCBhqhRz
+FDMPnNFNmBPzvRPRBg
+nNgMrnnDGjDmJMmnFdZTTsdsrZrslcwcQr
+pTmczpCldcdDDnPttpvWSqbpJf
+jgjRZMGHhGLgQrjvPWzPJgJvzStbbq
+LGNLLNBBzcDFCBwwFC
+nJTTqnrNvTzNMzzNfqrTPrJnwpwPpZpsHccZVsBRpcVHwpcp
+bgDhgbghLWmFmStctVpZtBCVCCpfZp
+LLSgLGSjggFGbSSbmMnrvqvzjfzTNrJrqM
+RRpDmmPMTjwfGmJQgQ
+WsNscdnvvdVZFVnnrZbjjflwljlbzfGFjQjq
+NnLZsNnrrVVVcvdBLTPCPCRMwhPMBMPhCt
+lbVvzngGJnVbJHpHtHNPpdSQvc
+TsMBswFZsWMWBZMNwPtNNtRNHcNpSQ
+CcZCTrZDsjZTsTsshWhrWrTnfgbLDfJzVVLVVlgfnzfVGV
+JzTTRtJRZWmWjrMHCT
+DDFGlLGcGlSSSLsFGBspPBmNMBHMghmWNmWjWCmWtH
+nSSpnbsGlLDnpPsSSspFtVvffRQdVzqvvbqdfVQwRz
+sMhzszlHHDsWbthHDqsbJjpLNtmjVJmVLLVLVLBp
+nrTPrGwfPLdprzJzdL
+wgPQcTGGzgccwCgnRwgRChFhlWSDqWWQMWhssSsMQl
+NSNmwtpSpCpvMphCsr
+PHcRGPLJMrsvzsqG
+QHjbnRMcfbPbQZmlZgZlgBBQ
+cPRPbhQjbQRdtPQdLqLHqzFZjCFCqLjC
+mmfsnnwrfvwrfSNZFzHHLDCFNlLlqDlN
+wsmrwswwGTffMrBnmQttJtcMZQQtPJPbZc
+MvBPDDRRdnnvHPCHZLHZsFLL
+rmJcbVqbcjWwWjQHLzTZFTHSzFrpsz
+cmwllVqqGJbVVVmmqbQcmgRnRvGhGfgDRDZBBBvRdd
+nMvMhMnvhnbTZWSSZgHmGJDFmmNDzBmbNmdGBN
+rCsPLRCssRjrLLsrLlwRVrcNJQfDQfdBmmfNBGJNzmDPfB
+CRjCpLltgtJgJJWq
+jshCzJpjzTPpmCWvSlpfwHfSWglf
+LQMMNMnHtDtLVRvwwgRWlldgWD
+qHVrQNHVMFQtrrBBQMBcrrZsZbzCZhbbJZJsmmsmFPTC
+JZQZnsQNMqTngZqJBVfBfPPVBNrwvfPw
+SSmDstFjpDpCszDjcLLhrPVlGlrGGVBwrvwVPt
+FSssFcLjFjbmFFCzjLcFLRDnMJnTHRnZZTdWqZZWnMnRnZ
+GbHRHpldwGMpWhHpCMBlCbRdVSLhnqJLSrDPLPPLPDqVDrhh
+gvjWWQvgZFtQFFNqLnVnDnSJzzztDD
+ZccccfTsffHdWWdRWwsw
+ClCtbHMlnnPPlszV
+gSDWSLgWQWQJJNWqgtQjPsnfcdVcLVdVdzfzVzff
+WQgqtFQgDgQSFqJhqhSJvNDRrZMZHwHMCbZhTpZbGHMTMG
+pZJZlCQtHFhPfdNfCh
+zcmLSVczwcMcLDNFHdLPhPWH
+szvVVnBmnTGQtHTQ
+RVVCNDlNGzlGZqHGHWqWhGqQwH
+ZFLFTmpLvvmSqsbb
+TrfpBfJpJMlnnNfNZD
+qHHlDClHhltMqQsHDhHslGznwdTnzzwDGSdfnwGnwG
+mZRNcNcLLPNPBFFbbPmLmbZFSCVfJJTVndVfSwnRzznfTwCS
+CcCWFbbBLCWtgWgHjghqvv
+TjbzlnlFmfqCFFVVCRWr
+PhMcLpPDtMLpwPDvLPJbMhSgVCGqggVqQgCqCgCgSWvv
+btbZbNZhJDJJhDtwtsTTTmBzzBBmlNlmHj
+FqhjWtqlqmmsnFPTCvMCQMTTCjQd
+pfffRfLpgrgGgzrNVzzpGVzRCdMCPJbwwcVMbQPCJVMVdbww
+DGGDZRGrHggzSsFQnnWShmtH
+vtHVVMMrvVMVrSHvLgvlHcZFCnRCZcccZtRRZfJFCJ
+rdDjGsdTQDcNZfdncCRR
+rBDsTwBbjbmbbQswswPhqVmmSvpVhlvvqMhHhh
+vGBLrqMNvqSLBvvrNbllLHfwStWWtFttccjtRtjtcj
+MhCDJmhMDzmcRRcjzWfztH
+ZQDmDhVVCQbBVdVNMvvv
+ptCtCzhWPWptnhVzzpGZbZTjTjVjFGjVFgVl
+fQswRRffmRqZlgrqqFjjSgGg
+HwsQDNNsDsmRLLHmffsfvHptBnhtzCvhWpZWBdhnMdCh
+RlHzzTqczBPfbnvcpB
+wVtNwpSZstppwwMsZhsdnLvnbtBBmbnLFFdnmF
+WNQJMVWsZWwGJWhhSNrQzlgHrDCgQRHpCHrl
+RrZWpJZRrZpdTGstlchLGGlLMd
+NqjDPCQPnQCSvtMzSLhhjM
+nQVQDDDDfwBwNCVCNVFNpWpgJgrRTmLTmTmgRTWF
+SHMcrMHpcjGcjSrMMbvSvvSvwFTLJwJNtFGFWJNtDLFTLfWN
+zqRnPfzQCRzqsmRPzznhszzLtLwQwwFTgWWLDLgWFTwTNQ
+qVPZmRZhsCZPhZlRCqRRRCbfpccMBjvMVjdHjjMjSvdf
+VVQdHwBZLVltlddtBczhrzvGcWWFRwgsFG
+TDTTTqqTSSqjqnmTmPqPPmTmGhRszvsrzsjRsccgzrRzgWGF
+DpJPqpWqHbZpllpt
+cCSCFsnnZFnscDtNdJFJtJtdmb
+VgBqBsqRrHtNdzmNrt
+BGLLVVjRBsqPBfsGwPsMfSSZCSfTZTZQpSphfS
+plCHCHlgglHHGpNbtngNrDvBDpfQDBQfZDfWZVrr
+mTmMLhRfwhsLPQvQZDMZQBQWMB
+cwsssmqRTFFfFgtbCtGl
+LQPPrCPnMZwqtRMn
+cWTSlJWlcplJdDTdGdpDlGcGgqmtwwZtqRrNRRmRdNZqmgNq
+GSJcJSjsjTpsvWGWBHLLvVVBBBrFrzVz
+NVPCSPMNDSNFVSWCsJJJmpGmZZGLLcpZLHGGtsHt
+fwzlBBqghqvzqqlDrHbpHjZHmGZbLZrHLb
+dnBgnDqQvwRnSnnFMFMP
+BCbPsFFwCRHmDSBmWnvDDj
+phhZVzdpVfQZphhZpRhSVnjmrcvvnrWtDrvWDS
+TfQJMfLphMhJdfdzpQJRTPbwHHNlgbGwsTGgCP
+ttWLlnnvnNnBBtlTqWlpvpndQdZsQQFssFDdsRFdVdRNFQ
+jSgrScrbGZSGrrCGsFVMssFsPPFcDDMV
+bzSmJbfCZCbzLwllflwqtvvw
+zmFTJwFLPmzLztmjDzTJwfNrdFNrFppBSNRGNGdbrpBR
+gqlhWQgsZMsvqMlMMvsvqsNlLbcdppbrRpdbbcSrrbbr
+vssCgVgCsggZQZCgsnsqWgWvfJPDLwffwTPPmzTnjTPmPmwJ
+SpcRTPQLBLWpNNzjmmwwwRrR
+tGlfvGhfnbDlbqlChnfFMrwsmwNssTMHMHjFwv
+ZlhtCtffCdWcZWZVVT
+jTTCcWHWJNgCGTzTmnzrmnGn
+BwRRbFvtvvQmJJFMpMJr
+ZBBwLvqbBZsRsbVsZSqbcZdJjHHjhfPCJfJfHhgc
+VrnDSvvrLrfTdTLGfdRp
+zcJzmcFcHGfdGmWTVd
+tHsMhwPVctccHFHFcbSDbbPjnNbBnbvBQB
+QttWQwLTnLnWTtnffnLQSBFVjNvBjBFNgMdCsVWsjv
+pDqcmmRPHqgVBddjvN
+DcclzbcbPbJLnNTfnw
+plRcpsZDGlGZvWvMCNcLtttq
+SrfrwSjSVrSjwbmSrHzmHJCQQPQzqttNNQJMzJtqMW
+wSHVnfHfWwwHWFVfSnfgmmRsslFZZDBBGZsZsDTdGRTp
+qSFQSgQNgQBrBHHcrW
+VTmjVJLTwlTmwTVmsMJMVlJmPvcbvvbCBbGBPjGvBbBGWcbb
+DnJTZwmnZRhnpqNdWt
+dTVHjZLLZDVCfVHtLDDjQbscjWbSJMJPjsbWWb
+FnqrnmzzFllmsWwtsFtQMMFc
+lmqzzzngGmlNNBqGllzlBNRvptHHpTCHpDLpgDZdgvHvDD
+sdRZQbCfZTSTdlfTZCffccWPHPPcPPwLwctRnLWn
+BBJDzFVgCDrCJrqDJJhqJVVMLPHwcctFwcWHHGLcwGwGHnWc
+ghpJgqqjCZbQdZpd
+tbcpzbHSszcHBgqHGZgJJJhhww
+jfvdvRTffQQrrFCRFTnGwJRqNRZVpJGZLZggLh
+nQTjTnMndlTdQFMvnrClCnpzmzDtbbmBbcPSzzlmmtzP
+BqBqTCSTcqHsJHHM
+WWPGVPLtzVgWtjWPGzVjzVGcbDhPsRbDcsbJwNRswRDRss
+VQfWjfLFGWLjdFfVzTZZpJTpnmlTrSQlBl
+jLNsZjqSHCsGdsmpsm
+MvnVFzWMwMVWzfnVDwfBMfnnrCtdtPmPlRrdrJCJrtPDrrPD
+zznfFWwMfMfFMwVTMQFnQjhjgjSZhCNbLSTcHHgbbC
+GGtssttVmvnnGNMQrrVzgwVrCWMz
+FdhfhhcCDhHLfzclZMcrwcQMZM
+HHqqCBhHSSpdmjGqmGjtjtjj
+bbQLtGMQQtQRQtrDtGprrrbCqwplZhhqSqmdwvdzqqqhSmpS
+FsJjJBfnsJcFcFfjVPjWBzldqhqnlZZZzzhmnSvSnm
+JPcFfFWjFHJVVsVjPVscsDlLNRHGDbLRMRCDNrCGbG
+JdMdlMRJnTwdvcjv
+CDLHbNSzzLFgHvnTjrswBNBTNT
+QgbvzSFQmZQPQQRW
+NTBrNzrpjjjCwGbB
+FRbQlcvFvcRQQlRsMlRRRZjwCqMwjmjwJZdLJmjCZC
+cVPPQcvlWDNhrbPz
+VdbVtbbZJdtJVVdDVZmTLqqTSQvNLjjDShhvSG
+zplpnBnFpnrrlghGNpLNqHvqvjNj
+cWncllnlPFWzcMwtWWtsVLVRmJWCds
+ShLSTnZnTSttTSbLQdfSZTMwcDHwwcHnJvDHnlnlclMM
+NmPMsssRrVwjDclHJwwR
+gNNMWGzNmqGdtfZTbGGb
+sWNNlRHnmJtmntJt
+brbbBTbbFbCbqqGgBTrCfmQVVZfSSQQSVtJZSrVZ
+bbFqvbDvvGGLGbCCtBGDLbLlcPNHhhccPNcdPPchlsdR
+DCFvDvnCnNfMBmMMslDZML
+SQQQJHwpSgJSJHQWSWHqJWWbmcBBBLLTsmhhTcZbMhmlshcb
+RJRgpJHssgwSQHRqsQPGGjjtNCrrFvvnFjjPrP
+mThmsgjzTPjMpcvtWP
+GNNBVqVGNZbbNbNqqZQVNVNbWcpdtMCcpCtMWCdCPpQccmpp
+VSmNrmmbBfZVlsrssrLTRhRhTn
+TdmCvLDCpTRNTdFbbWnnSWCfhjbbzn
+GrrMsPVGcQHBGMbhjjSgWfHHDbjb
+BPBVqqrQPsQqwrrmmmJdRLDDqFRplT
+fpDDJljDlCfDTjprjrfbddWthCSCtdPPQFhSSSWW
+HsLZgMGbgBBsNzMvGbdVtVQzFRQSthhFPdtP
+sMBmGBmbNvLHGMnrDppTcJmcjpqljf
+ptSpSJQqpbNGGDDhcMWrlNHcZZWWls
+zRLRRRjvvgjHMMsMpWpc
+vmCPLCgwvwdnCzmvLbpTbVQqJJPbJPpTVq
+TJCfhhJVFffrJJQQllNWcvWhwvWD
+GPSGjjpLslBbpLpLqqqPDvdwvwvNzQWGzDDNdzGN
+msbRjbpPqsRpHnlZrmJlnVHT
+GGfFsCCTvGDsfTTrhsCMMzptZJMdpdgtrpdMcV
+LBlwBHPSqjwwlVggHpnMZcVHMt
+ZlZZlBbRPGGTGfmRsD
+CtCjbVvzQQZTWVdd
+MlSqWlmsmGBSHJHTDFHZ
+pcqsmsplwsqclwRtRWgtRnPPvb
+zCrzCrsdjrhGDCFqGDjRRPtpWfQQcpfQZcCZPp
+VSVwVMgLHHLTwMDTMMVnbWPRZQRcRQPptWnpbZcb
+MNBBBlSMvLVwTlVTFdNdhNhFsqsGDrzm
+rBLWTwTThWwVVDTwHBsZZWppvpGtpptppmRvFFFMFMfL
+qPPNCCbqcbcNqbqQjjJQqzjRpptmlpMGmMlJtftmtFHpMt
+QnCgzzQbbQqPcPQnncbdQdnVTwDssZgrShBTVgZZsBSDHT
+PFGJFqnfqmPgFJQPWdbLdpDRhbphWjDm
+rclNHvcrzCNwrWRprjdMMMph
+wsZHwZNvRRQsQqBV
+LqlGCPlPLTCPqqQlpqLlWfBfWgcHNRJRfWNsncGH
+VVtdwVtDDdVmhrdwSBmjbdzNHgfgJnNnsSnHsNffHgRsgR
+wVzhbjmDbDrwjdbztFDDthMCvqPppZQBQLZQTqTvFTvZ
+BnQnQFwRmRwmwdBSFDFnmSDVLCJTCTppVVmGLVTCLcgVpC
+ZlWvhvZjNrbNvqjNhlfPfqjCGHrsspggTpVLpsJCpcJVgg
+vPzNvqjWhqFzGSnRGMDG
+wZnMZzzZZchDRtVsqtCtwV
+WmWpWWmPPWrmrmBmWrTlTFPNVqVCRSDCQHcqVTtTqsSDSTSD
+PrppdFlWWlfrWmpWFffrdcGjJJGggnnhZGdLLgGGndvz
+FShHNmNhRhNJmBnQBQJrmP
+VTgzDTjwfffwzDvwlcczzVSJbQlBQSWBWCnPJPbJWWbC
+tzSVtzvSvGSRZqqFMNtpRR
+hPZhGDZpnCGtDhznjmLmdJffdNzJ
+glwsSrQwBvLdgLzdcj
+QsRbHllzzlHwHlBszWlTBFbpDPMhbPDVGpGFpPtFPp
+SRjStRDctgDSBzLvPvNrDhmPLr
+QqTHGTPJmmHmhNmH
+TGQZsTqFnQZCJTPsnJnZQMjVRBVtcVRSVRBlwccSCtBS
+bbsNsvsvnNPTRRllbblLqhtQCqQSLCGGHSqHNC
+wFpzFgqVzqVJWFDwqJDmSBBmHBHhShLQhCGSBCGH
+MJVpFMqgwMqRRbZsMbZMrP
+PPdDhvNDQdmgQPZmQVHHtHGGWVGbffWGvs
+MMLCTRRLlLclTLRMRLCwMLHWVctbVVHWWWFfVjVGsFWW
+MRSMMlpTJRqClBCRqBDnzqgQPnqgznZPZqbP
+MrMNPNNpjvdprWtrpMsthqBfqlnfqcGhVBqFRcnqFG
+QbDgSSQbgSDDmDVmlqSCRllRcFqnqfBl
+QVJbVmwwDQbzVTgbppNJNMWNjNNPrdpM
+WwJJNbtHfpLpVgZZPVFhZh
+vmmqlDvRvRfqBSrlzmmMjRBhcVhQVZhVghCQQQQTcTrPTP
+jSqMmqRzMDDjvqlBqsBMBmmwGNJwJnwLNfbGwddswnJtJH
+RLgRmRggbvbzzPmmRNmzsQWFtSGNtwSNQnntFwnnCw
+pDBrBHpHhlldphHBHhJVFSLnWWFJttCtQSttSS
+hfHrpphHBppfTvmzgMmbLbgf
\ No newline at end of file
diff --git a/input/day3_example.txt b/input/day3_example.txt
new file mode 100644
index 0000000..9919ffa
--- /dev/null
+++ b/input/day3_example.txt
@@ -0,0 +1,6 @@
+vJrwpWtwJgWrhcsFMMfFFhFp
+jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
+PmmdzqPrVvPwwTWBwg
+wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
+ttgJtRGJQctTZtZT
+CrZsJsPPZsGzwwsLwLmpwMDw
\ No newline at end of file
diff --git a/src/day3.rs b/src/day3.rs
new file mode 100644
index 0000000..bc430ed
--- /dev/null
+++ b/src/day3.rs
@@ -0,0 +1,127 @@
+use crate::day_solver::DaySolver;
+use std::fmt;
+use std::fmt::Formatter;
+
+use super::util;
+
+struct Bag {
+ left: Vec,
+ right: Vec,
+}
+
+impl fmt::Display for Bag {
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "{} and {}",
+ self.left.iter().cloned().collect::(),
+ self.right.iter().cloned().collect::()
+ )
+ }
+}
+
+const POW_MASK: [u64; 6] = [
+ 0xAAAAAAAAAAAAAAAAu64,
+ 0xCCCCCCCCCCCCCCCCu64,
+ 0xF0F0F0F0F0F0F0F0u64,
+ 0xFF00FF00FF00FF00u64,
+ 0xFFFF0000FFFF0000u64,
+ 0xFFFFFFFF00000000u64,
+];
+
+impl Bag {
+ fn priority(c: char) -> u8 {
+ return if c >= 'a' && c <= 'z' {
+ c as u8 - 'a' as u8 + 1
+ } else {
+ c as u8 - 'A' as u8 + 27
+ };
+ }
+
+ fn find_duplicate_priority(&self) -> u8 {
+ let left_mask = Bag::build_mask(&self.left, 0);
+ let right_mask = Bag::build_mask(&self.right, 0);
+
+ return Bag::match_masks(left_mask, right_mask);
+ }
+
+ fn build_full_mask(&self) -> u64 {
+ return Bag::build_mask(&self.right, Bag::build_mask(&self.left, 0));
+ }
+
+ fn build_mask(chars: &Vec, initial: u64) -> u64 {
+ let mut mask = initial;
+ for c in chars {
+ mask = mask | (1 << Bag::priority(c.to_owned()));
+ }
+ mask
+ }
+
+ fn match_masks(mask1: u64, mask2: u64) -> u8 {
+ Bag::find_set_bit(mask1 & mask2)
+ }
+
+ fn find_set_bit(v: u64) -> u8 {
+ let mut r: u8 = 0;
+ let mut i: u8 = 0;
+ for m in POW_MASK {
+ if v & m != 0 {
+ r |= 1 << i;
+ }
+ i += 1;
+ }
+ // println!("log2 {} = {}", v, r);
+ r
+ }
+}
+
+pub struct Day3 {
+ bags: Vec,
+}
+
+impl Day3 {
+ pub fn create() -> Self {
+ // let lines = util::read_file("input/day3_example.txt");
+ let lines = util::read_file("input/day3.txt");
+
+ // Put the input into the day struct
+ return Day3 {
+ bags: lines
+ .iter()
+ .map(|s| {
+ let (left_str, right_str) = s.split_at(s.len() / 2);
+ assert_eq!(left_str.len(), right_str.len());
+ Bag {
+ left: left_str.chars().collect(),
+ right: right_str.chars().collect(),
+ }
+ })
+ .collect(),
+ };
+ }
+}
+
+impl DaySolver for Day3 {
+ fn solve_part1(&mut self) -> String {
+ self.bags
+ .iter()
+ .map(|b| b.find_duplicate_priority() as u64)
+ .sum::()
+ .to_string()
+ }
+
+ fn solve_part2(&mut self) -> String {
+ return self
+ .bags
+ .chunks(3)
+ .map(|bags| {
+ Bag::find_set_bit(
+ bags[0].build_full_mask()
+ & bags[1].build_full_mask()
+ & bags[2].build_full_mask(),
+ ) as u64
+ })
+ .sum::()
+ .to_string();
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index fd136b1..55f4059 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,12 +1,14 @@
use std::time::Instant;
use crate::day1::Day1;
use crate::day2::Day2;
+use crate::day3::Day3;
use crate::day_solver::DaySolver;
mod util;
mod day1;
mod day_solver;
mod day2;
+mod day3;
const MAX_DAY: u8 = 2;
const DEFAULT_BENCHMARK_AMOUNT: u32 = 100;
@@ -74,6 +76,7 @@ fn build_day_solver(day: u8) -> Option> {
match day {
1 => Some(Box::new(Day1::create())),
2 => Some(Box::new(Day2::create())),
+ 3 => Some(Box::new(Day3::create())),
_ => None
}
}