DSL instance_eval, eval - Advent of Code - Day 2 with ruby

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's up welcome back this is another episode of advent of code with ruby we're gonna be solving day two today it's a really fun one we're gonna build a submarine that sort of dives a certain depth and then comes back up uh yeah and i had i had a ton of fun with this one so let's jump into it so i'm going to come in here to my advent of code i'm going to add day 2 as a directory i'm going to add day 2 spec that our b as a spec require relative uh dot dot slash day two submarine dot rb and uh let's see our spec dot describe submarine do end all right so the the submarine here is or like the way that this works is you get a bunch of instructions so it's going to have forward and then a number and then down and then a number so you're going to kind of get like just a bunch of text that's passed in as instructions and then you want to sort of move your submarine along uh and then ultimately at the end of part one here you will find or you'll figure out like what is the um your depth times your horizontal position to figure out what the answer is so in this case we're going to try to like take in this as our input and then move our submarine along and then spit out some number that is going to be the depth times the like forward motion so here um like i think what we want to do is we need to make methods for forward down and up which are going to change like the depth and horizontal position so what we could do is say describe down or something and then it's supposed to like um it increases depth so so down like when you're when you're at the top of the surface of the water your depth is zero and then as you go down your depth increases right as you get further and further from the surface and so uh in this case i think we want like submarine marine dot new submarine dot down expect submarine dot or i guess we want to have like d is submarine and then we want to expect that the new depth is to be like be less than d or something i don't know let's see if this works ah crashed and burned that's because i don't i think we we don't have oh wait we don't have the do ends lined up do and describe it do oh this is not that should be an end all right let's see uh okay um no such file okay i think there is actually no such file now okay submarine.rb okay um and then we can run the test again all right uninitialized constant submarine all right so let's add class submarine and then run it again no method depth for submarine so we'll say like def initialize with i don't know what we're going to take in right now but we'll just say at depth is equal to zero and at horizontal or well we'll just keep it keep it easy for now depth okay run the test undefined method down for submarine um def down and this is going to say at depth plus equals one every well actually it's going to take in some number so down n right because it's in the problem statement they're going to give us some numbers so like down eight so we want to go down we're going to increase the depth by that number so here we want to say down two or something like i guess uh we want to expect that the submarine depth is a specific number at the beginning so we'll say that we expect it to equal zero when we first start out and then we want it to equal two after we move all right so that's working and let's see what else do we want to do here all right so now we need to also describe uh like up i guess um up it decreases depth um so then we're gonna expect that the depth is zero um let's go down let's go up two and then we'll just expect that it's negative two it shouldn't be above the surface but whatever let's just like let it happen um and then uh we'll say this okay so uh up is going to decrease the depth by that number and we've got all of our tests passing now okay so now we want to work on forward so forward is going to change something else so describe forward so forward increases position right so forward is going to increase our horizontal position so forward x increases the horizontal position by x units so let's say that our position starts at 0 and then if we go forward 2 then our position should equal 2. it's very similar to down but instead of depth we want to change position so i'm going to add a new instance variable here position and then we'll make this method forward n is going to be at position plus equals n oh gosh we didn't see our test fail we didn't watch it fail um okay we're still getting zero uh is that because oh no this should be zero all right cool got it so now we are we're moving in a forward motion now we've got depth we've got position and if we were to say like it uh works for the example use case then we could do something like this we could say like create a new submarine and then we kind of want to like just take all these instructions and paste them in here and instead of just doing that we want to say submarine dot and then we want to expect submarine dot um location or something i don't know like we ultimately want to figure out some the location yeah like what is what do you get if you multiply your position by the final depth i don't know like we'll just call it location location doesn't really make sense but whatever 2 equal and then in this case it produces 150. so we're going to say that equals 150 run the test watch it fail there's no method location so let's make a new method def location and this is going to be at depth or yeah depth times position watch it pass okay so now everything is passing that looks cool and this is great if we wanted to go through and like write out the code for each of these uh like we could just copy and paste in and then do like a giant text transformation for all of these method calls right we're kind of banking on the fact that ruby doesn't actually need parentheses after these so like we're technically calling the forward method here but we didn't actually have to go through and like wrap that all in paren so it's kind of like a little bit like cheating i guess maybe but there are some really cool tools that we can use um inside of ruby and these are typically used for defining uh domain specific languages or dsls and so what we can do and you've seen this everywhere in fact we're using it right now so we have our spec cut describe do and then inside of that there's like this it method and another describe method and other stuff that you can just do like directly in line right here right and so like let's let's make another method it works with dsl or something like that and we'll we'll copy the same the same expectations but instead of calling this with submarine dot what we want to do is take in essentially what like the same sort of format that we're going to get as input and what i want to do is make it so that we can call this by passing a block into the initialize method of submarine and then just kind of like calling all these methods inside there and then having it spit out the right answer so wouldn't that be so cool if we could just make our own forward method and down and forward and up and whatever that you could call inside of a block well we can and the way this works is inside of our initialize method what we can say is like if block given meaning like if a block was actually passed in then what we want to do is um instance eval for the block so we're going to call instance eval and pass in the block and um let's see so then we should be able to run the same code and it just magically works like isn't that insane so like this instance eval business right here is saying um taken or like given that block of code evaluate the methods in the context of this instance of the submarine so instance eval super handy when you're writing a dsl also we're going to try to use that for our sort of solution here all right so we've got a submarine it's totally working it works with this sort of like instance eval thing let's add our little file helper at the bottom we talked about this a little bit last time so if we're running the code from this file what i want to do is add an input here which is our actual like puzzle input so i'm going to copy and paste the puzzle input into this giant file so there's a thousand commands here a thousand different instructions and what we want to do is um we want to re read in those instructions and file.read input or i guess like we want to do argv dot first and um that should give us our instructions and then what we want to do is call submarine sub marine.new do and we want to like put the instructions like inside of there right so here we want to say like instructions or something and then we want to pee out or like we want to like just put submarine dot location and that should give us the answer so if we run this right now though so we wanted to say ruby day 2 submarine day two input um we just get zero back and that's because when we do this this is just a variable we're just like referring to this variable above right that's not actually like plopping all of those instructions in line as part of that dsl so we're going to use another ruby method called eval which is sometimes called evil because a lot of people don't like to use this especially not in production it's super dangerous but we get a cool answer back one four eight zero five one eight one four eight zero five one eight so that is the solution for uh yeah for this this first half and that is the right answer and like whatever i think it's super fun instance eval eval uh creating your own dsl moving your thing around um kind of fun all right part two so based on your calculations the planned course doesn't actually work like that so instead of instead of using having up and down change our depth what this is going to do is now it's going to change our our aim so there's like another variable called aim instead of depth uh or like in addition to depth and then what what happens is like when you say up or down that just changes your aim and then that's kind of like the angle maybe that you're going sort of and then forward goes like in that direction x times so um all right so what i did in my actual solution is i copied all of the submarine class and then created a new class called aiming submarine but we're just going to keep hacking around on here and i'm just going to call this a i'm going to add a new actually before we do that yeah i'm going to do the same thing i'm going to do exactly the same thing so we're going to create a new class called aiming submarine aiming submarine and it's going to have a an aim actually before we go there let's add uh some some specs so our spec describe aiming submarine um it okay so now we have to do like similar stuff right describe down do and like it um what does it do down like increases aim i think right down increases your aim yep so if we have a submarine i think it's basically going to be this instead of depth though we're going to get aim and now if we run it it fails because there is no aim method so we want to add that we're going to say at aim is equal to aim and then down is going to change aim up is going to change aim and then forward is going to change aim also but for now let's just call this a good start okay undefined method aim i thought we just aim aim huh oh we need this to be an aiming submarine uh oh gosh okay got zero expected n oh wait expected zero but got nil oh because we're not initializing it i did the same thing all right so yeah like usually when i take stuff in as arguments i pass down like that all right that works all right so down does that let's see uh up decreases aim and then we want to say this is up and this should be like negative 1 or negative two and that works fine i already implemented that in practice what i might do is just comment it out watch the test fail comment it back in and watch it fail again comment the actual solution back in watch it fail or watch it pass right okay now we need to do is describe forward so forward is going to be increases um position by aim times n or whatever right so then this is going to be uh forward and we kind of need to aim down a little bit down two and then we'll say forward like three um in order like otherwise our aim is going to be zero so we want our aim to be something so that when we go forward we go in a direction so right now we're gonna aim down two and then we're gonna say forward three and we expect that our our position is gonna equal two times three uh okay and we'll just see what happens here and undefined method forward for aiming submarine okay let's comment this back in we know that this is actually going to be times equals no it's going to be plus equals n times aim i think and okay cool so we've got passing tests everything is still passing because we just like totally copied and pasted the aiming sub or the submarine thing uh it's supposed to make it so that or i think the the one of the reasons why they do the problem like this is so that you have practice refactoring and you realize like oh i made all these assumptions early on about the the way that i was solving this and i want to refactor it now um okay so i think we're pretty close to having an aiming okay so we've got an aiming submarine can we just change this aiming submarine and then run our input we get back zero okay so what is the problem there aiming submarine dot new instance eval down up position location is depth times position i think that depth times position thing is still the same yep okay so why did we get back zero so aiming submarine.new eval instructions let's drop a buy bug in here acquire buy bug just to sort of step through this stuff day two submarine rb day two input okay so uh next um okay so we have our instructions [Music] and that's all of the instructions uh when you're in buy bug if you do l equals that will bring you back so that it prints back out where the line is like smack in the middle so now if we do like next we have submarine dot location why is it zero submarine dot depth oh yeah okay so i did this wrong so the location all right so we increased the position okay so here we go we messed this up so it increases your horizontal position by x units so moving forward should actually increase our position by three so this should actually just be three um and then it should also increase our depth by um aim times x so this is all right so when we move forward our position is increased by that and our depth is increased by n times that all right so then we expect the depth to be 2 times three okay all right tests are passing we come back over here run the input again all right we get this giant number it looks like this one two eight okay let's just search the page four all right so that is the puzzle answer this was super fun i had tons of fun making a submarine and yeah i hope you enjoyed it yeah so this was uh day two of the advent of code thanks so much for watching we'll see you next [Music] time you
Info
Channel: CJ Avilla
Views: 104
Rating: undefined out of 5
Keywords: cjav_dev, web development tutorials, web development for beginners, vim, ruby, rails, advent of code, submarine, instance_eval, DSL, domain specific language, eval, advent of code 2021
Id: O-68TZhjp4Y
Channel Id: undefined
Length: 19min 24sec (1164 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.