diff options
| author | Tom Smeding <tom.smeding@gmail.com> | 2018-12-05 13:15:03 +0100 | 
|---|---|---|
| committer | Tom Smeding <tom.smeding@gmail.com> | 2018-12-05 13:15:03 +0100 | 
| commit | d38746c3b68f139fb2f6df78a219c2577fc0338c (patch) | |
| tree | bf51edf668f9054ea8b3c28aa6043061ad136d83 /2018 | |
| parent | d139374ef1518c5bd4e5c84e1d88263fdda2e15c (diff) | |
Day 5 + benchmarking
Diffstat (limited to '2018')
| -rw-r--r-- | 2018/input/5.txt | 1 | ||||
| -rw-r--r-- | 2018/src/day1.rs | 10 | ||||
| -rw-r--r-- | 2018/src/day2.rs | 9 | ||||
| -rw-r--r-- | 2018/src/day3.rs | 8 | ||||
| -rw-r--r-- | 2018/src/day4.rs | 8 | ||||
| -rw-r--r-- | 2018/src/day5.rs | 88 | ||||
| -rw-r--r-- | 2018/src/main.rs | 86 | 
7 files changed, 177 insertions, 33 deletions
| diff --git a/2018/input/5.txt b/2018/input/5.txt new file mode 100644 index 0000000..b14de78 --- /dev/null +++ b/2018/input/5.txt @@ -0,0 +1 @@ +CcvVeGgRbBxCcXbJtTjBrMmmaASgGceECGgARrjmMJDPpFmMjJSsfMlLmUYyDNnduGgFfwKJjkWuUiIdbWwBWwKksZQCcqzflLFfFZzZrRzmMNBbNnnjjAamMJqQdDoOJkZTtzKgGZzSJyYyGgYJjjsVqQrRfNnmDdFfMFjJXxSsGTtgMmuztTZVHhvBBbMAambgUuaAGjJcRrefFECIKmzZMkuUixXIiSsqlLOoEeQNFfnFfUncCqQQqkKxXbHEKkexMlLmgHhGXAanOoGgVvNRrUuBbYBbyjJoOWwDdhIiBNvAaeEVSSssccCSsYWwyXxLNnqQlCaWwbBjJAWeexXiCcIBbkrLOolJaAjnWwNnNRjJKEHhqPpQDdERrgwrhHRgtTGtwWTiYyvVqQUuyIiPpYyYakKxXBOobTtKfFkAItRrmMTaAWdPpwWcCuUPpRXxzZrCcDDdNnbBuUwWoOyXxYupocLlCmMAaObBWwzZPWglLlLGoOGgDgGcdjJDwWCUqCcQudfFjfFJDdiIDdbBipPwsSWaAIeEvVHhskKSoOUuPYypRrkKlXxLrUupPtTtThhHgGHVvROoXdDAaRgGtTrzBbrRKkhHBbUuwWZxwUuPpCzZcJFfcCjbBkZzKFfuUKktTUuMcCiELlSxaAXQqseIqQfuiIUDLwWljJdlEeLhHaAcCFQqnKkNfFRHHBbhhrNiInxXRroWwODddpPjJzZDtTTtSKGlIiLgwWZlLBbpPzktTyYzZXxXQhHqCcxsvVkKHhNRpKkPraiIJjKVvkOoluMmsSUeEtkKQqYyYygGWvVQqwTmbBQqMjAXxaXLlxwWTtFDdfDdqQwiIuUsSWulLUJLVvgGoOxNniIXGgEVvZzXcCuUxwWpPMmzhHHaAhQCbBTmMBbtbqzZQxXBXCxXIiEexXcxDZzTSstdjJVCcQqvSszfFZZzzGAagnNZAdDsPpSItTiqVvdDZzlLQkKGgrvVLlONnoeEIihYyMzZmHdDVvkXxrBbDdRpPKnNMtTtDdIiTWXxwtTxXlLVKyYkvyYwWSsmPnNAapoTteEOxTtyvVYQidDIYyIiTeEtdDRrQqrRCcrRSyYbBmMifhHeEhHeEkcZzmMCKFkKJjFfIEespPYyUuLlZzjJlzZLzVvniINSsZTEkKeAJfDdFjazZtlLlkKyYLBbNnnwWNgGfFDRkwWKFfQqxLlUuRrjJZzXkYWwyqHhvVPpBbCNnAaaAcQfFKVDdsRruUlLJkKiWwLaAlIjHhHhRJjfhHFrfFOogOoGaiIAfOoFfFxXHhRrAaSaAHhxiImMXToOtvnNGwWgiIAYoOyiIMmsjJpPdZzDwhHXxHhuUWSxQqjJvVKidfFDKkMmKzZGpPgkIfgBbGOoFTtdDrRIiHhSVvsfFaAbIiBXZzyYzPpLlZNnoADdjJYyNnbSsLlXxeXxEJEURFAafrOnNoubBeeWfFwZzFfECYycWnNMyYzsSeEZmwvKkqQVWsSqlxXLeEJjTMmJjhHKkNnKuSsUgdCcBNSsHbBLlWgGwBqQbnNhQYnNymMqtTriIaRrGgARYkKyBEeEwWebhNiInkKHCchrRHnbGIigFEefyYkRrKDWwCGmMCcSsKkpPtTgQiIgGqZzUulLwWzZCAaDdcmzZMjWwYyTtGvXxVgYQqygXDdSsxLVvlPpGpYLlyPPpUubBcCXWUucCwVveEAaYyxXYyUuXxSsoOQqJjxGgCciGiIgsSSsIfGFfgAiUuqQIeEKkTIiEtopPIUuiOFmMfbBdAvVCctTCctfFHMHhmhTajFfJMmsGgSrsSRDaQqSssPpsSRNnrSoOQeGeLlEgSsziITtABbaZmMZJeEjBSIiLlsbxXfgSsGYyELlQcCqhHeKnNzZkYySsfFXghHQUoOdDjJuqvphHPVYyqQJjcCKkaAsVmxXWwMvVfFvomwWMgGOacCOosSWwsSDkOoKqQkGgKddwWVvZjJzRDdrkKkqQNyNnYnzZmMFfVDIidvwWZhQqHmMzlFfLmMkKKFtoOTfKkBRrZzaAjYzZyJbxXLlDRBbmPpMutTULlkKAaWUuwoOalLArCcEIiIikZziIVfFvsSvVKeMmrRcosSJjrQqROCtTZzUHhuXIHhiNsSnEeKkJjfFkKFjfFeEbNnBbtTOovVSxYyXYytzZTohFfHOJwWYLlyWHhyYCAmMacCEecwkIoOgQqcCGVvZiIziZcCzKTtpXsSxPUNwWQoOqmMxXnBblVgGGghHvxXXxLQqXQuUqxXxutTrRbBBbxlLMmeOQqoEeEfJtTjWwFavcCWwEeVCcGgAjJoOAaMmGgAaHhumVvMOolLBVbJjBvbvVncGbBHVFjIibBJOofvKNnkfFyYhdZUuzCcjJpPwWnufFUlkKLyYFfVzZZiIzHpPKkhNnvfSsFNPpAdDEeaSsyDdsSfFPiIuUaJjApWwHjJrlpPUuLuzsSSiOoVvWhpPqeEQMmSDdseEHwYvVAaAMtTmJsAalLSjqQJmZmMzZzxXeEMfLwzQqZsSWlQqZzSMOomsWLlsSOoIiMmcCVxXbBviLlIlzZKUFfuZzkLZztTHhLqQCclUEbBeYyoOuFfESyYsVveNnuUuUENntBbToOhHcCcXxCdDeDmMtTdDAadgGPpgGOonSsheQMmqEJjFfHQqyJjZXxrROpPpPUuojxXJfFmnpPNOoMDdPfsSdjJMmEezZDFDAbBGgVPKkSsyCcYxXpPKkSstFfzZoODRrQbBqUulWDdwLlPpMmLUubBLlPpNCcYynAaEepPhHkKfxXnNFVvdJOojYyDdRuURlGguULhAaPICciFfpHrrRrHfFhAUUurYUUmMKsSkQqfFkKlLuxXMmkKrtTRgGuUvrJjRfFKxXmMprRPoOAaeCcEWOfLlFnNowiIeNLlqQSRuuUIdDiRrvVtFwWtTMmGgMmfYeqgGJjQWwMmEesSZzEyTjJtIJWEeEwXxtVvdDFnwWLwWlaANpPMmtTegGppTtPPaFXEexAuUdIiDaaARwWHhxvVXIiWwIiFfDdrFfUuOoYytwWTKxXzWwZYymMsSdvVMmZzrRQqDWdDCiIcMsSMmqQdDmYEeySGgkXBbkKxKbBAaRrRmMrIuUKrQqFYyfgGSsKOoRrDdkBbrRwWHzZnNWxXwNnhtTFfZIizxxXxuUXXCZzcuURSsiIOokisFfTgGtpCGLlwWgGZzgvHtoOThjVVvvJGgetZOAUTcLlCtTtPpuGkKgayYjOTtLloJQRkKNnJjrqamMaArbXxBRCcXhHcCJjgKkGuUKLRIiGgOorlmPpMqQHVaAEexRrXbgGjhHJmqQMQjJPpZHhhHzoOvVCcKkOoyYzgGaAiINalLWnPpNGghHwtTuUeVvEaAqZSbCclDdLBszZzSsIirRcCkKmMsSOofFlLxXrRqQRrKkBbDJjUuUhHkqQLlKnNLpPHOogPdoOhHDvJjVpknNEIMmitTavVAPpDhHDFtlLTAaVcBbSgGFfsCWwjddDDGgJmMmMBWwbMKkmvIiMwWSsrRkKAMmamFfSgGoWwfFWwpSsPhHDCcdmMkKuHhUgqQGZrRuUTxXNkKeEDdDdGgSRrbBsnxCfFcXbBiIIitIizHhsSsmMSbBSCcsPpIlLGgXxvOoVfsSFlKkPpRrYyMiImiItzZNQqFBzGVvgZPplVvcCLbjRyYlLrJEpPMmvVEpPHhetEegGgOooTtOGJrRjIifJvdDYyNoOnXLlxFfVpPNFfnuUjrREeQFfquUEefSsFqQdbgGIiMmoOBZfFzbQqBIiXxNaAGgcCLlPpDdzZzXxZdDXmaQqAMTCcEePptWgGoOrRTtNnfFDSWweEUuBbsYyqQwWwWsdDSYysEetTcCcyYoOUutTCMSPpsmWOotHfFhcCmMoOTSzqQcSNnIVxqzZQDdXvIFfiwWnNxXdDvyYtbCceELOMmoRrmvsSFiIfjJGIhnNHXRpPrXxNUIiMmuntTPFfpKknnNEWwOopEeQqZkkKKzPkqQrwwopPBbfFOdwOoWElLWweDtaAMAamBboOEeMWwWcCwggwnzmMRrFfCcZCTtKkTtxXcJIijROorvVWwYjdDJFfyzZjnIiNJBgGrRSsbCsScHKkSQqIcCgAdTtDaGifFoMmOsvVhKkWxXNYvVynSIlLlXxOoLioOVpdDLlYyYvxXVcTtCvFpPfVfFzsjJSZpKZzkgGxtTpZzPRMuUmrIiBbfFfeLIilyYElLRrGbBgkKhHWwlvVEehHLlaZCmMVveEZAalNnLzylLYlLvVEnAaNRQqcgGCbVvSyYsCWQomMOqwWwhYRrygGHhHpPlLDwWGgzBbZHhUudEemlLzcCfFyYZVhHvWwRfFbBpPrYyxXANZNnTtcCVEeOOoOooSSKEyYwWhuUuUyYlZzLVvHGgeEZzwOoaAWnNyGgpPHHgbBiZCcywWNnUVvJBmMuUbJKkjjuCcDdWwYyaAsSFfYtTcOoCfFeHhEfIiDiIhHdmMDdDjJhHLFfldeEltdDZzTxXHRrhNnOsSIioTlLtLlLceECFjTtPUupaAHeIibBhHCuzZUbiInNMmJjAYysyYjJSKkmbzHhmUmMnmNnMJjaANHjJPpNnhbBPpUuGcCgfJpCcPNbBxXnhHjeErRPpWwOovVrRHAMmYjJeaAEULoOcTBbbBwWhUGguHtcCCfFlLcDdEtTeLlVvtSsQSsIkKzhamMAyqQnLlzJjyYaAzJjeEZiIpzpPvVTtLlZdsoZzraARMSxfFHhyWwYhNnHFflLlWwiIkOoEeIiKRrcqQCXxQqwWMhHmzZcuUCHhQeJjGgrMmBbRAaiFxXfIEGyBUuoISsYnNyfFiFfsROoHhdDrSOoaAOovVjUuvxXVJvIikKzaAZgGpPVvTeEtUuxXLlZQqoyXxaAtyCcYdDTaAeMgGHZzhkKmzfrIiRFnNKYyoPPOopoODdDxcCdDnNVviNiIwWtNnZzkmMKWFfRrmMwNNnDZzdASszxXpzZLlZzNSsnVvTttjJTuUUuPZqwOwWaAXUuxUuzmAaMWCcCMmcEYcTzZbnTtTpPQeEJjuUqtWwiIYSBjZzNGgdDnlAaXYyxLzZXxwWwsSRrRrQqlPpmCUpPTtBbSnNbjWwXlLjJmMBuUbjJsSoOxJxoOyYqQVvXsSIFEqeEQefecCAGJDdDdNNnXxtTnxXAiIOowcCWMSsEjmMJeetDdHhLLlaAlbBkKQNnZzOvVoqYywWoOrMSsmsSxXRulIizZxHErRaAqQZyYDdsSzgnCcNiImMWwFfmncCRraATnNHhtwWNFrRrqNcvXxVaXxyOoVkKlgGLDdvvyYNngGiIbBgFfbBFHhkvgGVKVsWwSrVvHhRvYTtESAaMmMhHyYmsGgAacCxrRXEmMeeESsPpJjjVvJhkKHujJHhUtXxslLEeSdRtTxXsSrDVEXxDiILldouUOoOBbrGcCeExXgUtTuFfRwdDLldFfxXiIGgbgqQrEraAmMReOosfFAaSpPXxLlRfXxFGoZzOwCYYyaeEpeEPionfBbFBbcCzXxFRriuRrUIzAIinsSNCctEkUuKszZyofFOYYydDiIIiZLlEeZqrRPKkPYyHhupPDdUhzIidDZhGsSgoOTthIiHAtmMXaIjdDJFfwvVQdDIikKxvVBIibXYRVvryfFZgcmMCjJGdDWwzeAaSsvaATthHyZhHnNZRrDdoZzOhVvEwhHzZYyeEEeakMmpPYIiyGgcDdbtTtTBNBbSzvVGgZDdkKfFyCcYyzZxXlsKkSfFBbGCcgHhxsUJjJjuDdUXxShDOieeJjEnmMNaWqjJjrRJQFeEfBRcCjJAaxXBQqmMSsZzhHIiIixgXvVxLlxXGXsbBoGghwWuUdNwWkKHwWNnhnVnbBtTNvDzZnNFBbIcCQqAZzaMGgmihHIeNMmbQqoOBdvGgVWVKoOkKmMoSsUuOrRknjTtuUiaAITeaACcGcCggGdKkDTtsYSmMyYsPpqSsNVvfFWwMNnzirlOoDdHhLrRWwRIZmMithHTrRAaImAXxFfUuaAPptPpTcKkZzGgCSHiIUYyyYTtuaAKiIQfNKNnkVvVvnqQVYyvrShHKkbnNBLlsGelLuUuEezZUdDiYFfWnNwThHQqkQqmMKncCiINQizZuUIsPpxJjpPIsSfFUfFuiLlQHhGlLgoOvVIrRRriRrkUuIwFGgfwXxWCcWUuOyYoijJICcigVvcFQqiUmMAtFgGfTMDdDXxftTthHTFvTPpMmFYIsSZBbjJSsufFUmbAeEsSoqQauUAkKIYyYTZIwWRzRrLfFGgGgYylkKEegGLlqvVQsDddDhZzHFZUlLuzOfFoTjPpbKsPpvVbBjxXsSwoOMmZWwdDzlLHPphUuOoeEBQqGrROAaDdCcfFCpPciUuIqDdzZQJijxxcCjJklLVvKXXcCKkYygGOpPRBNnVvnMmnNMmPIhDdfvVFHzZUMQWgGwtNntWwaATAjAGgGgafFaJjrqQRilLIncCNOoASsTNkKnyuFfbgBjJrRKkcCZkKeEcsSCTXxyYVvOVvBBblLBOobXxuUKaEmMvJjTfFZcBbjkKDmMxXHhsSfFdDdOoJFfrRTzZJTtpPjtRriIfTtFCsSjJvckKEeTtCVzMtTbBmWHwjwWJgGcRrBbYykwWtALFTlLTWwtQqgRHgrRWwGhyYKzZGggxWwPXQuRrmbBjFfkdAQKkqvkKIUuhHiEetTbpAavrRVPBPREezIitTEeEeAlLabvVgGBaAXxPpGjtTJgZzOoAajTtKCckXxjaAjJTeEVvYqCZzXaAkDdUydDYgGVnfgUujJGsKkwWnNSbBaHRFfrwcFfaACYoOyCcxgGXWLlpgrjJagGARBbShHsoOnNPGLlmfFMfFqTtYyEVveUugUPJbckGgeJjEKCBjJSsdDbBAKQbBqAaMmkEejvVoOOoZzMCcmoRrxXuUOJlLQqjVvsmMXZNnzUupboOhoOrRuxXWwUHsSBPiRrScVGgGgLvkFfdhHmKkMlLKfKkFkrEekxdjLlwWqvQqmMeEddbBPpDIiQoOqnHMXxmCchNDxXLYylRrUOouMBvVbSxXssSXHMmaAKkHhhxsSsSsVvSQOFbBfGeEFfcCgSsXBbnNxoqvXmqQMmGghlLYyPpyvVKkJjJvAGgaVjZzVvYFfhHmMHDdbPpMmEeMmwKkWMbBmBAahNnpPHONuTbUuBtYsSbBAqSsFutTaAYyMhHgrdLlDdiIDohHqQNEWweASUuRJgGtTjEBEeRrbWuUwCckKeEeYyQOoIizOooOEPpbBRUuaAdgGDCcrRyYrLnrMmRrRVvRcCcNZzcCzQqIiaRlBblLLrAZOIitlvVOoOoLOxIiBPpbhHXicCIxfFwWlnNIimrREeMCcQqFpPDdPkKpJGyuUYxZzXxXyVaLlSsHZCcgGzDuUGgdhnNfxXeEPpeEzZFLlPpAQJODdosSjFfqajJWwGgxXEehWyYwyNHhnRDGIIiIiLPgGWbBvXVFfvGgQqIyNVvKnNacCYWwBbyAeBbjJVviIVvEXxkDeEdDoOxxXkhHSsmWwXaaAWwAxSbBOosMXxKrRFLlloUmMVvuONnLiOgGdKkOcCrRoWmMIiwBbLWpPwloObXxlLtBbTpPsSghHsMmSMmQqZzLaANLFfrcFmMMmugGQrRSsqoFfmJeyKCckIiYqnlLHhWXxwDkKdWwvVjLlJNkKpPCcfFRrVvDqQTthBbFfHFfPsQqjJAfFagGyOkKoPYRrWXxWwFasHhbxzZJGgmMdKjuUJkOodDDHhiIaAjJHLlhjgGPpWWwjJfkosSOKNnhHNsYySEBLRrlkKoOXmCcFVvdDvPpcqQPpNwWnyqvVtTuhMbCHhcBHhmHUlFfLFtkkKMmtbBTBbRuUEeBbrRrcCKqwiItXxTWQuDIqAaQRrderRwZghHYyGhzqqDdQWwKrJjRkzZIgzZFAMmgGXxZzXOonNtLlTrnNIJjiRlIEecCtTaAAdDaeEAuhHUiVRrzQHhLcClueiIWwlLIBbiLYyljJEhHUlLXpPxODPpORrUuAaApPZQqdDaMmsAaSoOIiUsSujawyizZoyYFceEGfFgbBCCcZLjuKDdbBkWwMmMmUJoOlkKzgzZkxnhHBpPqQnNmMzZwWbSBbppPinwEeJpPbBjXMmvVtTwuUWapHVvhfFgGEePpodDHhwWQqOUuLzkKZlIVvOPpjgSsGJoOJjWwrRoilVzZWwQlLkKlFfBNnbHhoOJiIjBiIbRryYBbLqDSsdzZvTtpPYPqBjJbxYyXQyIiYTtWwjUNnKkIiacquUQCAgGuVvSsgGnjJNcCdDiWZdDWtTudeENCxXDdcsHVvtThSKzAdDCOMmiIjJobkKDdFfCowICxXRrxoOXuNnKTVpPvSsJjOCcoRrMWrRomMFSFfAauUrYyRkKTcCtMmMmwWQqckKfFcCrRaoOAbBmMncvVoywWivVIYEedHhkKDLlLLlLlLVAaqQuqQUpPMuUmoOUGgudPpXYyxXTtqQXxCcyrYyRPUuoOUJAxXXqQLysSYnwQzrRZqHddpVvMLlMvVcLlBbCHjedaXvuEIiBbjJiQFfNqQQYyFLlfkGgrRKhHzZqoyYgPpSsdDUubBzljJmxaAgIzmTtMLoOwkRrGtaAbiQqmMgXxQjJqGdYyFJLlHYoOBbbByvnNIiCcVqQkKsSvsxyYfHHhgGhFrDWwxtTouDEeAkKaBDdbSsPwWufFUTtpXxYySsTJLNnoOksSKlcMmjvVJAalLgfZzFIiOEeVvovVBFfFfwhoOLlHkKpPxtqQjZzPttiIdQkNnnItTMmiHgGhkKmLFEPTfvuUsStmMRrTRrPEetTpdnJGhHiIPVXuEegGyLlDdaAPpjqKwgAxXmhHNYyLlWwQqlLbBBLyYlbnNgbKcCEeqIiWwQOHJjEOauUlLAUDeEBbdAzZyYauosnNSSsTHhtHmAaMhVfKkCJjanNCNsSQqUulLYgGmvVkfCcFKErsuUOoSrRXLZcZRtTraAEeSBLlIimxeEXMvdDRrVvcUuCTsStCczmMZbBakqHhNgGnhMmHXqeJjEQxtTXgGjnNxXUuaGgXxAMmJZnNzWzaADLldcweSsEjZzXMFAahHZzcCBZLpkRAarKPFfpPPpoOeEeTmoORrKkvVDeEyYDwWdBwENrgGRhdDfFHUunoOLfFlepPUuuzVcCeFrPpRfExXXxQqNnYmMSsyCfFcUKkeGGGgggQqllrRCceEZzoOBbSWwvVOoWNnTRrNDdcCnuUQEGgeqtaeEwWSsAJWwGgsSWwtDfiIBeEbSsVvlLPpAgGsLnNwnNDqqNnQQhHdrMyYaZznpPkwWKRrAoOHhQQqqNncYNnaAmMCcYyytdDByYiIsSceEeCDQqkVvuUvPDdkKpBhHTtEvVgGjSsqsSQtwWTtPpKYydDdDTEeqJpJjTQwWqSbRrBVMmvcMLgGzZiVvlJjLqQqkKyGPfAnNaFuFwoOWMSsGgYVvyIkKIiiWwTBcCbLltfFXEeSDCcVxXTtvzvVZRIkqkfFneESsNPWSzZXxVvlMmPpgGTtLQQqayYAgGqlQVNneEGLlgzZMUumXxQqCOocBbgcCsGgrnNkKdDxUuXrhHRiCwuUMjJuUfFAxXFfOyYQHHhEfRrJjFGgxqQzHhWvIiHhOvVoAAUEeuwBbMmZbBmMzFfPpWYyrlLRRcCzZeErkRrEQqeKwZIioOzjJgGdDLwEeAatTcCWtiXxSskKIEesvLlVaruUkigGpvbPpBtbeEeEBUoYyjJOKkoORDdDnNolLOCgEmMgOoCyYqQcGhHxzZBMIHGgumMBWNnaZQqCcfQqFzRWwNnAGgKEcxXpPjJCfFCGgFfmBSVvJjqcVbBvuUWwlpcRrCwWdDNjOeNKYyEektMXeEkPpkKKxmJjfOLlNCcfJjFnJrWwcCRILcSAaWdUqtBbMmTJjQQxmpPoAaNnOgKfFkeQEeGgFVvNNnnlLUNnuhAakeEKSsyOTgRvbBBbVPproOOqQoTMTtNnRGgmeHlLdDTLcCqgGQoPyxtqnNQuDdUdZzpCcRrsSXPpTtftsDdhHGEegInNRmyYMWwrHdDIXpWlMmuUXxJjycCiIBbYmwMXxmZzXxhHWFNrDIlLiISsSQqpAiRtTrAaQwWYdDeESsaTtwwWbMmBOogkMmKGuUWwQqDvVgmLlaAtKkcTJBCnNfcCiIFiIsScbBVvugGDWjdbBmRGgqQioRnNrMmhTtHORuUSxqQibBfVvISsvVLllLsSAaBbioIBboOmrcCrEeIRriRuUbBNnuiIUsSMmVvzZVvoOMmBbLlTajFfJAmguUAaGMXxxQQqTtVRrvEhHIieKkqzZBbBbXhJjDURrbBZhjJhvVHHhoOmgGXJnNjhMmrRSsHykaAKNnNHYyhnRrqQGgEsnUuqvVaAoOBDdOdEejqFmMBbWvVjeEJwhpPfFKkSswvyYihyxFfXayYFTkKznhhHDdwUMAamuhHxXdDNaAIiDzlLZbYyLpKkVvmjGgFfQiYyxKQqxgtUHaYNTtpdkaaAXxTiItvrtTVvRrWwkXOoxIiDdNTnZzqSsnNQcCouUWwQqFsuUOerHhREpRPapRrPPfFMAamnLlNnyOodDSsnTsfqQFUurqQRDhkKfFEeHfalLAKUVjUjJKNnTtLlOohlPBWwIJmEuUeMYyHhAaVdfFDdZoOUuzHbBzDdXmMxUzhHWwhbOoWAafVvVvTzZtTEAlLTtAadHLlBbBbDqwWIizZglHaAwaAWQgKMdDhHsmMokfVvAaFKtiITvVlLOpWwNnvVvVPGdDTlLCnNnktTkIiAFAGZnsSoxXdDVveExhHXuXxMmLlUhHuUNSsncQqRrAylLrRxBbhHGdtkbBKTDDdwxXwaCdrRuULlGgUuDpVvPGzZgEecxXZbHhNnBobBRrObUeTrMmGHhHgLjwdDDfFdlLDvKfMWwmVmrRttTCWuUNFRrfgNfZpPzZvPpoOnxXTtcheiIpPOGiIQKxzodFoJJjoOWwmMWaUrgGvcgQmVAgSqaBKkbAQfFMHhONnPpcJIiYeCBBbVYyvbtvZbLlpGHxsGgPpGTtginnbzZluUHEeaAhFnNcCMXxYfFvUryqhrRxrRXTLltdDDyYrgGMtLlCCcGfHSsfwrReEyYgGlLfFMxuUixXIWuYnNyUdDuegVvfFjJBvVyPphHcnNCAaSOnNUKdzzWyYwZaAZCcRrkEVxXYoOEKkzZeNhHFlUuXhgGnkKSshLlAaluwWULHKkcUuCzJgIiwJjWhHYuPTKkhHGgVvmMtTYOoyUqQyYjAawwWLKmMfQqIirRjKhGRrgHkNnJYKQqJxXaAqHjJLUukIxXTyYjJWwtiKCcpPLlCtchiIrgDdKzZfFpXgihHLjJlSssUuSLpSeEtmMUlfHhLxcCpPYzZRrIisMhzNAaqfoOFfpMmgAaGCcHhPcTiITtvVkluAaUukHhiIdDQMmqKiVvyYkOoUCizzZZuwdyYMWwGVvmMgZmTtxyYXMzaxFREsPpPpjLAahlLfQqFlLHYybEenZDdcfFTtFvVGgPpuUFffCpPawWwWAEbBbBenOeAzmMfFMIwaEaAjJwTWwmJjMtjJXxbBWKkcCnNaQXxXHhsSDAapPKvQqVuUkdOoxpPrhqlvVLxXhDKkcCdakKlLNhHyYnkKnSsNAmMtDdTkKFfMmNNnoeESlOoKMfFmhmMyYNnHvynNmMwWnNMmFfBpHsSuUcUueVvtTEChPUuhNmMrgGapPeZxXbZzoOmFfpPMIbBeYovllLLoOKkiICcbBRoOiNntTcCzJRriIdDKlrfrRFvVRLkqQuUwWUXtTxjJaRocCOCcKgZUuxoOollSsWMmwLWwlOYyoCsdDSOvUuzGgBTNEIiIieLlnpSXTdDBmdquTwRrVvROoruyYeEyYUzZEeNnYwWekfFAaVZwWzzZdKkYCpPEeqQsSEBPetXzZxRbdDUxXIimMuQfPYqRrDOodQfNmMSflmlMmJjyRheEHIDdWPpZqRyYrxooJjaAKkURbzwUuoOWKZEeEKkzkGZzwWWwwWWwOnGggDdErWwHUuvOYVQqvVpPbDXxPYUuDdyWlLsCODdRroeTpuUGgNhUugGaAgEPpFfyoOYezdDFfPCmMTtyoCcOeEvVvnvoGUugOVvuUMmpPZwWzeqQUEgXxEeFjJsTmUuMEetOohBbsSHRrWwipPTtnxXiIWwNuRrUStoOTQqVORCciIroBbZzuULlvOoxXxCcWwXeEaxLlSsZzujJaGBbJjWRmMrpHhPFHPSzvRrVFfhqQHZYKIsSokKOhnNWwYRjxXLlDdwefFEHrRSbnsDdSOoNmMwrMnNDHyYrRqQrNDgBbHyYfOovVFBbddDuUhHiIBsOopPpoRQqJQRoryYKxXkRDlLduKkGgUOPQviIkqOSuUsoZeEsquFfUQqfxXFQJjsSaSsAvVPQqpCpTtLwtOooOSsdRrwWDhkVvKiIuvVVvlZGgzBhHtTvVrUuwWpmMAiIsjJSJjnOoyDdahHAdDiQGgzZqXrRDYyQuUrdDtoZzOuUclAaxGhHdpPDgveEhHeEmWKHSCtqndDVSsSmgNtiIUuAaTXxKvhhHqxQqXrRQHVvaAVXsdDLlIissStTPpYNnyFMmAvVnNjJYyNnLOonNvVUuIBbilYnNqhqQHgsSJDpntTNPaANmMnIidJjSulLUzdQuUqHRrhPYmPRnNlLuFfULBblFuUfLlJjRrCcrmMfeEFSsxXWPpwvVvVCaPwIFfSsuUDAKkRxXxkyYKiCcIOmBbMIinNchHDdNDnNsZzSOooIoOQqPpdDirROqJjhHZzQiIpuPUuXxpnNUrRPiICldDZzKkuUNRrjoOakKEJjZDniBHYyvVwZzGzQqcCmBGJyLlqnjXxJkgUYyprRPGqQaOodDAaNZznxvHhnNjkQYOoFfylxjJXmZfFaAzWpXhKkHuUYyTywWFflbnNJQOyYotToONlLROorTtSsbjJBkKHhOsImIeEXUoOjJBxXbzKkZZtTzrOoOortrsSadDryeEgGeEOoYriYqHfFStmMTvFhcEexjJZzXCBdHdKWwdDHUzrRZpPeEvgpPDgGGHhgdfYBbPaAdDQRrnhHNiOorzZXIiqsSUuQtYOlHXxBLlbTReFKkqQpPkKfECbBIiXxmfcCFLKsSklMvEelLYjJyeEfFohmMChHtTNniVRrnNSshWygWtgqQPpxXTWlQqLmMAkKNngGawWCdrRDcwtYkKfNhHUSiIPpSsYyKaApPkMEemMNKkmIfFMGgkKEeTteEsNkKbBxfFXFkFfsJFUuXKkxsAkUWwujJGTMmHqQrRJLBblCcQqdFXJZzpHheJTtjfcVvlLUukcCkkKZzsSqQSAaVvsiILoOfFvVWZzRLzeLlaAhHqQsSEKLllyYLFurqGqQuURrrdDRRrXWwLzZUIiuZrlzZgKxrRIOuUtTUuoEeuUaMUjJiWoMmVvfvbBVHhQqFXxiwFfOoIpPaAvFfbawUpbBOBMloOiZVvzDdBblLPFzYgSsorJjRbBGZzzBGFfjUuJdxjJBrCdVEgGLlvwyYYUKrRyucvVJjvHsqQjJzmWwMZGgtgQdRcnNDdJjJaFftTASegGyKkXMmVkgkPpzxXZKGAaAPparRKJjWwsuUwWEeQtTiIqIibBAawMmRJGAdDQqMwNnWMmmMEejJwkKWmuUISAalLVBbnNxeEBbXAaoNnOvVRTteEKoQqkKrGDQKkqVPpBbzxNzeGgEZGeEaWPpnNABaanUfFfTqQHZzwYIiuvvVxvBbCcNNLzZYyrlLiGgItTqQRrfknMAoKBbGgzLnNlUunNvbzZBsZLlvHhqeEuXIPUCcowWOUSGgKfMmFcCfOoOoFHeEKkcCsWezkdTGHhnNngGNKHhmzCVvcWNPsSkWwbBKCRWwOsFqSsQQqUSGofFDOoRrddRIKkVvJjRgAaGaAwjJWwYbBtTqyMmYLlTtrRQyYsxXoOZHhRPLpPQSsagkKGAVFfWZqQcCHmUefjLlJAaEkUuKypPYGqSwzZqnwWsScZgTIWoeBbEuUbBcCOcCMgofFOzZXxGsDdfFShHmCcEePEYHIihpTAYyaAFfzeEBnNbDHDbsknNrRvlLHmMNWgGwnbvsSbRGXxaAwNVBbvOpPDGgddDDsBbfFnKkNfiIFIUJRruvNwWnVrFfPcCpuUrRuTOotRrhJjvDTtdVOoOiJjIpPsSSsoxFBVqHhuUQvivVIVvajiXxsuSsUulMKkIvMmoOViOoKDdbBkiYHhyIunNMmUnNmMAaTotTEQqQqLbBNlAJeEOWTtFiIxoODuMmzLMXnNNGYMwFfFdKtQHveEVhYeEIilRXxHhrBWZzmubBtLWwlJjSsmMrkKQpmMdBJjbttTKOcbFCcfMigGRyQsSaeEkKYyeGgWWEqUudiycvVAXJuUjJdpPkjJKClWwRtTmcrRfFdDyeOoDIyZzelLEYrRcVQAlHhBIjJdDsSfSHxXRogGnNuiIxeEPpNCcDdnNLmMBbimMLjxuUXJHdtRQqrdDTMIKITIiEwrRxXkyAgoOgpPkKISnOoNRJjmUllLNcwwdDiyYUuAtCkPVvvivvVpcCJjPypPEeYyjoOwWMmJYkdYrRJgDdsSIiYyonpJpTtRrWwrLEeaLlocsdDShwWwktIPSsGqmDdZzMCoWwtZorRjJHbBmZyhLlMVqQKSsTXEexNnwfFBYwWysqtTgsSPbSsBDbBTPgGVoOAUueMgGeEmEEExqQohHXxpMmhxXPpLmgGMuUUTdDbQbZkKzgGKkBqroOQCcSZzfJkVMmLvKhKRYbBkoOKMmXWGgCoOgGWwvVUBgyYsWueEvVUgGzwdXAaubBMPpuOORrNQqtTHhnxnzZNXtTFgtTiyYwBMmNnfFfFTtLxXLlXOEefFoxlLbBlFfhhHHoOvVWwtPEeLKkxXdDvVUqemWnTuMmZZuACcaxHhWyYwLlwfFXxmvsgGSVeEMEtBKkzecUSeEWNfFPRrRrEEeWtDdJjTrTdCrRJzZjReybBNHSgGsoOmkzXxAkKRrIifjEepoKEIcCieKkLlpPvbBVJjZzTtyoOXGgxwWiIfFmtTxGgxAUuaNNnnXbjBoObJQmMxDeRrEpqQPjJkZzKeEOCfFeQMxZzPMmKiQgCRrRrYUukBbNZzokKeQoOqyYyWAyYcCcCXIiijMLltThHmoOJXsSnWCSEeyYRbzDyXQrWqTGJZgJjGwWpIHhkkQqKKuHhUiPzgGPpjSsJPprPpRjJjpPZdDsOlrRmhcGgCHkWgBTtTZdDUHHCMmvhHbIiinQqYyPpeOngGNLQlLqjPJjcCaoOjzOoZMLRrtPbqQZkHaAhKIogGOIiwZZVvVvdBjmUAQQyIsSQawWbAaUwmMhHFfDOdDLpGSsgPLYaAbvCcjTZxIosSOVvyeUvLYBbomaMAwWajaATtJXxIHqQNnwWkAekaXlFflFIgmIigAIiYVvygGDdxSPKjTtKKkkaAyUuYljlnNSsPpOVdnNCcOGNnzoAaOeEBNYfFSvxpPYyXCQqAacAUuJsSHYyqQOYyFfiBbSLMmfqQFllBbiwWImMCcURrQqVvNnqeHbBAonzZgEssSSpPTLSsLllFftNnptiITJjQZdUkTNXgGHhHhxntZHhYvDWlogXxXmqZUIsSNiIhHVvsSnvUtToOuViNttTlLVWBbEenKkswWSyYNfmtkKpPTlLKtWwTigGkKUuJZzZAzZpPAeEBbaUuTBsqCkqQKcqWwBsSjNVvnvMLlrRAeEaAzBbvIiiiEmMekvVoOOhHogAaGzZDLMeGgtwWTyYGgASaVZzgWgGBbZyYXBHdDhwuUWGgbxzmuYyFfUMNnTFoOfjJFfLlJXxjTtMrnohrRiIHslnNheEzzHhZSrPqHhQppPDyzZtxXTuOQsvVMHZzhnhkUubBjJKqCcuUAaGJjsrNnRJdDnNziIhHrCzZcQqUuuVvUhHPBKkpPucGuUgcAaRipozEBbsSmuhHgaAxXEqEeEbxXWHhwwqcCsSFfmMppPZIizqTUPhvxXxLlXOhHzwWZowxXgPpnNGkUZJjrRsAoOaBbnQMJjDVaAvFfnNBMmURzTFvVfGKCmMVWwbIiBvckuUMmzZnXEHNGgtNrFrDLNsOtKSaACBbrRarRqqVvQefcoOHQwWuUdeqOoHsSsSpqQMYyzTttTHhtQKmMkcmVWmGglBQqBbbSsEekkNLlbBYybdDNnBkKFNAavVgGyYiIeECcdDkKyYGgOojRrJJqwEgGezXpfDGgtTdyVQqvlLcNiIeHEewDeIiYxWaFSncCNhpGWXskKLgrAaDsSdRJjSsiIEMmenYyNfFoOTtiIRSYWwuUwWWbBcChkKHMpPrRmCXOZrXFfJrHbSYGDdkOHPoucCmMFWwfwzOHhzHmMIiEeUvVuEAaeuuOoREtxIiAaBnVvNbbBwtTWIUwWAausSUCcAhHauQqmMVyFfWRzNnlXxsSYRrGgYYyHglOoiIsOxXoplVwWpsuUUJjumMeEXxwvXyhHqQGOoBVGgvnNWOzpPzZxDgPpwVvbQqtsSpPNaAnbSvTpbkWgGiClRrLZfIjBCcbEjJRBbtPpThHrSPgaAGpQyYNnuaKXdIiGgBTtbNVvnJdqtTEFfLxCcXdDleQaDKiIPpkRrPVHDCzqQtKkQMmspioOFfQvkEicmMeAVbxXEeOoHomXviwkHQOVwWcyYswWJoOfFaMmGgLVvkTOHhaZzlBbCcQHnbBNYZfZzSsIFycCsSTlLtYfiIszZSBCgGKkVvwIioiNlLnQqnbriGlLoOinHxZzvAhYyQqJYYSyYDkcCKfUuFPpCUuPpxEjJedNwiIWnzZDxWmMLlzZyTeEmitHqQhKkjmMFKsEuUVcCQDjJsRrqIiQAjqqQMkZkKkKEXrRxekKkKXxyYavAXxfgGSDdXLlxZzTsxSsbBJPpxXorRZQqJvgGVXxiIjaKvVCcjlLJLlZmMsBbfFSJoVoOvgGmMOfhHqYynHhJjZzNxXUgnNWwhPrRMXxRPtPeEpNnVHhdXBbPHLlnxXNhHqVRvvqQwWMRsuUbBSrZzAaEnAFfGgLlSnaACcBHdHfFWvVsKLljJskJGcfQfFUyjoObpYEeyoqmBVbiLWwnNbzZBlxcZzGxXggnOodwnHhzZNEeNkizZfFqBinNNDCcoOdnneLlfsqbqqQqaSRHhFNnTtfciAchgGHEXxeYyhgwmzFeqaACetTWqSfOoAaHhdkFfzZCcTCJdDtUnTQqtDuhRqHhQAjqHmPpMcUuCQEeqjJOgQZZvVozTaLqQlXYyxlpPWFViRZzAaRaqMLbBlzDdeSPjvHHFGRlLrIigZzZkXNOopPzNoOunpPIQqjdDJjJWdckTbacCcCtlzYflEYIwWGteEOovVOjJWwxFuaAcCKkUuQKkrvVOzZWlLeExAZAXhHUhFbjJBHyYewWRrEEPURrkMmiiiHyYmMUqQuqQUcyYOomMCUgGROqQDLldqtpPdDCBbEeVXxcSweDdmHknGiIIpiUWnNzZweyGgEepuUlLPzjeEgGkzZpeEPrLuUlySsSECcQqnmGgfWwsOoPGxXnPSbaFjJcCTthNnHTtjCcJSzKkvyYEeoBbmMqRrFSsiwWGqrUwWBbuMmPAXxapGLWEDdepWwzZrRHWNnoJTtcVvXqeEQWwCcATubBDcCUfFuHhtTXxsSMmZrRzqdDJjuquxOoOzNnLlnNuWwUuhuUBhdNRrnqYlmHaCCAaiHhGBtTCcqmvHhMmVnNMOoeneEEzZeIiIlgfHewxXQqWEAnrRWwNFEBbeoOZsiQKrRfemMndDNEMmjSstTJGWfFNgzriJoqQqFTtnNrvWGgfFDdGgGrRLPplruWWsXxJefFTtEOofFBbrGgOqlRryYLnNAUlyrRDGqXxQqonNOFjiIJidIiyYDIKkMYWQqeTkEozjJokDdctFfKkTazJUgGUkQqgsSUDducCfXPSspZzvcCndbQqqQmTNqlLYYyIiymILlhRTtrwpFsSsvqgcCTjJqQzZtMsIDNGgnlLClLdGgeOpNnKCVvcGGwWgVvjJUurRgMAaMSQUuqsjXyXxTXlLxlOBmMnNWwMCFpPvgMuUfMeEQVCqQwWcugxDVnFWzzRVyEersADdmMETtkKeaAzmMDFfdTKftDdxXTXripOOVvotoGOEvUTFfKnmLXgpvVPOXpPxZqQHmMhzeEoXMfIiydvYyVbEeBDxhSsHyiVLuUXKFfiIfFqQFqbYyMmzOOowNdDnWoVvCXFSiBgGtDFiXgCZzdGBblLuFrRNfxXFnfFOEeGDZYkYcPOtYyNndDQqTBbUuoTZzyYZLeqQpLJvVkKtTsIhksAIiafaAFVvVxDmDGgMmikKIHBnNbFHhfzKkuJAwWekQqVvKmbBVJjsPpiOrDnJjXrccNepbBqpJDsKrkKBlMzRrSpPfFrmMRoObBvWwtTWwVTAgKkQqnlFbyIlJjeNLlwIIwWBuUOobstbBbkyrDHhdRiISZJjVPpZgMNnmUuajlLXXnbBmdcCDmQUuIiDdEdpxXNsSnGIefFSTuUPoBETtlgvVvBjiKaEJamMAUudDlLHRRrXxKkdxsZzoWsigGDJMNYyRlkKlSsMPpJjMBQInzsuUcCRyeUubiDdJjHnnxXNvJUujMKVwBboPpMORgvDdYaAyfFiQxCRXqQnvsEsLlhHJUFfpFIWIhHiylLYoOcAalSswWBbUqQHnmMNUYYQqnXxhNYkKoWjJWoOKhHkcCwBgFfbKrfzOoCcwWfvVuCEGhgGgSlLsGpPeHhEYCcepPecoOChBbVzqGghBjiIQeZkzJIMXxpPfZftqQTFpmMPHHhIRjwlkKtTArXrRQqXxqHTjDdoOpULluPQqcYaAciICgGTjJFftACciIjeEZhWuUknhUuHTSxXhHyYIZSgGPpkMmazZBqyLJCbTIQPpCguSZzskKVWwvGCcNngkWHHgxAYmAawWMJaKkHgFfBbkUuvVDdKvVzjIrUwIiWuRiDRPtjJFMwWKUakSsKAarRFKHhoGgkKLBeKxHHRrrRxvAaKJjLPDddQBbyvPuLMWMJjlLNnmamMHhNncnvVNcCboOBGMmdDHtmAaMXxwWsSpsWrQLlDdstpGaACeEccikSIJFUufGdbpwWPpsflLAazOoDtTMmEPlLsSroMBSbBEDxdDXgGqQLLKDdUSsWIzKkEeEWwngbcpvVoONRrmUutTiINDCGgcXVlLvVqQckKcCgoOQGgVBWdDFfcCoAaQqUBbZAaskKgGSWivmMQvVqHEehvLEFfehHbBlhHwWesLpEWlINndDiiLoOIzZioDAVlLXcCgChEFSaAbZzmkKHDnrbZzBlzZLeqFkohHxXvXNnwWxRruUVnEecnMmNbhQLlqAnNNnzZuPHHEGtTgoJvVjrROqtTAaQtgHhGKBRMmPyLdDiwiEQhUUIiUuTGgthORfgkDdyuWwrGbBVqlLwqQuRrUWvVPnNpKgGOfsSFpGkPFIyvnWweJjqdDQBbanviIVBbNWyOiuCcDdmjJxXCctTSUkIlzcrUneoUbSMmZzzZzOapUuMYGgwJzZjLwTFHcaAhFDdUutTVXVvxvzBbLlJfFqQhaAozZkjjRUDdQrNPxXGiGgIbBTvVxHWhHwVBTesSyOFfAYyXRryJNnXRrxKHAatKzInNirPBUAiDtDdFNqaRrEOoPRaebXIixaFrpDsxrSsTKkbIznNlhcYgQXxqURrUuYGAasrvzGFiiIInKkORrPpHQwWqKUuwZIUcCuxlQqwWLgIQqtdALYJjQpwWUWwzYyBbvVNnMHxXnrrRFrqQuXxuUFfuNnUaZzTiXIGERZOJFYvnPBQqoAlLapPUejjJuUFortMNuZzEeUjRrRvViIOMEAlLLDTVvOWnnnNNseufpPFKkMmtTKkXjvrAaRZzVRSsUntNnZCfdNnoOlhJjpnJwECTBBoOdDxzipOoHWwNTZztfRFfrCclLCrlVHOwBUuvgyOsOoaXVMYychQqHKdPpDkidtTeEbsbjvTtVDuCjTtJQFEWuUBdujCsNnfHoOFfhNnFbeEwDdduIOyNnXxPkKofFXkWwYXKpPkHhrRKkxycuRuUAdhHDhHPpOUmIicChJjLloOYdTdDKylXcwfFwrCyYciIYXdDUuOkiWwrVvRuBaNSRrQqsmmsaAjeEJsxkEernpPrDpxXfvYBeBbPHhwaBLlEeEnNkOtYOsAJjymMNZbxXKxXjJNqQaNnchRqOvMmgFfnNwjpudDvVJKehWRrbdiEeIGgjJILzqjjyRaACMCAazZGkKiItTgPBLlscDWzntTdOoQWwqoCPpUVLlpjJmCcIiLoOxXJjlTsaqQGKpPrRLCcZqDqRFyYFIiTpPtwWZGgvJzfgEetLqnUuNVvQUuvTHqQgrDdRRrCTZztcnvOssKkSrRZgpxXHZWwOeElwWgJPdZjSspPJputTjeYsSzBatJjXxSsdKZKkGNJjKkIkKJrhHRAaMoFfbBnNuyvLdDqfFCuGgUcBbQhJcsSGgDSSDhmzduUKprmwytTYAnNafFMmuNBuUWwVvjxvxXbJjAFVqUPpAoxlVvLSsgGUMmuoXPVSiINwWndjRrZPpLlZLkXxPvVzydjJVbBrjXvqQAzCYyclfrWwDdRlVAvxgGXVRGgwsSABTFfmMnlLqMzdqQasktTNTtCnVvruOonDmeEgGvaAiImMWiWcVnoEICoYQmsrRzpPZSaWwAWgGBwhHDdzxOEYyeUkKDNnyKeEHheEBbXPpDdvVlsuIrpBRrogGWYcEetiIefouUOZgGzkxIbBmgGMisSXdWwDLLLjJJucQDEuUhsSHebBuUnlLUOoRLSLmMWkKyRZhHCwWCgaXxuxtNSQhHUyYgyYicCbBQhXxTPpgGKktxgkgVdUGabBNndDIigGZzHNnYuUyncCrElLbrsjHdDwSwqQWxXfHhWVamLelWinkgUIXwSqfrhhHIirRLoOWdDVPLlunNUSsVvyGnSqZQzZiZhoaAKklLYZvNNoOnnVnDVvdDdNhJjAaoOKrQrMZzNSxuUFVvnNIrROoutTANnaiIuwWCjntRrwwtuRuUafSNxZSsBxNnDIiVDdDOxtOwWtTbVkKgNirbXcKkrRmMvJJjathRnNFjJooTLltgnAgGqAaQTtWwOLKkaASIvtTHhVidpvrJFWwmMlLySMmsLfFlXiJaWWwPpWwLlaAxARruUBLIwWzIimFzMfFnsSNFFTXCKkcSsTBbyrQVhHbUuVLlvpUyvHhVYazZCRrcfmeEKkMvWwWgBbXBQqmMoOHImoZldgGDgGkNnvcxXUubBWXdAaaADeEXxFEnLlROQcCLlGNAhjJHaeEnvufFUrRHfNSsnmoScgeuUEBnqQIiNbevnjgoOxXGimRCZwWEjJwIDdiOocgGJyPpYJyssyYyYifUWZPpzwCcaNNlrICXnFfMmYFfyTnmuhyYHUIrRibBWwJCrRcGRrIeEyyjpPhUuhHkgQXxeEaEKzZevUdJGexXmMfAoOBbSldjSbnNBqrtThIRrxXOoPpUlDgGdodfFxbBHyFHhrLOEitTyBbdmMDzZjbkDdAaxXoCjJjJcFAnGuMhtzXxewhHtZOItTKMmNwVOSGYydDgFavhHClLDdcfBGXmhHwjJZzJRMtiEevGlLgVEPrlGIDrwyXoUxPXxpAbeJjJjEBaPrRpXpGlhKiIcmrmMRMQmMqmPphHMjLMkTthAtLlIZpPRwOUHsSbBGpPiIOZzMuqskZacCnIzlLHbzZSeJwidRvVDWwdMGnmOouTsYsvVzhDHRrMuamMAMsMmSlgGCcLZIitDRuoOFBsigAhazZNHogBXdgxXcemzZeQovVaAdDyIIiuPpUxpYtASarJeEjgNrzZKkUuFSFvVgKkYyGnNaZRxXKGgIiSsceXxlyhYKSBmMsxXggGSMreEKkKvTtoOEeidDmMiZGPpktLttCcitfUZjJMOCpXVvwWvqyAaYrRdLWMmhwWSKkLIxXilIiaLlJjumKJYkvHhVuZuIMvVMPnkKNjIdZeEmMEeRCcOXxnmyYMmHhTXnNnVtHjJmXtDdOgaPrRDdmHhbBXqQRrRrqfDdmMFQaKktTuuUcUYeEgGhoOAJXtaJBZJNMzZAlniIoONSstTLvVamnQqPPCcSsHSsgUIRKGQqxxnNXGgmtHhrRTGVWwveGxPXpUBjGgmtKkHhTjVytrtnJjNrXmMpPGQCfjJifFYyinijZjjLYvzmMZewiCUAaWLNnEeuNgfKkXkKkKyYXPuUWwpZuUDdWrxQqxLKktDrPWwaAnbuxuwlYIiyLdCrRqiMPfoNnGGtRrlSsWqfEqWkGbBxXgKyMMmJtBAvqQlLVvXlLxnuUKkKHnPEekJsSXuVfCESwTUQxXqumMzeYyyKyYdITSJhHnNcCUwkEeKBeBbTtPpGfXOglDdechyYynSsYSQQfwkXZfFPPpXLlokMmnNarNvVpmlLRYyUYLlywaxknUDeEYyaAELjJiIlxaxXWtTYeEBbnKkHnGGoOsXxNQpPAaOhHGgoicHahCcWwCJCvYjrRICqUFfbBTMytqQsCcTtPpmWAiIRIiNnaDdtTAHFcCvPjwIXxiWvXRrgZeERjJrIRFfmUONndveEqPTfKGlAaLKkljJFzZKkDdMuUvVmfuBypSwWDktTtNZRrfFztEzwsxbBEhHBbDLlVvhHiaUuZOoAeEannTlZzANyuUJjYUuYpPNmeIrRcCiDdeEdwvHQcPpvZzCHFLZzbIidRrDqqlIzZvwiIAagNnNLUuldDLwgRzywWVMKrHEsSDUunxlLWxFpQHhqgGGgPDTmrCZzodhiDsSQoawXYOmScEpApPlPpwWoUusNiIBwWbnBLlkKpPeEMlNzrdqWjJwnAdYMLtWwUuTaTborBaBXMRrsSeiMGgLlJYylIiZNnMAaACcaAaEWBanzVvxZpwKkWLUuhTtYDdxpctFuxrXxRXYTjKkDKvrNKkFfnsDCcdSuVvQfFdPMmKwsSWWCcEevVvVjQfFGqnNJYyhoTerRaxnzfFVGgXmXavDdVqQoDBPpABbkKkzZTNSkKkbwHWORCcJRbvVgGaJjnNiIDsLagmMdDyYGRrkSsywVOoJjggGGsEvVLxLYqDLlQaTimFkKeEfobBylhqjlYyjNhEeFwnrRBDMHhGSsrDnNVIKcrsUuSRrUsEcCOJvUcCuIlYxxhFeOYydfkPpUpPumMfFfFFAaqQftrZzHhibqwWdrjvVxpPXHhMmwQqLlWbOoSsxylfyVdJYLnpDzpPoiIOZmMDVGgDdxkXBiIQcZlvMRaeEwWvxlAHUuHDKktHmxWFjMHwAawnNuUdcuHpMmKYLPgCZzNczoOHhoZzSsNTEVmgGMXxYIfcLVBiIbfFAaBZYwyYOabQOOBboOpudEYmpWGpSvGZdDcTtMJjmCkKecyZXCvyFtnSvOzZsFaAfSsVvSoxOuUWHnNNnUuJrGClVGvobBKktFtTfFIifEcCeVgHhVbceEPzHwGYHEjZDrCPpcwQHLMoOmlelLopqOowRkKCWjoxlLNxejDdFXxaSTtsyUcEQqelVKcqVXyAaYANFfInFkbBiIKjpprLlRPRrMmuKkuNbJzZldaUWwZzuAGgJiUuzHhWsmhIiOgtqkPrUjKFAThnNJMmYcCHhGIMmOobSXLHzMUulaArlLRZNnzRxnXxNvVWnFoOfZbcCUlDdsBbUOjaAMCEedSfmrRMukIdYQqyDegGEujxXJEeLltlaIPvgGobXydflLVJvVNnrRmUEnmGgzZWwjjsVvNtTEsEWkSsCiUuIcKlLUuldjJhKFUXdWMrbJDSRrNaALlnhXVgGvIixrEZwBVWgGwsuUSrbYyoWwIaAyYLzzHsSTWMmtTxoOXSuSsIaaAwaAWGkKsSwOosPPplogGbRnNpMmbRvwVOUugGdVKCnVPcJPmyPaLlNeEnBbbtdSsqqQLkPJJJjeMyZtyGgYuULlMmaAQqaBuuQCIkcFKdsVLcTFVpzoOZdvOoVyExXiayoreERFWkYjJMmRalEeCcEevUBPdhVKdQCcsNMOOHhSvxODdZvVXJlqeYzlryYSsRLFYdZewJzbiIlbBLZLYpjOdkCcAbKOoTtsSpYTtaMeaehoeIiEFRrGgjRrJfuKNQzFSsBAahHfLXxlxeTfFOwpuQwveDlLdGPWwpEeHvFLeGmWdDjGuMmUPpeEMmKBDuUKREJEFfEewWHheEPRrCEeTtZiIqAdDaQXhRNfucFcTcRctTZjwmneRicfGzZoOLizvVxYyXeEIOoqUnqAyiIQquURrVvFMmzQqGhtTFPhHpzGgXUvyfFzyUurovvLRegYXxrTDbBIOQqVhHHlLCcXqQpwbwNLleNnkEOEBEHpXIixBbPFtJjMmdFfgZhKPCcpVvlObNsoOHZrUREHaAKgGkpPFfAYXnNenNKGEiIefZcMmxXBLOoQuPBoETtYhIiipPUuvCIAasyYvVcJltVSyYsvBmUfSTKkWBMzHcZzCMmLYoqjMJSsNyxXBbQpwWboHQweEoOHHaAuDdDNHtkKMmRoOthoeJxQqFfLlpYYMvsvVIqmMQgGeHIKSbhHBRreRrEFFoEhVvFXpYuNnUyPhHsIvMMmBFOSogiATIyIdHUuMiekKHtiQiIhHTsFkOZzoKYZAaYxRzaGtpVvZlLhufFUUsuaArFKJwvPBoAHJUxHhtqYFfdDARrpPoCcVNnnNvshOPpqYyPwVQazrRMrRivVMmIBbagIeuBbPEeaAmMpLlUudapdDPADTtUDdEiHhGAAMmaOomWrRwZAqvRrWTtpQUuoHSYyZzVRrKkRnAaNrvOzZZnEeEXxesSNzcCaFfviISsVyQTXujhaSsObEepbBJjVSsWjkfMmRtTUSuHlLqQzPTgAZrXyDXxdzMmyfBbSmMtqIThnNEEeImqQuDgGdUhjJDWwiYzZixXLltaIGOsofbfFmCcViSCcsSxmMfHsSeOCcfKkfskihcCETtilLSVMeEgdDGmmyNnyIiPXXxWwjEdDOHToOGgrThndUhyYXxZzheyYEWrRqhOBOowWPyYqWwGgDdHhuUnNYuUQqnjRrmJQOylcChZmbwtVvGXxgsFMYymuMbMmDjJdJwWjTLjmMCSBbiFfcVIYyHazZAQwWqyeObpwWUqfFlhmMCKkcHbBbCdDzDgGDddFgkExyaeEnNheruRuUzhSnBoLVvPsSpkHzGDTtTfhebeoeKXxEEenWDMmbBdBWPxHcChhvoidtRJjyGErlOEeoHhVviIVVORZzBbYQlLqZYVuxZfHgZfxXYaQNuQioOPpZIhHlnNgFCIrrRENMWJzfFCrNnCtChHfCUFJjnrkKsSHmMxzcgGpHVzrRZvhXxeAeNnCcEajerkdbkgJwMgElfXxVhgDdEVWqUPVvWotEXeEFbfuUbBZIiqnkcCUeEOHEAxXoOEmAyPOokBaKDoJsSuUPzZycClzlLBUuZZzGglLjEeWEzDyfZyEQLjxzSsoXVsoWwcComnBbSCcqOoDkvHDpbuVLAcryjJKNnwWwsSxXfOYAIRreWwYDPvftCMmlLlvkKSDkZzfCCxXGgcKicpPqUXxUbAAaTzYmEjjpKzZlQmMDyYtTTBRrApYMpQqjCOopvIiNDdckvDWwXxtToGgvWVrBPrBOWcCwLpSWgAWwdDiUnNsWKkwwjJthZOoEeZqQNnlmMuBbXxUiOBWtTwRWwvbWzeRXxHsdjBRmwDxYyufkHDLlaALPpweSeneESwWJJMNZzEeeuMmMnNjvFDdDlLYpPxBVvPpOVpiHhALTlLSszZUiKoOUFsDEecmJouSLuBzNwXrjlLKkJvVLxaAXmZhlxseEgQqGBPpiIigyCaAcjHXxvVXFfxtafkJuHhRpKQTGoeEHMSwUYyuDdZiuUIbBUnNuIjDLMmjBOonnNUGgUPJfNiCcnaxvQYyCkvBbLzZDdTtCuYSsEeAQjJqfJEXWwnLlXuUOJwngGNcgGrWQnNPOEhqWRdpPzJehoOygnNWuUgGhBbXxZpCBHhvHhGDEPpeaAdvoOTKUukOVgvLcgRjhwoXVsNTfYVcxzYCEzSdDsgVsxXPgwSsPMyEDdeiIeDUPopPIioqBAkKFfoWmMyaAzbvpPlCFihHDdylLveIhHitnxXOcCZCncGpuUlykPhUCDWWhmJfwXpPMhMmTdhDuUMmdpPhIiaxxXJDHhdjoOXvVLaAXVArmVLpuUPlLzCqXxtAaTbxKXvdKkdPNkKlaAyjDcCWlLwvYBXxbFLYXBwzZWJRDQBIxHnNhDdXZzRlLTfSsPZoOzzZpFwSsWKbFfBFDoIiEfHXXyLiUuVMmjoDdeSutTmMRCkivmtTMkKdHhRgmdbNWfHOonJSQqsLJQHLYxXOAaZzqqQQMItKdDkAGgqPpylLYaAdQnNBbyyYlXlLzZlezNCKkcnZGkKQqgSvWYKAluUSdAJOYtTyojBrjrowhWBKtTsntKfFabSsdOvOoVAxjJMMUumQqxvZNXAEtOHjQgqJCsScwkpDqUfFRVkdJtWweEyUfTCPzZXyHlPDdqEeQzXTtRrZNAbwsSVvoOevVmzLjmIEmxbAbROBhHtAQLlqtTlmykKDuVvUaNQDRZnLtTbBWfFwmbmMCcHhSjJOwWLarRPAaeCsMoyxWAOqdIHDOcRMtQqdpQqPfDdXxXwXNacCAFfdehsSRkmvYZrGWLUullAanGWvVViLQbBEeQQqBlfhcVCqhmMMmTtVWDEMmMnynarRLtXxNVvtZzTnNIiLlNQzZqAazAIDdNDlLDddnLldxXXTHhtxeXSqlLQeEBbNnWZeTJjnTLunNUlPBbpuUKdOosPUuYbULKkuUgkGgFtWwZzpQNneEVDDdMmFfouMrizCuUcGxVJpgGVjJXnUuNxfhruYyEeUawMSTYmtEeJjCcnNVvuMmQJjcQqbByYiJyVcjWwcZzPOopHAhCIqQjJjJKkqntTtTTtIiSggNhNOoyTtXxwAXedSsuNKXDdAWHhubfFVrRPpvBrEeHiIhMPIinRCcAKOxyYpANnPpazxKgeElLdDGpPDdWFmbBWwMqGgKkqsyNYHSbOoPsSpBsCEkXxKLGowWHhxFgIiEbWupPoObBBbjCcstiDkYEZtWsecFbBvMmUxjKwaAiIWXxpNPphkNpPXGgxpPpPVabPgGAapTjlLEmMemYwzZgGKkQesSFQwjCcJLrRbwIiWBTggIiKkOFhHpmIQcDWUXUBNdDPpUupRdcCrRoOOoTlXXRwVvWwzxxdDFGnURruCcUlQqwucIWETtVygmMdDGlJJzJIpPNIGgfFgGIFcqOoaAVKfjJFkvJjgxRnfVvFNTRAaTYvJMsSmMJDdbuPnNxpXGggEgTfqQFtMNKknXBAabgbBkrzZiuGhmMqaAZzVvQpplLZzjzbjATxjSsabBHyulLCUAxMpHhAqeEQGoTxMhUuTvGgNxtMNYyorNnzDiJpkKmmYyiUzUNnaDdAPpyYKyjkMUvrRVARVvrZzsXxVvHwlDQVxPRrcomzuUuFDdTITTytTYnNKklYyjJTKgzIImMVkCcRDdmsVtTnNvGgGSbsnZzjJNkyHYPpLEvVCUukBbrzAlLfsfboOBROonGMmRAsaTyPXLliYrRtTTxjJXtvwWVOqERKkxXraAMECGDxLlcCbGAaWBbwPZzoOpOZoOzrTVvtRsTtSqQhnbBQcCqEAMmaTJjtelLAHsSaGISbXxfUGuUgfFrdTzcCmUmNnzZhdHiIZSrRyStUMNgmrDIWjJjEsBhZiNAzKSiIQUmANngGaoTtgxXlLhunNjJoWrIicCziQqTaHTtKmlJCkHLgPHhuOxdDYWRdigLRAaBbpeIsSTmrjcVvCzZZztTWeEMRJjmMrxgWwyQqYbmMPpFzZRrlMmLVAfuUsdDWwBblLovWnkiozpKkPTLmMlWEuUZTHlLJDdRrjmtTUgNafWrRNnwOBkKbgmMGOoKBJUuYIeolRfYhXDOJjLuiYyHCcRQsJJwWnNTtjDLshHaFPpEgjDuVEGXxgJjkqQeAqnNRcCrGKrRHJYYiIHkFfKhiUugHhLlCcjEMmtTexXQNnqMIvViNtNxciRLntTWwnAuFIOoSSYjjCWXxemMzcrMIgxXsSGJtTNVWwVlwWLvEGCeEsOMFMmCcTthVyYZzkKglLuUqoPprNefeBbPUuTtpPpEgGIidDxWwwmMvVFmMfxXCVuZzUKHhLzOMihbxpPGwVFAWwuPHJADdajhdDIiBvLlqRgGIiYtgqQGCuUcAAaamMxtffmNnZfMbBZilbbBxXaXWJjuUwwAjIxLFfliEeIyeEYqQYfjRmMVPDuUskKaAamMAEeaAlZzoaNmMGOzZOfrHcCTAjVCxBRIGgnGPpvBfFoTIitlLTXoskiIhHKSdDdvvVdyYXzZFfbhEeHzXnsFAhHrUQqsSTWWTNJgGOocUUifVvWwoOuUXxWwXsnmRqRkaoOAvVCclLaAoObBHzyBbOHzCcIbBqzQszZpPNgYJjpvwoOlQqrtTRHRuHItOoDbBdTihUFQseEWcCAaxiuKUukbBGKraAgGRuUNIwUuLElMVvAvwFUusWhrRJSRByYeDAabBcCcZzCSsdRtTcCcCNncCZzNhFfAgucCDvGKGXEeHpPxXOoqIGemMEgGuqQqsnLlyYTXjJOoUAGcczrYwlslryYuNCcdGgqCaAUjlllKFETCywnNOuwwWWUbPRPpiUSaAHhpPLwWTtaAxkKkYvVvVTtdaAqoOQuoOozZXZWbwMqyRrOcnCcNieONvCwIwVMdFfFfiIpPNnNUyYRNcEeniIWwKSVvADBbZrRhHXxMmmQHhNtfFbaAyYaWravLyYFSzZsLjJZaGgVxJRvDYAaZpHhKlfFzrRzMmJBbpPtyYTDVvsvBbpxhHOoIiOXOauQvfaBVXJHhbbBnCcdxXDUWMRPEekDmMZMSXxsHdssdCjHlVOoxXNnYUdDODdVvmjtTiWwngzboOUuBkDvCAacVTAbZyEJWjJyYkKwUPpxnNEDdeXGgPKksSzDpQqjzZGwFfKpPkWXSsxLoiIzhPGzSoVNGhtWwVzKkZlTGFZjVzaAfMmKkfUupPrQdQzlpPwWrSsRkgASteEMPvucODNTYytDdZwdCSLlbppdDPctTmcrYbyYBJJQfFZlEeiIiDBwhHHEkjFfbLlBUPJWGVoQrHeECAFfnkdDmTtMyYBuUznYaHhSoyToKejJbOoAWwWpEbBYybVvyJjVFPdRYyNROolLKXBbSSMdaAsSDMbBnAbUIKoxTtyZOozPpnNRWWnNCxLVvNnYCcHhlLkeEtDyHmMHhOoMuRroarzZUCKxOHhpYoPpWwJjbBOAaoiUDWBSRiYyIrcsSJUHhrRDbbBAaUqQupPvVweBbfqcUdJBSYyBDICmCcvBwRrWbxAGgSoxXYLlRrGVbXxWoJjhvLRcRjJrFnhmMPHHhhzZIZlLXbbtYyceCEecWTtjNPHLnlLNoOTtbfFBvVYybBDFczTNurJLlxGgUESnNdDNnNcCwotdlaemocCDrRdrJjJQiIemPpMWwEqnmTROfJpPEaAuObpZAazNRZzRrZGgzrVyfjYyoQEeqBbzreQoOqgixItAIKkiaAgGbBvVUSsRMmfRNrjJRhmZnNuPzZqSsyxXlaDXxTiGXiziITtWkhQqouUNiOoOkKoIfoOaAgDdmMZVRwWSgyuHhGyCHLZiBtRXMmSsGcDSsdTtoOCbBgPpqvVQiISdPRfABEaAArpZyYzeGgtTAMmQnfTdkQqKIaOoucjJaACbpREeZkThkTtjYOoxaoYEtbyYvhXtgzZpnRquGgrJJKOHVvjPpcCcCZWmPpMjJzZBbwfHCgGhGgDdfXxtTtvVWlcCWyCcmPAoZZGgzrJjmMRsBuOCcENuRCZLiKusUlLuMEMmeUIocCGgYwFfAFfQqNQqrRnENVkKgGYixXfOopZzKgPokQvgRqQUYKGFrowcCWHoNnOuUgGxeEXuuHmMqeIiITtWIdDGglYprbkTlmMiIFfoOLaAehhpUaHBTUutYbBPpxwaqCcQeEAWXCjJcyCNNnHhOKeEvVfQEPpZzoOmMdqQTtDRNIisSdhMKkBscCfeHcGxvGgfFnNadOWWwwlNnIbBLhHwePKWDdAaJjwkAaCclSEeEVTtmMVIEewXxzuOwKkKksSbvqGqQCZzqQvxcCHhdnrRMngUuGhrRdDHPCcCBGNeZiwukmMznNalKkLGQqbBgJjUuxXAZlXxCcBbldTtDhSsHderRNnNBbMmoOnFfsbmObBVvjJRpedDdZFSPBRrBbwWDdDgjiseEHBbheEKQqICZVPpvzRyyYYcFfCrgPbBTSLlUuqWHhwRwSPTLlhgcfFNnCQqxYyXZRrzCAzoOoOZYyLlSsekKyYlLEwmlkKUpBbQqZwcCWzVYTtaAqsKkSDpKklkVTtXhhXqgGwuUFfWQkEblOkNnflLrRACcCcukFfmBbrRfTprdJZGhgGAgcCJjGtTtTjyaXZzGhhwKUTtGcdDqitqQQqBOodDcjlYQbAKTtshHzUuCaArRcistNKwHzJZyYzalLaASsyCTrRTttwWpPJtTthQnNTtHhoOxRaLWQqXxEeJrihEeeEzFmijrJjBgGbRZKqQgGzEqLtTlpPJbHjJQZvHEEykKIJjYynYyNiOoHgVvgGecUFZTtFRYyqQdDyEObBoYYyyFfeYkBGbBbYAayWQqwweEOynHNyyuiILlAazZhuLJjCZzwiIiOofTMlLmtPujYyLoxXOlSeSsWwZzSwWVNxTtrTtXqIZzNfFnVGQqrkpOxXeEeEoPKrRomZzOwWWaAvJjkCcmVNhVvIYyBCcoOEVviIYPpiIrSZizZINiqbmmLLrnmjdhHISwOSXjJDrhzZjeAkIJbVGLRrkKebpPOptsIiYyEidDooOOgPcClpNnPLDoOeDdqEeMtTMNfFtTxbBTtaAxJsSAGZoOzzGgvzuUMrRaXxAmsVEevYKaAScgGCsBTIiCcSiiWnELiYQqAaBeCcEfLAaNGatsZmLbtTRkbBSdjZzJBnoONbjPoOQoAaOgGPLlEyYzZnCiZzICRxNdRMmXxIirRoPpISlyYLvPpSZzsMEajUZmMhddDigGIMdXMmvwWKkNBbEenKkSmMKHiSPpJjvVgGjlPElMmztpcCCyKyzLldgofqRxXrQUwWgDrRcGuUBgCcGbxIfdTtglLGTtTAabIsfxXxcLlfyYFZBQCcfwWkpPxllLXxlEsSePpLvtkKTVvIYXVvYFmnNJjBbxqQGxdgGgGDliIFfLlPpMNSsktUunNuVeyYoLlgOToPIRxFktZtTyiIpWwPYadDSRYeEvTtrXUuxZvXxEeVZwGgfNvdGgXVvGXxUvqmFmGVXxfcmlLbAWSIiSsxXsbBbBwfpPFaoLCcTTtttYxJSZXxzsmFfEemOoIxXigGksSPtToEsBbSDcZzqQXxdiSmGQVnMxXmKkNPpSjUuWwJfPCcWyYRrmMHiMOeEkKoQqQntMbBBEeNnDRrNVGgxFGKuMmujZACKTtbMmBHhODdZkoOKOeKtEgoODdGwuUymfnNZzQpPgUudYLubBhMVvBbmSgGuUsyYPpCcHalLlLQwWoCZzzZeEcReWAawEjeKkzZCcjJEDdKkSZzwtTwURgwJjWKkzZjHhJkGgKPpkKfxXFwVRTtfQOlLVvjIRWNnwZCFfyPpYcGnwgeEAuUajJFwYkKyWkqjJISuUnNzfGgGgYyahFGLiBbGgCzZcNEQPpYmMybbBoOgIUuAanQqbBNcctwWTZTtQqzAOohMLyQDHtTbgGHSsUAaLBbIilZoXrRUUuQUbBBbQZlLkKJjzJjdUzZtcCcCaUucCxCjOGgwhSsPfFwRrlgwNnWvVPhHxXpRQgSsIfQIiaAZYyzwWOZqQzUuPpVKsSfFrJjRkZsfAdDBsCcpNqQgpSFMNvVGgeiIsYRKJJjFfYyZYuUEuITtPJjBbaAiwWUugNOOLlWwQqooyYnNGgpPKJQdDFfqdDtTjcLlChGgMhHcyYqMiIRrmQCEyYWsDYydCAaDdvqQcTqQQovVruuhIIIKupLbBjJvVleeEhYfhHFzZyeEfHuxeYyEazQqaFvKkVfeUuEXwoABbCcaJjvuUVRqUfXwWoTgigGyeLFyZAaLTmMACccCaAXxBHhtKcCCDwjJvVNnieEmvVMNGgUnZQjJqfVvFVvYmMZzynHhcCHhroORxKzvVVvfhhVJpsEoFfOZLlHhotTKkOmQAtfFTrAarvVHhFfIvIifotTOwUoOuLMmLleEAtZOzzqGOoohQssSFfSJarlLHUdNzZuTjFfctdDKFfKkDXnNxFsQwEwWcQkKEfZeEzZMWwgGWAaGHCwWapPWwvVICVoOmMdOoDvyYrmMsADdFBGgbVvfQTtQBQSRmMreEFENIbOoQIKnaAWDaANGUuCWpPKkwXaAcCIBvbMCcQOPMmBWwDWAawdJYuqFCgjKeELlSwNSsxBbXnWkSwhBbDhbNsDIIikKihjJTtGKkgHdaNXxerRZzPpmVwWVQUuyXxoOYAaVvqrvVRrvQQqLleyuUYKkEhMmpxxXDvPRrpTprmdDpsSDdeEHYyGFfukKThHtjJNnQZzCjJcFjzwcdDCWwuUYywWnNWkyFfgGiIYAnNzOhHZzFvIiVfjXStsZzFaQuURrRCRAagGrcrqPpVLlSsAzAanNKmpPQJaSIidpPqhHFfEeveFIifSnNkfJTIMtYiuUIJjOozZwKkXXtZdDzTxXchHdMqQlLmsqQyIiwWThHZzmMhHtyjYyoOHaVqQXhNGgrRNnINncCXxgpPIiIRyYBNIoOOWcbiFzynNhqlLLQeEqAotjJKlcsSCVvAitTIjSCPmMuUpvVvoqwWhKkKWZJjzIVCcxMOhBvaEBbCIXxGgemMKVqKkIWkKwTtSsPSqTZcdoOHhhvpCcwgGtAaTLlWOoPabBApgGdADDddDjBbRrDxUukqQAUXxwWZzqseJrRiIiDdyYFyYbBzAazZcrJjRrVSsvRCcIwoOKUfFuBPtgGVhHtTlOoLsBzZcCptTPIiTqQBWGdXZoxXwbYygYxzZVDdWmvVHmMhMSFhHMlLmfPYyZzvLTtPLlYyOoZzSNnLGhNnyyLlLZoOrnNwYvTtisSXrTtRKkTerUUuGCcBbgUhZoZWUGgOphoKgeEgGysBhRDPpdjxRoOzoxcwTtKkysAariAakAaKIeEAaiIFfVvGsSUmMulSxwgPDdHnNsfhHZzUuAwXLlkKyEdWhEpPnCYkKFfRrFPKkxkKZnNWWwQjtTBHhbnfGgQNnqnKPpLMpPwvVvMCgxXGqTZmPhTtWwpPQsPplLSXxEODdoDrXxRgGbBtTmMqhGiIgCAZzaNnFEQAjJsSrxXRBbcsZzkToSiInldReSsRrDLlVvdEJeEjnNfGgRncCTnmMhDdHoOheKkxCcNNnKkgtHPpUFfuhZrYyCsScuDdbOTtodmWwkKqNSzuKvVWpPNKknVHpHhuRrtqQQPQWBNnaAeCLlcMmQIPpieqQKkUuxXGgFfGSIisuUUMeZOPIruTtUCsOoYySsYySxXVvQqyYCUrRbpzZAaCcRZvVjSTtgZzQHuUNmSqeEodDUYdRsHaATtYkKVvMmBPpPpbyhnAaNkeEKBbZHVvLZzSOlLNjJVvMDdmRvVmgGFaAftwsIiSpPoFfOFfGBbcCvAsvvVkKVSPpsPPpOopVKkCcvahHbBEmldKIfOxXotTFTtIVZarRmVUuOoJbtCchDdFfYyCcHTQgFfXxGcdDCQSEaAeGgbnNzDdZsStazjJjIlLktjJgfFGTVvMFRrHhHhDNndhHvVwUuHhThHtvTnXxuSszGJjgQMYeEJjyxGOLwdVyzKukKwwWvVWAagGeEDzqvVVvPwWKkeGNPpOaTthEQbBuUugGLQsSqEesIohjaVsZzyWwdtTDnbMmZVvgoHhgGfCcFiICcDvZzxXoNnLWwHhZzaAJkKLJkpnNsXVvfFaGMtToOvVGifYsSyLLlLxAmMvVKoOzZEDdAbBaaKrRhOoixXPpmAsSuUMOylVuuUEdFZzwWfCcDYiIyYiXIiztJVByMSBbsmHhloOlodvMmaAVUuWuQeEqBMHhmBbAVsSvBbqoOlLXxpfPpBbFPiYqqaLjJxXlbBpPuUuMJbDzBbzWSsVvjJGPpgVviIizBpEDdXxeTCAaJjcldDmMmcCJAWwpJlxXorRRrNnENFfIlYyLBVcvVhhuztbyYiIyYkKQqGSswFfmMEeKMkKtTLoSVvdopPODzXxLlWwgtQwRqtpPTxYywWYLldqQZkKkKvdDVpPBPprscwNxIxxXasSmMwYVvEOnKAacWwCaACcyOocGIhOoHiqbBIkEepXgGmqEsnLlNScoAxXPVvpadXOoqBQqOomMXMQqYvKkVkOPJFaZKOoMYuUyhqHhQnwWYErZzcDDdtROCcJjygGYpPoGgLlfDdFweRrpnwsuCEeEyRrYZbTwpPWeWXUztTRrzzZUtNrBbRwaAMLlEQHhxXuaAQqFflpSsTiIOQqobWDdKkfWwFIVvnNGEefooZzbBUxXSsmUxDWZwvAaVwWwWSGbuKkKkcnoONnCcNwxyCcrkHkVlvLleEanNCcAKjsSFsHhqECIichHeRuUBeThHtEdHhDBbkKtugGUulHPxZzXOpJKkHhjdDPXDdedDeDdaGgGgvMmptdnNpkrRKRrkKGQSdDYybWtEeIiCcJQqjSsktFfTlLHhpPvcCmkpPKHUuCoOcZzYuUzyYMxXhOeEzTtzZTgGOWGgwcQgGgjJaAcCpiTGgaAKpPTtWeDdkKeELlRrEHvVCOzZAlLlRPjQqPBbNmMOBbWwGjpPyDKHlLhyYVIyYVNndDpKcTaIsSWYyXKzZkxWniINCnLfFurRMrsiGGfFaYKWjJeRrEoOetPHPphpiHhkimDNnDdhlLlIlQqWwTOGgotnXJjnLrRlNvVlLHhyNCRrcnLlVyYDdvYUOrhsFEewWoOsOopPSibLaqvFfCZzyWwGgYidyYEYCMrdDLcDjxaEzZsSsSLlsSeCYxXIDQChHcAaewwEnNUuARHIihrqYrImvqQPpHhEeAmMaVOoBAaCDdcComMkTDRrPNXxXxnuUqRLlTUMwZzbPXlLxpPpLyqTkIirRTtqQcTSfFstCCccCtTDfWmygsSpPnuSsUeEMeEmxmlZUdPpXfwuUojBbdDaLnleOtqQmSsLUnNGgrqmMGgQRzcCZWwSiIIJHhKkAbfUuXDQqdbBvVHkKURBLlbwWUjuidSsDGgTtXxSdLldDoMmuUnfFVvWZzOFfogSsriIBVBxXhOoVKSBdcCyYBbuUhfsSFEBbeUudlLZatYyPybBepMfFvVmamMAwcCNnSsiKktGnNDrRoOdmMeEoOzCwUuPpWPpNHhQWsQgvVxXOoeFEuakKRrAMhzJNniZzIiIjEewFfvqlprVvapPAzSkKTtoOtTyuUOoWhHVvrKkHhFQfFbBqfpAaPKEekYyLliGgZzTHhnNtrDwWOgsuGRrgtTSsNnRrfSoqQDdrDdwuUWcpnieEIwZYVvytFfTLMmlMEegGkgtnTtNrRbWrRtTZzwBDKzZZrREwPQpPqpShlLBbksuupikKfmMFxUuUnNdDQpPHhsSVDdzSVnNgEeGeEPpZYykRrOamNdDKFiJjIAaFfRlnnPPpKPpPpkpPpZzqaAzPpZdDJjQUuVGgXVMjJmUytTWhtFkKfFuNAAbKhHknpPYLlyNawlZzWEewLSsjJAgnOoXbBJjZdDMKkmLlvdgRNnOINnLUuliYyqkKQkrBbvsmMiuUVvVvagiIoOjIiiIXxkKrnNRrRUurtTWSMmdDvxYzZEsDdjhHCfWwWwFrsQbBqNnnFLlzZWwfnXxNNyYSDqxXGTkKSHjJhhVCHhtTULbRrBlCcYkuvgwWGOoVyUuhHWnNVsSLeEnNldDrRxXXxevDcRbXpPjJDgnNbZgOGiIyZGgfpILmboaAPuWAeEBAabtTBVCciWwWIOPplLwIumKkAkKiSBbsXSqQsYyPpklLmMGLRzlxOJvmAaMlLVjhHoOogQRqQjJUFHhHhffeEMRrmkQWwqZlrwlwWgGFfRrKKcCoOHYcCyhXFfxOoClLFEPjxzZWwRrfvjJVBRYyrbDBbjsSIihtgKgGaSfyYjSKfzZnPdDhnNEeHpSQCcqmiMVvnJjmslcCLDdunFyGTwGYRrVvwHnNFfnNvyYSsYGIieEGggdDyIoOoOlMsSmLcpPsxHhBbnRrNnpPNXVkVvKvSHOYyNnVcrlLyYthLiInNopPybBPpgGDdTxRIqppjJPjJGyaAYgyFrRgGGVIsSiLllLbBHhuhkDyYhDbQqHOonNfVsNnhhHQyeElLIVvRrIiRjJRAREeTRAaRaACHhDMmbQqBXxtjJOoJjTdcalLAuPAapVvUwJQqjWqQuxiNnveEVYyMmMiAaSonqjBLYSstxXZzMHhmMmxXhCcHTVvtlLLBbeElJOoIiAaBbaAvVjxPwkGqQLlgKMLZzqKJGgVskKSkKPYHhCcypDdkKXtsSTCcGgAJPhHpSscCRJjrjguJjMmGKNQFfiIYpPjOogbsSMhHtTZgBhwMmWkKHbuZzEeUmMlYyioOIKGgkKYykgGLpPeAaEWhhHnNbIlLOokAaKNnNdziIXJjDdWwxebBtTAJmSsaAMnrRMmHhLrMmRlLUucdtTnCoXradRriWpAhZzHqQpPcFpPfeENHhDdnRvVXxrpwWMypDZsjGzZQAaJjyaffFEeeEEePpHhhCcHSSxkzZnxXGyYMsvJjJjNQTWwcskKhOokpPwMAaVkKXSsDwWiIdLwWuUCTQYyqqlLTFftYyQRqdcCxIFfYNcVvCaOoKkTuaAUtPHMmHhhRUubYENneyLorVvRVvOUvVrRHTWlaAPcQqSnNzQIIWwrRxXiitdhHDTvVKBLlbiVvIVxXqpLASshHWwalrWwqjmMrOPSbDzZhGDdbBbBWwdcCnRFfhHbBgGrRhdmnNcaACRjJWBnNshWuYyUswWSeTtEoOtTJrlLyKkHhwWyYHqQYyXxyHhBbYKkIiikTtBbyEeYRryBbXxZbBiOoIzCcsPpphfwgAIiUqQXASsvWwiIjJZzVsbtTBqVvxXnNQnNISHyYhfGeuZzLlpZUaAuQqzFfPSsqQVNIiPpVYwOoEuUejJWcpZAaeBbEGHcCnNyYhwWHZznPtEcSwjJptTEeMVvmrRdtRrTBvybBozZhHVhBeEyYXxbRxXeBbqQGuUNogaAKZefFzktTZMmBmMvKkNnVruOOXQuUzUuwirHhYJjLGgMzZLFsFfnbBANnaFXxyWwpRrFqRKkrkpPKWwBrTjZzAJjadFlLfDJEURrupaakKAAbbBecyDvVZzLlnHhhHNvKKkeEEWxXxOooOXVvWwMmLVvlNnwMmLlyrZzRsSRrLBbuUudDUlfFWtUOoSsQyYDMBbbtwQqWxsPXxkxXkKKNntbqQZVvpPVuUhHCcosXxScWwLMmLOcwqQWCcDdCSGaAWwgsXzLlGkrAoOkKuNnjZICckCcKoWwOrqQkHhKEeXxVIiUdDuOyZmMzEizdDJjZkGgKBzEARnVvHVvGgaAqQdDLlmaAMGgbYOoIiVkLKksOnGcCgdDWMmHhwfFcCHQHDdRUUuAaIiyYMhjJHmyYcCtTxXuqAKeHhAaPpIiPpAWxXimRrcvVCdDZaRSsrNnbBgGEokRrKNabBjJAMmzZRrzNuUBlJhHSQqepZzLlPjJaArfbBXSsAGZzoOgmyYDxXGgMcCmjLlJXxkkKKXxWbBUxXtTIuUcuKIULKvVUuOolLtAcCCcadDHhCFQfFfFnZMmHpPmIgGwWiSjxXJgGyfJrRjFXgSsGlHhjJGgFWBbyRrNQqnWwYrDdgfFGRwyYLjJuDdTkaAKsPMmlIjJeEGEexPkGRgGHtTPpYyCTcVvsSTelLErFfsSRcCKeEkKnNktesSElLleEfRrFhiIaANnQgGjpPkyyYXxPpFklWJuHHiIhIihAatbBnsSNCcZzpgGUyOogGNnvVZzpPGjOobPpBZbBNHxnNuULfnSsyTtCcMmvQqQUuqegGIjVvJDdiKDWwkuosYQqbdDrRGEnNUyHhYdDuVvUfFaAwXmMmrAaRyoQqOhHLlYxXsSWFeENnfFfFlLmxXMrRhihHIHhnMmNHhFvVgcTtTkKBbMUummjBiICcJjbJQqejhPpHVvJERyYqQdxXuAaUHcCQYdDRqQkKRrupPVnHhtTNqylRrLYQdDyKDdkRaArmfLBNNfFISXhCcgPiIBzVTzZcgGejJEEyjComFfWwZzVvvVsGQqKkOoavMtTqrRrGgRGCVkKaCcARrkQqKtTRuAgGwgGZzjOfDOZIiXKkzZkBbBbqgvVofFOoQqEHeEcCLliIMmCzZNVzFBbxOoXltTLnsCcSvVrRTtGmMnmSsMqUuQoiIOiIIiqAaQwcJjTMMmDdvFRrkrRVfBbFdWMmJSkKsuUbXxBbkKBlGhguzZUvjJVZzeVqTtiIQtThHvFfDdERpmMPRrPOoptEuxpPXBbbUuBxXIiBwWUuzAWnNhHHJjhWgXHhYxXnNaSsIWwiwCcWCIYyinqQaANaAOjJNzaAIigafCMmCccadDPpKbgGBKxoOwdDWyxXYkKXIibBXLlxdDNMmvbBDsSdjEQqezZJVwcOoCWTMmPptctgfFfFkKEeVvSmIikuUBbvdDSsVufsSFUGcYyCbBqwWwdDWxQqXwWhLlbBLGYyQdhDaetMmSsSsFTGgtrRzZxQqAaXwMiImBaAHAahHlEeLIiZucCZhBCjJJjcfFzZeVvEtTvVVvxXbDvmMuCHhHjJhcnfdvVDFNTtskBbKSeESsUAaJjjiGglLfFMmVvbpXIaMmweinNIBbTtEWAixLHkPUuTtpKkuSYysHwWRiImMHhrhmUubBVvMmMmbBMJvusSkFdSYzZFfvVysShHtNcCJjYBbNqQpAphHrdgGDhHPoOnNoSsuUSFRrffTtOzZMmBHFfhcCbMxpPVvXmNtJjvVNnUuCcnYbBKkyJjSsKyFfYTPpuAaUtRgGlLnNVAZKkuUzeEKDbByYOqQoTNntPcCnCcyAJMmWnNwjhuTCcGjJXkXIbBFfqbAaBJMPlrRBdnWdlLDHXklLEeAanRrNKxNZEetqqQkKQwWfAyYDdiIYNnpUugGPHIMmVWHhKkEeHRrfQJjJDoMmbVgGvaAbBQNjRrWwACcMmaJSehHqAaQeEBbwUuUuYyWYxYyHhMHJjzudJjOqQerREoLSslvMmVHtTtRJhHjMwWXxiOFUuQqjJLlIiIXsbBiIrImMxXrhHFgGtTlLfMDJwdUhHbjtCTyYMZzGdTtQqWiIAyaAKkWHFcCfhhHwMmqkKIaPsiIidsSPpNnRfFfjJyYorROdDBbxXFnOofwWMmMLRrwMmPyYfJjFxiIidHhPpYyDeEhCcRrAvmMVaiSTFxPDAauUsSTsSXcCYCBbmMcpOlYytgGsFfSKOoklLOoxXWwhEMvEeVuUrEenNmzZNbBntGZnNzqiIQEetBboYHmOoMDdcCXxXxlLfRrOoxlLvVttxKkXDpktTZzKPhHHhFAafDddvVTmaAtTMpPTgGXOmcCZzMmMoqEabBAnNGvYyddDDFfzIiZrGgFfLRrlRViIrRVvMXquTtDzZAawsCXcCxsSCclijuUoFMmkjJKkKUuTnEIOjJoiocCVvJnPLJjCcCQxXmnNMsbMcVGcpPpPCgvcCekiIuADdaCcePpEvVUasSNnrAFfwbNneUudDcCEMmlLCKkSscrRyrUuRYUIiIxXihjJimUubXeGmMwWXxcoOBbxJcCjrwWRlLXNZFfzBbndrvkAaKVuTtbNlLnAgkUuKGauUDMmdDdmMBAaTVOosSPIKNnrRRbBAqQWwGgSTwMmWlsXxSBbWXlLmMuUZzZzxUuuUyYjJavRrVaICcioOVckKCwZhHXeaAUuhqsPjJpSVUZzuvoammMWcFcCfhHjJfrRFILlRSGBbUuvqLzZssSwpKVhXxHcCVvEevQkKcrRCrRSsKSsbZzrRKKkkBFKkfitTzZrddDsEeHgGNnhxsbBSyYYyaAVvyYwwWWmfXDdxDdUnzZjJNpgYMmQdDIfFqgGJjQfFiIlfLZzYylFyYmhHEeAasSkKCaAdDstPjaAQdDGgtaAzZNndDqQgvVGdDRrtTkeETaAVvJWweMmbVKdKkcEVOovCbMmTCuXxSsbBxXUQqaNAmAahUuaAHRRrKdDkWoOVvloQqOSoOaFfFIieEdcxXCpPTofsSFOWLlfFwjDdiIdDrRwlLjSsxXJspNPpsSnRSsrPLLEulLWwvZnNJjKkDWwdUcCWoXxXxOGgbYygGhHYydFfMoONRrntElzbfmxVOoJjfoHhUuLlOoOlLFgGvqQTtHRrhAaYyLoOQqBKkqkKQEeLlbAazZdpPpPvGgVaASsxXDlbBJWDjJQqdCZcZzCCcweExQKAaAVbRrszCzxXOoQqzZyYlxNnRetGSsgfFTgGFkKfgGzZMSRrsPpyncGbBgAPpOocFFfvSsehoFlLfyTtYCckIiNJjqQgWwSsGKknwWFWwLlfCcBDdGnpeEwWbBEePMohHmMOGgaUuTtqQwzZWGKkrRWVvkdDdtTlJjYyLaADSsQeqQEDdJYxEeXZzYqJjAaQKktTyyYUjJeExOoHhvHhRrjJpgjeEnNNEeYyDVVvFtiaAIqQpdDpkKPoOeyKkLlYHhLaAlZzRcnNCrfqQlqQvVAaYdWwDbByeEUuRIiGVvgrMHhNWwKqaAaADTBHhbTpBeEbCcyYJSsTBbXwgGTtquUQzZvVIiWWMmbNiInGJjWwdDAayYLlCjNntdUOXdPppPRXEeSVtTIihQqjvVfDVvcCIBTgKWlwWxMmXTtxXZiGXCcMUuLZGuUOnqfFEeIeBwWbUViIaAxAzAaZDrRNnEfFXhHxyYvVqQeEtwWTRbBYxXysSiIrHhJhIikcCHhKmmPjJjJAKkaDCcdDMmiIDlLhIiNnWNlSsJjYyaAxajupYzbBbBuUZZzOocCQqxDnNwWvlyYZzjFfdDyYJlOCNrRCzZKksfCcPpfkKoOdDFOvVUKkuwmtrRYyIiIikUciWOvVcTtqQcCDdBcHhquUQaaAZvVFcCfUuOqnNeoOEQpdDPokpPuUnDAaUAaFfjnNJwcCzdDNnRrwgTwWtfFGgAasSGPpMmIJpyLPNWwnOoxXAxGgdkKwWDLldDWNsUuSIPAasNXKGMmRrkKIifOIUuoOQqYWvVePpENnAoOpvpTcCtQqDHhFfVQqvdIiPFfagIiGTalLAtAVPOgFfsSGxYynNgGXNnhQqHoaAJAgGeEKkdDzzZxXaMiYyITtmonqQNZzGgIWwWwfwWJjFZztTrRiHhcxXCdXxRrzZoxXqpPTtBcCQqbpPxXZvuPTtpgGUDdrRdDIaiLxaPdDpFffeEPpdrRDGiQAaZHzEAaeWwWiBiIbIEuMcCmUDwWidUqcCLlFmMfQTIHhiAaMmiNnIwWwgGWSsfSsAaiIvVQKVvklcCLHhYCVfMZzxbeGXxaAgJjotTOnfwWFSsFwXBvVbtTeEekKEBSBhHfFmMbAfwypYSpVNnvdQNZznzuUFfZDdxIiXxXJjZzEjMOIiAHhKkcCaUfCWwRBblUXIixunlbhHBfGVvgFWwXxGhqZzQMmHBNXxnrRDWwoBvVRrDdkKbINnfpPXuUdnCcyYIiFZzNnfYiotToOmxXMOWwqcCIIiikKQbBuUxeWwEVwpliKkgvVdJjBbBRbBHhrbTtrccfFCYyWGgwCYzWwZCcZzqvAacCcCFfDdUurRVQMHheEfFmHCcJjbBfFeEmMxXAvvqQVYTTttXxjFfHhJlLgtTgGoOjIiYyfYyYyDdxXfFLRrHHhhYyNnXMmlLeEoTcCoVvxoOXPpnhHPptIoOiTCYDdyrXxNvVNnGgleZXxyNnVvYhHOoHhqrtTqQKkYysaJjnOPpRZzCcBbGtTXxTLlbBtmBIiVvAaLKklyYfFbkKCcUEeyYxXwWwqQWeEEeZhHMmzfZzQajJfzlpEePaHhFfGgLKkzneENZWwlPKkpAvVxXLZIrRiOoFyjJvVUtTKknJjdoODowlLPpJjWLgGoFfOtFfTbBOoOoLllqoIiOQYSnNsyMvVxEegpPGXdDRrxwuUwWWVQqgGIiDdUumJjVQJDGglLDIinNdXkYkKyKTXxtKkKkKRrWwFfRDKGgNnVlZiIqVsSvQztTvmMCoOlLsTtIxvVHhSsSgGJYyJjGXxgHhajpQqPRrpuFWwIifZzOoGQmxXMgpoODaAdfFrRGrRsSYgGpEezZPRryFfaAuUPBbhuUAFGgdDnHhJmMjYyNFbBfkKNvuUDduKTtMmRriIiIUujJxcVBbICcirRdiIDvQBbyBQquUxXpPQKkqbuUtJjGgjJJjJwWAaRrJZsUuBbShfFHCcrpoORFfHhSsAaLlrRrXxvVVayYtNnTkKDnNKJdvVDBbMUiIqQqxpXGGgdBbiIgGDdDkrGtfCclfwWFapPZIizTxXKCeCkDdKckLlZzKcxXCfFEWByYaAGgbtTIiqEYyeQmMRrQqhwtVedeEsfFSDSsAktSsTWwxXyYTtsSkcCKYydyYvVaAXxDTtdDbotcCBOoAaEfFebzjDddDJbGhHgONnuUxsSXPpoMmGgOoHhGwWlLHdDhLlxXBUYsStKkJazZFfTSsbBHhdDqnNGgmuUuxXJKwWkjEjJDdvVeDdOWJjwoTzZQaApprRPPqkKtkKioOUupcCYyOoEqrnPpNlJjTtLRQLyYleNNlLnbZUuztDdDdjJBWwXxnNQMmqDdaAbTriIoOUqQuovVDdKkwnZzNWJUuIjIPpZSsSsoOtNnTgGzaAWwZzikKoloOAaLgbrRWhHJZzBbStTpPkBJtfShGgpPlLHYNnjJlLqfFNnLlQyHXxsSIMmiokKOjJhreERZCcrizZztBbyYoOiIoiIBbOgGyiiIOaIidDHksSKeESshBMIimMzqQqQsSdxXDlEeUaAunNpPLLlhHcCEeiWfzZFsSwyALsSlEFfeOoaRSsrfBbgGdDQqtmMVdeEwWYFfykKYymuUjJaPpVpZzPvAaRiIruDddDhJKkjHIOofsRrSUuCEeVvhHGSsKUoOuqiIXyYSiIjJxXqtDdyIGgxXEixvVXxfFKoOoOkXIgeEbBjFfWwHhJRUuFqkKpaAPlLuhwWwWHlLeEpvpPiJjyYIVPyYrRUkDdhsEeGgHAahaLVOovyYUulKkiIiInQyAOoSsXxaSEtJlLyYNAaBbinNIhAaHVpPvCSspcoOYyJjChHPpPUuzZcvwWwNBbfFWwnVvcCDNnnoOEVvivVfvUuVHDdmMbBwqQWFfNnOBbSGgbUKknNuIhHAajzZJirbwAfFSsEInEeNoeEorROdTtwWWwHsSpPxXwWaAbBsZzpGgPuScCXLPpcCYYysEoRrOenTtrCczZhHxXpPRCvVbBOoBbXxKAlLWeaPpAaAjKkJhHxBbXzZyLlEFWFfweEEeRrVvfvllLLRrVcCeQqYbBHzeAaVvbBEzFfrFfQqLlWFgPpGfwqQnNEeRirRIiIgGkKvVYVQpPQnoONqqEqDjJPpdNnWhHiXIIiqQixAxuUFxRrFSsfXfnNTkvEeVKTtSsoOSsaATtdOcConNDajJToOtHGLlgHpNqQEcCeDJjdnpqQQziIzgGemFfMEnqQNSxXvVeyYPrRpTlLafFZHsShVMmvfUuQqEeDFFWlLwyYfQqfyYdlLrHhxXUuROzZratTJOojARDLKkkKlBbzZdvVoZoONOvVdRAaUsSuJjQsSdDqwWIiroOnNXFfVvxBEebDkKgGICzZcrRUsSNnYyuxXfFlLAycTtsSEeWBDWgGSsSsRrevmMsSVvTWwyYWwequUFfQwWkKyylqXxQLYfUyYyYDdtTOoBbeEQquOoGVCcYqQKkACNnFfXxnQJkhHKjbBqQkKJpPjqiXxIQpPRfMGZOotzZjvVJTfFbBtTbBiIcCzehnRrlLNnNXpPLlKkYyLRdDrUTEzZvVVxXHFPFfXPqQpIiIixpeEIifFfhvRFfrmwWBCcbyYaKNnJjkYybBgGnOopPjJNSsnUuAaNjRrBbyYgOmMoaBborROEHWwhoOqQYytTJQjJqjUuFfiOoKkBMdDmaAsyJjYHhfFLlSpPZzsWVhnNHvYyLaAlwucMGgPpLWFfJjJbkKFfAnNaASsEeacCNnpPCcFfAasyWiIDhHdaADhHdwVVvzxXZvwLlVjJvWNBtClcCeEVvLyjJbBesaAJjSbkKBIiJjwZoaAWVvEeQsSHhxXuUOBRrboansSWmMLlwTnIUtTJqQjuXEeuUdpOVvkVvTtHhHIsSihZfFnNEYyMpPmASsUuoOVvfCsLlScFaAaYRkKnNWwaAxgGUuXrfoOxXFOZVkKvzcvVvVCVvoOzkKgRruYphHaAPydDUyYDdHhGoOdzZlLDSsOVvoVQgGqByYbOiwyYTtWxXIbsrRSIiQqSiYyIzZCJjcsDdHhVvvMmiIVbDdBMmYlLguUmeEBbrRxdeEDXrRHhMcCpxXPmMqkKLTtXGgZzsVvrRuUfFzZZznNsSTtnNeEmOiIiIBbiKzZMbBmqQkPpbBISyYsSuKkUDPZfFNAYZzyaYcCHZWwiqTrRWoOwGKkgrDdRCVWwvsSvMmVJjNiIqQhHnuUqQfLlHhgGJjFluyahVZzTtEeayYjJAFfvFuMZSsBTHhfkKFjJfZzFnRrTtNKnNktMNJjnvVaCcsaFfAPpSUubBLRrlwoOWLOoIitTKkeEUuqQlBLLJjlyYNnvgGVlDdcGgPpEPptsJwWjDdSTCclZAazFfxZzXLZzoOhJnGgNtqQTUBbOHhgvVGvVoUOouJVvjuNnmMpPznNIxXGuSsiIUuUhDdQqhLlSsYheEHCcNfFOonUuKkTtemsSMgCcGFfXxpPirRwWUuMSeEsuUmIxXIiSsLluUUXwWHhcCxukKnVqQvNGvrREEeeDdVwWHHhZzcGgCOoKkPphLlgTtOohHkssjJaACcvzEeEVvfFeKkFfdDRrEenaCcMhHUHCcdDsShufFOokWwZzKqQPphZzHcBwWMlLmrecCfFHtThUGgugGcjJzGgALckKCUuiIFyYzLlZfFXPabBAEWwexSsXVvVIiIivyPrRtTUuHhvGgdDsWwWwwZXxzNKkAabBwWWQqcfFCbcCNneEBGnyYNGRrzZvVSsZzDqQdmjJMFfTtLuUlFfmJWCcwjsStTXxQqnNPpNnOoTDGgiIrRIidWWZzqQWwRKEeeBbHhgjJGNeExXPTtTZrRIvVizttcCsSTZzpwLlYyWxigLQqzZlVOoMmMlBiIlLoOKkwWTDdyjJYqQpPeEVEeisqQCZsQqAadDwwQqWwcCWOoLKkQqEelvGgVSXxlLdJjLTtlIiwhHxXqQkZzCcCcKkKfFxbBSsnDLlRrzZaAmxXMFMMmmMmTRrCJjtTcfFCcOjyYgGJqEeSsQoejJfedDYyESwAAaaWovVOlkKLGKhBZzbHkgyUTtuYLlLiQqIlqQvVMmnNeEzZTtJjEestTsSMmnToOPpoOJjsSONKkiIRrKknFAafoLitcCEPpBbpPeoOTrROWFftDdFfVnyYNtTjJvTWwwgpPQqQaAKZzkqrRGxjYytTJmMXtTtTZzvVVvIvViyjJIimMYubBUvVsBbwWMmjJTtHhrRaAUuvVtToOCcRrZpPzVvmHPprRTthutHhTWwUEejJMKuUkSsqnNQblLTtuUfxXsSpPrRpPFBrXxRYFfShHRrtTDdbBsHhFfDjBEebJbBdGgyDdqDdqQQfdIiWDhzZHdEeNnrRvKkVwdpPnNifsSSsFRrWAadWwDWwwAKkZzaIfFRrTtOoeLBblWwYyZzZzSUuUuUFfYyusrRWwGgKGsgGAaSVPBbpvhludQAKCckALlYyatTnKkEeZqhnNHIiLlBdJjDvheEbBkxqlmMOoiIwWLbBRrJjpPRrcCQFfwarWwRAWAolvVLzTqQzPpdDzZZYkKyEFKkfVuUoIiOOowWIiqcCVSsIivlLTtUuhaAHkPpUurRvYZzyVjrRWkKwJSsKcwWCBtCcMJjYaAymTlLqBbQbQcFOKqxXQkoZWwzmMfmMPwMmkfFYynpPJJjxXdDjLmMdDlLlZZzpPzuIiaAyNnYrRzquUSbBGgsQZUNfAEeABbaEprRZzPuUKPCcpkAhPpsSxXHJjYeEyafLlLVvSsYydDlTMmyYGkKgqLldJnNjGgFHhfDQWfFeFPpftHhHhTbxbBRraAXxvVLlXIiBtTwjXxmMiGgbkKBbBTUqUuQrXxPpWwuULlqQZzsSsCsoOSbBHhcjNnJnrRhHEmDdPPppcCIiMkNnVuDXsSxdmBCqQvyYFbBfVcbOIioYyyGgMmYhHqQMyDdbEeHhtTWuUcCwgGBmsSMdDRuakYybBWwPpkIiMmHhKRrhHIifFKTtUupTpPtPnNOoCyOssSSosSTtTtPnNpOGJjgrRoYRiIrEyYecRryYfpJjPFNLlnTbBOoEeHhHhhHOoYFCcZzfvVSsbBMmquTtAaLNnZzlUnNQyhHpjJnHsSEkKeYyhNvOmmhHMVvMjJfFoGgCctHhTwWxSsAaEeXocCoOqQPpOuEeIkEeKiRrUZjlLJdDGgzpMOomFfPadQqrRFfploOoOLHhSsnNlLGgvVFfKkiHhIzdhHJaAeErRHhSsjufFBbUTCctqQxXJoOVvjNnBbuUDdDdDiIuUFLlfeESsYNJjllLLOaAXxokKiIwFYyTtpIeEiPxXvVhZvVzHRrVvrRbPpBuULlDdGguUyYjhHJjTtNnayorROIAaCzuUzMeEmZZlLtTcAXxhHmMgGnNekKEEeahIiCcHMkKmNnsXoOxrRXxiIVvZLlEoOclLhHZNkKnXvVxzCejJGlLqQgvVFfUYvKkVKkhHykVvYykKBbAawZzWoOKJRrbBbBTQqcCRrYytRQqrjRGgjJpfFPXCcGgxtThkKGgETtKkehHFpPfVvCcFyYfRUurpPBbYYyRrlLDJjXxoOBbdDgvGgVwWIiQqVvBbBbNnOgGoCyYXxDdUuSXHWwOobBhtyYHhTJjxjJHhsNvVUmMeENnpPXGgtFfTlVHAahwWvQqjJQmoOMMeEMmiIOofFmtTqEiIewjJHhXxVeEvXxzZUuWQqwWLiIjEiIerRUuhHsByGgYrVHhvFfRHIYyihSsYyajyYJeENngGALlamMIiAhsSHJhHYyHhYoOyDdDiIdfKkxJjAeEkKBWwLRrlbzZxTEetXSGbTtBMmaCcAxzZLlFrhiIHRzpPEaAxqQeyYELrRnNlxHbBhcCXkKjJjgGJpjJYybBPbqQBDdjNNnnJXqZdDzFtgGBbThHaAUtkKfFTuJoOuzZpxXZzPTtZzWwYytTLlVvChKkRrHcUKwLlWUukkKztPpWwmMOMmoaATZfsSFkKEeMMmmcxCcXJVvvHhViIjGwWgDduqQrRjJzZCcUOofFmxXMIicCIWqQwfFiVvgpPGGzZkgrLlRGtqsSwWQQLzZHhPpSsvVliIwaRrARtTruZzkqQKXxUjNncJjoOCBalLSsOOlLhHUvoOVPpuZzOoXtTxMmoxbBNnkYyXakKaAfFrlLDdIPpIJDdjilLUuGLnSsNlaAgGuUiIsSxXgKknNsSDyYdFfiSGTtgZzsAvVQqayOlqQLoYdsaASzZBhHbAbsSHhBtTJpeMmLlmMEjJwWPnNXxrRaLlGgbBAvfFVYgGyrYyRHhEkUYyuKdDVTtvekKGgyzZgGuYyUYGghHNWwlLgGnhkKxXHjHlLhaJjJjKkyYIiADdAaaCcrJjglLGJTtjlawWAfFiILCcEeAayYAadHhUBbwWuccCCDoOTHibBIhKwWkiIYtTytZzRqlLjJFfqYKkMmyGgVvQjtTJJGZzaAgzoOZFfdNnDjQqXaANMmnRdDacqVYyZoOzvLlNnZesSTtqRyYNnCcrigGICcWTtwaAbuUBQTtAYdDywPAaLVvnZzNENiInuUeEelLlpwxXaAWGguqQvVwWNnUHhEzZeWneEkKzZoOkKfFOOoccCCoZzzYyNbBAaVWwvnZgGaAwlLJBbjLlWykbyYBhHhHKUueSsEYlWBbwJjLsSUunrRzZsSYyZzpPNhHmTNYqQXxRroOobBOynRrIdpPDitBbaAyCcYMmrsoOSRojJybBYOlmMtfBbFksSKTdDskKSiTtIFNSsnFsSffGgGpYyPbaAsIiSBgmBfFbMpfyYFNnDADdahHrRTtEeDdaArRHQqhcCtTFmMfvVffHhaAFFXxxXduLlUmVvkZEezKsSYyMmuUxXzZykFsSTtfEeKYyYNiITtnbBMhHTtPOUukVvUKkvSsVugGiIKJjIcCijJxPoOLzZlgGMmpXsHhjJgGaATNntjJSsSoLRrUyGgYRrUsSJSAaVvsjrRufFuALMmlaunNkYyKOrawWMmAsSPRrpEeRBbeEwWopIFfivVvVmsSMCcBbyYvVxXUuQPpqvWwVrwNnWvVRzDdHhZBAabWwlLuUSPGGggpGjJgbBkKyYVvPpNnApPPsSBbpLkKlnNaJjEPpBblLCcBbesdxXDrRUPpuJjhHKkctTPpCNnoBbOuUtbBTfFPkKbBNnxXwWwXxWKktTJjLlyIiMmYlIDMmpPcCrRrRTtdBxXbiZzJjgGDfcCFTtdLYyjadDxXXxAVxXvxXYyJrWCOonNcjJUuMXxXxmcCJjwShwWHsSsRpPUIiUTtVvNnZzQqGjJwQqvVFeEfPpLlZzFfqQAaNnplLYgGyhHCcItWwTiPTjHhDWwdJtXxeHhEBeEbBpPbyYqQvdDqlLQRWwrepAarRtTPQCcgGcCZzOoqHuUhCcQqEaAShtTwwWlkKLpPWMIimHuUqQMygGYmPpbBUuRgGrpPlGgwWDdLlFfjSlLszpPVvZaAxXUuLlSxLlXvRrRJzZjgGeErVskKnNQqJpeEQqPuULtTXmMcrRDdCxagGkKSsuUdDaUiISsuSbBYyWwmMtkKrROotTThHtAaAaXxrRCnNnNcpPiITcgGHhCmFfMMwWmBbsSaYynNMmAssSAuUUuDkKQqdsMmsSOocGgyYaAmMJgeEdDGvVjIiDdqQRVvmMsSrCEhqQwWXfYyFxcCiIBbyYHeoOFfOEeoMmuuUEqQeSsUlLvVZAZoOzazyYbBVKkEevVvYyKNnaAZzkGEeKkVYyvIiqQgTBbtXPpxJYyQqVvHhjMxXjCQqNnkKcJbBePPpXxpfUuNnDdFvVCcdDFfEOoelLtKkTEsSYySshkKxaAfFsSXmMeEvrRZzYyVHWwZTSJjSOfFossEXIixSsbBRaAWyYNnwjpPJOorEeetUuzoOXxJjNwQqXhHxWGmMoOgmMxXnNeEhPpHnUuCcFftTvVzVvVveEbBGGDdgtBbTgdDtOozZTtTgGwWZzGgZhYyHZIizPplLiItmMRrQqTuUjJjTtZzeKkEcCxkKXGQqCcvkKVbBDdozZOGuUUuggJQqSsE diff --git a/2018/src/day1.rs b/2018/src/day1.rs index 741f5b3..b86387b 100644 --- a/2018/src/day1.rs +++ b/2018/src/day1.rs @@ -2,11 +2,11 @@ use std::io;  use std::io::BufRead;  use std::collections::HashSet; -pub fn main<T: BufRead>(reader: T) -> io::Result<()> { +pub fn main<T: BufRead>(reader: T) -> io::Result<(String, String)> {      let values: Vec<i64> =          reader.lines().map(|l| l.unwrap().parse::<i64>().unwrap()).collect(); -    println!("{}", values.iter().sum::<i64>()); +    let part1 = values.iter().sum::<i64>();      let mut seen = HashSet::new();      seen.insert(0); @@ -15,11 +15,11 @@ pub fn main<T: BufRead>(reader: T) -> io::Result<()> {      for val in values.iter().cycle() {          res += val;          if seen.contains(&res) { -            println!("{}", res); -            return Ok(()); +            return Ok((part1.to_string(), res.to_string()));          } else {              seen.insert(res);          }      } -    unreachable!() + +    Err(io::Error::new(io::ErrorKind::Other, "Invalid input"))  } diff --git a/2018/src/day2.rs b/2018/src/day2.rs index 6564938..38fd4ba 100644 --- a/2018/src/day2.rs +++ b/2018/src/day2.rs @@ -15,7 +15,7 @@ fn close_enough(a: &str, b: &str) -> bool {      return num == 1;  } -pub fn main<T: BufRead>(reader: T) -> io::Result<()> { +pub fn main<T: BufRead>(reader: T) -> io::Result<(String, String)> {      let lines: Vec<String> = reader.lines().map(|l| l.unwrap()).collect();      let mut num2: i64 = 0; @@ -40,7 +40,7 @@ pub fn main<T: BufRead>(reader: T) -> io::Result<()> {          num3 += have3 as i64;      } -    println!("{}", num2 * num3); +    let part1 = num2 * num3;      // TODO: Can this be faster than n^2?      for line1 in &lines { @@ -55,10 +55,9 @@ pub fn main<T: BufRead>(reader: T) -> io::Result<()> {                  }              } -            println!("{}", ans); -            return Ok(()) +            return Ok((part1.to_string(), ans));          }      } -    Ok(()) +    Err(io::Error::new(io::ErrorKind::Other, "Invalid input"))  } diff --git a/2018/src/day3.rs b/2018/src/day3.rs index 15a4dc2..baba8fe 100644 --- a/2018/src/day3.rs +++ b/2018/src/day3.rs @@ -49,7 +49,7 @@ impl FromStr for Claim {      }  } -pub fn main<T: BufRead>(reader: T) -> io::Result<()> { +pub fn main<T: BufRead>(reader: T) -> io::Result<(String, String)> {      let w = 1000;      let maxnum = 1500; @@ -80,13 +80,13 @@ pub fn main<T: BufRead>(reader: T) -> io::Result<()> {          }      } -    println!("{}", double); +    let part1 = double;      for i in 1 .. maxnum as usize {          if free[i] { -            println!("{}", i); +            return Ok((part1.to_string(), i.to_string()));          }      } -    Ok(()) +    Err(io::Error::new(io::ErrorKind::Other, "Invalid input"))  } diff --git a/2018/src/day4.rs b/2018/src/day4.rs index 90cab72..f5e219f 100644 --- a/2018/src/day4.rs +++ b/2018/src/day4.rs @@ -68,7 +68,7 @@ fn argmax<T: Ord>(v: &[T]) -> Option<usize> {      }  } -pub fn main<T: BufRead>(reader: T) -> io::Result<()> { +pub fn main<T: BufRead>(reader: T) -> io::Result<(String, String)> {      let mut records: Vec<Record> = reader.lines().map(|l| parse_line(&l.unwrap())).collect();      records.sort_unstable(); @@ -124,11 +124,11 @@ pub fn main<T: BufRead>(reader: T) -> io::Result<()> {      let sleepy_guard = guards.get(&max_sleep_at).unwrap();      let max_minute = argmax(&sleepy_guard.asleep).unwrap() as i32; -    println!("{}", max_minute * sleepy_guard.id); +    let part1 = max_minute * sleepy_guard.id;      let consistent_guard = guards.get(&max_times_at).unwrap();      let max_minute = argmax(&consistent_guard.asleep).unwrap() as i32; -    println!("{}", max_minute * consistent_guard.id); +    let part2 = max_minute * consistent_guard.id; -    Ok(()) +    Ok((part1.to_string(), part2.to_string()))  } diff --git a/2018/src/day5.rs b/2018/src/day5.rs new file mode 100644 index 0000000..4638858 --- /dev/null +++ b/2018/src/day5.rs @@ -0,0 +1,88 @@ +use std::io; +use std::io::BufRead; + +fn reactive(a: u8, b: u8) -> bool { +    a == b + 32 || b == a + 32 +} + +fn react(line: &mut [u8]) -> usize { +    let len = line.len() as i64; +    let mut gone = vec![false; len as usize]; + +    let mut top: i64 = 0; +    for ptr in 1..len { +        if top >= ptr { +            continue; +        } else if reactive(line[top as usize], line[ptr as usize]) { +            gone[top as usize] = true; +            gone[ptr as usize] = true; +            top -= 1; +            while top > 0 && gone[top as usize] { +                top -= 1; +            } +            if top < 0 { +                top = ptr + 1; +            } +        } else { +            top = ptr; +        } +    } + +    let mut j = 0; +    for i in 0..len as usize { +        if !gone[i] { +            if j < i { line[j] = line[i]; } +            j += 1; +        } +    } + +    j +} + +fn full_react(bytes: &mut Vec<u8>, mut len: usize) -> usize { +    loop { +        let newlen = react(&mut bytes[..len]); +        if newlen == len { break; } +        len = newlen; +    } + +    len +} + +// Pass 'typ' as uppercase. +fn remove_type(dest: &mut [u8], src: &[u8], typ: u8) -> usize { +    let mut j = 0; +    for i in 0..src.len() { +        if src[i] != typ && src[i] != typ + 32 { +            dest[j] = src[i]; +            j += 1; +        } +    } + +    j +} + +pub fn main<T: BufRead>(reader: T) -> io::Result<(String, String)> { +    let line = reader.lines().next().unwrap().unwrap(); +    let mut bytes: Vec<u8> = line.bytes().collect(); +    let mut len = bytes.len(); + +    len = full_react(&mut bytes, len); + +    let part1 = len; + +    let mut minlen = len; + +    let mut bytes2 = bytes[..len].to_vec(); +    for typ in 65..65+26 { +        let newlen = remove_type(&mut bytes2, &bytes[..len], typ); +        let len2 = full_react(&mut bytes2, newlen); +        if len2 < minlen { +            minlen = len2; +        } +    } + +    let part2 = minlen; + +    Ok((part1.to_string(), part2.to_string())) +} diff --git a/2018/src/main.rs b/2018/src/main.rs index 98c0f7b..f9098eb 100644 --- a/2018/src/main.rs +++ b/2018/src/main.rs @@ -3,39 +3,96 @@ extern crate regex;  extern crate argparse;  use std::io; -use std::io::{BufRead, BufReader, Error, ErrorKind}; +use std::io::{BufRead, BufReader, Error, ErrorKind, Read};  use std::fs::File;  use std::process::exit; +use std::time::Instant;  use argparse::{ArgumentParser, StoreTrue, Store};  mod day1;  mod day2;  mod day3;  mod day4; +mod day5; -fn day_switch<T: BufRead>(day: i32, reader: T) -> io::Result<()> { +static NUM_DAYS: i32 = 5; + +fn day_switch<T: BufRead>(day: i32, reader: T) -> io::Result<(String, String)> {      match day {          1 => day1::main(reader),          2 => day2::main(reader),          3 => day3::main(reader),          4 => day4::main(reader), +        5 => day5::main(reader),          _ => Err(Error::new(ErrorKind::Other, "Invalid day"))      }  } +fn file_for_day(day: i32) -> io::Result<BufReader<File>> { +    match File::open(format!("../input/{}.txt", day)) { +        Ok(f) => Ok(BufReader::new(f)), +        Err(_) => Err(Error::new(ErrorKind::Other, format!("No input file for day {}", day))) +    } +} + +fn benchmark_day(day: i32) -> io::Result<f64> { +    let num_iters = 100; + +    let mut input = Vec::new(); +    file_for_day(day)?.read_to_end(&mut input)?; + +    let start = Instant::now(); +    for _i in 0..num_iters { +        day_switch(day, BufReader::new(&input[..]))?; +    } +    let end = Instant::now(); + +    let dur = (end - start) / num_iters; +    let secs = dur.as_secs() as f64 + dur.subsec_micros() as f64 / 1000000.0; + +    println!("Day {}: {} secs", day, secs); + +    Ok(secs) +} + +fn benchmark_all_days() -> io::Result<()> { +    let mut total = 0.0; +    for day in 1..NUM_DAYS + 1 { +        total += benchmark_day(day)?; +    } +    println!("Total: {} secs", total); +    Ok(()) +} +  struct Options {      use_stdin: bool, +    bench: bool,  }  fn run_day(day: i32, opts: &Options) -> io::Result<()> { -    if opts.use_stdin { -        let stdin = io::stdin(); -        day_switch(day, BufReader::new(stdin)) +    let (part1, part2) = if opts.bench { +        benchmark_day(day)?; +        return Ok(()) +    } else if opts.use_stdin { +        day_switch(day, BufReader::new(io::stdin()))? +    } else { +        day_switch(day, file_for_day(day)?)? +    }; + +    println!("{}", part1); +    println!("{}", part2); +    Ok(()) +} + +fn run_all_days(opts: &Options) -> io::Result<()> { +    if opts.bench { +        assert!(!opts.use_stdin); +        benchmark_all_days()      } else { -        match File::open(format!("../input/{}.txt", day)) { -            Ok(f) => day_switch(day, BufReader::new(f)), -            Err(_) => Err(Error::new(ErrorKind::Other, format!("No input file for day {}", day))) +        for day in 1..6 { +            run_day(day, &opts)?;          } +        Ok(())      }  } @@ -58,15 +115,17 @@ fn error_handler<F>(func: F) -> io::Result<()>  fn main() -> io::Result<()> {      let mut day_string = String::new();      let mut options = Options { -        use_stdin: false +        use_stdin: false, +        bench: false,      };      {          let mut parser = ArgumentParser::new();          parser.set_description("AOC 2018 solutions by Tom Smeding");          parser.refer(&mut options.use_stdin) -            .add_option(&["-s", "--stdin"], StoreTrue, -                        "Read from stdin"); +            .add_option(&["-s", "--stdin"], StoreTrue, "Read from stdin"); +        parser.refer(&mut options.bench) +            .add_option(&["-b", "--bench"], StoreTrue, "Benchmark the given days");          parser.refer(&mut day_string)              .add_argument("day", Store, "Day to execute");          parser.parse_args_or_exit(); @@ -74,10 +133,7 @@ fn main() -> io::Result<()> {      error_handler(||          if day_string.len() == 0 { -            for day in 1..5 { -                run_day(day, &options)?; -            } -            Ok(()) +            run_all_days(&options)          } else {              match day_string.parse::<i32>() {                  Ok(day) => run_day(day, &options), | 
