From 2023211beb3858cbffc95d9651175f4044a5b9d6 Mon Sep 17 00:00:00 2001 From: Jens Kadenbach Date: Mon, 5 Dec 2022 12:01:00 +0100 Subject: [PATCH] Day 3 --- aoc2022.cabal | 14 ++ package.yaml | 4 + ressources/day03-input | 300 +++++++++++++++++++++++++++++++++++++++++ src/Day2.hs | 2 +- src/Day3.hs | 14 ++ src/Day3/Part1.hs | 30 +++++ src/Day3/Part2.hs | 32 +++++ src/Day3/Shared.hs | 31 +++++ src/Lib.hs | 4 +- test/Day3Spec.hs | 51 +++++++ 10 files changed, 479 insertions(+), 3 deletions(-) create mode 100644 ressources/day03-input create mode 100644 src/Day3.hs create mode 100644 src/Day3/Part1.hs create mode 100644 src/Day3/Part2.hs create mode 100644 src/Day3/Shared.hs create mode 100644 test/Day3Spec.hs diff --git a/aoc2022.cabal b/aoc2022.cabal index 5368e0c..407d72e 100644 --- a/aoc2022.cabal +++ b/aoc2022.cabal @@ -31,6 +31,10 @@ library Day2.Part1 Day2.Part2 Day2.Shared + Day3 + Day3.Part1 + Day3.Part2 + Day3.Shared Lib other-modules: Paths_aoc2022 @@ -40,7 +44,10 @@ library build-depends: QuickCheck , base >=4.7 && <5 + , containers + , heredoc , hspec + , lens , split , text default-language: Haskell2010 @@ -56,7 +63,10 @@ executable aoc2022-exe QuickCheck , aoc2022 , base >=4.7 && <5 + , containers + , heredoc , hspec + , lens , split , text default-language: Haskell2010 @@ -67,6 +77,7 @@ test-suite aoc2022-test other-modules: Day1Spec Day2Spec + Day3Spec Paths_aoc2022 hs-source-dirs: test @@ -75,7 +86,10 @@ test-suite aoc2022-test QuickCheck , aoc2022 , base >=4.7 && <5 + , containers + , heredoc , hspec + , lens , split , text default-language: Haskell2010 diff --git a/package.yaml b/package.yaml index 160f28f..1b8bd5f 100644 --- a/package.yaml +++ b/package.yaml @@ -25,6 +25,10 @@ dependencies: - QuickCheck - text - split +- heredoc +- containers +- split +- lens ghc-options: - -Wall diff --git a/ressources/day03-input b/ressources/day03-input new file mode 100644 index 0000000..02370bf --- /dev/null +++ b/ressources/day03-input @@ -0,0 +1,300 @@ +GwrhJPDJCZFRcwfZWV +LjnQlqNpjjmpmQlLlqNfZRvQcTWcTSTTZcSQcZ +nNqjdspspngnmjmslqmjjjCDGrHPHMGddGCMCGPPPJWC +GwmVZmPWWFFmBbVbZVwmbPsTCnlgQgnQfhlffffZnlQh +DqVDSqqSMzLLDDNSHHLdqSdSllCQjsTlClhlflnTlhjgfgfM +VHJztNLHGtcbvvPG +bjrPrNCtNrjdcCPpptfpTVspDtfTtB +JGQJMJQMmmmZMnnLpLBTpHCD +WJJqWRgWlCJZhZRCQZwdPScdrPNbvzPzwvqz +QNSQNBWQNLjZBNNhLhSNRsTcsrTTVzcwZZZsfrrbwb +tCFtHpppppMldpvpqnMFmMVGrbPcrwbzswrzcccfvTfw +pdmCpgqCdmHHdJVWgSRNJDRVVj +sNrFnvNSzrjQtQjQTj +lcPmcJDLdPDbJPVLljdGGBBThBQTGwTtBw +PDLqmJmpJQfFqfqsCM +BnhctqdnqnRcBnslCJJCMrJrsG +wNDMZpbQwMpCvCGVjlss +WfzNwZFbwZzZmFZbLzNwzzzzcdqgRMTTPdHPTTPMRdcWgRPt +grsrVSFSSdFSDFVFjZZWwpWpZWZplgZZ +mcBPPPBLBfNdLlvvWljWJC +dMcmcRdbRzdVhFthSsTShM +bzvJZMTzTZSHLCCdDzmDcc +hqBqWPFssvshWvvssNqtsHftmfpHfdcdDGHmcpfctL +WvBQgNNNhghTJbJQlJTZlT +chcdwNwdbCbQctCjnnQGHsQspMHMjG +nSSSJqJZzJgWWRfZDJSnqvTTsVvvHVPpHVfpjHMTjP +BZRDRmmrDWSrZWWzWSRNhdnCFwChclFtwbNdtr +lNgmssCtqLwqCCtfsCLHPFhhhmMhVzBDbVzMDMVz +ZnRlQTlJzFQFQFVV +npZJvRRGZSnWvSvrSLglsClfpfcLgNgpHf +tVtqcVqFVtZhcfFtqlgSpmpDSDNPzSzZmNpw +LRGTHqbrHdnGHrTCSSwNDzMDwPMzNwbp +TqWGJrGHCHnTWnhsWcFthFjtfQch +qNnTbwtctvffFcqfrHjMrFjVHRjSjZDZ +dLLzWWPmCmCzGdsLgBLGGBDRMVMHRlrrrZDDZsNMrNNS +PJQWggCzWNWJzGWfchvfTbJvfnnwtf +ghzdgzzdQsdqzzhMNqQzvhgQnRRBWTjWWGTRGWwGTZhwGnBT +fsrfJHbFfDFLVLVFHrWCWrBRZZTGCCjwWZ +HLLllcDPbLPQdPspMNgvMt +fNDJqdPNbtHpCbwpCCCp +RTMRLrzGrMRMRPWnnvSmgCHFCCFmmT +WQsWQjzGWMsGQzWclQtVBJfBftNdtqVPfP +gbTCVVmDVFdsgmgrrcfwlwfTfPlcRR +qhQZqQvnQhLQhJnvfPcSwSwlfjGcqjqj +tLNZLZZJJZthpzhMZDCdFmFsmWWmtDDgsw +bqCvLvLppzPzPPvPbFztFtttBNGdGsRggSgGSHDdggHSzNgH +rMQpWfMfrcTjWJhwWHHsSBsRBdSTTNBgSR +VwfmWjwMWwccrWcWpQQFnFtlCqmltFnFLbbZmn +cWqsMWJMzqJJMHsJcqsJqTqjSbLBdfdSbtzLbbLfbSfShfhd +gplGvQmRrCrgZSZtSGZZjhbj +CQmmmmNQRPvjgRClCvmmcVHPqMFMFsWJVqFFcnTJ +QHHqvGwjjWNqvGTQGvTFcGwJRJbszcPtDbJVbtPzVbDptp +MLdrgmSgZZdhdfbLVRpszlRDstRL +gdSgMCSfdMnrghCWGRQvHwvNHjnjvv +RDBZwvZBrMlsvnlb +WdFQqdjWWcHHPrwSPnnSWnSS +mLdqgqHmcjHHjqLHjLppmhfBfgtDtBJZJfVtBZwGZB +CCWRJQnZlHtHtNZRFDcBhrcvhDrJVVDv +dPPSqLzfsqGLSTzfLzLGdLMVVgvBcmgMVwmmDFrVgmBBBr +SFjdTGzqpjdRbNRNnjtnQR +hjNcwBDDwDFcjdFfjtFhtcRsGGgTsGRRRTsGGqZGRq +gbmrLnbzLmvQJnQVVpqZTqzWSCRpqRTsSR +MQMvVMbPQQHrQMnMPldtwNNfgHtlwBhdwj +zwzwpzMfzrBMWfCCZrwzrMJDGGGnNmGNZvgNZsDDsGsG +FbFqSbcSbSHqTjmgGFnJglllsDJm +TbhVdVjqdtqTjVHqjPdthPBBWpCnRfwRPRCfBCCnWR +hlpmbfJJpCSChmJMmrSjTjcSdjTtQQTtTtjF +gqrgsqLzgnBgZGzHBnnsQNNQtjjcNNjjtNFQNcNH +LVRzgGGzzzPCVrJMbPJb +VHrmqFnVdvlzzNrr +PMtwBJPBcPwfbwBJndplLvLdLlgMMzLL +bBZnTwbtnScfQJPJwPTjqGZFsVFjDHHGhhHhVj +cftqScHJrfVfrrRZ +DTTsDvvlBbTGrWBwwsWDBbWdVpZjjZjpVPPGhRRVjVZNRPNN +lsWdWDbrTLBsbdrmdwbMJtmHMQJccFHFnJFqFt +SWNPTPVSWChCSmQQhpppJdFJLpDpgLJmLd +NGGtNtGfHtDpdJdqLB +NcsNGNjHZsZGnzZfnGhQnhPClrVlQPhTVVhl +QDdgMBsNhhMgcWbZdzmWLzFzWH +fRqRJJqGCvrJGjCRRrSJlfPtHzzPmfFbtPtLZZLnmt +VjvwwjlwVGGqJSSqJFccshpgNhQNQTsVgBgT +wvDLDwCbFgSTfTSJJgfB +qsRhmhqchmVhPdfTHJSzpCtJpfPf +hmdhrWrddmhlqCRcwQjDLMQnMFDZnlLl +trMWtlwwMplMZMCZWltDpzBLBnflVLBbHzbBSGlVlL +ghhqJTfmjQjfqqznznnHnBRzBLmn +sQhPQsjjQcQcTsPqZWwwZcFfWrWcrZww +MRVpVCZZTHWVMCHvgNvVvbQSqgQSlg +NFmnrNDDfnjFnndfssmcStvjvQQlvzvllqvwQllj +GGPNmBrFNdcfcGrsGcdmDFhJHMMhHLZJMhpLHCMMMMPJ +DSvDGdGFlGGnDZFdVSZvfPqwnfhpnrqpPNpLPrrh +sWcTjtHCsTmsCNfgMPjpfPhqhP +BtHzBzChzBBvFSDJvVzFJJ +sfsNrsFFBTfjwwtNNWHPVCVWtSCDDCDmmS +zMdhMMZnSccMmmWVWmCPlC +cLSScJZQbcvLhZvnzBwfTjrpNwNrBFffpb +TBrCBgrTngVQBVbhrCtgJJrGssGsMGRGcjMcNjfN +LZdSLvHMFdzFRWsLjcGRWWNJ +pHpzlqPqFPvdBthgMbVPDhgh +SZlnZZvBvvMrcBnllBMZSvhGMtQwFMGztthfwQtMwwPf +HLqsDgNsDLDDDjggHDHszthzFbQGTghPGQPbTfFT +dmLqDqCmFNjJsjHdssFNHDVWZccnRllnVZvRSBZrZlCc +SccnnSGGftShfHSHHhnvbMjvVlCjzbVzzbMMTbCB +gRpppNNQLWqZgPZwNWwwBMBbDlZCTzVTjHMMbBjV +dqNQPQRqrqpPcGtchhdfhHSF +mfDzgnNMMszBtJCpHlrjnFppCdHj +LLRThGGZcbClBQpdWFGl +bSqVTbBbMVMsNmNM +BTTbbLVpfchmjbsj +JSQJHDMHqdNZTZlhFFhCFFrNhNcsrr +tMwJQlwMMlQwDDJtWGLGPpWLLGnTPn +LcVQQCPPLqTzqQTcllTzhnHHfFJRcGHcFfwRGHwJjJ +stdWDDBtVgbpWgZbsNgDNdWFGMnnwHfjHFpfwwMGMMGRjJ +ZWSDtgNdWNBdgsdsNDDsdbDlTzCVSTCqQmSqTQSvhqLVQq +dZbgdZbNtmqttFJtHHzcczMcFszHnsvH +wwpQplQQwqVVjqwPjCGCSMCMcHSHvvzHMzvcsrMc +pfjlQRpPRRLQWtmLNdWdmqqJ +CPTPPmbjmVjVGCvzbjjPrGsnnMpttdtGdncdMccDRd +lhlHzQSHwzhJLwgWgpMDMMsDdcDQMDMMns +BHZghLWwSFBJJBFvzmbfjNZvZmCvmb +PBGcvvcRwpwNcZcNPpPNcTHGdMtrCWrCCtCLWMtWgbVdMV +fmsJjnqmmfsjQJnjFzSFSqsqgWrtMttZgMWVMbbVMdbSrLtr +qQjjZFmfjZhZmwcvPhNpTNBTwN +HHlVVmmsbbqMsJmVzGSBMSrQQrRrGvvnDn +PZcphZPPZPhjcpdWgPZhRPfcDSrtDBSGNvtggrQtnvQNGNDn +dcWwFjpcPhRcCpjwdCPLzHblJbLbzmsmbTwzqH +hRfzTTfRrTGzhGWTrRrbfcQZQSttWtwddJtvdJJvWSHq +npjnDjFlpDnFFNMjljCnFMQtHHtqNHNQJwwZZqstNwJJ +DCjpLjjpVLDMDpVLDLQbbhzBhVrcVgVGQQcz +LncLBLjCSNrNrNpCLQBBBGwqQwzlzmggvqRqgllmzwtv +fMZPHhhHfthMdbRgHJzmVqlvwlwg +hfsPbZFPPDsfGLcBtSFNBSjL +MlZmszBMJBHrMBMbShwSFpbZSZfwwb +TCLCcPNGTgTPNGWtCtcWtPcSsRfRjRwjFbfpNFDjwsFspw +nVtqqsWsdHzJHqmM +RCrhSmWrmrvmrvhMvRNrRCzCJcQQbPtsMZVGJJtsZssPcQcZ +jLFBGqLFpqBLgZVbPbsLJQcbsV +HjDljGFwrRHRRTrS +GZZhnrwZBwNjRPRCbCbn +fJtJJpsVfpgNTbVNFTRP +JJcpLJfLdcWLdplwRdQMBvSqwRhvrG +wmZDPlRlCDwglgsHtsBvdBHLFLSddr +VbVMnMftfVjQWFFHdMBdBFMFHr +zfjtnGqqnjGqfjPcDPlZPlRDzccw +BRjhfhvRgnTMlFDDJfZzZFFQDZ +qLdqcNttwwcwwSPSpqLNmrwmrZsGzzDFZGZFzVssrzJGnsQG +wSNdHScScdmwHSpdNcmmtLMvChRHbvBMTBnCBBvhvlCh +JgWTPfFPgCPPlCntQSGghHvQnSdQ +BzvMZvLVQpdQpSZh +RwVVjRDVcRDNDTlJPqTv +SGHSrBBRPhPPHQcTccQTRRQjTN +vvWvspCbzWVWVrWdjj +wZpDzCDgDbCZJZzJGlrlqPqnqPllmH +FCncCrDWMLCbjMCcFpLdzZfmZzwwWzdzNRZdWB +sqsgTqHSqllNldMwlZzJ +MtHPTgQhvhhqcrDrrDpjLCQc +pPPvmPWSClqqPvqCmSwqmgGBWDjhGLHfjhDLJGjBBhNj +zrbdcdMndcRdTrsMcbTRdzRFVHjLjDjNLNHsfDhNGjhJNhDj +RdFFcnTdZcTrRRdFFbZtwQCPQglvPlwJwQPZSqqP +wlmbvwmvQvWQsvmbsSsQbswlRCNPfCTcTRVCffPtTSCPNRVP +FhJJJFgFqJGBtDpJhTTcVcVhdcCdCdTV +GDFtgLFnqqDGqGZsQvsllrjbLjbrvw +lnFSnJvmgvLlfnJpgnsjnjgfDQWqCJqZdDtDCtCtCdDrtDDQ +VTBBMPFcNNtMZDMW +VTGbzGGhTbTGHwVPvvFnfpvjgHnfjppp +JJwHqvlvDjljDwJFlZjZDwHNNsMqhNpphNpmNVzpsnsnRV +mTLgrLLcLSTTTdmPPfrrrnssNhRNWhgngzMWzgzVnM +SmTfdSBbBJbtjJvljl +bPNLwTCLLQQqtJsf +zdnnZVlWWGGRWGWdgdSStQMqJSMRptftbsMf +FWbvgvZZZZgnTmwrrhrFPCrP +HcGzzszFGllHWHbZspHbHGsHTwwrTrLLCNjSZwNjNjjCCNLj +PBJMJQJDDDnDggRhMdRSLmjTmTwwVjVQSvvwvC +RqfdhgDPDJDqJJnBdfzWWHcstslcbtStfHzl +zvRRlCqrdNdZcZpjBpVwjsmjsm +fgbTDqbhGfDnLDnLLqLhFmsHpTPHjHppppBwpwws +nhnnnDDngDtDbfSbDnGhhgRlNvQdQqNvQvtcQQNJRNJN +cZbCcbbScCbcmPGjPfSBQQSq +lnMnnVsMVvmzzGMDzPDf +LhrTsTTglrnsrrWWVvlwTnNtcpZRCmhtbCZFdttZbRCp +NWrFPZVWNVrvvrhtnNdddtpldmjm +DcBQBDsJbCwQnbtdzmjjjljbpjbz +qCDcGsDJGCcBDBcswJnBJQDfWfqgvZSvgZPfrVSWvPvZZZ +vcsdHdGtHtMHMFtVsddsWCcbppZwjScLpWhbjRWR +NTwrnzJrgTPrDwnlphRpjSpWbJJLLZWj +TlDPfPnzzlzTBzzvQFFBHMtVtqBqqw +NHnqqfZvZBNHHvgfrSlJrJCSllJRVrCn +TDTdhLMWjFcddMJPSSPJRmlCPz +bljWFdLLTDLtdFtLlwZvqfbgwwHfwqHNvw +BRRjhRQndRNVqBjRVhFLccjpwMmLmjHmgFHH +fZJfJvzPPWtWWlltZzZPpcgFMsFFwwFdpHdgwtdw +PCrdrzzfWCPdvSlqTqNSDnnQVVQQGT +DjbfBMDSfBljBsLSjSZbzrGtPtMCPtVPvvqrzqzG +mWdJWcppcNTdpppjzjRRVrPRpq +QncmnHwmdTmwQcmjNTfgfhlBShshhsffnfbB +WGDsMJsrjHCWtDMGDDVQqSvZqfSJzSnvnvvv +LgLFLFBFLVVzfBzMqZ +lgmFcwLhNcwdwwMLwhmcRDjNpCWRsWRspGGssHCp +PnPzNccnjFfvCvhbSBVcWqdhSVhV +psGMDQJDDDJgQNDHHJbwqwBsVqqZVWBBhBdd +DlDJDQGptpgpGDfTRnrTrFPnNTlf +MSSSMLLmFHcDScSq +ppZnCsbjPZpnnJcbRDmzHJqRRD +pmNmnGnQNnClZGMVMdBGrMgVWg +lsTTGcQzBcljCcQzGcGjGptttpmvSJtmggtwwswwtS +qZRnrhMbRVdhZRhhdnnVRPbmwSNwNNHtmJBvwpvtwNSvSb +VnMrqrrdqhZrnrBLLlzzlQjQjLfTcGfFDF +dJJTlHvhZqZlQTJnSgQDzgsSbScsSBzc +RRNtGjCCpRPPpRtjfrttRzmbscLsLZLgcsbmLzSGLB +wfNttfNrtWwPNNFfRtpfrdJMTTTZTMZTTVTlVwTlvM +PQTGLmdNTgPmGgNNdCPLQlrMqBrDzMCMFqDqFqjVCBCD +hhRwwvpSFmzDrmFh +vwwZfSfsmvtSspnZLLLdLGWPTGTQtTWG +pMcWzWFvWhFpPMWzvvhpdprHTZTQrHrQdZTJdfTgQTnJ +CGbjBbNjjDmRHJDgrTVVZg +NNttGlGqNLsbtlhMFMFcMLwMvvZz +CGSCBNCQBtBCQttBwCGtGtQrqrLrJqZHLHbqHvLDHLrq +nVVhPMfVdfVPbfqLLqgDDqPvgZsv +cpVncbfnhFcBltTplpmTBC +MrdcdStbMnddtRBdqMnFmbqGCwqCVHVsNHwPfGVPqsCsCs +DBLllzWWQQzlZVVVCsGWHfsH +JQphjTgBjlLgjjpTpLgvTjQnnnSJJRRFmdbRRSdMRtmdMc +QbRZMSWMblwLsgpwZzqZ +BFncBrfcdNrrnVrNjsFzFTJpJLGJsGqLTp +VjhDDBdrfdhQMllzHmPQMh +LdVVjFVFbpVGRQGllG +cNMcJNHzJWJtCWHNJHcHczWpGmmhMQmBBqrlRhBmpGpGBQ +JZzTTtCZtHCJnNnNwPfbFpnfdDdLdnvP +TpMlrWTTddjmlmDmgQgRtw +MNNVMSsVSNSnNVMFLDqwtGgRRtGbgFRwtR +CCLSCPSCZZHVCfZscBJJhPphpdpprdhjJM +gSMSHJHsMMpzRgHzsRMPPSzsPhtZtZdqdDqQDhdCdZmQldht +FCcCnrGcNTfvvtqqfvlflQ +TrTrWNWwrTJLMzJCzWLL +TpTzwMrfbrpFpMbFrrrzbPSdZmtSZRTlTZRlmdCVlCtJ +vqvWgqDJQJsQCVtZgdZdRRGd +vsvLJLchWBcqnvczwjLfzPjfrjzPrz +zqzbqCFZgmzzmNmf +vpRWSbRVbVWddVpwvwdRSwnSNgLHsnfNgMmgMLMmnrns +DwWVpJRlpdbpRDWdGJGcGlhFtPPCqCCBFqZPQttlqFBq +wQRlwtBJBDwttJdGvLfBvHLLfTLz +MMmNZcMrcMFnRHzfjjvvHfvc +FggpbFnhrNNrrMrMbMbnhQVJVhstJwqWCVCRsQJQ +DQbCGblQlpQFQlHjCbjwDQQMggNmJmgnnpRBngfZmNgJMf +zvhWccWVdWBchdssPrrWZZZfmsmmmgsnZZJRsRTf +zBdtqPccWPHFCqCCqljq +ttrbRMmgtHgfmHSfBpLfnBBZBppB +CVTJDCCNPwCPDwcqzmddQZdTQdnLBQThWp +zwFDjwDJJPzjzVNcVJwCcbRHGmbbMrFHgHvrsgbblG +gZjjwHqHCzrMZVVR +hhzcdTzPrVhVCGMb +fPcmLPNffsccJDdNDjBnpwzmHqgWjHwwvg +SJQFSvQBlzbSCgdPPddPPPSN +pcrjcWLwwcHcgPNgTPLMNTCB +pRsjsWRnrpHRmrBrHrjlbJFvvzQFnzQblQDDbJ +VjQVMQPVMfVPPbGPHHbGJD +pcqSttltsbDGddsCJG +TSchqLtTLFhgQbMMQMrr +trqzMRwNTtDzLPJQgWmjmjrf +lbBQdpZbsmhGmZhmmG +llVbpCplvvHBBHpnRDcDRRqnRRQnFRzT +SLSSFFmzLShsVSSHnLnrJdbnRdZZbrRw +qCfWBftpNWNNlqvTpwrRbGGCnwGmgRJGZn +NcTBNpvWvBWpMftNffpqWlTpmzPDQPSzFVMsFQVhHsjHszss +VtJtNBRBGDpdpNbC +QgLncnttvFcwwhLvFjSGsSbmmQCSDdpCmpdG +vLgjLhhrctMvLFFjLtMTLMgfPZqBZPZzJBBfWZZPRZZTRV +mJzDJJpJBvfsGMQnBM +CwPWCLRRWwRqwPqhPsrZrnrlhhQrMTrvZl +dCdLLSPRLSqWqVSLqLjgJDzDmtbngFVtJtzz +mtgWtMWrqjzQTTjghwwfczlNJdlcJnlc +FvRsDPPFGRBFvvslwDnTlcTTdwndlh +SGBZRBTsFGBRvLpvSCmgQWQjgggMrQjmmSmW +GcsRrQhrVVjhRcWlnDFGGmvntDWZ +TPbSgJJgBSCbCTbLHMCMTTZdFHvtZlWZDZFzmzZHZmmF +gBCMCSpbPMMPjcjqQQpqQprv +nZJcnZwvwzvTTTVtpDFnHH +DQPBqGGGdMdTRHRBpNgFNR +dCGPfhPWQdWWWCWShWPqrChWLLwLswjcvSJbvbLjJLbzJbJD +QrBQtdtrQBrdtFHPrdQBDvGhLGnPnCWnmpDmLpmD +NjlRJRlNzJJVbSSRVZwwJcmpWDGCWnbchnLCCmnWCG +llSJzsZzMMlsSZjSjZwJNQqtHHdBFsqdfTHhqFftQB +zdTJFHTdDBzrNdMnhNnNdM +ZlLZZcLtVtcWtGjtzLjLZjCrnVNrnRbrQQbQSRVrRnSNqS +lZtGtCvjZPCGCctPpsDDBzTHFmPmFszD +mQSMvdMQtQdZhQrPWCPqPQrN +RwjwnZGzJFTZgzggzJDDwJnCPPhNNqPrLhrGNcWcWNPqCq +ZTzDfnwFzTngTwJvfSlMtMMlmsHmHt +lZlmFRVZWmgQWhRsRpJsCJpJct +PTbPTGTGwwGrbdfjNNZJvcCsCZtvpTsh +bGdBBqGrdBPjDMzzVFZgqQzFFL +szvsmLvppPPtzGLGWpVdTSHTNgjHQRmHTgSH +FnBMBNZwZNcnDZMcnZlZgwgdQTTHjVJjHHVRQHJj +DnZrFCMZMNffrLPbLsfW +rJvmnBgnrCrGRSGNQR +hthjNfhwctwpjTLtVLjTGSpldSCGSPdlPSRzSqSz +TVcTfHNFcwtjMhTvgbHZsBbWmmZbnH +WsQgstQmvQJnssWsWPzhRzhBjZBSBRZSnj +qwCNqFwDrrlDrFPvRhTSPPzLRz +bppqwppCddlvfbDNVgmMmtMfVVmfmVWW diff --git a/src/Day2.hs b/src/Day2.hs index 3e96aa6..950f3a5 100644 --- a/src/Day2.hs +++ b/src/Day2.hs @@ -8,7 +8,7 @@ import Day2.Part2 day2 :: IO () day2 = do input <- readFile "ressources/day02-input" - putStrLn "Day1" + putStrLn "Day2" let score1 = day2_1 input putStrLn ("Score of all games: " ++ show score1) let score2 = day2_2 input diff --git a/src/Day3.hs b/src/Day3.hs new file mode 100644 index 0000000..559128c --- /dev/null +++ b/src/Day3.hs @@ -0,0 +1,14 @@ +module Day3 (day3) where + +import Day3.Part1 (rearrangementPriority) +import Day3.Part2 (sumOfBadgePriorities) + +day3 :: IO () +day3 = do + input <- readFile "ressources/day03-input" + putStrLn "Day3" + let score1 = rearrangementPriority input + putStrLn ("Sum of rearrangement priorities " ++ show score1) + let score2 = sumOfBadgePriorities input + putStrLn ("Sum of badge priorities " ++ show score2) + return () diff --git a/src/Day3/Part1.hs b/src/Day3/Part1.hs new file mode 100644 index 0000000..6108c9c --- /dev/null +++ b/src/Day3/Part1.hs @@ -0,0 +1,30 @@ +module Day3.Part1 ( + splitContents, + itemsInBoth, + itemPriority, + priority, + rearrangementPriority, +) +where + +import qualified Data.Set as Set +import Day3.Shared + + +splitContents :: Contents -> (Contents, Contents) +splitContents c = splitAt middle c + where + middle = length c `div` 2 + +itemsInBoth :: Contents -> Contents +itemsInBoth cs = Set.toList $ leftSet `Set.intersection` rightSet + where + (left, right) = splitContents cs + leftSet = Set.fromList left + rightSet = Set.fromList right + +rearrangementPriority :: String -> Int +rearrangementPriority input = sum priorities + where + contents = lines input + priorities = map (priority . itemsInBoth) contents diff --git a/src/Day3/Part2.hs b/src/Day3/Part2.hs new file mode 100644 index 0000000..31c0a43 --- /dev/null +++ b/src/Day3/Part2.hs @@ -0,0 +1,32 @@ +module Day3.Part2 ( + splitIntoGroups, + badgeOfGroup, + sumOfBadgePriorities, +) +where + +import Day3.Shared +import Data.List.Split +import qualified Data.Set as Set +import Control.Lens + +type Group = (Contents, Contents, Contents) +type Badge = Char + +splitIntoGroups :: String -> [Group] +splitIntoGroups = map asTriple . chunksOf 3 . lines + +asTriple :: [Contents] -> Group +asTriple ls = (head ls, ls !! 1, ls !! 2) + +badgeOfGroup :: Group -> Badge +badgeOfGroup g = inAll + where + (a, b, c) = over each Set.fromList g + inAll = head . Set.elems $ a `Set.intersection` b `Set.intersection` c + +sumOfBadgePriorities :: String -> Int +sumOfBadgePriorities input = maybeSum $ map itemPriority badges + where + badges = map badgeOfGroup $ splitIntoGroups input + \ No newline at end of file diff --git a/src/Day3/Shared.hs b/src/Day3/Shared.hs new file mode 100644 index 0000000..ec24c4e --- /dev/null +++ b/src/Day3/Shared.hs @@ -0,0 +1,31 @@ +module Day3.Shared ( + Contents, + Item, + itemPriority, + priority, + maybeSum + ) + where +import qualified Data.Map as Map + +type Contents = String +type Item = Char + + + +itemPriority :: Item -> Maybe Int +itemPriority = flip Map.lookup itemMap + where + itemMap = Map.fromList $ (['a' .. 'z'] ++ ['A' .. 'Z']) `zip` [1 .. 52] + +addMaybe :: Int -> Maybe Int -> Int +addMaybe acc Nothing = acc +addMaybe acc (Just y) = acc + y + +maybeSum :: [Maybe Int] -> Int +maybeSum = foldl addMaybe 0 + +priority :: Contents -> Int +priority cs = maybeSum prioList + where + prioList = map itemPriority cs diff --git a/src/Lib.hs b/src/Lib.hs index 1a619a9..4a2a3d3 100644 --- a/src/Lib.hs +++ b/src/Lib.hs @@ -2,8 +2,8 @@ module Lib ( someFunc ) where -import Day2 +import Day3 someFunc :: IO () -someFunc = day2 +someFunc = day3 diff --git a/test/Day3Spec.hs b/test/Day3Spec.hs new file mode 100644 index 0000000..21502ae --- /dev/null +++ b/test/Day3Spec.hs @@ -0,0 +1,51 @@ +{-# LANGUAGE QuasiQuotes #-} +module Day3Spec (spec) where + +import Test.Hspec +import Text.Heredoc +import Day3.Part1 +import Day3.Part2 + +inputPart1 :: String +inputPart1 = [str|vJrwpWtwJgWrhcsFMMfFFhFp + |jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL + |PmmdzqPrVvPwwTWBwg + |wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn + |ttgJtRGJQctTZtZT + |CrZsJsPPZsGzwwsLwLmpwMDw + |] + +inputPart2 :: String +inputPart2 = [str|vJrwpWtwJgWrhcsFMMfFFhFp + |jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL + |PmmdzqPrVvPwwTWBwg + |wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn + |ttgJtRGJQctTZtZT + |CrZsJsPPZsGzwwsLwLmpwMDw + |] + +spec :: Spec +spec = + describe "Day2" $ do + describe "Part1" $ do + it "can determine Rucksack compartment contents" $ do + splitContents simpleContents `shouldBe` ("abc", "dec") + it "can find items that are in both compartments" $ do + itemsInBoth simpleContents `shouldBe` "c" + it "determines item priority" $ do + itemPriority 'a' `shouldBe` Just 1 + it "determines priority of contents" $ do + priority "abc" `shouldBe` 1 + 2 + 3 + it "determines rearangement priority" $ do + rearrangementPriority inputPart1 `shouldBe` 157 + describe "Part2" $ do + it "can split into groups" $ do + length groups `shouldBe` 2 + it "can determine the badge of each group" $ do + map badgeOfGroup groups `shouldBe` "rZ" + it "determine the sum of badge priorities" $ do + sumOfBadgePriorities inputPart2 `shouldBe` 70 + where + simpleContents = "abcdec" + groups = splitIntoGroups inputPart2 +