 start recording until now so if you're watching on youtube nothing happened until this moment all right we catch the airport shuttle try to book a new flight to your vacation island due to storm all direct flights have been canceled but our route is we'll be able to get around to the storm you take it i'll get your flight you decided to check with the elves back in the northpaw because you're playing a memory game and you're ever so excited to play in their rooms okay in this game the players take turns saying numbers they begin by taking narn's reading from list of starting numbers okay then each turn consists of contenders considering the most recently spoken number if it was the first time the number has been spoken the current player says zero otherwise the number had been spoken before the current player knows how many turns apart the number is from when it was previously spoken okay seems uh seems legit so after each after the starting numbers each turn results in that player speaking are allowed either zero if the number less number is new or an age it's the last number is or an age okay so it's a zero three six now six was not so it's the first time the number has been spoken four times spoken zero next continue again the last number seems to be zero since it had been spoken before the next number to speak is the difference between the turn number when it was okay so it's gonna it's gonna be a loop right okay and so it's three three have been broken so we say on turns five and two so oh minus two how many turns apart from one from the number is from when it was briefly spoken okay okay the one and then zero nine's number broken four for us new notes okay okay there's no end okay what will be the 2020 this number is spoken in the example of a tiny ten symbol of a spoken will be four three six I think it would be cool if we could like figure out I guess sequence like will it repeat and see if we're repeating ourselves because that's what I think will happen in this game is that it will like we will come into a loop essentially and it will be again again again let's see let's see let's put on something else by monster cat this is I mean this is good but we might want maybe a bit too much okay playlist I've never heard these songs before so they might not be good but I think they're good I think they might be good okay so let's just simulate this first right very topical stuff no need to write a parser today so by writing the file path I list of numbers get input I've mapped all right this won't be a so okay we won't even get a lines thing so we'll just say how do we say this set by one repeat so okay what we're gonna do is that we're gonna you know we're gonna read the file um and we're gonna so and on top of the read file we're gonna take the x we're gonna say we're gonna add a like a like a list on front of it and then a list character on the end of it and then we're going to say uh x and then we are going to read at list of it equals let's just let's just see what the input gives us now we see you today 15 and we compile day 15 jutsi day fifth oops jutsi we're gonna say o3 right away so we don't have to change it later day 15 got hs and no we don't do and here measure command day 15.exe we have to oh I forgot to split I can't see measure command and okay let's see here jutsi o3 day 15.exe so I'm wondering uh like those of you watching like what programming languages are you usually using because I you know I feel I mean Haskell is a bit esoteric right but uh is everyone just using JavaScript to see or something like this they're like I mean I see a lot of streams and like rust like there's no not so many people streaming Haskell so I'm just wondering like is it is not a thing okay we got the list now I think I think you know if we just simulate this it won't be too bad yeah chrono Kirby is a Haskell the only proper language am I right let's see let's just do an int map module import data dot int map int map import data dot int map as I am qualified yeah but that's not out yet right it's gonna do like gtc 2020 right so the initial numbers are spoken so let's initialize our uh our map so we are going to do uh in it in initial shell map it's gonna take a list of ints I'm gonna return us an int map of ints initial map it's gonna be a I am dot from uh from ask list no just from list of uh sip and we're gonna sip the input with zero one okay and then print out initial map see what happens yeah I mean I use Haskell 2020 I mean I'm always adding new extensions right uh because I mean that's that's what's nice right so so the first number spoken starting with zero three and six now consider the last number six and that was the first number I was looking for number will be zero okay so next num is going to take in a num and an int map of ints and return us a num now let's say here update update is going to take a pair of like current number and the current int map and it's going to return current number int map int so what I think that this will be like fix we can just like fix it and and it will it will it will become a sequence let's see uh update cur num uh so far so we're gonna say uh case so let's see yeah case cur num uh I am not this year so far we look it up in so far of just I so then was last spoken in turn so okay if it's nothing then we want the result is a current number will be zero that's what they will say and we will update uh so we need the current turn number also okay so let's say here spoken so nothing will be so next so so so turn prime is going to be turn plus one and we're not we don't we're not gonna but we're gonna be updating that in both paths here so this is going to be the turn nothing turn prime and then if we if we uh if the spoken number was not a member of so far then we are going to say I am not in search uh occur the this the number uh we're gonna add the current number and then what is the element that's going to be turn and uh and then it's going to be the so far right no actually this is so this is going to be at all times so far prime is going to be we're always going to update the number because it's always last spoken this time so far prime so if it's just turn then we do no uh just a last spoken then we return a turn minus last spoken comma turn prime so far prime right and then this is probably flipped no uh so far so in so far we're gonna be looking at spoken okay let's see let's just see so now we're just simulating it uh so um we just simulate it until 2020 I guess so solution it's going to take in the uh the list of integers and it's gonna return the int solution uh so it's gonna take in the input input and it's gonna take okay so uh run run to the run okay if it's so it's the s spoken comma 2020 we match on the fact that we're going to the 2020 turn and we don't care about this equals spoken okay run of this equals so we're gonna say run and then so run okay so how what's the initial the initial map so we're gonna be we're gonna take everything so let's take the uh so in spoken this is initial spoken again uh rest this is the reverse of the input so and initial so far it's gonna be initial map of reverse rest and these are gonna be easy operations you know so run we're gonna run it with the initial spoken I spoken we're gonna start off at third turn this is turn one so we're gonna start off at turn one and so this one actually has to start at turn one now we're not gonna start at turn one we're gonna start at length rest and then we're gonna have the initial map of the rest so if this is gonna be ranked of initial rest nothing so this is gonna be ranked of the initial rest plus one okay so uh no this is gonna be high so far high so far okay so this is the this is the kind of the the entire program and then run so otherwise it's going to be any other input we will say we call run on update a other it's just gonna be crazy bad took three hundred six thirty six three milliseconds but uh oh this is supposed to be four thirty six this is are we off by one this is supposed to be 20 so okay let's look at uh let's look at the trace here up until turn 10 we're gonna run until turn 10 and we're just gonna say here trace show id import debug dot trace this music is a bit intense right i'm gonna switch back to harris heller he is it's more lo-fi you know it's more relaxing this way that's how programming streams should be we're not doing hardcore stuff we're just relaxing so zero uh let's say turn turn four zero okay turn five three turn six three turn seven is one and then zero and then four and then zero okay let's i think we're off by one somehow seems to work uh oh is this off by one this way that's all the turns do do do do do do do do do do do do do do we're not gonna review this so let's remove the trace so yeah thirty three six earlier no it was three three six right oh four three six oh i thought i just i looked at it and i saw three three six and i was like what okay it was a okay uh now let's see i'm just wondering if it like if it repeats if there's a repeating pattern no i mean the turn will always be going higher and higher right no but that would that'll be okay uh let's just let's just let's run it for the input let's see let's see if this is this crazy bad let's let's not even get the okay yeah let's not even get the input let's just say do just paste it in right and then we don't do this but rather we say print solution of input thanks grog Kirby we could have been stuck there for a while never trying it again four six eight that runs in bracket time right 24 milliseconds i mean that's not too bad all right you know okay identifying patterns all that jazz we could have done it but like you know this was so fast that there's no need i think i think what we've been engaging in this stream a little bit is what Knuth calls a premature optimization you know we've been optimizing way too hard in the beginning and that's just and we've been just you know wasting all i'm wasting i mean we've had fun but we've been spending so much time oh thanks Remo for the follow by the way i missed it i was so focused totally missed that follow anyway so now yeah now this is gonna take a while let's just see how it takes damn solution two because we know we're using we're using int maps and stuff so it's not going to be that bad for this is definitely i think you know what you're supposed to do here is that you're gonna say okay there's a pattern and you can jump you can like jump a bunch of terms right let's uh give it like two three minutes okay took 59 seconds let's see i'm gonna run it again because it usually takes less time than second time but 59 seconds i mean yeah yeah i mean that's so that's why it always says like 500 milliseconds and then i run it again and oh yeah i know i am compiling but i say i measure command on this expression which is not compiled right two minutes did you use a regular map to me less than one second yeah i'm going to say that you identified a pattern is that correct chrono Kirby but you don't know you brute-forced it oh no oh no did you do and say vio okay one minute okay it wasn't faster let's just check if it's i mean it's correct oh my god data vector mutable unboxed yeah that will go fast let's let's do it let's do crazy crazy fast stuff but we're not gonna do vector we are going to do you array my favorite import data dot a r dot array array dot sd yeah let's just let's just do it i mean we've been here for half an hour and we're already done i mean usually we spend so much time optimizing everything space leak better to have a space leak than a gas leak uh because gas expands into space i don't know sometimes i just try out jokes and they're not that good but i have a very dedicated fan base willing to listen to all my jokes that's a trick you know find the people will laugh at your jokes all right let's let's go let's sell our souls i'm in the mood for some soul-selling uh data array dot so we're gonna have unboxed elements that can be manipulated in the st monad solution to optimized i mean dronecker you didn't quite properly if you did not use unsafe perform i o d dupu wait unsafe unutter probable d dup perform i o no this is in bait white string i'll take it here where was it again selling our souls in a referentially transparent way yeah i mean technically we could use linear haskell yeah i mean it's in the source but i i just i don't remember which modulate is in is it an internal probably internal right and safe oh there we go unsafe dupu perform i o this this is the good stuff a cursed unutterable perform i o this is the best function in haskell look at this it is in fact a malevolent agent of chaos it unpicks the seams of reality and the i o monad so that normal rules no longer apply it lulls you into thinking it is reasonable but when you're not looking it stabs you in the back and aliases all of your mutable buffers the carcass of many a seasoned haskell programmer lies through strewn at his feet a bunch of ghc tickets do not talk about safe you don't know what is safe oh my god this is like please do not use this function and then they go ahead and use it all the time in buy stream but what does it do well it just does i o it takes an i away turns on a but how does it do it well it matches on the real world you know let's start there it matches on the real world it takes the monad i o monad matches on the real world token and that is this is the token like you have to look at this value here and evaluate it to kind of make sure that all the operations that happened before happen but what do they do they throw it away it is not used in the result boom this is this is i o this is how this is how they do i o in other languages they just don't care they just run things it's good stuff okay take a list of ins to it now input is going to be we're gonna do the same trick here we're gonna take a we're gonna take the yeah i spoke in rest sd code again unspoken we're still gonna match on this oh my god why i v copy the word it's good stuff copy the word we don't care this is gonna be spoken data dot array dot mutable this is immutable i'm we're looking for we're looking for mra yeah we're gonna be done doing run sd okay that's what we're gonna be doing because we don't need this run sd u r a because we actually we don't want an array we just want the result uh run sd do run sd run and this is gonna be the uh so we're gonna have an initial how are we gonna be passing things here or we're not gonna we're not gonna pass things around even uh if i couldn't yes exactly dollar is good it so builds a new array with every element initialized to the supplied value constructs a mutable array from list dimension elements the list gives the elements of the array understanding order beginning with the lowest index okay so we're gonna be doing a new array and we look at the numbers and they are never ever going to be larger than 30 million three million right why has school because it allows you to write code in a safe way you have all the type information to guide you so here we specify that this should be a list of instuint and it kind of prevents us from doing mistakes it's also super fast you can parallelize it not in this problem but a lot of problems can be parallelized very easily and it goes boom super fast and all the type stuff and the referentially transparent stuff just makes it go fast makes it go you can just parallelize without worrying uh maybe we should try to do that sometime you know right like concurrent classical code let's do that later on the channel okay uh so uh this is going to be just returned spoken now run uh i come up last so so spoken and in some other term so then we're going to do this update stuff it's gonna be do we are going to check so we're gonna we're gonna we're gonna get the read array write array uh let's see does that answer your question so that vulnerabilities like buffer overflow would be null with haskell uh i'm not gonna claim that it's going to be it's a lot harder to write vulnerabilities in haskell but it's still possible especially if you're writing stuff that's goes super fast like byte string and this on cursive unutterable perform io that can go wrong okay but cool thing about haskell is that you can kind of say i don't want to use that um but also you can like add security information to your types you know because sometimes it's not even it's like the information leak is not because because of uh like you we were overflowing a buffer or something it's just like you you accidentally made the password available like in the hgdp request or whatever and then you can use something called uh dcc and uh make it like you can like type check you can like say in the types this here password is has is private like this value here is private and and like functions like print would just like and then you can write functions that say you know print only safe and they would only work for values which which is is allowed to print so there's a lot of like the type system allows you to write not only like functional guarantees you know in the sense that this is what it should take in is what it should result in but also you can write like proofs and programs and and kind of so the thing is that types are kind of theorems types are saying this is what this function so like this is this is a function that takes in an integer like integer and returns in another integer um so you can state in the type exactly what the behavior should be so that's a theorem and then the function itself is a proof of that theorem um which means that you can you can do a lot of cool stuff a lot of cool stuff so let's write here in each run that's going to be do okay this is going to take in the ref do can i can i like do i i have a reference to a beautiful array right um array new array read array write array new array wait let me see new list array list array and then this is going to go from zero to maximum value and we're going to do the reverse of rest uh this is going to be the array i think we can do this yeah yeah so that's what the thing is but the thing is that you can't you can't accidentally oh cool yeah but the thing is you can't like accidentally you can't print the password you can tell it however you wanted to print but you can't like use a regular print function so you can't accidentally you can't accidentally print it which is cool for data dot array dot m array uh i want to say here new list array uh and then i want to say in it run ref they're going to be new st ref to that array import data dot sd ref and then i'm gonna write that array to the sd ref uh write sd ref do i can i can just pass the array in right okay and then i'm gonna say uh wait can i just do like this new list array uh zero comma oh my god let's run it for four five fourteen first do i like have caps lock on or something no why does it keep going like that uh why does it keep like scrolling up it's very uh there's something wrong somewhere run new sd array zero fourteen and then here this would be new oh my god need to run and then this is gonna be i spoken and it's going to be the initial turn it's gonna be length of rest plus one but there's some bugs somewhere there's some some syntax error is it here it anywhere in this function yeah it is somewhere in this function so solution optimized run new sd oh my god okay i found it undefined that's great yeah i'm trying to teach people trying to make them realize how cool Haskell is now this one here oh no i have to import control dot monad dot sd beta array new list array um control moand now this here it doesn't work because it can't figure out what kind of array to use uh so and we have to provide that somehow by providing so let's see so run is going to take in a tuple of why why are we we're doing this is a tuple we can just do it like this like this right run takes an end and another end and returns an sd can i just do i can just do sd u array s int yeah yeah they are sus exactly correct sd s and this is gonna be wrong well it's going to take in an sd u array s int i'm going to return an uh what sd u array s int has kind okay we need one more argument here so the index is int and the elements are also going to be int now this works and i don't need the parenthesis here oh so if we're at the end we just return we return um now okay so if it's if we we're at the end okay if it's not in right when they say do uh so first of all we say val is going to be read array what is the what is read array that is read i'm just okay so we taking the array first r read array and we're going to read the current spoken which is going to give us the element and then we are going to say wait what did we see uh no so i think i think because we need to know if it's actually so okay what do we see okay so it will never be zero so new list new array new array will we will initialize everything to zero we initialize it to zero uh let me see i think that's i think what i think new list array does that let's just see will it complain i mean so that creates the new array and then it just takes from the list so that's okay so we'll initialize everything to zero in this array because we're using st so we could use new array and then we would just have to write the elements in the first elements in ourselves that wouldn't be too bad i'm gonna see here if val is zero then then it hasn't been spoken before and then and then we're going to return then we're gonna rerun and then the spoken was this turn plus one and uh right array right array then we have to write to the array and then do uh right array r spoken turn turn plus one r right same as we did here spoken and then if it if it's not zero else do okay so first of all we're gonna read the value currently there and then we just always write to it else we're going to run the what it's it's it's turn minus val turn plus one r arrays don't expand do they because right now you just have a tiny array with 14 indices i think they like they're lazily initialized like i don't think it will literally allocate an array with all the indexes uh let's see let's see what solution to optimize it does because like it just it just creates an array so what it does is that it creates an array with this range and then it fills from the list and then it just kind of says return you know so i think i think this will be fine if you access outside the bounds isn't that a crash no i don't think so then so what it says is that so it uses new array underscore where new array underscore uses r l bottom and r l bottom oh that's going to be undefined array element let's see index minus 12 out of range okay yeah so we will have to so init r is going to take in a list of hints okay so top val is going to be oh shoot yeah i should have uh max val is going to be it's going to be okay it ran too far no it still happens where is it getting the minus 12 from oh turn minus val that correct yeah turn minus last spoken so then it takes an index and element right okay let's let's do it the other way this is going to be a new array a 0 0 comma 14 and the this is going to be the initial element so we're going to put r and then we are going to write map m prime x comma x comma y and y comma x it's going to be right array r i e and we're going to do this on zip the indices will start with one this is going to be the input and what's wrong here return r and it's complaining here why not uncurry okay yeah init r now it says one four fourteen oh we only went up to turn 10 uh let's see here why does it start at turn seven oh i'm running it on the input still let's just get your input test input test input was zero three six right yeah zero three six let's try this for the must be nice to have a soul huh tell me so as you get three is six so we get zero we get zero on turn five we get zero again that's not good oh we are still doing it for this shouldn't be the issue right so we get six and so the three so so turn three we get super get six yeah turn four we should get zero oh it's it's the opposite i think so if the val is zero then we haven't seen it before it's the opposite so if if it's zero uh then we haven't seen it before so then we should say zero turn right let's see so four should be a reader oh okay oh i this should this is this is for the wrong way around this should be one like this we get six zero three three one six zero three three one zero four zero zero four zero cool let's see we can even move we can even move this here so we can say run if val equals zero then zero else turn minus val turn plus one and then r do do do do it do me get 60 seconds it's not bad now let's so for 2020 for a test input it says 436 let's still work for the test input now solution optimized on the input and what was the result we got late earlier we got 1801753 for 2020 right no 468 yeah that was the same as result we got for initial one we can have it like this this is a bit small right right now let's see if this all paid off here it's running in two seconds running in 1.5 seconds that's uh same as chrono kerby right i mean not like like not not too far from chrono kerby right how big is this number here it's uh it's 30 million oh wait it's not too not big enough in 16 32 000 so we need in 32 right yeah let's see see if we can like do this with like unboxed integers i think there still might be some laziness so the st u arrays are strict well that's just data word right uh we need word 32 no i mean we're not gonna we're not gonna get anything better from word 32 because we need we need anyway to a lot more right this is the thing i mean we could have tried to analyze patterns and whatever but because i think like i think like if we see if we see something spoken and like if the array doesn't change there will be a loop in the thing and we can then jump a lot of spaces ahead but okay uh 1.5 seconds yeah i think that's fine and we didn't do the whole program program analysis thing that we sometimes do why would we want safer arrays okay we don't need the safety chrono kerby where do you where do you think the laziness is coming from let's profile it yeah exactly right yeah because like it has to check doesn't match 30 million it's spending 77 of the time allocating the array and this number is 100 it's 1.8 million and the thing is we need of uh yeah spoken is forced to rig the 1.8 million so you know like the the range of indices here needs to go up to at least two million so you know we could cheat bikes like if we know the answer and we can just say two million here um and you know oops i don't even use st ref so we can cheat um and say because like we know and then it won't have to allocate such a big array oh but then we get out of index out of range oh why is that index out of range so this is two million oh okay yeah because the final final one isn't actually the final one isn't actually like the highest number yeah we could yeah yeah yeah exactly so the thing is a right array this is right array i mean isn't this selling our soul too much here we're just like yeah this is too much right and i think this is what st array uses internally anyway okay i think this is uh i think this is good for for today uh but what i'm going to do now since we've finished so fast is i'm going to take like two minute break one minute and then we're going to do day 12 how does that sound okay it takes 1.5 to do both yeah i mean that's what i i think that's what i really like about haskell here you know okay yeah this first one just takes like 24 seconds so that's what i really like about haskell is that you know here we quote unquote sold our soul and used like unsafe arrays but it was quite okay like the type system just makes sure it all works this isn't even an unsafe array unsafe mutable array haskell data dot array dot unsafe this is where it's at oh shit oh shit okay so this is just freeze and unfreeze so we're not actually freezing anything so this is this is fine and we i mean so a faster way to do this like the simulation way is to do you know would be to do like a dynamically expanding array but like this is just i mean that's essentially what the int map was doing but that wasn't as fast for some reason anyway i think this is good i'm gonna take a quick break now and then let's move on down with the git add day 15.hs that's actually add the profiling information i think that's interesting people want to see oh okay let's not edit git commit day 15 all right uh two minute break let's continue with day 12