 Hey all and welcome to today's episode of Haskell in the advent of code We're gonna be doing day 10 today. I haven't looked at it yet. So I don't know how much of an issue it will be but I'm hoping it won't be too bad because as I've said before I'm a I'm leaving tomorrow for home for Christmas I'm gonna be wearing a mask on a train to Stockholm and then I'll take a plane back to Iceland I'll be wearing a mask the whole way. I got one of those face shields that they wear my Virologist contact my girlfriend. She hooked me up with some sweet sweet face shields for The trip and I'll be tested when I get there and I'll be tested again five days later. So Yeah, hopefully we'll get good. Hey, so I won't be back tomorrow I'm gonna take so be traveling tomorrow and then I'll be traveling again on the Saturday, but I'm hoping I'll be back on the Sunday and Then we will do day 13 and We'll do day 13, but then we'll do like a marathon finished a 11 and day 12 so You won't be missing out, but it's gonna be a long stream. Well, maybe it'll be a short stream. Maybe Friday and Saturday are just super easy. We'll see But yeah, let's get started with today's stream Uh, we got today's moving cup. It's the same blizzard cup as before. I This is my new favorite cup I got it for Christmas and I got I got a matching spoon like this is a moving spoon I really like moving stuff. So nice All right, let's check out today's problem. Let's see Advent of code. Oh, this is day eight Day 10 of the advent of code Let's see. Um, oh, yeah, and we got our first two subscribers yesterday, so Thanks a lot Really means a lot to me. You know, I'm just here to chat with you guys and gals and I really just enjoy programming, you know, but it's fun that And you think I can kind of I can't you know, I can't support myself, but I can't get a little extra funds Uh, because Yeah, I spent a lot on The whole setup most of we're doing proper talks, but Yeah You know, you gotta spend money on what gives you joy Right. All right, let's look at today's problem adapter array Okay, the weather forecast. Hey, you're too cheap I hope I'm not offending you by saying your name Oh, yeah, and we got an emoji now Are you ready? Are you ready for the Oh, no, we haven't did it. It's not up yet. Oh damn it twitch has to like Manually review all the emojis Otherwise I might send like an appropriate emoji, but it's a good emoji. It's gonna be it's gonna be lit Okay All right, so that array patched into the aircraft state of your dress where the forecast of a massive tropical storm Before you can figure out whether it will impact your vacation plans. However, your device suddenly turns off Oh, shit This is a stormy trip for santa He's not doing too well actually Uh Oh to me to me I like to me Keeps me honest, you know He's like, uh, I mean tim is a good programmer uh, so If he is worried about part two It's gonna be something that's safe You need to plug in there's only one problem the charging outlet major C3 is the wrong number jolts It's kind of like volts except it's jolly I'm guessing always prepared. You may have all the jolted adapters in your bag. Yeah, I also have a bunch of adapters Not joltage, but like We can plug into whatever Each of your jolted app is rated for a specific output joltage your puzzle input Any given adapter can take input one or Take an input one two or three jolts lower than its rating And still produce its rated output joltage So it's gonna be a range from the joltage to joltage minus Three In addition your device has a built-in joltage adapter ready for three jolts higher And the highest rated adapter in your bag If your adapter list for three nine and six your device built-in adapter will be rated for 12 Okay What language is this? We're gonna be programming in haskell But we haven't started yet so The empty language any theoretical cs people out there got that joke Super funny Uh, what's up reaction cs? What is the problem? What is the trouble? We can't help you unless you let us know, you know Uh, if you use every adapter in your bag at once, what is the distribution of joltage differences between the charging outlet the adapters on your device? Yeah adapts with the following joltage ratings with these adapters your Devices built-in joltage adapter would be rated for 19 plus three So that's the maximum Because the adapters can only connect to a source one to three jolts lower than its rating In order to use every adapter you'd have to choose them like this A charging outlet has an effective rating of zero jolts. So the only adapters Okay, does it always have zero jolts the rating? Yeah Okay, uh So the only adapters that could connect to it directly we would You would need to have Joltage in one two or three jolts But these the only one you have is an adapter where you're one jolt From your one jolt adapter the only choice is your four jolt rate adapter On the four you can have five six or seven How in order to skip any adapters you have to pick the adapter at five jolts And then we need to pick this number on a six and then the seven I'm gonna go from seven to ten 10 11 and 12 Choose 11 and 10 10 12. Yeah, yeah After 16 the only valid adapter has a rating of 15 then 16 uh Getting a message After 12 only valid adapter has a rating of 15. Yeah, then 16 then 19 And your device is built an adapter. So it's three higher than the highest adapter So his rating is 22 jolts Okay, so we just need to arrange it. We always want to use all of them So here's a larger example In this simple in a chain that uses all the adapters. There are 22 differences of one jolt and 10 differences of three jolts Four find a chain that uses all of your adapters to connect the charging outlet to your device is built an adapter And count the jolt. There's difference between the charge and the charging outlet What is the number of one jolt differences multiplied by the number of three jolt differences? All right, let's find it out A reaction you still haven't told what your trouble is. Uh, let's see touch 10.hs To me, can I just ask how long did this take you? We need to make a new directory Okay, 10 Touch day 10.hs and then touch test small touch test ping And then let's open day 10 .hs It's gonna be a module main ware We're going to get the input It's going to be a file path to i o int get input First but easy bc second part took more than an hour. Oh shit. That's just how it's gonna be we're gonna map read at Read i o no we're gonna read that we're gonna read int over Read file We're gonna fmap read int over read file And the we need to take the lines first Yeah, we need type applications. We want to do this I just always write read like with an explicit type because I always want to know what i'm doing And I think type application will be in default task in 20 and then the gtc 2020 version so So you get input test small print it Let's open test small I think we already copied it Yes, and test big Insert it Okay So there's two so okay, so there's a couple of ways to do this right? But what we're essentially doing is We have a graph and that graph is connected You see what I mean? So, you know, it's so we start at zero And then we have the input right One two three four. Okay, so, you know zero It's going to be connected to All like it's going to be connected to one A zero is going to be Connected to Three and it's going to be connected to How do I do a reverse slash? I don't know Let's see. Oh, shit You all saw that right? Let's does it Why do you prefer Haskell? a I worked on it for like five years now It's kind of my language of choice and it's fast But it's a it's right at the Point where You have the most type information With the least amount of effort Because it infers so much That's why I like it Let's see So and then so what we're going to do is we're going to build the graph and then we're going to just find Find a path in the graph That visits all of them So I haven't used o camel so much. Um I think I've used reason ml a little bit which is like It's like o camel with like a slightly different syntax And you can compile it very easily to javascript And that's okay, but one of the things I like about Haskell is that you limit IO you can only do IO Uh every now and then Tyrion Lannister How is that? I don't I don't get it What is Tyrion Lannister here? Anyway, let's see So zero is going to be connected to One two three Uh and then You know so zero is connected to one two three One is connected to uh Uh So you need a adulterated rating one two three only the only one is the raptor in one jolt. What? Oh, yeah, this is a small and I was looking at the big one Yeah, okay, so we have one so we go from zero to one We got a one two four, right? So we want to find a a path That visits every node In the graph Exactly once And uh, there are uh There are no cycles Because uh, it's a directed graph And it's going to be We're gonna build it in such a way. I mean so it's a directed graph and you can only go from a lower one to a higher one Not the opposite direction So It's like the traveling salesman problem except in a non-cyclic graph What is it called a Hamiltonian path? This is it's where it takes exactly once Uh And we are trying to find a Hamiltonian path in our graph So If an helmpoint path exists whose endpoints are adjacent, they're presented in graph cycle. It's called a Hamiltonian cycle Okay, so did it dot graph has come So like we're just gonna do it like properly We can import data dot graph Uh And here we have the path and uh, okay, we can't just call We can't just call um What am I saying? So we have the we have the we have the list, right? And we can only go from a lower one to a higher one, right? So we we can just sort it, right? Let's see Uh, let's close it Let's say Let's first Sort it Import data dot the list I think I think like a graph thing is We're complicating it too much Because we can only go from a lower to higher Oh they did So it's 1 4 5 6 7 10 11 12 15 16 19 we have to use All of them exactly once And they because they can only yeah, so we have to use all of them So we have to use them in order, right? That's it, right? I think we're complicating it too much. Uh, so we have the sort And then we just find the differences between each Uh, how do we How do we do that? So we want to find the difference between one element and then the next element So it goes 1 2 4 4 5 6 7 10 11 12 Uh, okay Let's just do it, right Diff's Can I just I can just like shift it by one and then And then do Yeah, so I'll do that. So get input Okay, so sol 1 That's going to take in a list of ints and it's going to list return as an int so sol 1 of the input That is going to be So we have two lists and we want for each element on the list We want to solve prime. We're gonna do imp and tail of imp Sol 1 imp It's going to be So, uh, this is ahead of i Is and then it's going to be T ts Okay, so Sol 1 If either one of them is empty, we're just going to return zero Uh, no, we're gonna we're going to return an empty list actually We're going to turn turn a list. We're going to turn a list of the differences. So sol 1 So the second one will run out first It's going to be equal Yeah, that is true to me That's actually That's actually very good We can actually do sip width Even faster Sol 1 So let's just do sip width minus the tail of imp and imp So what is So we do sort So first we sort So, okay, let me do sol 1 Let me just say Where s equals sort Let's do it here and we do here Okay, so we don't have to sort here and so, okay So three one one one three one one three one one Okay, and then we do Sort again And then we do group Which is I think What is the complaint here? So, okay, okay, let's just sort this first so you should see what happens It's one one one three three. Okay, and then we do This is going to be a list a list of things if we group it Let me do group So we got the ones and then we will just return So, okay, now we we've grouped it and now we want to turn it into a map So we are going to say imp equals This is going to take a Now, okay, let's just So We're going to return a list of pairs So this is going to be a 2p f it's going to take in a list of x an axis Lee, okay, and this is going to be just x and whatever and we're going to say f of lee It's going to be we're going to count the number ones and we're going to count the number so number axis and then the length of lee So we're going to we're going to do map f over this I'm going to turn off the list of pairs Okay, uh So I because I'm thinking That we will let me see. So what happens if we run it on the on a bigger input? We have 21 and so it's always one or three. Have I ever met Simon Peyton Jones? Yes met him a couple of times. He is a very nice guy And we work work together a bit on the type toll stuff And that's I think that's one of the best parts of the Haskell community is like these legend people Wow, yeah, thanks Lenny. I also have a a nice t-shirt on I got for Christmas Uh, I won't show it too much because I I think some of it might be copyrighted But yeah, so the one of the things with Haskell community is that the like the legends in it like Simon Peyton John Hughes Phil Waddler like all the names behind Haskell let you go on like in john lunch break like if you go on the vikipedia page Like and then you meet those guys And they're really really nice people I think that's why the Haskell community is I like considered a very nice community. It's like because like the main drivers of it are these super nice people So, you know, I really recommend the Haskell community Okay, now let's say let's say let's say let's just say that this is going to be An int So we're just going to take the second of these pairs. So it's because it's always going to be ones and threes All right. No, let's not do that. Let's say It's going to be a map of ints to int And then we say map dot from From list Because I'm kind of sure that we're going to Look at something else than than just Ones and threes later So we have here from list one and six. Okay, and then we just say The map is going to be this from list and we're going to say map Of one I'm gonna look up look up the one here map of one times mp map dot Of three now. This is wrong because uh, I always Mess these up Is it like this? Oh, no. Yeah, okay. It was correct. I didn't mess it up. It just because this is going to return in So for the first one it says 24 and then 189 Seven differences of one wall jolt and five differences of three jolts What? But we got six and four Oh, we so we have to count the first one. We have to count the second one So what we will do is that we will take the input We will add the zero to the beginning because the charging Thing is always going to be zero. Wow. I have so much spam And you're like they're always spamming the same message. I wonder why Twitch didn't twitch be better at filtering these out But you know, I got active chatters. So Okay Okay, so it's going to be sort and then it's going to be Uh We are going to have to add the maximum No, so it's always going to be so it's going to be zero at the beginning but then it says that it says that a It said here that uh The built their device the built-in jolt is adapted rate for three jolts higher than the highest rate adapter in your bag So there's always just going to be one higher Gift me a sub. Wow Uh, so we are just going to say here mp prime equals A map dot modify with Key, right? We'll go with modify map dot modify Data dot map I think there's like a we can modify key How do I change? Uh one key let's see update at Update the element add index by zero based index in the sequence or if I give the answers out of range Zero based indexed in the map What's that? Does that even make sense? Update man update mix adjust. Yeah so we're gonna say Adjust and then We're gonna say plus one For the key three in map So I need to we're gonna be map One and three So this is seven times five and this is 22 times 10 Okay, so I think we got the first one Let's check the input. This is the old input. We're gonna do New file input here Okay, and see we're running it in two milliseconds. So I mean for the tests that that's maybe not so cool Input let's see 2240 Doesn't seem too bad. What if we don't what if we just print out the map what happens then? Okay We also got just these two Let's see 2240 that's what we got right 2240. Let's see All right. We got part one But it was easy peasy as Tim said But Tim is interested in Part two. How will I do part two? I think that's where I have to do the graph stuff Uh But let's see FUN. Oh my god Every arrangement you'll need to figure out how many different ways they can be arranged Uh Every arrangement needs to connect to charging out the to your device Previews about when adapters can successfully connect to the apply first example above Supports the following arrangements zero below. Okay, so we can connect those. Yeah Uh Has many arrangements. Okay That must be more than a trillion well-advised arrangement. Surely it must be an efficient ways to count the arrangements What did I tell you? We're gonna build a graph And then we're gonna count the number of paths Starting from zero To the end. How do we do that? That is that is fun Uh, but let's see So we always have to go from zero to the first one. No, we don't have to do that, right? Because we could we so here let's see we can't start with three, right? Now let's just let's just build I think building a graph. That's not too bad, right? Okay, so We take our input Uh, we're gonna be using data.graph Uh graph from edges Build a graph from a list of nodes uniquely identified by keys with a list of uh Let's see Build a graph from a list of edges uniquely identified by keys With a list of keys of nodes this should have the edges too So the nodes are just gonna be We're not gonna use the nodes So they're gonna keys and that's gonna be from a key to a list of keys Here we're gonna use Haskell standard library, right? It's gonna be powerful Let's see. So let's fix solve one solve two Okay, uh, so The graph from edges Um So zero connects to zero one two three, right? So safely uses a be matter of strength. Let's have it first No, the outlist may contain keys that don't correspond to nodes at the graph They are ignored So I think we don't actually say We could just always say Plus one plus two plus three I think we can just you can say that all the time, right? So let's see graph from edges Let's see Import data doc graph import Qualified data doc graph as graph Sol two, okay, so we're gonna say here Well, just let's just not give the type yet. So solve Two is gonna give us We can take in the input. It's gonna be a list of hints Uh, solve two. Okay, so the the Didn't know about data doc graph dimmy you gotta know containers Because they have the stuff you need, right? But yeah, if you see I know if you spend an hour building graphs That is not a long time to spend building graphs in Haskell. So I applaud you sir So, uh geez They best respect my geez As the poet once said What they say I'm from the project's best respect my geez I think that's how it goes. So we're gonna have units as the nodes When the exponential time algorithm hits Am I gonna click click this? So I know borders from twitter. I think he won't post anything too bad Oh Yep, see how much I trust your borders. That could have been anything that link I'm very easy to Uh fish apparently I bring a do I To I plus three right over So let's find so and max input max i equals maximum Of the input So Of the input let's just call this input geez. We're not that lazy So the maximum of the input and we're gonna map this over The input We're gonna add We're gonna add We're gonna add maxi plus three and we're gonna add zero to the input. Okay, so let's just say here graph From data. So it's gonna be graph dot graph from edges Of the geez Let's uh, let's check it out, right? Let's just see what happens here Okay, a a So g v What's it? Oh, what oh, let's I want to have the type here. I can click this. We'll put the type So We need graphs we know and we need a vertex It's a bit annoying that uh That uh What am I saying? It's a bit annoying that g atc id doesn't realize this it's not it's not the greatest with scope Oh, what? Yeah, like this and then this should be vertex, right? Yeah Like this Okay, uh We don't need these Because we know these are ints Let's let's look at what happens if we say a g v a I Get input of the tests small Into uh, so yeah, we're gonna We're just gonna read the input twice. It's fine It's all to map over this Can we print the graph? We have zero one two three two three four five four goes to see see how cool this is zero Oh sweet Get input test small a print So we have print the sort of this So we seem to have keys here That don't exist. Oh, no, so i doesn't go to itself i goes to i plus one So zero goes to zero and zero goes to one one goes to two two goes to three four five But three four five is not in the input So let's say here Uh Input set is going to be set dot from list Of the input import data dot set set import qualified data dot set as set Uh, so the input set here and then we're going to filter This with oops Set dot member Input set Okay, uh Like this And now we're actually going to say here that this is going to be find max of the Input set because it's going to be Otherwise we were repeating some work So we have zero goes to one one goes to two I don't like it. I don't I don't like that this graph here Has an edge for like up to 12 I like where's the 19? What is going on here? So we're we are Does anyone know what's going on here? We should go to six two, but I don't see exactly I mean 19 is not in this list Right and that should definitely be in the list Uh But okay, maybe this list Uh, let's let's let's see here. Let's look at it Let's see. Let's let's print g and let's print a v of of 19, right Is index 19 out of range Let me debug dot Let me Christ Show it Because this is suspicious, right? Something wrong with data doc something wrong with the way we're calling data doc graph So okay the input it's taking in it's definitely our input Maybe this list is wrong or graph from edges So build a graph from a list of nodes uniquely identified keys with a list of keys nodes in this should have edges too. Yeah Okay, so Let's let's trace Show it gs I mean our input list looks okay, right but then the Okay, graph is a raw array based adjacency list for the graph Note from vertex it turns out not associated with a given zero based index into vertex vertex from key Returns the into vertex for the key if it exists in the graph nothing otherwise so I have here 19 goes to nothing Uh Okay. Yeah, so the input set is wrong also Let's should be maximum the input This trace show id this should be This is just input prime And then this should be input prime And now it's complaining about input set because yeah, so we just want to say input prime here I think this might be Something adjusted. So okay 22 goes to nothing. Okay, but 19 goes to 22 at least And then zero goes to one. Yeah Passive 22 is a target vertex in 19 and that for 22 is max plus three Wait, but we 22 is a target vertex. Yeah Exactly. So now 19 ends up at 22 I was just like it was just missing but like I'm wondering so this so this is here's 11, right? So this is zero goes to one. Let's so that's the one goes to here, right? this four So zero goes to one one goes to four four goes to four five six, but it's just that these are like adjusted Uh, so I I think I just need to use The let's let's let's make the nodes be the keys here So I think that's the issue. So So, okay. So, you know, so this is the oops I didn't so this is the This is a note for zero. This is a note for one. This is a note for Two I am this is very confusing So this is a list of the so 22 Goes to nothing zero goes to one 16 goes to 19 This returns. Oh graph note from vertex and vertex from key. Oh my god So this is graph note from vertex, so note Vertex So this vertex of 19 That should give us just 11. Okay, and then Just 11 gives us this one, right? Now, let's see note from vertex. Okay, so Let just uh end the just v equals vertex of 19 And then we're gonna print the Nordics of 19 we're gonna print Note v Yeah, and then we get the node so 19 19 goes to 22. Okay now now we have the graph We actually have the graph which is good. Okay. Now we need to find Hamiltonian paths in this graph No, not Hamiltonian paths. We need to count we have to count the number of paths From zero to 22 from from like the start to the end Well, let's just do it more efficiently. Let's say here start equals zero End equals There's gonna be the end The maximum of the input plus three So we and we add start and we add end here That's the input prime Okay, now Count the number of paths from A spanning forest of the part of the graph reachable from the listed vertices How do we count the number of paths from But we only say we total number distinct way you can arrange adapters. Yeah So I guess it's going to be uh It's going to be Paths from the first node in the graph to So times the number of Paths from Every possible next node in the graph That's it, right? I don't I don't think I even need this graph thing here I don't I don't even think I need to build the graph, right? I think we just need this gs that we built and we're just going to We're just going to sort it Let's just So we have the gs here, right? So it's going to be, you know, zero times the length Of one and then, you know from one All the paths from one to the end So it's going to be, you know So let's see Spanning forest is a part of the graph reachable from the listed vertices spanning forest Can I just do We have the graph graph.dfs That's going to be a list of forest those illicit trees graph.dfx of Of the graph and the vertex zero We're just going to use from just we don't Don't care. Let me see So this is a list of spanning trees starting from What's the length That's going to be one. Yeah, and so it's going to be just one tree, right? So that starts at zero. Wait, I can there's a There's a couple of stuff in forest I can use Uh data tree Data.tree has goal They also have like just like a way to make it print it nicely Draw tree draw forest import data.tree We're not going to use it directly. We're just going to say qualified Qualified print puts putster and then Draw forest A tree of strings to string so I can just map over the tree, right? Can I just I can just not use integers, right? If I just just for this but I just want to see the tree that's coming out of here And then we need to take this away and the issue now is that forest string actual type fourth vertex Is that just a return here of It's going to be a forest of vertices Yeah, okay, we can't print it Let's not Let's not go down this path Dangers dragons lie ahead right in this path This goes to zero one one two two two two three three two four four to five five two six six seven six seven two eight Eight to nine eight nine to ten ten to eleven eleven to twelve Okay, uh, that didn't help Yeah, I think there's no I mean, I think we I think it's way too difficult if we're gonna be doing Like We don't have to implement a graph algorithm. We can just we can just iterate over it, right? So let's see Uh, so we have the graph Okay, let's see is this all to get graph salt to So here we're gonna say So we are going to take in the graph And we need the functions to write Okay, let's let's just let's just keep working with these salt here Let's see So I have the I have the graph node vertex, right? So let's just write that So this is gonna be v to n and this is gonna be V to key right? That's what these are graph from edges vertex to node and k to v equals the graph to graph dot graph from edges of uh Yes, it's gonna be it is There is Now, okay, so how does the algorithm go so I want to start at zero So let's write the salt to prime That's going to take in I'm taking like the current one we're looking at Okay, I mean it's going to take in like this whole thing I gret Uh graph Graph build I just Graph I just want to name this something else because I'm gonna be taking in the same here So it's going to take in a graph build That's going to take the current one we're looking at And it's going to return the number of paths from that one to 22 Hey B snatch Why I'd use dfs or dff and count all paths through it. It's a dag So the tree is finite, right? um But you see here that we we did the dfs And There is just one path in it Because it it just kind of finds one of them. So the length of the dfs was just one So starting from zero just so it didn't it just finds a spanning tree not all spanning trees A spanning forest right not all spanning forest, right? So if it were all spanning forest that would be fine but But yeah, it's not not that right I think that's the issue Do you agree tibby? Oh my god, I think I give you Okay Yeah, we need every possible dfs, right? um And that's not what the function gives us that's the issue I think that's the issue So ker I'm just gonna go first here case a Key of ker of so if we so we have something If it's nothing then we're just going to return zero So I think I mean k of ker that's going to be like a Like if the if the key is in the graph And we're because because of the way we built it. It's always going to be that way Uh, we and I guess if we remove this it's going to be it's going to be okay Like we So we we're essentially doing this check so we could just say it's always going to be this but like So let's let's try it later and like drop this condition Okay, now, uh Just n this is going to be a node Of uh the key the key And a out Uh, so this is this is going to be a A Yeah, so key from edges that's going to give you returns to maybe a vertex Key k to v So this is just going to be res. We're not going to be just going to say res Okay, now actually we're not going to be changing the graph So this is just going to solve two prime. So we're not going to be changing it So this is where we have so here we have the graph. So this is going to be k To v So if we get a vertex, uh, so that's going to be, you know, uh vertex Bert Then we can say Let's see We let's see what out degree gives us Because I think we can just kind of multiply all the out degrees somehow Let's just not give this a so let's say Let's just see what the array of the out degrees are now. We're just kind of exploring right? The out degree of zero is one zero one two One two, two, three, three, two If I remove So let's look at the array Let's say ellens let's say We're using all the data structures right now. These are the elements There's one zero in it Where is that zero coming from? I removed max, right? Oh, all right. I'm removed I removed the end here So I'm going to do something crazy right now. I'm going to do a product of the Tail of the reverse 12 One two three four five six seven eight. Yeah. No, okay It's eight That would have been something right But uh, it's not that easy What about the in degrees? Because I mean so like there is some theorem about this right would be like just multiply everything But uh, I think yeah, that's it would be would have been too easy. We could have just done that So let's keep here So k to v of curve nothing just vertex and we're going to say Let so the key and the value so we have the curve And out equals V to n of uh of vert in So that's going to give us the outs and now we're going to say Maps all to prime on the outs and then do the sum Let's see. What what does this do? I'm going to give zero Because that's a year Because it sends to be one Nope still zero. Let's see Uh, well, I think we're missing like a base case somehow Trace show ID of the outs and okay, so zero goes to one one goes to four four goes to five six seven Five goes to six and seven six goes to seven uh This is going to be linked outs Plus of the rest right that gives 57 that's too much right That is too much. Oh, thanks hint a super. Let's see essentially, you know So the number of paths from zero to 22 Is the number of paths from zero to one and then the number of paths from one to 22, right? And the number of paths from so because they all end up at 22, right? Uh, let me let's uh Yeah, this essentially never happens Let's uh, let's look at the current one, right? So It starts off with zero and zero goes to one then one goes to four four goes to five six seven So it starts with five if I can go to six and seven Six and go to seven seven can go to 10 Yeah, I think this is what you kind of have to do here Let's see So what do I want? I want sol two to count to count a This this this goes like, you know, because it says 57 right and the total should be eight um I think I think I'm kind of have to say length outs outs So the thing is that this is going to end up with being So let's just say here if okay, so Case outs of shouldn't it be like this? I mean, this is how I want it to be but It's not how it is Here we got eight But this isn't this the same as we were writing before So I did the length outs times. Oh, I should have just have been doing some But that gave us zero, right? Yeah, that gives us zero Oh, okay. I think it's just because we want the empty list to map to one. Oh, okay. I think that's it, right? So So if there's no out then we are then there's only one path if we only add one Otherwise it's going to be The sum For mapping the solution to outs works for the small input. Let's see. Yeah, okay. It's actually It's like this And it works for the big input, right? So it works for us. It was just the fact that we were We were not mapping the empty list to one. Okay So why would it not be one? Because the sum of the zero It's going to be zero And then if all of it is zero then it's going to be Yeah, the sum is always going to be zero. So we kind of need the base case that it has to end in one Okay Nice What are we we could just do this Because when you've got nowhere left to go you're at the end and that's a path. Yeah. Yeah, that is true The only note word that has nowhere to go to is the path is the end I'm just wondering here that so here we say k to v of ker of I thought like that because yeah I guess we add too many things here. I thought like if we Oh, okay. So here we have the outs list And the thing is that we always at the outlets and then So here we have the because this this will like give the end three paths, right? Because we're like depending on that are in fact being a path here Okay But this is quite fast, right? Oh 19 milliseconds We don't need to sort this What can we do better here? It's going to be a sum I don't think we can do much better here actually I think we are going to be actually in this case Uh, it's always going to be Okay, I don't think we can like memoize this Okay, but let's see. Let's see for the input Let's first get uh from to me. How how how fast was it for your input? Oh, this is you run yours first. Okay That is way slower than we've been doing usually, right? So it took Can I get an f in chat? For how long this is taking You see if this wasn't a live stream I could just Go and get more coffee or something But Now I just have to sit here and wait And be like Let's say if it takes takes let's give it let's give two or three more seconds Or a minute. Let's give it a minute or two You're going to have to use some graph maths. Damn it to me Could have said there's a lot of trouble. Okay Use some graph maths Okay, let's look at it. Let's look at it So I have the graph from edges And we can get the out-degrees And that's essentially it here, right? We're just getting all the out-degrees and then we want to get the out-degrees of all the Of all the other ones. Okay. Let's look up graph maths A counting paths in a I just want like an algorithm. Um Let's see I have something that graph library could count the paths in a more efficient way Yeah, it would have been nice But this is going to give us a lot of because here we're like essentially we're counting each path Right, let's see. I mean, it would have been very nice like a recursive way of just saying Like looking at the out-degrees and looking at in-degrees But you kind of have to trace all the paths, right? Let's see what we have here A spanning forest of the graph obtained from a depth first search of the graph starting from each vertex in an unspecified order So we can do topological sort We at least have the graph right in like a nice graph way This is the worst part of advent of code, you know when you're like your initial thing doesn't work And now you have to start thinking. Okay. How would I how would I do it then right? Let me just see. Okay. I'm just gonna cancel this. It's never I mean it's been running for five minutes It's too much So this will always work Uh This will always work Okay, let's see here. Let's see if we can gain some efficiency somewhere So we're just gonna Because we're only gonna be looking because we constructed the graph in such a way that It's always gonna be it's always gonna work That's actually, you know, let's see. Is it the counting thing that's That's that's screwing us up Or is it like the actual construction of the graph? No, okay the the graph The graph gets constructed pretty quickly I mean, yeah, it's just doing stuff, right? Uh just like So constructing the graph is no issue It's just that we're kind of for each path counting the paths, right? Um, okay So the issue here, so I think we can just memoize it I think we should memoize Because we're gonna be running into the same edges again and again again, right? Let's see here There's like a memoize Uh, I think there's like literally a thing you can just do to just that just memoizes Haskell memoize Because I because I think there's like a data dot function dot memoize Oh, but you have to import the memoize package. Okay We don't want that So we are going to memoize it. How are you gonna memoize it? Well We have a map of it to hint This map is going to be lazy That's better for memoization Uh import data dot map Dot lazy Yeah, I think that's gonna work, right? So memo Of curve So, okay, so how do we So for curve So, okay, let's see If we're encountering this curve for the first time So so case Curve map dot Memo of just val going to return val Nothing So we've never encountered that one before That's it. Yeah, because I don't I don't want to All right, we're confusing this a bit If this is going to be nothing Okay, so if we if we have it then we we want to memoize it, right? Let's say curve Couldn't I expect it? Okay We're gonna be looking up Cur in memo, right We found it then it's gonna be there. Okay, if we haven't found it Then we have to fold it, right? Let's see here, uh fold l What is the type of fold? I always forget Which one it is So then we are going to take a fold l We're going to say map.insert uh hugel so insert data.map Let's say we're gonna insert something into the map Because we want to like keep the same map again So, okay, so we're actually going to fold Okay, so here this is going to be the map of int to int So and then sol two It's going to start with map dot empty And then we are simply going to map dot lookup zero in that So, okay memo of curve So if we already have curve in the map so If a curve map dot member of memo in memo Else if we so if it's already there We can we don't have to update that value Now if if if if it is an actual vertex So, okay, if it's not there We will just return memo again, right? But this doesn't happen so we don't really have to consider what happens, right? So The outs is going to be a list of the vertex going out from that one Uh, so if case of outs of if the else is an empty list then We will return memo Map dot insert no, so it's map dot insert We're going to insert the curve with one the rest Are going to be I think I'm doing something Something weird here. Let's see Do I want to like for each of the outs like inserts check check if it's there an insert I don't think I should do this. I should I should do it this way Then memo memo map dot if it's if we haven't computed it before This should be I think we need to return both the integer and the map into So then We read if it's already there and we just return the pair If we haven't Then we have to kind of compute it for So if it is just outs then we just say case outs of so it's going to be one comma Map dot insert curve one If it's if it's something else then we have to fold over the current one Fold l This is going to be some function our initial So we're gonna we're gonna fold with the It's going to be memo comma zero And it's going to be over the list of outs. What's wrong here? Okay, it's just so so Where f F is going to take in, you know, the current memoize function and the current sum Curve sum I think isn't it just going to say This is going to say salt to prime And what's wrong with Memo here. All right, this is supposed to be the end Let's actually have it like this And let's have this be Curry when you go this direction, right? Oh, it's uncurry Okay, what is this? uncurry takes a map of int of a map into into map of int Now, uh, it's going to be f. Okay where f is a type Map in comma a map into int To an int to a Map of int comma int it wants something right And this is going to be a map of int int So I don't like why is it saying this? I'm not this is supposed this one here is supposed to be an int right And it's complaining So this is okay. This is going to be a memo. This is going to be the rest. Okay, and then Map.insert Oh, and I need to supply the memo Right What is it complaining about let me compile it because I can't really tell what the error message is It's the same thing again So fold l is going to simply take the current memo It's going to take the current sum It's going to take an Uh out And it's going to say It's just going to be a Where it's going to be m prime comma Uh out out val it's going to be Sol to prime of memo and out And this is going to be m prime comma curse some Plus out val and then then then at this point we have updated all the Out so Let m prime comma res in And then I want to say map.insert cur res Cur res m prime You think this memo station will work I think it I think it should work Let's look at uh, let's look at what we have so far Okay, we have to start it out with something proper Sol to uh Map empty and What so yeah, yeah, yeah So mapped up empty This will just be the second of sol to prime Of map dot empty and Okay, it's much faster for our test inputs Like before this was taking 912 milliseconds. Let's see boom That's memoization for you This is called dynamic programming right memoization is just dynamic programming Uh, it's a functional version of dynamic programming is memoization Let's see if we got it. All right, and it was correct Whoop whoop whoop Oof I was scared there for a second So you have a function that runs doesn't run fast enough It's memo is it Especially like here this was uh, it was always calculating The same outs right so So what we essentially did Is that you know when we were collect, you know when we were calculating this graph, right? It was it was checking this entire thing, right? up So now we kind of just memoized so every time was going to ask about this these three things It just looks it up instead of calculating it, right? so It goes way faster A way way way faster because you can just actually look up things instead of instead of Calculating them directly Uh, yeah, so we've memoized Stuff let's uh, let's see. There's another way What's the way to me tell us Graph math right to me is typing up Is extremely cool solution to this problem, but I like this right there's just like, you know We can't just Brute force it anyway anymore. We have to if we're going to be brute forcing at least memoize our brute force solution Did it in Do you know how it to me you're I think we can actually You can remove this case here now because the fold l will fold l will work Music, but it's like we changed it from a We changed it from a zero though. So it might not work, right? Yeah, it doesn't work It doesn't return the same values So this would return the correct one for uh, okay, we have to check for the empty list Timmy, do you just like have a Like a github repository we could check out With your with your way That now I want to see what the graph math checks out to be right Look at the prime factors of the answers to the two test input Look at the prime factors of the answers to the two test inputs Why does this work? I do no law Okay, let's wait. Let me I want to make this bigger for you all Look at the prime factors The answers to the test inputs Then look at the jolt deltas between the sorted out in the deltas the number of consecutive ones Map to a factor of the Of the correct answer Okay, so if we change saw one here Let's not multiply. Let's return this All right, so we had seven Seven ones and then we had five threes We fix the chat again. This is not the best Uh, exactly. Why does it work? One one one goes to one one goes to two one one one goes to four Look at the output of the zip with All the jolt deltas. I see ratio id So We want to sort those first Uh consecutive ones to a factor. Okay Because you have to go to one from one to three I guess it's because Maybe that's like because it feels like it shouldn't work I see so the thing is So for all of these ones, right? You have exactly one path, but then for all of these threes You have three possible paths. Is that maybe it? I feel like it's uh I feel like it's kind of based on The fact that you will only have A delta of one or a delta of three And you'll never have a delta of two Oh, yeah. Yeah. Yeah, that is true That is cool That is a much smarter solution to me Yeah, yeah, I mean that's the problem right because So, I mean, okay, it's a problem in the sense that I mean, it's never stated that there are One or it's only one or two or three jolts, right? It could be two jolts And that it's never stated, right? I mean we could always, you know, look at our input and then we know that So it's only going to be one and threes But I feel like I feel like that's uh I feel like Yeah So like, you know this way, I mean it's slower But it will always work no matter what the deltas are and uh And this will even like this works You know, so like if we change the graph here This is just going to be The number of different paths, right from From the beginning to the end You know of like a of like a triangle of like a dag, right? If it has one beginning and then all of them end at one point, this is always going to work, right? So a little bit more general But we actually have to do a lot more work But because we memoize it, it's fine Let me see This was a lazy map Let's stop trace showing it And in the lazy map we're essentially saying, you know input the res here And the res is going to be the result of this thing so Like it doesn't quite profile again Let's look at some See if we can profile it see what it Turns out to be like where that main What the main time is spent on doing It's we spend a lot of time doing f. I mean that makes sense, right? It's a sol2 It's gonna be so this is gonna be inherited time with me I need to zoom out a bit here So main takes all of our problem all of our time Like get input takes Okay, this is allocation so inherited. Yeah Uh Why is get input inheriting taking all of the time? Is it because Because it's kind of that's what triggers it home. I don't know Anyway, it seemed the Seems pretty quick seems like like Most of the time is just spent on reading the file And then after we memoize it, it just works great Okay, uh I'm going to cut it short now because I have to start packing for tomorrow Uh Thanks for the session. I think we We learned a lot about memoization And how good memoization can actually get you It can actually make things super fast. I'm just gonna gonna Thanks to me Maybe we'll do like a break of a functional programming meetup sometime over Christmas if If that's even legal Might not be right Input set Uh Yeah, I'm just gonna go ahead and Commit this Uh get this Skip add day nine no day 10 But it says we're gonna add we're gonna add a test big test small and or input Get oh It's not shell script. It's Haskell Get status get If what did I change in day nine? Oh, I removed it's a comment great am Day 10 Get push. All right. Yeah, like I said, I won't be coming back Tomorrow or Saturday, but I'll be back on sunday Five o'clock UTC That's six o'clock central european time That's gonna be about uh noon On Us new york time Right now you want to wake up have a nice Something to watch with your uh brunch on sunday morning. That's uh you can watch And thanks again for tuning in and uh Thanks again to me for You know giving us some perspective on the solutions, right? I like that. I like the multiplication solution It's cool, but it's like because Yeah, I'm not quite sure how it works Like I agree with your explanation But it's just I would have to like look at it stare at stare at it for a while to understand it Anyway, yeah, thanks again and see you all on sunday. Bye. Bye