From d24e400dc4e5c6271c5e8dc07fa37158856bb24f Mon Sep 17 00:00:00 2001 From: Dendy Date: Sat, 3 Dec 2022 09:27:12 +0100 Subject: [PATCH] Day 3 --- 3/1-2.zig | 115 ++++++++++++++++++++ 3/input.asc | 300 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 415 insertions(+) create mode 100644 3/1-2.zig create mode 100644 3/input.asc diff --git a/3/1-2.zig b/3/1-2.zig new file mode 100644 index 0000000..a90c464 --- /dev/null +++ b/3/1-2.zig @@ -0,0 +1,115 @@ +const std = @import("std"); + +// Wanted to implement both in a single modular and expansible way, so this is that. + +const string = []const u8; // to simplify a bit +const Iterator = std.mem.SplitIterator(u8); +const stepFnType = *const fn (*Iterator, []string) ?[]string; + +pub fn main() void { + const input = @embedFile("input.asc"); + + // The fundamental difference lies in the way of processing the file, + // so we abstract that into a function to be able to pass its pointer. + std.debug.print("Part 1: {}\n", .{sumPriorities(input, stepInline, 2)}); + std.debug.print("Part 2: {}\n", .{sumPriorities(input, stepInterline, 3)}); +} + +fn sumPriorities(input: string, stepFn: stepFnType, comptime amount: usize) usize { + var totalPriorities: usize = 0; + + var iter = std.mem.split(u8, input, "\n"); + // This buffer is needed to not allocate but it shouldn't be used directly + var _buffer = [_]string{undefined} ** amount; + + // Use the stepper to divide into slices properly + while (stepFn(&iter, &_buffer)) |containers| { + + // If it wasn't found just contine with the next line + const repe = findCommon(u8, containers) orelse continue; + + // Convert to priority as specified + // 'a-z' -> '1-26', 'A-Z' -> '27-52' + const priority = if (repe >= 'a') repe - 'a' + 1 else repe - 'A' + 27; + + totalPriorities += priority; + } + + return totalPriorities; +} + +// Helper to find the common needle in n haystacks +// Returns null if not found +fn findCommon(comptime T: type, haystacks: [][]const T) ?T { + // Why + if (haystacks.len <= 1) unreachable; + + // We need to find a common needle for all of the haystacks. + // Compare each of the characters in the first one with + // the other ones in sequence. + // + // - If a match was found, jump to the next haystack. + // - If a match wasn't found, just to the next needle. + + needle: for (haystacks[0]) |needle| { + // Semaphor to know if something was found when reaching + // the end of loops. + var found: bool = false; + + haystack: for (haystacks[1..]) |haystack| { + found = false; + + for (haystack) |blade| { + if (needle == blade) { + found = true; + break; + } + } + + if (!found) { + // We didn't find the needle, try with another one + continue :needle; + } else { + // We did find it! + // Let's see if it's in the next haystack + continue :haystack; + } + } + + // We found the needle in all haystacks, hooray! + if (found) return needle; + } + + // We ran out of needles and nothing was found + return null; +} + +// Steps the iterator and slices lines in the specified amount +fn stepInline(iter: *Iterator, buffer: []string) ?[]string { + // We reached the end + const line = iter.next() orelse return null; + // Line isn't valid + if (line.len == 0 or line.len % buffer.len != 0) return stepInline(iter, buffer); + + const len = line.len / buffer.len; + for (buffer) |_, i| { + // Split line into slices into buffer + buffer[i] = line[i * len .. (i + 1) * len]; + } + + return buffer; +} + +// Steps the iterator and puts whole lines in the specified amount +fn stepInterline(iter: *Iterator, buffer: []string) ?[]string { + for (buffer) |_, i| { + // No more lines + const line = iter.next() orelse return null; + // Invalid input, try next one + if (line.len <= 0) return stepInterline(iter, buffer); + + buffer[i] = line; + } + + return buffer; +} diff --git a/3/input.asc b/3/input.asc new file mode 100644 index 0000000..c827b9e --- /dev/null +++ b/3/input.asc @@ -0,0 +1,300 @@ +jVTBgVbgJQVrTLRRsLvRzWcZvnDs +dhtmhfdfNlNNldfqmPCflqGbNZDHsDWcRzvczWsczZNzHz +tmwwwCCfbJSMbwMb +hsrZZhHlhrHmPPbMbDFDQdnQgLfMFDdDQQ +GpBtwtqrcCcjgnLgqfgDDgRn +cJwVwpCpGJctJtBcCrSCGrVJhlsbvSvTvbmHmmsWmHslmsHm +gCtWJvmfmGGwVVMhJw +nzRSpZbSVFFRDFSDzcplddqplqMhQMclMp +zFLszzRTDnZnbTZTRZsVNgCjrvfvgtvNmtfvLW +glRQRpQQtQtGtQws +TnmbLqvBFRFFLPBFnPbvRBhshTtHWhwzdwtHdsdzWhws +qmCLPNmCFnLBnmPPqVbFLRrJjVggDgJjlZVVDjDlDD +vRRgpWvPQFdTFDDNQs +bqtCmltmlbwqLVLZqwtmLBBTMcGBddTTBgFNGcZGMD +bbtmJmjlVlwblwwbwzbbvrrznvzShgRhRvhfWrWn +ZMhThfNcpbbMNNjsHpmpsRqsPmRs +wQjDgggQDPqqDlsD +SCwSzvLVCSVtQVgLnrccfdGdTdZfcZMtjJhG +wNnNmNHnNPPwwPGCrLSZZvdVVZvBtMMvdm +WQzlhzjzbBtMMlBrMl +szbgWhJjTTcsWTqgzsqcsGHfwNcwfwnHHrCGCPPGwr +CNsbpFCMSrmDhQHNNGmH +fQPPPcqvljQzjVDDgRBhGGqDgqqD +ZctlcVzcfltQtnrndbQMCM +NQjQjQvZvZjcvrrrNjgTQgBQwTJsJswJlbGstqqtmGhmwhqw +PWpHRzRnPHHSCnPFwlqhbtqGZClJqGqG +ZzVpMpWPHnVzzpWzDRzSZrcdDQdrQNrcQgQfjcNfjf +BSZMtdtZBzMFvhCbBJDbhDDC +qcqVVmccrmVcjrlHqTrjDJRPQhWvPWWfPvblffDf +cHTrbGwpmGwVjdFMnzpLznMztd +DGDGGbNgTgJQQLMRMMTNVzvPsPbdsfPVsdVVZfPf +lcCmmlpwwnwSjCHtFpCpHzCrZsVrBZZzdvDfVrsfZd +lSHwnjpFmppHqppttttcFmnhMLGNRLhTMDqJLQNLLQNLhJ +WqWfDWBjBjLbfcbbqGbWqQsrFFztsppMFCzgCJzJCrFpCM +VRlhdHZTZVRRmZwlmFrJwFpMMDDrrrtJwg +PPVddvvDZmRmHvndTHmLcbcjSjLQBGWGGQWSqP +HHvgvwHMPMwHwmcRfJNFchFGNNCm +BsTDsjzBCCBJGffN +jznSnSdqzqnQTbdDljQjQSMHWWvvgWvtZlrWpPfWwtPr +DJCJJCNjCDRfDfDRhDnNhfjFPgbGbddBTjFdTFTPbgGSdF +cmMcMVqBZVcwsGFgGqgWdFqb +vcZVzwmHVcrtrwMMvvmBHwNNCDpQRfhLhrNJNfJDDDRC +VWSSScsncpDRdnsWsVncVzTwMMMHtMTrLTLMMVHM +fjJvQqBCQNhfQlZZnqmFHLFMTFTzwzLzrHMB +CqfjjQZJPjjvpRppDPgbnSnP +tLnjNwjRWttdCwRLsfGzfzPbzbWbQQPT +cvvBvlBrFrlTffsbfTqZ +vmrFpsrvFMMMNwhtDwhN +wzgRNqwtgzMWtqGwCssBBSBZnSRsrQQS +bbjLTmpjpHcpVncVdmffPCDrjZDSDsZffDQC +pbVFncvvbpbbHJJHVdvqMGMJNwWlNlJMwqzlNM +TdszlzFsRQqFdRzqwwQGlFsGmmSBBdmdVVmgSZdSPZBBBmSD +HMCCMbJHJJLHSmSvZLBcSDBP +NWbhPjfrbbNfWCPjhNnGsNzsqpQszTQGRwGQzR +ppQpTNCPBTlNBVmNQTNrrrrtqsrWbGrVFWqhZb +DMvDHnjRvMDLghhhgbqZWbqFSS +vWvMRRJDLMnHLJjDwWnnndcllNTzBmClQBpBBzQQzCBzCJ +VsNZfPMnrCnlCnWtbvBbvwtTbZwT +JhJQdQhmRHDRdLmHJhljhphgGwtttmcvbwwTWtvtbGBttc +jqLpjSLDHlhnffCMzsqCPP +JzJdLRmmzJwrLLwLJwLTWwBrMrpHlFnScVVqccrBHSlc +tvQDQhjhvbqFqFSpjHSV +QbgZtsgfbNNQbgbsbQRfmWRJwJGWWTPRwqzR +MwvDgpwszSpSJPsssMccTQfTDfTQRTljfRfT +PmGbWhbVtZWPTqRrcTrrjTrt +NbZbWHBmVGmLbZVBVNLPsMBzwSSzMJMCsCzvnvSp +cTpgTnpzbZlJHTZm +jRrLVtqtvtrjqsHZhvpmBfJHmhhp +FqDsFLCwCVRDqwgNQcQMwnncnMpg +sCCtssdZdZJmMbNJDmtmJzLSrcGfHGLTHDHnGLrHTSSn +gQwRRWqwqgpggFWPjPpFnSTSnHNfLLQrccrLGHLL +qqlpqhjFwPgPwvvRgFlPdslZCzMZtVdtVdVMtJlN +BWVmPtRVRRWDNtZBVQzCfdscmfjcfdfzzSfz +MhgJLbGggHbqpGgpgJbrFJdjwsCChCzllzCdjDSszCCD +grpDLFrbgpJnqJrHGFHGqMHBBPRWQTPWZBQVTQWnPNVvBt +gJfggdmHDgfJJWzCcbqvcqcmTG +hLZlRBZNlBlrpprzrWqvtHvvGtbvHT +sNLRjHZLNVnZZVLppnhNsMFJSjFPPQMjwgMPPfDMfS +mDDzHfrPBvJRJhpBRg +SsTSTwJwcbCtwssGFVWppgZRbLpLRNhpLhbLvg +ttVCGjTGrfJJMfjD +ffhcsTjnfqHLqvZSHvHB +CsgmPVmstsQVpRbHBvFbHBDMvZLZGB +ppgpmmRVpVPwPrrrTNlcrwrlWs +NDtssPNBjQtCtCcT +ZZqncfqhZqhJZFTJTllCGVljSl +ndrWbfZwWhngwbqbZnMZcwWhDmmLDmzvHPvzNLdmzsvBBHHP +FQtptwMppSFQRRQfSfvTrTJJJTrvLjMMJbgJ +CcDqWBWzbldcchDGCWBCBhdGrvhnrsrjjsJvLvghrjjnnjsJ +GDBldPDGqPGWVBBcwHFmSmbpSpNRwHFV +CwHwCFwtCmdCDflHDpwFnnvzhhNJhJNzmhzhhNMM +sTbZssPqScTrqSWSShdMvgMRRzdRRQ +brBrsWPTrdrWsPcBcTcGqDLDDHjFfDClwLLBfFlFlw +lNptNFWpbVMjlBgQgvdNBRQLrd +TsDCDfSCQqqQQqDq +TwTmwPPPzZSCccScJwpWZHljtbWMFFQVHpnj +fhFmwbrgnCcSnwtS +vZVVZvQZVPZsMnNSccMHPN +ddzvQJvQzBzWRTJzdRVSWGqbRbgmfbFFbmbgmpmlff +wdslVdQtdlBVHDrHBcBc +TJWvpncCcJzCWcRfWvJRRpfZHBDZZHmDZPBjZHjZrSfb +TRJFvvWpTRRWCpCgGtgtGQdlcNtsGlwg +rCHvRLJtCjpbRCLpptHMVCQgGlMndVlQGNcCMc +zZfzSmsfSsMzMccQMVcN +ssSmPmSmhwVhZBZsTBRJrtRjtbDvjvrTHLtJ +wswRCNHHhsrWFsGfGWFBGb +lLtngDPLgLJPttgWzQWlbCfBlmBFCW +DcDnVpcnnJPngjjcdpRhwNZSCZNdNdvr +NWNzWpfMRHfwsRNznPdjtdjJtPVPHVdJ +CSLTZBrGbSmClvBVdGzFVVcFdjjjnV +SrZhZbTvmmbbLvwQzMhsfhqqWwQR +vvZqwFBZvzZzrqltPsQstrGGpMcbbR +bhJdjJJmTRQMTMMPPM +mCmgLbdVVVLhVnJmLgJhBWZFDlqFvwZDlZBnBvWB +sMrcmQcHHsLLrSHZhvdCddvtJJFl +jzjjWplWpPRPDzPzfRGjqvdJqqqCtqdqDvdDqtwC +pPNWVpGGVVffPlnSMnMsTmgsQVLr +zGMMRbpGmqqqNRmmzbNfbzPRPlvThCTrHPnrHSVPlTHR +LSjjwgsjtTjhPhHhvC +dJZtJwFgtBLDZZbmNMGzMMqS +ZrnstppPWccnsFWpnZnRdjRtjbCtSSRjjjLLbG +JgBQPJvPgHHJvmmzwGGLdjHGSjShGHqdHL +wTJvPzmTJvzJQBfwNmTmlPsrVfnVFpcMVZprDpFrsrVc +ssGCtltsSdJJtQjPdvHvfbfvqLHqZtBfVb +pzRwwDwDTgzbqVTVvHqVWB +grzHnRpmFpDMnmzFhplJCjlsPdGJSjsFCdFs +CTGBBGCBlSTTSsnTMrQbNrBMtpVzNddWHWzVpHVtdHmwhphm +JqPZgMRFFvFZvDZMDFcFFfDchdtdPWpzpWhtHWwwhVzWpddW +ZfLZMcgqRDjgjcLccDRDLsbbrSBBlQGQBCTrCBnT +VjVGVqSqFLFVSqCjFJSsbfPprHbCCRRPccRWPW +wwnQmtwlvNmpZRsPsWWNbZ +DBhhhznhddldnvjMqJMTqDMGPSjF +TTJbsJPPBDsBVbJJGJBGWLfmWzgmDmzmLqmmLddQ +jHwVZZjwFZlzLzWZLMdLqM +HHHhjHplrHSpcCSvjlsNPbNRbRnVTrRsNNNJ +NzMMLZtwRmbwFnVDhnqD +SlsJsSdSJdNJnFphVHFjph +vlrsTlGPTgvvSBScGcBvfzmmLLCtMWNZRBQMzftf +tRFLmZZRLrtRvtvvrvvGgvtLNfwzMzNwgdznMpwwpnMpqHdz +hcsBsWTcQJhjbHMncNwzMqnzwl +VWSWWTJhWBVDTJsTVWQWTVVbZtCPSvrrGSLCRFRGtRZLPmmq +hbdFhdShGsFSGBlQhNhQMLLLlLJCvLLDtVJDLlwtwD +WcqWsmcWrmqcmtDHJjVHrJCjjt +WPWcnggssmzqzzzgfzZnWRqqdGpSNFdMSFdBMSFZhSFBZZhh +GNFNtRQMGjDjwfgDZjmz +bqDsPWWbsqVsdvvBJvBfmgfLLzSwzLcmzmfB +WPWrrVrrVJhVWJDVsqnPdRQllRQRNhQGMlFQFMplGl +mChChmSQGSGJrjPHCpPFtwgsFZjtFVZfgVwtdV +MBMqvDWMlTbzlRWzllDzblZfsrgdZffgrtwrswZfdZTd +DlcMvBbBMnqMDqcRqDBMWvLmCGrGLSJhnLHCCHHnPmSQ +tscfGqftGfDnnppJGDGCZLbzMVMwPPhsblzbjzzMMz +TWPTWWmHTmFRSBSvgBPwwwlVzhMdwblhbVjRLL +TTQNNWWgHWQHPBWTNPWNcqJtGCnfqfpQZJCZpQZn +CqzCGDQJCzzftfRqRzzMdvFpFpccdZFvFMtMbd +rNHwmHVmswsHVsPTLnbFSTbZZpFcpvSZZgpg +vPLhLLwHLhVVNVvQhBqDCBfhDzCffG +WsBbBbsWNhsPsCNssRWLPLpmLDDQHlJlnlzFnDDnzF +gcGfqggMqfjjGwrdDZzQFmpJQzZlFDMF +qdwqvjdTrwfvvBCPtpVvtR +RQdbbRHtHRvqZtwVcmwVwV +WnLNnqFDlDWzzNLLrjClwCZCGZcglGCccZ +LnTFfWBpffrfrhBqdsSBqhBJHb +sqsgJpDMrNQgGsFMsPCfjCPChPWjqSWSjh +RBnRnZVcwZllLwbwwLbZVLclhpjRttSdtjPhjWShWdphjCPd +HwHwVVwVnBVBmmGppNFzrrsgJJ +WpmDFlQlzmmgMMLMLQVTvTTSwNbmTVwTtHHw +jrhPDnDnnZfjPTNtHSVTcjccwt +CJqPfGnhGZCBfnPJCrBCqdLqMlQqDLlLRgLQFFRW +vZVvDZsvhDZhZvzgVcgVqPqmwWMqcw +bdTbdBBFQcdCdcGmcP +bmjQpHfbpzDJRjNhJZ +twRrwjFptprQjjjtQRdWCmNJTlNSCmZQcNlmlSST +VVDzMWDnDHMzLZDNNJSqqCJZZD +HHhhsfVHGbnwgjfrgdpgWj +GmszZGMrLmnmsfGVRcVlwtwccc +SSCgbNqSTgCCJMHCJtlVcwVbVljlclVfwf +HTCgHSgHQThMqWQQSgDnvBdsFDvrzdZsLdmLZZ +PRlMlBPPctVBlstzVLhsdwCqCdCNDjSDdWmMqdNw +fZrQQHFffgGFprSJSgvZrfnqjmWdnndCNGWmWDwNNDCG +rTvvpJZZrfpFSbQQvrrsssLRVPPtlRtRPThzTR +FqgHFFMRTRjRFRpRRjFtNdCtJCMnNNdrdMLdrQ +VhWSmwGwWVbGbvlwwlLZJLZSdJZtNCtnTSCJ +BmWwWWzhvVfwWhmhwlmvwlRqHpscHRTpTDRFfTsjDPjD +MJMgGqMFLPGgWVjpcmjZTpmZjZpJ +hdSzzlCtzNdtWSdndttflBmjpBRmvvpjnjcvBjmvHj +zdhCrfztrDSzfWzdChrhlhgPPPGDgqFFLGGFVVqqPVQw +ZQZNQRZzFdCCgfLcCGDfScjDcG +vsmwVHTmTfGcSHjcDS +tMsmMVlSWWzdWNnQNJ +GPRcQnwwQWwFFnrnnldSqzMfSCdfdldrJf +LpTsjmZTsBZjpmzhLLMdSJJSMhCC +ZsZBssBsDpDmmVBjCmDZHgnVNWvPQPNPGvNQncQPcRWn +pznzpzlGFrvGHGrnnMvDmBMfgfTmsBsTTghDsg +LJtWVCWLCNPcSbdcShWBgBThgTfjzwfhhz +VZZCdLCVNNCVbCLzFnRqGqlHprQZHRqr +dFTsQPdMFsMnWFPdSnwBltftttvlflNN +VLZhZLqghCgzqgrLrcgVgbCvtDDtwpqNpDtlBRflDwNqDpNw +cLmVhVcgbZrVhrhCLhczhQdJHTmPJJTjvTJsPFWFTW +SSwNPNHldNJSngHqBssQvBfccB +mMppmDprWpFGRGWmWrDrtGzQfcvvQZBBzzczqRQgRqRT +WtFtFvhvpLphNJJVSCbSNP +chpGMMzcwSSGnQFRQQFWcFWn +sgddTfjLqsWrRtLvQnJr +CsmlZgssbRdMhzCHDGpGGG +vHBrTzpMPTHMtbBRRJGtDsNB +QJWWVwnCZmQlWQWlLWCCmmLwRgtDdDbgngqtRdRGbDNDGtGq +LwmWQLJcWmwPrpvpjjrcjT +fcsWnWzhWcWgcbfbvtbHTRvpvHttmLtR +lNSjwjrDFjlFhlZlQTpLHvSHptvTSRtLmJ +NwjwrQDwFCZBCfWzqhqqzc +fgNJNRcvvWRfWRrZFldlwlFwfFllflDH +spQshQhpqhJsLpnQVLqBqlFwddHSdBFFjSFmwlFmwl +hppLsqPVLnpnzJPtqtPPJTCgNcrcNbrrGNcgRNrzcZbG +PWFdgDGCFPGhMtQqHBrpJqqW +nlllLNmnVNNLllVbVRLRsQMqqpccQQJcJtqcJcnBrc +NmvZLsNrbZNjNZVNGvdFFfwdDhPFdDzC +LpZpwgLsLSzDdjVGpS +bWBlHqqBhNJWNbJQFzGtCtDtGGjNGDgtGC +RBRbJggbWRRmhWqTcnnfnmZMTTsTcP +JJgzvfzpdzzJjJhgdfhvqfdScNsLwwGsrRbwRLbcbVrVRp +WDFBTTDtHTntltnCnnntCDwGlGGbSwNVSssrbwGVsVLs +nCHMDtCWWTCCHmmPDnZQgvfQgZNJJdvdMZQg +lFDgvlsGvvZGDsFZWgGvWrPqnmwwtqmMVSWrSqMM +hRpJhLQHhdTTVPmVSrqwtHmV +ctJJJfjLpjglZDGCGljF +CnnVMbhVRbQQZjBP +rlfsLFLtmLSJscttFfsdjZwZNNwBPWRjRNZBZBfQ +tFrmDFlDtmcltFvqVzDqQzGvCVCG +JzzJzVrmzJpCCmTFmjZS +HtDDtggWssqWfDgwDWvsfDBBchZjSnGGpCFjSFZjpGjFShZg +sbvbvfbbDblWtrNVNRzRlJPCzM +nlFnFWsWhrctWVdJPDPTnTNJPJQJ +fHqvHSqRqSHjBmqvmqqHCtJSTZGdMQJDPQDPPMdNTMZN +jzqmbtRRztmbLHcFpgWVsFphpcLV +PHZFZFVZZfHgpwjFtmgjtq +rpTrTNzzNdrTJwgMwqCBJzJz +vsTWbvccRcdRbrRnRRbRrcvVpGlGHZPspSVhSPPQGGZVHV +HWnDDjfPFccDPhfchnMMVWGzzpvGszCCGWWV +JNBtBTQJNwJQjTpRVRMvpLsQzsRR +JltNSrBjmrHfdPHnDlHg +ldCJHlZFspjzHMnp +zvcLQBQcQvhBwmcDppqbNpjMLnLDDn +BvcmQhWWRzPJJzWWWg +ggSTPZBwTPTPSTRwZPBnwPMLdVvBqzsqLzqqtVzqtzBszN +QRmhQhffCQhJcDfmpChQWJmJNNtzvqtLdvNsGtLqNGzvWqvG +HQFCDhDFCCQJQmZTZwTSSwrZnRFS +QbFlsMbgPWPlJWzsJsJZntvnvZtctHBfZvBZlD +VTqpTqmSrhVLqrpjNppgntfBgfjddHffZBdtcB +VCwpqqqNVgNVgMJJwbsWWGMGFR +GCwRjQlsCQrPrGMQPsRvpdvgnjgmVVmSStptgJ +DzNcZNHZZhzzHhDzDTLWhDzSdJSSpnnVSTSvJJmgvSdmmn +pfLNDppNWHqDWfWbzcHPRslCGbwRCPwQrGQPCF +hVLnDgCmbhltrmDlhbhVmcgFBWdSBSZZBFPwBLBPfWdPWZ +TNTjJNpjqGMTRRsTTCZddfWwFHFWHSSJSFPS +CGQqvQRTNzTpQsDtmcrgDQllhnQl +SWrtcHWjcWrPcwWrBwSPffnJNsqfMNCNqNfJFfSq +QLQvhBpbbvdvTdvpTdGDbDQqqqslsNMJlMMCqMfQnlfC +gThhpmDLbzBmGLptrmRZcwHWHZjVrW +gQvzQRvSSbvvJvQgfRrfbSpGqBPGwqwVjPBBwwjpRmjB +TcNHHVVtNsDHcMcdMBjqpBnGnwlGTwlPBl +MHsMDHFMdDtZddZdFdFrhhgbFFVvffrzzffrrS +QSFmrDSSQrqlfmDDHPRTdrrTPRbsTPTsNN +wBcclhhgwgMhWLLtVMgVvzRTNNjvbszzTdjNdsRbjp +nJgVMtBhwLBctmQHQlnCGqmQZZ +sggtjzzggfGmPbCMvRCMvTmT +RDqqhdQdDlcDpqVlLbSbZFSTTPllbCMv +hqpQWRhhdncDQcBsrwzjnfgtgGfgHs +MTrzlgMNQNggrrrPlzQDPCsFRfscTfFVhVftRsFFsScS +nWWHZHhZWJjjwjLjwbLbwHGSFppVfFVcGcFLfFSVttpf +jWhZZBhqBbwvZvBjZNNQrQQQzPMlzzglPB +jLVhJZQjwFCLRjQhPRZFLDzrGDHpDGsGqztGHststC +SBNlNmWnfvdLmlnvfNSbzrDTTzprdqrDpGqqpHrG +bNmSBnBmcfMmcmnlfcnNSnLhZPVVJhwjZRJPwjZMPjMZ +VpzBDgGTGVNNpSGzppMdTQwcvFdFMQdcdFwc +ZDsqfRftWtllmlWbLLtjFFMwMrjCcwfvMFvwcC +PHbDLHZtZJSJPpVgnV +bRvTdswLLSTvwswSbDhsDTvFmmGRVmJGZJnRcGGfFVJcqn +MWllQMllWHrjWPNplrllQMPZJmnnVmqJcNmVFFnJNFqVGC +PgpQrQjjzQWHzpBdvtwhwdSShBZTsT +MhTwjMTsTRFStjmSMqqppBrHpDrzHtPqbD +dllNcZWgldLvcsvvvvgvWddlHffqBHBBfPzbbqBpPHrpHNbq +VddvgWWdCZhnhsCSSCGT +LPjqHnDNqqHNllqLpqPCZCGRCssGdGrGFrPrgr +WVBztWTQSQMBQrGgRwwwCGgtwg +QJMTgvbTTWSzWWvSbVJTzJllJlHHhLpNqpHqjNjNHpjq +PCHCbPPPHPlTThBhjGTTNhMNTh +FrmfLqdqgfmfttqtWqfrqdhshchDBshDllDBcGDhGDWs +mqgdpvFmmdLdqqQCPHZZblvwZQZl +bQGqmngwwgSNrBWJWdHZmjfZWB +FlpRLCptFLMlLPRLlCCcCCMpjJZJHShWdWvBHHdcZdBWZvSv +FRPCDTTtFptVTnQnrGbwbS +LsdmnDMTLbzsbNtqcb +lJjCnHSvQRRwQQjRRHQbgWbqctNJPbcWrcPPgc +RhGSQGwBvvGShnGlHClwjmfpmfdmVmfFDBLDDZpmMf +ppDnPmwvNDjTjjcssT +qqfRHzdCPHWfhHHtTjjbbLLGZr +MhzqWdJCzqJWSJnpnpvvPSPP +NGWdQgDDHGJgQLznzzsJFFzvzB +twRCpZVjVWqVSqVwwjtZfrrfntfvznBssBncfLrc +jRRwCqwCZhlhZRpSZpjSqWwqmDMQdMmHPQQMHGdlHdTldNGd