each_cons, inject, and File.readlines - Advent of Code 2021 - Day 1 with ruby

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's up welcome back a couple days ago i posted a poll uh for the community just checking to see if anyone would be interested in seeing some ruby solutions we did have at least one person who said no but there was a lot of other interest so i thought we could just go through and solve some advent of code problems with ruby so day one sonar sweep the goal here is you kind of take the input as a list of numbers so for part one of the advent of code is you take in a list of numbers and then you want to figure out how many times it increased from one number to another number so you're kind of just counting the number of times the depth measurement increases if you're not familiar with the advent of code this is a project where through december like the first 25 days there are a bunch of little coding puzzles that you can solve and once you have solved it you can enter in your answer so when you first sign up you can log in with github or google reddit twitter whatever and then you just click on the top bar here and that will get you into the day and the day will tell you um sort of the problem so there's going to be like a long problem statement then some example input and then like an answer to that example input so in this case it gives us this list of numbers and it tells us in this example there's seven different measurements and then you fill in your answer and in this case my answer was one seven one one everyone has different example input so you'll you'll come down and you can actually like get your puzzle input here and your puzzle input is going to be a giant random string of numbers and it's different for everyone so no one has the same input at least that's how i understand it and you kind of yeah you go through the process and you try to figure out what the answer is so i've gone through and i've solved some of these already but i wanted to just go through the process of my thought process of how i would go about solving these so let's jump into here and we'll just say like this is uh day one so we're going to take some of this input and what we want to do is find the number of times it's increasing and let's see so we'll do advent of code 21. and what i did is i made a directory call for each day so i have like day one and then i also had um uh let's see bundle init so i want to initialize a new gem file at the base bundle add bundle add r-spec and then i want to say like r-spec and knit because i want to use r-spec to write some tests for these little problems because when you have some tests that can really help you quickly iterate so r spec dash dash init should initialize a dot r spec file where you can control formatting and color and also a spec directory and so what i want to do is go into the spec directory and add day one spec.rb and at the top we're going to require dot dot slash day 1 and then like number increases dot rb or something like that um and then our spec dot describe um maybe like yeah for this one i'm just going to use a method um and the method is just going to count the increases because this is a really really simple problem and i think it's simple on purpose because it lets you sort of get started so here we want to say like it counts one increase or something like that i can't spell increase all right so then we want to say something like we're kind of like writing what we want the code to actually look like when we ultimately implement it that doesn't make any sense we're writing the like the way we want to use the code that we ultimately implement so here we might say something like um actual is number or maybe like num number of increases for and then like in the actual input here they're giving us this list of numbers it's going to look like this right it's like this giant list of numbers but ultimately i want that to be in an array format because it is a sort of list of things it's not a mapping it's not a single value it is an array and so i'm going to store this as an array and we'll talk about like reading the file and parsing the file a little bit um and but like for for this initial test what i want to do is just say like one two and so the number of increases be with one and two should be one so i expect um num to equal one okay and when i run the test it fails there's not actually a file over there so we want to make the smallest change possible to make the test output change number increases.rb so all i did was create the file now the test output should change maybe i spelled it wrong it did not work day one number increases all right whatever we've got our we've got our at least we've got our tests running um albeit uh like a kind of a annoying way okay so number of increases needs to take an argument we'll call this like the input and what we want to do is we want to iterate over each of the sort of the pairs in the input but for now what we can do is we can actually just return one because that will get our test passing and so what we need to do is have at least two tests so that we can't just hard code the answer so counts two increases uh and maybe we'll do like one two three and so this should give us two increases between one and two that's one increase between two and three that's two increases and now we actually have to like uh write some write some code right because we need to iterate over the input and count up the increases and so there's a numerable there is an enumerable method ruby innumerable each cons so each cons is this method that takes each consecutive element of um of an object so in this case we can say like give me each consecutive element uh where there's two in in in the pair and that will give us back each pair so what we want to do is say something like input.each cons two so that's going to give us each pair each do or maybe dot inject or something and we can start with zero and so actually before we even do that let's uh require uh buy bug just so that we can see what this is doing so if we run this now we can see the input is one two and if we do input.each cons two that's gonna give us back an numerator where it's going to iterate over each pair so if we did like each we could say pair puts or p pair and that's going to print out 1 2. that's not very interesting but if we do it with the next input then we get the pairs of one two and two three so the the array one two and then the array two three are the arguments that are yielded to the block that we can then compare like is um one bigger than two or 2 bigger than 3 etcetera etcetera and so what we can do is instead of just accepting the pair as an argument to the block we can deconstruct this into like x and y like that and now we can say p x so that gives us one and two and if we p y that gives us two and three so now we can say print like x is less than y and that should give us true right so that's giving us true back now what we want to do that kind of like gives us how many times it's true and so instead of just passing each what we can do is use inject and inject as a way to sort of like collect up a bunch of things in fact collect is like another name for it um i think maybe it's map i don't know uh let's see so inject ruby so the inject method here is uh available on the enumerable it takes in um okay so i guess the alternative is named reduce so it takes in an initial value and then this becomes your accumulator so your accumulator is um or like this this is the initial value for your accumulator then your block takes in your accumulator and then each element that it's passed so in this case what we want to do is pass in an initial count for how many times it's increasing so for our case we want to start at zero because there's zero increases then our accumulator will be the count and the element that is yielded to the block because we're using each cons will be the pair of x and y so let's let's take a look at how we might solve this so now we can come down here and say something like each cons.inject now we want the initial value to be zero and then do and then the count is going to be our accumulator that's the number that's increasing and then we want to have like x and y as like the two values in our pair and the way that we're going to use x and y is we're going to increment count so we want to return count plus 1 if x is less than y because if x is less than y in the pair that means that we're increasing and so now what we can do is remove by bug and run our tests again and we have two passing tests let's make sure that it works correctly when we're when we're going when we have a decrease so it should count two increases um with a decrease so let's let's say that we start with four and then we go down to one so that should just be zero and then we go to three and then we go back down to one so this is just there's nothing here there's one increase two increases and then it's a decrease so it's just two increases so this is two increases so now that should also pass and it does not plus for nil class okay here we go we've got an uh a plus four nil class okay so what's happening is we're saying increment the count and return that if x is less than y but if it's not less than y then we should still return count so another way we can write this is we could simplify and say if f or yeah if x is less than y then do this else count and right that's a little bit nasty um so another option is we we can say count plus equals one and then return count at the end of the block for each time it's a little bit simpler um yeah i don't know i kind of like this this format this is not actually the way that i solved it in the original but we should get the number that we see in the example so the next thing that i would do is copy all of these and make a test it works for example input and now we want to say num is number of increases for our example input and here we've got a fix this okay so now we want to say we expect num to equal whatever they they told us the example value was so in this case seven um we expect that that output is going to be equal to seven so now we can run our tests again and we have four passing tests at this point i'm pretty confident that it's going to work with the basic example input so now we can do um something here inside of our file so rather than kind of just running this giant file or like we need we need some way to get all of this input basically into our into our code so the way that i do this typically is i'll add like a new file here called input and then i will copy all of the input and paste it in there and now at the bottom of my ruby file i'm going to do this this interesting thing where i say if underscore underscore file is equal to dollar zero and what this does is it says if ruby is running this file like if we're running this file directly then run the code that's inside of this block and when we mean run this file directly we mean like dot slash num increases or ruby day one num increases et cetera et cetera so like um basically if we're not just importing this file and using it as like as we are as part of the test then what we want to do is we want to read the input from a file so we're going to say file.readlines and dot argv.first so argv is basically this constant that is a container for any command line arguments that we pass when we're executing our ruby code and so we're going to pass the name of the file as input into our execution of this thing so let me show you what i mean so down here in the in the bottom left i'm going to say ruby day 1 num increases.rb day one input so this is this is like uh we're executing ruby and we're we're calling this ruby file so we're running the num increases ruby file now this is gonna be arg v dot first so this is our first argument and this is just the name of the input file and so that's what we're passing in as the first argument is the name of the input file and when we call file.readlines that will read each of the lines and return an array that represents all of those lines and so by default it's just going to have each line as a string so if we do p input here and we just run this input then you see each we do get an array back but each element in the array is a string with the number in a new line so we need to do a couple things we can like we want an integer value and we also want it without the new line and we want it to not be a string and if we just call 2i on this string value we'll actually get back what we want and so what we can do here is just say map and 2i and this is just a shortcut for the same thing that we could do is like m m dot 2 i that's kind of the same thing we're mapping over all of the elements and we're calling to i meaning we want the integer values so if we run this again now we see that we're getting back the integer values for all of the input next we want to print out the value for num or number of increases for that input now if we run this we get back 1711 which was the correct answer for this puzzle all right so that's part one of day one of the advent of code hopefully that also helps you sort of get set up if you're thinking about doing this like helps you sort of get logged in when you're going through the first exercise you'll see input boxes you can kind of like enter in your answer as you go so that was part one sometimes there's a there's always part one and part two sometimes part one is easier and sort of like helps you get set up for part two sometimes part one sort of tricks you in like part two you have to like do a significant refactoring to get it to work so in this case it says considering every single measurement isn't as useful as you wanted now let's use a three measurement sliding window and what you want to do is you want to find the sum of that sliding window and then compare that versus the second sum of the sliding window it's kind of like a daily moving average or something like that uh sort of maybe not because you're not taking the average but maybe it's similar right so you want to instead of just comparing like 199 and 200 we want to compare 199 plus 200 plus 208 with 200 plus 208 plus 210 and so we're going to compare a to b and it turns out that we've like we've actually already got like a pretty good set up for this so what we can do is we can modify our code just a little bit so instead of comparing each consecutive two we want to compare each consecutive three and now what's uh that will give us each of the elements abc and actually i think what we want to do is yeah we're going to use the same tool each cons to give us the windows and then we're going to call a number of increases on the windows okay so let's get like def um windows of input and like we'll we'll say like how big we want the windows and we'll just return input.each cons three dot map um so that's gonna that's gonna yield pair like these trip these triples these triple tuples and we want to add the three together is there a sum method let's see uh pry a is one two three a dot sum is that a thing wow okay so what i was trying to think through is like dude can we just map this and sum is that going to give us what we think so let's see uh input or windows give us the windows of input so what's this wrong number oh wrong number of arguments because we want three and then this should actually just be like n so that we actually use what the input is um okay i think that actually may have worked so then what we want to do is we want to take each of those windows and call number of increases so here we're going to say something like number of increases for those windows so the first step is like breaking it apart and the second step is putting it back together and our answer is 1743 was that the answer we got yep that's the answer for the puzzle so that is part two for advent of code day one uh hopefully that was useful the thing that i like to play i mean like the the cool or like the the takeaways for this exercise is really like playing around with each cons um and then yeah like this is sort of a more functional approach i think some of the other solutions will use classes but yeah there's a there's some good stuff in here so hopefully that was useful and uh yeah we'll see in the next one [Music]
Info
Channel: CJ Avilla
Views: 185
Rating: undefined out of 5
Keywords: cjav_dev, web development tutorials, web development for beginners, vim, ruby, inject, advent of code 2021, advent of code, each_cons, File.readlines
Id: u1MwWSN_tQI
Channel Id: undefined
Length: 19min 39sec (1179 seconds)
Published: Thu Dec 09 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.