 all right welcome to today's advent of code I've been told it's a hard one today let's see how it goes I'm not gonna be too long though I might listen she had to work on let me just throw it out to them live streaming some some advent of code in has gone for the next hour come and say hi not too hard okay twitch.tv slash Trello boom been tweeted all right let's see what today's challenge is extended polymerization you got a little pressure that this test that's starting to put strain on your submarine the submarine has polymerization equipment that will produce subterritorial marine forces submarine okay the nearby volcanically active case the submarine manual contains instructions for finding the optimal polymer formula it offers a polymer template and a list of pair insertion rules your puzzle input you just need to work out what polymer will result out of reading the pair insertion process for example you copy paste this first is the polymer template this is starting point of the process following section defends the pair insertion rules we're like able to be maybe to see means that when they've been a be immediately adjacent element C should be inserted between them these insertions all happen simultaneously okay so I'm gonna goes to see and see goes to be hello sello hey little Annie we have my cookie a third pair matches the role CB do H okay this pair so love second element one pair is the first another next pair so I'll consider at the same time okay hmm so I think the trick here is that like the element and see it's inserted between them right so the only new pairs that we will have to consider are then between the two right we don't like we don't have to like make the string read the whole string make the string again and again right we can just kind of compute the pairs every time okay let's do this let's actually look at the how the puzzle input looks okay yeah she's a bunch of rules okay this is from yesterday now let's do like their day 14 CD day 14 make code day 14 dot HS code period I think yeah it starts anyone okay open it up new file day 14 dot HS come on my good new file day 14 dot HS there we go module main where is this tiny okay mainstream hello read input file path so we want so what we what do we want so we have the polymer base that's gonna be a string we want a pair of string and I'm gonna have it be a map of char to map of char char right so to apply this rule I'm going to look up the first one then look up the second one and then select the one that next and then create a pair okay let's do it like this import qualified data dot map map import data dot map map read input equals and so let's first just take the lines okay where it's gonna be the template and then no an empty line and then a rules equals lines of input so it's gonna be IO so it's gonna be do a so it's gonna be FP input so let's just like this template underscore rules read file FP okay so then we have a list of rules okay so so make rule map so make rule map takes in a rule and the rules are going to be these are all two characters and then blah blah blah and then a third character so we're just gonna parse it real quick we say a C1 C2 underscore underscore underscore okay so now we're at the 1 2 3 4 4 underscores C3 and then the rest equals map from list map dot it's gonna be map single ton of a C1 map dot single ton C2 C3 okay so let rule maps equals map make rule map a map takes a string alright so this is actually lines over this now I'm gonna do a how do I union them Google map merge merge we're gonna merge the maps merge map data dot map okay how do we merge them merge this is always like oh like why wouldn't I merge merge with key an unsafe general combining function okay and union with key okay so key and an A to NNA and a union function okay so let's say these are gonna be a return template comma rule maps and it doesn't like this because it's going to return a map jar map now what is the type of rule maps it's a yeah okay so union with a union with a union with a combining function yeah okay so union with comb map so I guess it's just union with a union right it's map dot union map dot union with oh okay I think it's like a unions with yes map dot unions with like this now let's read the read input a example print ding is of course extremely brittle but it's okay well you're not gonna be changing it open file example right we forgot to do the example okay so we get a B so let's go once I have B here B okay in B should be BN goes to okay so BB goes to N yeah okay BH goes to H okay so we got the rules now uh so we so we also do here um two pairs takes a string and returns a char comma pairs two pairs a a b r equals a comma b two pairs b r two pairs if I don't have a pair I just like this now from pairs let's say gonna be a char comma char to string for from pairs uh if I have the last pair I want to say the from pairs empty is equals empty okay from pairs of the last pair is gonna be a it's gonna be a comma b all right now from pairs a comma b r equals a concatenated with from pairs r and I need the around here okay so do uh template comma rules print a dollar two pairs template and what's uh what's what do I know like this all right now main is in IO that's true let's print the pairs and then NC and CB now okay we say uh apply rule let's just say type rules equals map char map char char now apply rules it's gonna be rule apply rule it's gonna be a rules a and a pair char char and it's going to return a list of a a char comma char now apply rule uh rules a a comma b so I'm gonna do like this I'm gonna do just a just a a f so that's the a first I'm gonna say a rules map a a comma just b so if we apply the rule and we find it rule so a f map b equals a so let me define two new pairs it's gonna be a I don't know so just a and this is a new new one it's gonna be a comma n and n comma b okay otherwise we don't replace the pair right a comma b okay so now let's say print two pairs now let's print a a map apply rule a so let's say concat map apply rule like this you run it okay so and then let's make that into a home pairs so we get NC nb chb NC nb chb okay so we got the first one correct we're almost there was a first one okay so I'm gonna run it for uh 10 steps let's say apply rules equals concat map apply rule uh rule okay there's a list of charts list of charts okay so um n steps zero pairs equal pairs n steps uh n pairs equal apply rules uh rules okay I hit the other rules here as well rules apply rules a rules to pairs and then n steps n minus one on the rest and it doesn't really like this because dune dune dune all right because it needs the rules so now let's say uh instead of saying this let's say uh n steps 10 a rules two pairs template let's run this get a super long string so we're supposed to taking the quantity of the most common element and subtracting the quantity of the least common element okay so uh task one equals a template rules equals a where after is equal to n steps 10 rules two pairs template so a from pairs and we do a map length over a group over sort over after and we need to import it at least for these two okay a task one so let's call this on print task one template rules okay at one seven four nine two nine eight one six one eight six five one seven four nine one six okay so we take the most common so the biggest max uh so this is the lens so we take a min l equals a minimum length max l equals maximum length and we return max l minus min l one of five eight eight we get which is the correct one now let's run it on the input i don't know if this will be faster now but i think the map lookup method i don't know it's not too bad right now we didn't change it to uh 2621 in 35 milliseconds it's not too bad all right we got the first one in a 21 minutes it's not too bad okay part two four steps okay let's just say uh task one goes rule yeah it's gonna be bad no i think we can probably use the fact that we um like you know if i if i take each of the pairs right and i compute that for 40 steps i can uh because like so each pair right just does it's itself so like it'll never interfere with the other pairs so let's look at the uh first pair in the input vn okay so what i'm saying is uh i can actually just put it again there okay let's just say i had just vn how slow would that be okay that's also pretty bad but you see what i'm saying right if i know the uh solution for a given subsystem a substring i can kind of look it up okay let's uh let's try and do that okay it's not even cancelling yeah damn it okay we'll see how much time i can spend on this today hey i'm gonna give myself 35 more minutes so i'm gonna stream for an hour but then i really have to get back to my list yes okay so what i'm gonna do is i'm gonna kind of cash it right so let's say i do here 40 and then we do this and we do like that so this is just for the first one for 10 so you get what you get what i mean right so i'm gonna i'm gonna compute like 10 steps at a time okay so i'm gonna say that um this is gonna be task 40 so task two prime you can take in the same things right let's just uh copy paste the whole thing actually task two prime okay so i have the list of pairs okay we're gonna kind of uh we're gonna we're gonna memoize it this is how we solo solve any everything so the memo map will take in a map of a char comma char and return uh it's gonna be memo of char comma char to a list of char comma char okay okay uh that way we kind of only compute each one once okay so it's gonna be a task two v2 let's see and it's gonna be task two prime it's gonna take in the memo map it's gonna take in the current end how is it gonna work let's say just just keep the task two rolling right um meanwhile i think it's gonna be very expensive right like to make it print out what level it's on currently right it's always evaluating i'll take like this right it's just still be an insert i'm like not controlling the evaluation very well oh thanks for the follow arrow bounce about something like this i can like see how far we come yeah it's like growing very exponentially right okay so what i'm gonna do here is i'm going to say okay so i'm gonna say um 10 steps equals two pairs equals two pairs template 10 steps equals map 10 steps killed okay it doesn't even it runs out of memory okay that's not good uh okay but that system doesn't die that's good okay so 10 steps 10 rules to the uh so p let's do yeah okay let's just do it the simple way map p end steps 10 rules and let's take away this one so i do 10 steps uh on the for each of the pairs you know stop just doing task not task sort after right okay so this one is good well okay so this is for kind of each of the pairs after 10 steps so we are gonna say that this one is map out from list dollar map p comma so this one will be so it computes for each of them for your 10 steps now let's see uh can we somehow yeah i mean we can we should be able to like for this bb here and this bb we don't need to recompute it so i'm gonna say actually uh from pairs here so you see what i mean so this is like that for bb right this is a string that bb produces in 10 steps now 20 steps it's going to be um okay i think we have to so for each of them we look up in the 10 steps one so for to do 20 steps we go uh well let's actually do here first this is just a just map from pairs over the pairs 10 step pairs then 10 steps is equal to add up from list a zip a pairs 10 step pairs okay but for 20 step i want to take all the steps in the okay that's gonna be a lot of steps right now we also don't want to recompute let's say okay but let's let's do it naively first okay we're just gonna go do concat a 10 step it's going to be stand tap pairs uh actually what what what what do we have b concats then concat map uh so it's just going to be concat 10 step pairs this is going to be a list of steps 20 steps 20 steps is going to be um map uh steps map concat map does this work it's going to be a lot of characters let's just see if it um oh map oh no given key is not an element in the map okay yeah so we see a pair that we haven't seen before you get what i mean right um of course it's not going to be there because i haven't done it for all of them okay so what are the rules again rules are map char so if i run all the rules for 10 steps can i say and rule pairs is equal to map dot okay it's going to be a list of a's uh so for all of these map k to i look up the key in the map and this is going to be a rule pair so this is going to be a map of char char zip repeat k these are the rule pairs rule pairs so 10 step pairs i will run for i run these on the rule pairs and step pairs okay so now i have it for all of them so this is going to be 20 steps it's going to be concat map 10 steps 20 steps it's going to be concat map so what do i now print let's see uh let's just see the length i don't want to print it out how can it not be an element in the given map uh because it i should set like this okay now i'm not sure if this is be gonna be okay so 10 steps 20 step pairs okay now 20 steps right so what so this is uh gonna be so 10 steps uh so i concat it to 10 step pairs okay so 10 step pairs that's the pairs for each of the rules so i have for each of the rules if i run them 10 steps yes that's this okay 10 steps for each of the rules if i run them 10 steps okay so to find for each of the rules if i run them 20 steps so 20 steps equals a map map with key let's just map dot map okay so for the h so i'm gonna map over 10 steps and i'm going to map a 20 steps i'm going to so this is going to be the a p and i'm gonna say 10 steps map p concat right so concat map this is gonna be like this concat map like this gonna be like this gonna be 20 steps 40 steps front pairs map dot values this is probably not gonna work right lms okay i'll probably just run out of memory yeah i'm skipping a bunch of steps but i'm still i'm still computing it right yeah it's probably probably won't finish no i don't want to hint i'm gonna give this 10 more minutes and then i'm out i mean i know that we need to do some more memorization but i don't feel like do do do do see how much this is using but it's not using that much memory which is uh interesting i think it's also because i'm keeping all the strings around i mean that well that's the thing right you say i'm gonna need a lot more ram but like my my memory is not going up maybe it's just frozen we're not even computing the the answer right we're just computing the length of the string let's see we can think about this okay let's actually cancel it let's run it on the example it's it okay let's go for a more classic memoized version okay so for the uh task v3 i mean it's just it's just gonna be a very long stick i'm i'm not gonna compute the string right so um let's see let's just do something like this we have the pairs of the templates okay so uh if i have the memo let me just uh let me just compute like the the number of each letter right i don't i don't need to know the actual so okay uh task 2 prime if i'm if i'm at the sito's level okay i'm at the end of a computation and i have a a and a b i have a map from list a one b b one uh but everyone at all of them are counted twice okay we'll deal with that we'll deal with that later we just um okay so if we're at the and we do like this so task 2 prime uh memo case and just r memo p that is like a what does this pair how much how many how many of each letter does this pair contribute is that the right way to think about it now okay so at the zero's level this one is actually a p uh is a map dot rules a case okay just uh see a rules map dot p equals a map dot singleton c comma one c one otherwise map dot empty so uh okay otherwise so otherwise i i look up the memoization of a p comma n okay if i find it then uh no so i have the okay i have a pair let me see okay so then we check the uh p at a comma p a case just see if i look it up in the rules map p okay so if this pair is not in the rules nothing then it's equal to map dot empty map dot empty comma memo map dot insert i think it's memo map dot insert i think what is it is it a p zero memo what's that map insert insert okay so it's key value yeah okay okay so then we see set the p as zero in the map and it stops here okay if if we have a just see here then we get um rules of map p equals okay let's do it the other way around okay let's say just here otherwise we don't have to do another look up because we know it's not there okay where okay so if you're in this case here um if we look it up then we uh we simply do so okay it's actually gonna be a another so we do it a bit far further okay a just our rules now this is gonna be memo map a comma c comma n minus one just uh r2 so this is gonna be m1 uh m prime and then m2 m prime prime memo map b comma c comma n minus one now so here i'm gonna look up in m prime so if i find all these then the result is a map on union m1 m2 comma m prime prime map dot insert a p and uh well no this is yeah it should be n right okay so here i actually want to insert sorry i need to insert something here okay map insert a p a so the key is gonna be p comma n and then i insert okay so i'd say comma m u is the map dot union of m1 m2 i insert i so i return m u and i insert p n and the value is m u into m prime prime okay otherwise so if i if i don't this is if i find all of them okay let's go back to the way here we turn it before p because yeah it's gonna be this so if i can't find it in the rules and just like this otherwise this one says that the result is map dot empty is it though and i insert a p comma n mr res is map dot empty i just do it to kind of have it the same i insert the mr here now this one has of course has to return a mr is map dot single term same one this is gonna be mr uh so it's gonna be memo and we say map dot insert p comma zero mr memo otherwise map dot empty map dot insert p comma zero um map dot empty memo okay so if i um okay so if i find both of them i don't care about this actually because this one so this one hasn't changed right so i find both of them in the memo then the result is a m u and then p n and m u and then in the memo okay then we have again this one let's say we just find the first one but not the second one and this is equal to um we can have a big where m calc because i'll then oh no okay this one becomes a then we calc the calculate so mc a m prime prime is a task to prime n minus one m prime b comma c n minus one and then we do the u it's always the same result right and the last one is for when we now we have two more this one is for when we don't find the so this one knows for when we find the second one but so this is going to be ac and it's going to be c b c c b this is going to be when we find a c b but not a c okay uh and then we compute it again and then the final case when we find neither it's going to be uh but maybe we find it after we compute it damn it okay this is not a good way to write the memoization function okay okay we have the base case so we write the uh let's write it like this case a memo uh map just uh m r m prime okay we find it in the memo the p zero we can't find it in this p zero then we say just see let me do a list again and we're not gonna we're not gonna reuse it like that we're just gonna and we just say no okay this is gonna be m r map dot singleton we're only gonna cast results right we're not gonna be caching we would like caching memoizations which was a bit um uh we're not we're just gonna be say m r comma map dot insert p comma zero m r memo otherwise yeah it's gonna be this one otherwise it's just the empty map now task two prime um n memo p case just res so if you already know this one memo map p p comma n equals res okay we don't know this one then we have to say we don't know this one and then we say just see just see uh equal uh to see where m one equals task two prime so this one will it will check the memos right this is gonna be a m r comma m prime task two um n minus one memo is it p add a comma b memo a m a comma c oh yeah okay we have to do like this m r m prime task two prime n minus one memo a comma c m r two m prime prime task two prime n minus one m prime c comma b equals a map dot union a m r m r two comma map dot insert and what was the key p comma n a and then the result yeah so and we're going to install result that into in the result was a m one m two m r is the map dot union of m one m two and then this one is just m r and map dot insert and we use another insert into m prime prime okay a let's say undefined here now this one doesn't work because i look up the memo here and then i look up the res in memo okay let's just define the type so task two prime it takes in an int it takes in a map map and it takes in a char comma char now what is the result here this is the what are we looking at we look up a char comma char and an int and we return a a map dot map char int i think that's what we try to do now let's see here all right and we don't return char char yeah okay and we return a map char int and a type um memo map yeah okay here i have to return the memo again and same here memo so this one will be um let's just start it off with the 10 right task two prime 10 map dot empty okay let's actually fold our this folder or is it fold l which is it so it's pretty much i use it i think it's supposed to be fold r fold l and it doesn't want this a okay what is that before though so we take a b yeah the memo and the list and an a and return a b so take a memo so yeah take an int take a memo and a char all right let's uh let's just do it or um okay let's just just define our loop then i mean it is a kind of a fold but not quite exactly so a compute for the empty list we return cm we return cm compute memo p p s it's equal to um let's just map this and initially map it over the pair just to see what it does for the example exactly task two v three task two v three uh template rules yeah what does apply rule do uh so if i get a uh something from applying the rules uh otherwise i don't get anything from it so this one is also the same so here we get a p one p two apply a rule a rules p and then this one becomes p one this one becomes p two and then we have otherwise because we didn't have that if it doesn't actually match a rule uh then it's just um map dot empty map dot insert p comma n map dot empty memo no this is map not singleton c right so i just need to say c here okay so it's very fast for a 10 at least what is it doing now because we yeah we mapped it over the directors let me see do do do do do do do do do do do do do do do do do do do do do okay so i only right so now it just goes all the way to the bottom but it never um it never actually adds the two characters right this should be map union with so map fst map dot unions with plus okay here we're getting the letters pretty quick what does it do for the put quite fast right what about 40 i mean it would be faster if we kind of saved in between but uh this is nothing bad so let's uh write then we have the um jars equals i take the lm's and then i'll take the min c equals a mini moon jars max equals maximum jars max c minus min c so for the example we get this number i'm forgetting something i think i have to do p at comma c and then i add the two then i do unions with m1 m2 and map dot singleton c1 so i have to add the intermediate characters as well let's see we're getting the wrong number but i feel like we're we're on to something right so what does it give us for 10 so for 10 on the example and wasn't it right before then we got 1749 and 161 so there are someone some of them we are counting twice something like that maybe it's just like this maybe we should end here under one we're quite close to the right one right i mean these are not like they're not an order of magnitude off they're just some of them some we are uh all right because it's i do with it for the pairs unions for each other pairs but let's just do it for one let's see if i do it once i want to give b4 c2 okay because we added uh b n c and b c h b let's see okay so let's call this run so for each of the pairs and let's do let's see so we have the run f f s d run let's see what the result is we don't want the memoizes so n and after one gives a b1 and c1 okay what is this after zero okay this is so it gives c1 and this one gives b1 and this one gives h1 okay now for uh that one was correct uh okay but it's not counting kind of the initial letters right what if i do the yeah okay so so this one becomes n c n okay and now n c n become uh n c becomes b and c n becomes c so so n n right this n n becomes n c n becomes n b c c n so this c there should be two c's here and i think it's because i'm not uh including the and that's the like that's a b a c b map dot from list a sip a b c repeat one this looks more promising so then the n n becomes it becomes n b c c n right which is and yeah okay this one is looks correct so let's see the jars let's see run jars here so this is after one round now after 10 rounds on the example we get uh no let's see what if this is after nine rounds i think this one may be one after one round what should i see okay after then of course i should insert one here always what happens if i put zero here yeah it's the same right so some of these will be repeated right what if i just add the a c and i kind of trust that the other one will be added at the other one and so n c two b's so two so there's two n's oh that's my one b damn it eccb so after one step there are two n's two b's two c's here saying three c's okay i think i should just add the c here and here i should add the b one add so i add the new one here and this one becomes map unions with one and two that dot single single ton c one this is after one step after two steps b five c three h one b five c three h so if i and if i add the ones in the original template let's see here but if we're like two n's off here that should be fine we should be one b off we should be one b off yes we're one b off and here and there's no h yeah okay so okay so we do we do we add the okay so we okay a temple count that's a group that's a classic map x comma length x underscore l two l comma x now okay yeah it's like this l add x underscore two length two x comma length l to the template of the group sort so we have one of them temple count and then we say map dot union with plus char's temple count what's wrong with this one oh right map dot from this temple count okay now we have the right count for the first one um now let's see we've got 1588 yes and then for the input we're supposed to get the same answer two six two one nice okay now let's check for the example for 40 two one eight eight one eight nine six nine two three five two nine nice so we should be good all right let's copy this all right we did day 14 the combinatorial explosion almost got us but we ended up with 300 milliseconds yeah i don't know what i started off with there like with a just like yeah let's i don't know it was weird like if it's in like we just check if it's in the memoization right and if it's there then we just return the memo okay memoization helping us from exponential blow up yet again we getting these base cases was a bit tricky though so we added we i always counted the character we added uh but the problem was that um that we uh the problem for the longest time was that we never counted the initial ones okay cool cool cool cool cool i will delete this one because it was garbysha this one is a ax exponential blow up let's see get status get add day 14 dot it just input okay did commit am day 14 did push okay we did day 14 um it was just a classic you know memo map return like check if you've computed it before then return it if you haven't do the computation make sure you get the base case right then return the result and insert it into the memoization so you don't have to check it again otherwise so if it's not a rule it ends up there we could have actually done like this uh let's see now yeah and then this case was a bit tricky right we had to make sure to count the letter always that we were adding and um we add the letters we sum up the two answers we've gotten so far and then we cash it and that was the trick right we were always kind of computing the same thing again and again but this way it worked out oh otherwise yeah otherwise we also we have to know when to stop right if we get a okay so it worked out thank you for tuning in what is a what is this is just a pattern match so uh yeah this is just a pattern match so uh so guards right they can be like you can have equalities or you can have a pattern match and it's in this kind of pattern monad right so you can run it and if it if it doesn't match the pattern then it just fails and it goes to the next case um yeah i don't know it's just guard syntax pattern matches in guards right i don't know if it has a special name it's no i mean there's no language extension or anything going on here it's just just standard that's cool nine eight point two okay so another key thing here is this right you take the memo okay you pass it to the first one right and then you have to use the new one with this one right otherwise these two are gonna spawn two trees right so if i say memo here it's not gonna finish okay so very important when you memoize don't forget to actually use the memoization although yeah i can't even cancel it so that's the thing right this is the key one right we so and this means we kind of only ever computed once because if we computed it before we look it so both recursive calls you have to yeah you have to update the memo and then use it and there is a name for this pattern somewhere right i don't know is how you memoize in Haskell and then yeah make sure you use the latest one this is also an issue right you can't i mean okay this one is not as bad i think because i think you end up computing most of it in the left hand side anyway okay it is pretty bad actually so also make sure you you return the latest one it's a bit funny right like how tiny changes to the code can make huge computational difference when you're dealing with the exponential blow up otherwise so we we do so this is basically like we apply the rule and if we get the result because it's a it's gonna be empty okay it's not gonna be empty but it's going to be it's not gonna be it's not gonna have two elements and then we don't we're not adding anything and then we can just say that for this case we are in adding nothing i think my 10 20 steps was kind of cool it was like the but it was just i think yeah it was too much too much data going on all right thanks again for tuning in and i have to see about tomorrow maybe i'll be here at seven but i have my listening thesis going for printing on thursday morning so i have to finish it tonight and tomorrow so we'll see about tomorrow but maybe yeah but at least it's been fun today and yeah just follow my twitter around this time because you know i might be going to norway and i'm going to iceland for christmas and all that so yeah we might be a bit the schedule might be not as regular but check my twitter it's probably gonna be an announcement there and yeah well thanks for joining in so far it's been a lot of fun for these last 15 days right just doing some memoization making it work having fun all right catch you all uh next time whenever that may be probably tomorrow but we'll have to see how stressed i am all right bye