Placeholder Image

Subtitles section Play video

  • COLTON OGDEN: All right.

  • Good morning, good afternoon, good evening,

  • depending on where you are in the world.

  • This is CS50 on Twitch.

  • My name is Colton Ogden, and I'm joined today by?

  • RODRIGO DABOIN SANCHEZ: Rodrigo Daboin Sanchez.

  • COLTON OGDEN: And Rodrigo has joined us before on stream--

  • well, he joined us yesterday-- yeah, while we

  • were doing a little bit of Minesweeper.

  • And it's sort of tangentially related to today in that today we're

  • covering a game, right?

  • So what are we talking about today?

  • RODRIGO DABOIN SANCHEZ: Today's Game of Fifteen.

  • So if you were here yesterday, you would have

  • remembered us showing the little visual of what it looks like when it's solved.

  • But yeah, we'll talk about it and--

  • throughout the whole stream.

  • And it's essentially just what is a board game in a fiscal form.

  • But we're doing it terminal based so just printing out onto the terminal.

  • And you're just trying to unshuffle a board of numbers

  • so that it goes from 1 to 15 with an empty slot at the end.

  • And we'll see what that looks like.

  • COLTON OGDEN: The first time I think you were on stream,

  • was it for Super Mario Brothers?

  • RODRIGO DABOIN SANCHEZ: Yeah, I think it was for Mario.

  • So I've been on stream twice just playing games--

  • figured I had to come on it, actually.

  • COLTON OGDEN: There was Zelda, right?

  • You also did Zelda with us?

  • RODRIGO DABOIN SANCHEZ: I did Zelda as well.

  • COLTON OGDEN: Yeah.

  • We did a couple of streams last year, towards the holiday season.

  • We ended up doing some actual, proper Twitch content.

  • Normally, people play games on Twitch.

  • We program games on Twitch often.

  • Why don't you tell people about [INAUDIBLE] your experience at Harvard

  • so far--

  • what you're studying, how long you've been here.

  • RODRIGO DABOIN SANCHEZ: Sure, yeah.

  • I'm a junior right now, about to start spring semester.

  • And studying computer science--

  • kind of a newbie in the field because for the longest time,

  • I thought I was going to do math.

  • And then when I was in my freshman year--

  • actually, the-- yeah--

  • no, the beginning of my sophomore year, I

  • realized I didn't really like math as much as I thought I did.

  • And CS, instead, was kind of related to math

  • while still more entertaining for me.

  • So I switched to that.

  • And I'd had just a couple of years of experience with CS

  • before that, mostly with Java, Mathematica.

  • And so I just took CS50 as a freshman.

  • And here I am, two years later, working for CS50, so--

  • COLTON OGDEN: Awesome.

  • Well, it's good to have you.

  • You also worked with me for the games course.

  • RODRIGO DABOIN SANCHEZ: That's true.

  • COLTON OGDEN: You and I worked together.

  • We taught the games course last--

  • you were in during the summer version, correct?

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • COLTON OGDEN: Yeah, not the spring version.

  • Yeah.

  • And that was awesome.

  • Yeah.

  • That was really cool.

  • Some folks in the chat I think are actually taking the games course

  • online right now.

  • One of the person's name, [INAUDIBLE],, and I'm not sure

  • if they're in the chat at the moment.

  • Let's look at the chat, actually-- just make

  • sure we're caught up with everybody.

  • So we have Harvey Neto from Brazil.

  • So hello, Harvey.

  • Good to see you.

  • RODRIGO DABOIN SANCHEZ: Bon dia.

  • COLTON OGDEN: I'm not sure if Harvey's been in this chat before.

  • So welcome, if this is your first time.

  • Oh, indeed.

  • Yeah.

  • Now they're a first time follower as well as of a few minutes ago.

  • So Harvey, thank you for the follow.

  • And also TaserHD, thank you for the follow.

  • [INAUDIBLE],, is on, Bella_Kirs, [INAUDIBLE]---- hello from Germany.

  • Hello, [INAUDIBLE].

  • Good to have you with us.

  • That's a new name as well.

  • Edwine21 says hello.

  • That's a new name.

  • Whipstreak23, Nate, hello.

  • Thank you for joining us today.

  • [INAUDIBLE], hello from Egypt.

  • A lot of new names today.

  • A lot of representation around the world, which is great.

  • Love it.

  • Andre's very kindly giving everybody hello.

  • Bhavik's not here.

  • Oh, that's a good point.

  • Bhavik's not here.

  • That's unfortunate.

  • Hope he joins.

  • I did realize that we forgot to post a pub yesterday.

  • We pubbed today.

  • We didn't pub this one yesterday.

  • So hopefully that's not the reason why.

  • If so, that's on me.

  • So I apologize for not doing that.

  • But we've mentioned it on stream before, certainly.

  • And then again-- and in case I do forget,

  • which I won't, about tomorrow's.

  • Tomorrow, David's doing a stream on Render 50.

  • So tune in for that one for sure.

  • And glad that all of you are here today that have tuned in right now.

  • Let's see who else we have.

  • We have Forsunlight.

  • Hello, Forsunlight.

  • Bella_Kirs, Twin Tower Power.

  • Are we going to get to see Rodrigo bless us with his knowledge today?

  • Why don't you answer that question.

  • RODRIGO DABOIN SANCHEZ: You know, it's--

  • knowledge is a funny thing.

  • No.

  • Yeah, yeah.

  • We'll get to see a little game that-- it's actually

  • inspired from a previous CS50P set.

  • But it was coded in C. And so I decided to do it from scratch in Python

  • and implement a solving algorithm for it.

  • So it's inspiration from the old, but some of it is from scratch from me.

  • So we'll see.

  • COLTON OGDEN: Yeah, we didn't do--

  • we've done Game of Fifteen historically.

  • But within the last couple of years--

  • I'm not sure if it's the last two years that we haven't, or just the last one

  • year.

  • I think it might be the last two years.

  • We've switched it out for music and something else this last semester.

  • RODRIGO DABOIN SANCHEZ: When I took it as a freshman,

  • that was the last year that we had it as a pset.

  • COLTON OGDEN: OK.

  • Was that two years ago?

  • Three years ago?

  • RODRIGO DABOIN SANCHEZ: Yeah, 2016.

  • COLTON OGDEN: OK.

  • So the last two years, we haven't actually done it.

  • But it's nice to bring it back.

  • There's a lot of-- you can go into old versions of the course on YouTube

  • and whatnot and see that that course-- or that problem set existed.

  • Will the stream with David tomorrow be at the same time?

  • I can tell you right now.

  • No, tomorrow the stream is going to be at 3:00 with David.

  • So tune in for that one at 3:00 PM.

  • Harvey Neto, hello.

  • Who is from Brazil.

  • Forsunlight, I'll try to listen only.

  • Everybody say computer science.

  • Martian Mars Boy says yes.

  • And that's a new name that I haven't--

  • I don't think I recognized.

  • We should make a group on WhatsApp, says Harvey Neto.

  • Everybody's super enthusiastic.

  • Tuxman29, thanks for joining.

  • And-- oh, there's Bhavik at the bottom.

  • He's here.

  • He was just a couple of minutes late.

  • Well, I shouldn't say a couple minutes late--

  • a couple minutes later than everybody else.

  • We haven't actually started the implementation yet,

  • but glad to see Bhavik there as a regular.

  • And Tuxman says studying CS in Montreal because of CS50X.

  • That's awesome.

  • Cool.

  • I'm going to bring us to the shot of your computer, which is just,

  • at this moment, an empty terminal.

  • And I'm going to let you take control at this point

  • and guide us through what you want to illustrate.

  • So go for it.

  • RODRIGO DABOIN SANCHEZ: All right.

  • Well, let's just-- let's-- for those who are not familiar--

  • actually, I can do this from the terminal now.

  • So if I write a bunch of just random things in the terminal

  • that you haven't seen before--

  • I like aliases a lot, and so actually I can--

  • COLTON OGDEN: So GC for Google Chrome?

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • I might have some jobs right now, so let me just exit out of that.

  • But if I actually open up Atom here, I have some nice little aliases.

  • So I'm really lazy, and I don't like typing things out very long.

  • So for committing to git, I have gcm instead of having

  • to write git commit, blah, blah, blah.

  • COLTON OGDEN: Oh, I like that.

  • RODRIGO DABOIN SANCHEZ: So just random things.

  • I don't have to write the same thing over and over again, so--

  • COLTON OGDEN: I should probably do that too.

  • RODRIGO DABOIN SANCHEZ: If I navigate pretty quickly in the terminal,

  • it's just because I kind of saved future me the headache of writing

  • all this stuff unnecessarily.

  • But OK.

  • So here I am.

  • What I was going to do is show everyone who

  • hasn't seen Game of Fifteen what it looks like.

  • COLTON OGDEN: Oh, good idea.

  • That's a good image on the right.

  • I like that.

  • The 15 puzzle.

  • And some people might know it as 15 Puzzle.

  • That's-- maybe it's a more--

  • RODRIGO DABOIN SANCHEZ: Might be a little bit small.

  • COLTON OGDEN: --popular name.

  • RODRIGO DABOIN SANCHEZ: Yeah, 15 Puzzle.

  • So this is what it looks like when it's solved.

  • It's, like I was alluding to before, a two by two--

  • like a 2D array type of thing, where you have 16 empty tiles.

  • And then 15 of them are filled up with tiles numbered 1 through 15.

  • And so what you're trying to do in the physical board game is just--

  • they're not-- they don't start off solved like this.

  • They'll start off in some scrambled way.

  • And you're trying to move the tiles down, and to the left,

  • up, and right so that you end up with this configuration.

  • And we're going to do this on the terminal.

  • So that's about it.

  • COLTON OGDEN: Tuxman says I was teaching coding to kids,

  • and a phrase that they always use, coding is the art of being lazy.

  • RODRIGO DABOIN SANCHEZ: Exactly.

  • I always tell everyone, being lazy is the best

  • feature a programmer can have as long as they still get their work done.

  • COLTON OGDEN: Yeah, I kind of agree with that.

  • Rabin Gaire also says hello there.

  • So, hello Rabin--

  • Rabine.

  • Good to have you with us.

  • What were you going to say?

  • RODRIGO DABOIN SANCHEZ: Yeah, because being lazy

  • makes you look for the most efficient solution, the one that

  • takes the least amount of work.

  • COLTON OGDEN: There's that quote from Bill Gates.

  • It's like, he'll always choose the lazy programmer-- or whatever,

  • the lazy worker, because they'll get the job done with the least amount of work.

  • RODRIGO DABOIN SANCHEZ: Right

  • COLTON OGDEN: I don't know if that's actually a real quote.

  • I feel like I hear it all over the place.

  • RODRIGO DABOIN SANCHEZ: So what I'm doing right now is I am just creating--

  • COLTON OGDEN: So touch, to be clear, is a--

  • RODRIGO DABOIN SANCHEZ: Right.

  • So right now, I've just created two new files using the touch command.

  • And it just creates an empty file for you.

  • You give it the name.

  • And so here it is now in my text editor, which is Atom--

  • which is a different one than Colton uses.

  • COLTON OGDEN: Right.

  • RODRIGO DABOIN SANCHEZ: I don't remember which one--

  • COLTON OGDEN: Yeah.

  • I use VS Code.

  • But they're very similar.

  • They're sort of electron based, modern text editors with a very well supported

  • plug-in system--

  • plug-in ecosystem.

  • VS Code has some built-in debugging stuff, which is pretty cool.

  • RODRIGO DABOIN SANCHEZ: That's nice.

  • COLTON OGDEN: V1Rani's in the chat saying, hey, guys.

  • Been here yesterday, decided to stop by today as well.

  • So thanks for popping in again.

  • Glad to have you with us.

  • RODRIGO DABOIN SANCHEZ: For sure.

  • And I know we don't do a lot of Python coding on the stream, right?

  • COLTON OGDEN: Not yet at least.

  • RODRIGO DABOIN SANCHEZ: Not yet.

  • COLTON OGDEN: It would be nice to do more of it.

  • I know that for sure.

  • A lot of people are into Python.

  • I love Python.

  • I don't use it in the context of game programming, but yeah, absolutely.

  • I think we should definitely have more Python stuff.

  • So this is a good step in that direction.

  • RODRIGO DABOIN SANCHEZ: And so with Love2D,

  • which is what Colton usually uses when we're creating a game,

  • you have the update and the render and the load and everything.

  • But with Python, you don't get that kind of a built-in behavior.

  • You have to implement it yourself.

  • And so in Python, if you want to do something

  • as simple as printing, hello, world--

  • or just hello, you literally just write it in whatever file-- usually

  • it's called main.

  • And then if you run it here, you would write Python 3.

  • But once again, I'm lazy.

  • So I just write py.

  • And that's how you execute a Python program.

  • So all of a sudden, we have our first Python program.

  • And before I jump into the actual coding itself, what I like to do

  • is build myself a little roadmap.

  • So what I'm going to do is create another file called plan.txt.

  • And I just like to write out what I need to implement the program before I just

  • dive into it.

  • That way, it's kind of like writing a rough draft of a paper

  • before you-- or an essay before you dive into it.

  • COLTON OGDEN: Yeah, absolutely.

  • I do that too-- actually, a lot--

  • when I'm working on a larger project and like some

  • of the ones you've done on stream--

  • like something that's maybe more representative

  • of a real world game code base.

  • It's very easy to get lost in--

  • RODRIGO DABOIN SANCHEZ: Yes.

  • COLTON OGDEN: --figuring out where you want to go next.

  • So having a-- some sort of to-do--

  • I mean, essentially, it's the idea of just a to-do--

  • RODRIGO DABOIN SANCHEZ: It's a to-do list--

  • COLTON OGDEN: --list, generally.

  • RODRIGO DABOIN SANCHEZ: --basically.

  • COLTON OGDEN: I mean, we use Asana for work, which

  • is a great tool for to-do list stuff.

  • And it's that sort of idea--

  • people that can keep track of all the individual things they do.

  • I feel like it's easier to stay on top of stuff.

  • RODRIGO DABOIN SANCHEZ: So I'm just making a checklist here,

  • things that we need.

  • And if we-- oh, I got rid of the image, didn't I?

  • If we go back to--

  • COLTON OGDEN: Lancemaker is saying, dude, I have a huge Excel table,

  • and I have to crush it down for work.

  • I'm using Python since I suck at Excel, and Python also.

  • But still, Python is pretty comfy.

  • RODRIGO DABOIN SANCHEZ: So if we're kind of taking a look-- oh, what was that?

  • COLTON OGDEN: They're basically just saying they have a huge Excel table

  • and they have to crush it down for work.

  • They're going to use Python instead of Excel because Python's pretty nice.

  • RODRIGO DABOIN SANCHEZ: Yeah, Python gives you a lot of flexibility.

  • And we actually-- David teaches a class at the business school

  • that starts off in Excel, then talks about database languages,

  • and then moves on to Python.

  • And it's just kind of like the different things that you use these tools for.

  • And obviously Python gives you a lot of flexibility, so--

  • but, yeah.

  • So if we're looking at this board right now,

  • and we're thinking about if we're writing a video game version of this,

  • what do we need in order to code this?

  • The first thing that comes to mind is, well, we actually

  • need a way to represent the board, right?

  • And so I preemptively created a file called Board.py.

  • But in the plan, let's just jot to ourselves,

  • we're going to need a 2D array, probably, to represent the board.

  • And then we're going to be, obviously, moving it around a lot

  • as we try to solve the game.

  • And we should ideally keep in mind an image of what

  • the game looks like when it's solved.

  • So maybe we're also going to need a 2D array to represent

  • the solved board or the goal.

  • All right.

  • If we take another look at this, we see that there's always

  • going to be this empty slot.

  • And as we shift tiles down or right, to the left, it's kind of moving around.

  • So it might be useful to keep track of the position of this empty tile.

  • So if we think about a 2D array, this might be position 0, position 1, 2, 3.

  • And then this is row 0.

  • And then this is row 1, position 0, 1, 2, 3.

  • So we'll probably want to keep track of this empty slot

  • because if we think about how we're going to implement shifting tiles, what

  • we'll probably want to do is just swap the location

  • of the empty tile with the tile in the direction that you're trying to move.

  • So it'll be nice to have a reference to that position.

  • So we'll need a location variable to keep track of empty tile.

  • COLTON OGDEN: The chat's curious about your distro of Linux, by the way.

  • Do you want to share?

  • RODRIGO DABOIN SANCHEZ: Oh, yeah.

  • I have-- lsb_release dash a--

  • Ubuntu 18.10 cosmic.

  • COLTON OGDEN: Nice.

  • RODRIGO DABOIN SANCHEZ: And I actually have to give a shout out

  • to one of my co-workers, Karin Zedan.

  • He helped me.

  • I was actually using Windows before.

  • And I wasn't very familiar with the Windows terminal.

  • And what I had to do instead was download a batch subsystem

  • that ran Linux on Windows.

  • And it was nice for a while, but it's still kind of growing,

  • and it hasn't implemented all the features that it needs.

  • So some things that I wanted to run on it, didn't work.

  • And eventually, I decided to dual boot my computer.

  • So this computer is actually running Windows and Linux, but separately.

  • And so when I shut it off and turn it on,

  • I can pick which operating system I want to use.

  • COLTON OGDEN: That's pretty cool.

  • RODRIGO DABOIN SANCHEZ: So yeah, it's pretty nice.

  • I can program in my Ubuntu, and then if I

  • want to do Microsoft Word or whatever, I can switch over to Windows.

  • So you know, that's nice.

  • So where were we?

  • Yeah, so we're talking about things that we need.

  • We'll probably want to be able to see the board somehow.

  • So we want function to display board on screen.

  • Let's see.

  • What else do we need?

  • We probably need-- if we want to make moves with the keyboard,

  • we'll probably need some sort of listener--

  • listener for keystrokes.

  • Which, remind me, does that come built into a Love2D, right?

  • COLTON OGDEN: It does.

  • RODRIGO DABOIN SANCHEZ: It does?

  • COLTON OGDEN: Yeah.

  • Love2D has a function called love.keypressed,

  • which is a callback function that Love will trigger.

  • There's a hook in the executable that is always pulling for input.

  • And whenever it gets any keystroke or any interface, mouse, keyboard,

  • joystick, whatever, it goes through all the callback functions

  • that you've registered via love.keypressed.

  • Well, it goes through all the callback functions

  • it has registered and then calls the logic you've defined

  • within those callback functions.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • So that's pretty nice.

  • In Python, when I was tinkering around with the idea for this game,

  • I actually realized that I was going to have to download a library in Python

  • to help me keep track of a keyboard listener.

  • So we'll have to take a look at what library to use for that.

  • And the game's not too complicated.

  • So basically the last things we'll likely need

  • is just, if we want to solve the game, maybe a function to solve the game.

  • And then how do we know that we're done?

  • We probably want some sort of "game over" screen or something.

  • And I think that's a pretty good starting point, right?

  • This is a nice little to-do list.

  • We can knock these out one by one.

  • COLTON OGDEN: I usually do my "game over"

  • screen, ultimately, very, very last--

  • once I'm on stream at least.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • I mean, it's not really like a functional thing

  • that the program needs, but it's kind of like a nice, OK--

  • COLTON OGDEN: It's a nice way to package it up with a bow

  • and be like, oh, here's a game that's actually complete, more

  • or less-- or at least feels complete.

  • RODRIGO DABOIN SANCHEZ: Exactly.

  • So OK.

  • We saw that with Python, essentially you just kind of write things down

  • and you can run it, because it's an interpreted language.

  • And so I propose that we actually start by modeling the board.

  • And let's actually put this to-do list down here so we can refer to it.

  • COLTON OGDEN: So Lance Maker's question is, are you printing

  • the state of the board on the terminal?

  • Or will you be rendering images?

  • RODRIGO DABOIN SANCHEZ: So the board will just

  • be text based on the terminal, just a simple--

  • as much as-- you see board.py, main.py, plan.txt here.

  • You would just see like 1, 2, 3 4, 5, 6, 7, blah, blah, blah.

  • That would be the board, kind of like in a square.

  • Just by default, I have it so that when I clear my screen,

  • I have my directory listed, like all the components and stuff.

  • But if you actually don't want that, you can have that gone too.

  • COLTON OGDEN: Quite a bit easier to start implementing something like that

  • too, compared to making all the artwork you need to make otherwise.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • We saw yesterday how long it took to make sprites and stuff.

  • COLTON OGDEN: And those were simple sprites too.

  • And then making games like this, you can focus more on the gameplay

  • so you don't have to spend as much time on the resource development.

  • And games like rougelikes, for example, are

  • very rich in terms of what you can do with them.

  • But they're Ascii art.

  • So they take one thing, put no emphasis on it, and then put a lot of emphasis

  • on everything else.

  • It's like pros and cons, you know?

  • RODRIGO DABOIN SANCHEZ: So what I'm doing right now

  • is I'm just creating a class.

  • And we briefly talked about that yesterday.

  • COLTON OGDEN: We've mentioned object-oriented programming.

  • We haven't gone into tremendous detail on the mechanics of it

  • with what inheritance is, what polymorphism is.

  • RODRIGO DABOIN SANCHEZ: Essentially what we

  • said yesterday was that writing a class is kind of like writing

  • a blueprint for something.

  • So if you want to represent an object--

  • in this case, we want to represent the board.

  • So we want to have some sort of idea and code of what a board is.

  • We can envision that--

  • things that a board can do is make moves, render itself, randomize itself,

  • check if it has matched a goal state of some kind,

  • if we want to attribute a function for the board to solve itself.

  • These are all things that a board should be able to do.

  • So what I'm doing is I'm writing a class to make the blueprint of what

  • a board is and what properties it might have and what methods or actions

  • it can take, et cetera.

  • COLTON OGDEN: Essentially let's us define a new data type, where

  • that new data type is, instead of being an integer or a string,

  • it's something that's a little bit more representative of something we might

  • find in the real world-- a board, for example.

  • In computer science, there is no intrinsic data type that is a board.

  • But we can define--

  • RODRIGO DABOIN SANCHEZ: Exactly.

  • COLTON OGDEN: --roughly speaking in an abstract way,

  • the different pieces of information and the functions that we might associate

  • with a board, sort of lump them together so we can think about boards versus

  • the numerical information we would need to keep--

  • have a representation of that.

  • RODRIGO DABOIN SANCHEZ: And so I just--

  • I was kind of typing a little bit while you were explaining.

  • And this is touching on what we were talking

  • about yesterday about the constructor, which is different syntax in Lua.

  • But essentially when you create a board, you define it as a new data type.

  • And you actually want to--

  • In Python, there is such a thing as an int, I guess.

  • They're a number.

  • And there's a difference between the theoretical existence of a number

  • and then actually having the number 4, like writing x equals 4 or something.

  • So we can have this blueprint of what a board is,

  • but then we actually want to create one.

  • And then when we create one, we want to attribute properties to it.

  • And so that's what the constructor is going to be doing.

  • So this kind of may be a little bit foreign syntax--

  • def underscore, underscore, init, self is essentially

  • the syntax for starting to define the constructor in Python,

  • where self is just referring to the board object itself.

  • And so what we're referring to here in the plan

  • is that we need a way to represent the board and solve the board.

  • So the goal-- so the solved state, if we want

  • to have it look something like this, I propose making a 2D lists of some kind.

  • And since we know that we want to print the board onto the terminal,

  • I'm just going to go ahead and make the numbers just strings.

  • And the nice thing about this is that I can preemptively

  • put a space between the number because I know if later on I'm

  • going to have a number like 10, that's going to take up two character

  • positions.

  • Whereas if I have single digit numbers, they're not

  • going to be aligned in the same way.

  • COLTON OGDEN: Right.

  • RODRIGO DABOIN SANCHEZ: So I'm preemptively

  • trying to make sure that they line up by keeping them in text.

  • COLTON OGDEN: That's cool.

  • RODRIGO DABOIN SANCHEZ: So yeah.

  • This is me creating the board right now in the solved state.

  • COLTON OGDEN: Kind of much like creating sprites.

  • Speaking of that, V1Rani was saying, those sprites yesterday.

  • Slytherin 2.

  • Because remember the snake?

  • The 2 looked like a snake.

  • RODRIGO DABOIN SANCHEZ: Oh, yeah, yeah, yeah.

  • That was funny.

  • COLTON OGDEN: And Nacleric, have you played Dwarf Fortress?

  • I have played Dwarf Fortress-- not a lot, though.

  • It's got a pretty tremendous learning curve.

  • Have you played Dwarf Fortress?

  • RODRIGO DABOIN SANCHEZ: I have not.

  • COLTON OGDEN: Have you heard of Dwarf Fortress?

  • RODRIGO DABOIN SANCHEZ: I am-- most of the games

  • I play are very few in number.

  • COLTON OGDEN: Gotcha.

  • RODRIGO DABOIN SANCHEZ: I play FIFA.

  • COLTON OGDEN: That's a nice way of saying no.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • [LAUGHTER]

  • COLTON OGDEN: That's a very political way of--

  • RODRIGO DABOIN SANCHEZ: I love games, but I don't play them that often.

  • COLTON OGDEN: Yeah.

  • RODRIGO DABOIN SANCHEZ: Well, that's a lie.

  • I play the same games a lot.

  • COLTON OGDEN: Are you familiar with rougelikes.

  • Do you know what that is?

  • [INAUDIBLE]

  • RODRIGO DABOIN SANCHEZ: Actually-- well, do you want to explain?

  • COLTON OGDEN: So if I can--

  • I'll show you an image here on a separate laptop.

  • So images.google.com.

  • So this is what a roguelike looks like.

  • It's kind of like--

  • have you ever seen an image like this?

  • Look something like that?

  • RODRIGO DABOIN SANCHEZ: It kind of makes me think of--

  • what's it called?

  • Everyone plays it nowadays.

  • The World of Warcraft or something like that.

  • I don't know.

  • COLTON OGDEN: Yeah, not quite.

  • Or like this, where everything just kind of looks like Ascii artwork.

  • Have you seen the games like that?

  • RODRIGO DABOIN SANCHEZ: This is all new to me.

  • COLTON OGDEN: Oh, OK.

  • Well, we can maybe talk about it another time.

  • Dwarf Fortress is a type of roguelike, sort of.

  • But it's much deeper roguelike than most roguelikes

  • are and much more flexible and much more catered towards building things.

  • But yes, to answer Nacleric question, I have played it--

  • only a little tiny bit.

  • A class is a struct on steroids says Andre.

  • Yeah, in a sense.

  • Kind of.

  • Depends on the language I think.

  • Bhavik Knight, why not use loops?

  • I'm guessing we probably are going to be using loops at some point.

  • RODRIGO DABOIN SANCHEZ: Yeah, they're probably

  • referring to me making this board.

  • COLTON OGDEN: Oh, yeah.

  • RODRIGO DABOIN SANCHEZ: I'm just like--

  • COLTON OGDEN: Yeah, that's fair.

  • Yeah, you could do it with a loop, I guess.

  • RODRIGO DABOIN SANCHEZ: I'm only ever going to have to do it once.

  • COLTON OGDEN: This-- you visually can-- if you're a programmer,

  • you visually can see-- there's a point to be

  • made about visually being able to see exactly what the data structure looks

  • like.

  • And so I actually agree with this decision

  • to draw everything out with strings.

  • It's just a lot more readable.

  • RODRIGO DABOIN SANCHEZ: It helps me visualize.

  • Now I can see this is the shape of the board.

  • COLTON OGDEN: One thing I probably would do

  • is I'd probably do that, just because-- that it's perfectly aligned.

  • RODRIGO DABOIN SANCHEZ: Yeah, that's true.

  • And it's--

  • COLTON OGDEN: A little bit like that.

  • RODRIGO DABOIN SANCHEZ: Especially because alignment

  • is important in Python.

  • It won't care about this so much.

  • But if I don't have this indented properly, it's not going to--

  • COLTON OGDEN: Oh, yes, yes.

  • An important--

  • RODRIGO DABOIN SANCHEZ: It's not going to like it.

  • COLTON OGDEN: --thing for those new to Python.

  • Indentation is crucial.

  • You absolutely need layers of indentation

  • to let the interpreter actually work and run your program.

  • RODRIGO DABOIN SANCHEZ: Questions in the chat?

  • COLTON OGDEN: No, I don't think any--

  • so dunder proto, anyone here got the reference?

  • I'm not sure what that is a reference to.

  • And then MOBA games, V1Rani is asking.

  • I used to play League a bit and Dota.

  • Have you played MOBA games at all?

  • League or Dota?

  • RODRIGO DABOIN SANCHEZ: League of Legends.

  • That's what I was thinking.

  • Not World of Warcraft.

  • No, actually.

  • COLTON OGDEN: Oh, I got you.

  • OK.

  • Yeah, a little bit.

  • A little bit.

  • Too many games in the world.

  • Way too many games.

  • RODRIGO DABOIN SANCHEZ: So what I'm doing right now,

  • I created this solved state for the board.

  • And what I did after that is, I imported from the copy library

  • this method-- or this function called deepcopy.

  • And the whole point of that is I know that the board is ultimately

  • going to get shifted around.

  • And instead of writing this all over again or doing a loop,

  • I just essentially figured I would just make a copy of the goal

  • and then shuffle it later.

  • Because if we think about this game, it's

  • not necessarily going to be solvable from any configuration of the board.

  • So the way that I want to solve it is I want to start from a solved state

  • and then make, I don't know, like 100 random moves in any direction.

  • That way, I know I'm starting from a position of a solved board,

  • making legal moves only, shuffling the board that way.

  • COLTON OGDEN: Right.

  • RODRIGO DABOIN SANCHEZ: So in order to do that,

  • I just want the board-- which is going to change eventually--

  • start off being in the same configuration as the goal.

  • I don't want to change the goal because I'm

  • going to need it to compare whether the current board is the goal.

  • So that's why I'm making a copy.

  • And the reason I'm using deepcopy method is because what it does is it

  • recursively copies lists that also contain lists, for example.

  • So--

  • COLTON OGDEN: Just saying self.board equals self.goal.

  • We just make a reference-- basically a pointer to self.goal,

  • and then he changes to self.board.

  • RODRIGO DABOIN SANCHEZ: Exactly.

  • COLTON OGDEN: Before you change it to self.goal.

  • RODRIGO DABOIN SANCHEZ: If I do something

  • like this, what Python is going to understand

  • is that these two variables are referring to the same--

  • COLTON OGDEN: Same data structure--

  • RODRIGO DABOIN SANCHEZ: The same data structure.

  • So if I change one, the other one will be updated as well.

  • And I want to avoid that.

  • So I'm basically making a separate copy of the board from the position--

  • the starting position of the goal.

  • And I'm making sure that I am avoiding the issue of having only references

  • to the lists within the list by doing this deepcopy, which recursively

  • makes sure that I copy everything.

  • COLTON OGDEN: That's very smart.

  • RODRIGO DABOIN SANCHEZ: Then I'm also starting

  • to track the location of the empty space, which

  • I have just chosen arbitrarily to denote with these underscores.

  • And I know this is 0, 1, 2, 3.

  • And then this is 0, 1, 2, 3-- so column and row.

  • Maybe we can have something like max col and max row.

  • COLTON OGDEN: Rabin is asking, deepcopy should be inefficient, right?

  • RODRIGO DABOIN SANCHEZ: Maybe with a very large data structure,

  • but this is so small that I don't think it's going to really make a difference.

  • COLTON OGDEN: Yeah.

  • This is a tiny data structure.

  • Making 1,000 copies of this data structure wouldn't-- you wouldn't even

  • notice any speed change probably.

  • But if it were hundreds of thousands of rows in a database type data structure,

  • then yeah, I could see that being very inefficient.

  • RODRIGO DABOIN SANCHEZ: This actually, semantically, I think is backwards.

  • Max row, max col. And I am going to go ahead and have these constants be--

  • well, they're constant, be equal to 4-- even though I know the index is 3,

  • because I can imagine myself wanting to loop things repetitively from 0 to 3.

  • And with the Python range function, the parameter that you pass into it

  • is not inclusive.

  • So if I pass in a range of 4, it's going to give me 0, 1, 2, 3.

  • And so it'll just be nice having these constants for semantic purposes.

  • COLTON OGDEN: The Last Kek was saying, why not just Control C and Control V?

  • For any self.goal, self.board.

  • Pretty funny.

  • RODRIGO DABOIN SANCHEZ: Oh, yeah.

  • [LAUGHTER]

  • That would accomplish the same purpose, but programmatically, it's

  • not necessarily great design to just copy and paste.

  • COLTON OGDEN: Dry principle.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • COLTON OGDEN: Very important.

  • RODRIGO DABOIN SANCHEZ: It's more of a me being a stickler, kind of.

  • And so we won't worry about this yet--

  • not jump into the moves just yet.

  • OK.

  • So we have an array to represent the broad,

  • an array to represent the solved board.

  • COLTON OGDEN: Last Kek, we know you're joking.

  • We're just messing with you too.

  • RODRIGO DABOIN SANCHEZ: Let's see.

  • I maybe just want now to make sure that everything's working so far.

  • So I may want a way to print this to the screen.

  • And Python has another one of these funky class names called repr,

  • for representation--

  • like how do I want this board to be represented if I print it or something?

  • So it's just a list that contains lists.

  • So I can imagine doing something like, for i

  • in range of the max number of rows, for j

  • in range of the max number of columns.

  • Then I want to just print--

  • we called this self.board--

  • at positions i and then j.

  • COLTON OGDEN: Often, you'll see y, x, x, y for 2D data structures as well--

  • RODRIGO DABOIN SANCHEZ: True.

  • Yeah.

  • We can do that.

  • It's the same thing.

  • But whatever.

  • COLTON OGDEN: It's fine.

  • i, j is also fine.

  • RODRIGO DABOIN SANCHEZ: Then if you notice--

  • if I just open up the Python interpreter right here,

  • if I print something as simple as hello, I get knocked down to the next line.

  • But if I include this additional parameter called end,

  • which denotes what I want at the end of the print statement-- by default,

  • it's a new line--

  • you'll see that when I didn't have it, it knocked me down one peg.

  • And here the prompt is the same--

  • in the same line.

  • So if I know I want to print the column side by side, then I--

  • when I'm iterating, probably don't want that new line behavior by default.

  • COLTON OGDEN: Oh, V1Rani was mentioning you have spaces

  • in these double digit numbers here.

  • RODRIGO DABOIN SANCHEZ: Oh, that's-- yeah, that's true.

  • Thanks for keeping up.

  • That would have been fun to see after we printed it.

  • COLTON OGDEN: Yeah.

  • That one's fine.

  • The 9's fine.

  • You can put--

  • RODRIGO DABOIN SANCHEZ: True.

  • COLTON OGDEN: --a space there.

  • RODRIGO DABOIN SANCHEZ: Good point.

  • OK.

  • COLTON OGDEN: Thanks, V1Rani, for mentioning that.

  • RODRIGO DABOIN SANCHEZ: Thanks for looking out.

  • Yeah, sweet.

  • COLTON OGDEN: Aeroman was asking, just joined.

  • What are we doing today?

  • We are doing Game of Fifteen, a prior CS50 pset,

  • but we're doing it in Python.

  • Traditionally, we've done it in C, at the Command line.

  • And then Rabin is saying, in JS, we call the prototype methods

  • with underscores dunder methods.

  • So they call those funky methods dunder repr, dunder init, et cetera.

  • I have heard that as well, yes.

  • RODRIGO DABOIN SANCHEZ: So I'm returning an empty string

  • here because the repr function, by default, must return something.

  • And so I'm not going to store this value anywhere.

  • This is just-- if I don't include it, Python will complain.

  • OK.

  • So right now we have a board with a goal--

  • an initial starting board-- and then we have a way to print this.

  • So in the main screen, let's just do something like b equals--

  • we're probably going to have to import this.

  • So from the Board, which is the name of our Python file--

  • from Board, we want to import--

  • it's this kind of funky syntax because the file name is called Board.py,

  • and so this is referring to the file name.

  • And now what I'm importing is referring to-- if I

  • want to import any methods or classes or whatever, we have a Board class.

  • So we're going to import the Board class.

  • And then here we can do something as simple as b is set to--

  • we're going to define a Board.

  • And then we can print b if we want and see what it looks like.

  • All right.

  • Unless I screwed something up, let's see what happens if I run main.

  • Name "goal" is not defined.

  • Oh, LOL.

  • So that's what the self keyboard is for.

  • This is called self.goal, and I just put in goal.

  • So thanks, Python, for watching out there.

  • OK.

  • So interesting-- we have 1, 2, 3, 4, 5, 6, 7, 8.

  • And now these are kind of jammed together.

  • So we might want to put some spaces in between these.

  • COLTON OGDEN: Aeroman was asking, what terminal is this?

  • I am new to Python, so can you suggest where do I

  • get this terminal or platform where you are writing this code?

  • RODRIGO DABOIN SANCHEZ: What terminal?

  • Oh--

  • COLTON OGDEN: Or platform.

  • RODRIGO DABOIN SANCHEZ: I configured my terminal.

  • So by default, it didn't look like--

  • it wasn't purple and stuff.

  • But in-- let's see.

  • Do I have my other--

  • where's my-- here we go.

  • Come on, Atom-- not highlighting.

  • COLTON OGDEN: I mean, what we can probably

  • say is that it's terminal with a specific bashrc or bash_profile,

  • whatever.

  • I forget what it is that customizes your Command Prompt in your--

  • we've talked earlier, 18.10 or 18.08 Linux-- or Ubuntu Linux,

  • something like that.

  • RODRIGO DABOIN SANCHEZ: Yeah, I'm on Linux Ubuntu 18.10.

  • And so there's the bash dot-- or the .bashrc file that helps you customize

  • all this.

  • And so I wanted different things to be in different colors.

  • So I knew-- so the name of my current directory is in blue.

  • And then my user name is in green.

  • Everything else is in purple.

  • And if I'm in a GitHub repo, it will show me the branch I'm on in yellow.

  • But maybe that's a topic for another stream--

  • how to customize a terminal or so.

  • COLTON OGDEN: V1Rani's asking, is "self" similar to "this" in JS?

  • JavaScript.

  • RODRIGO DABOIN SANCHEZ: Is what?

  • COLTON OGDEN: Is "self" similar to "this" in JavaScript?

  • RODRIGO DABOIN SANCHEZ: Oh.

  • Yeah, it's similar.

  • And-- oh, that looks a little bit better.

  • In Python, the whole point of it is that--

  • this is the wrong-- let's just close this.

  • In Python, the whole point is that if you're in a class,

  • the class is a blueprint.

  • And so let's say we have a blueprint for a house.

  • The house itself, if it has some things that it can do,

  • it's going to refer to itself using the "self" keyword.

  • The typical example for classes that I've heard used is a car.

  • A car should have a color property.

  • It should have functions like it can drive, it can break.

  • It can do all these things.

  • And so when you're writing a class that maybe is going to represent a car,

  • you can say self.color because if you instantiate multiple cars,

  • you can imagine you want one to be red, or one to be green, one to be blue.

  • So the "self" emphasizes that you're talking about the current instantiation

  • of the object.

  • So--

  • COLTON OGDEN: "This" is a bit weird in JavaScript because--

  • I mean, I haven't stated this in a while,

  • but for example, every function has its own "this" scope.

  • So it's a little bit weird.

  • If you call "this" within a function that's within an object,

  • "this" is actually the function and not the object.

  • I believe that's the case.

  • I ran into this issue fairly recently.

  • And the chat was talking about how they're having

  • issues with "this" in JavaScript.

  • And yeah, it's a bit weird in ES5.

  • The "self" in Python is much more consistent

  • and I think easy to understand.

  • But yeah, not arrow functions.

  • Yeah, arrow functions don't have that problem.

  • That's correct.

  • RODRIGO DABOIN SANCHEZ: All right.

  • So so far, so good, right?

  • We have a 2D array to represent the board.

  • So maybe we can get rid of this and put this over here,

  • or something like-- things we have.

  • And then we have a way to represent the solved goal.

  • So let's put this on here as well.

  • We have this location variable to keep track of the empty tile,

  • although we haven't used it yet.

  • We have a function to display the board on the screen.

  • OK.

  • So this might be a reasonable time to look for a listener.

  • And what I'm going to do right before that is--

  • you can have the main--

  • or whatever Python file that you want to run,

  • you can have it run just kind of without having to do any main methods

  • or anything like that.

  • But it's annoying if you want to have different functions that run

  • it different-- like at specific times.

  • Because anything that you have, just in that outermost layer right here,

  • is always going to run by default. And so

  • if you want to wait to execute some things,

  • it might be favorable to put it in a main function.

  • So what I'm going to do for now is I'm going to just create a main function,

  • def main.

  • And then all it's going to do for now is print the board, I guess.

  • I want the board as a global variable for now

  • in case I want to refer to it outside of the main function at some point.

  • And then if you have a main function, you have to--

  • I mean, you can do something as simple as calling main right now,

  • but the convention in Python is to write this

  • more cryptic looking statement called if name equals equals main, then run main.

  • And what this does is, essentially if you're

  • importing this file to a different file--

  • so if this is going to be a helper file for some reason,

  • it won't execute the code in that one.

  • And if you're just in this one importing other stuff,

  • it knows that this is the main file.

  • And so it's going to call the main function.

  • But we usually just wave our hands at the syntax.

  • All we know now is that this should, in theory, accomplish the same thing

  • as before, which it does.

  • OK.

  • So now let's look for a keyboard listener.

  • And the one that I was toying around with is called pynput.

  • And this is for those who may not have ever heard this before, I

  • wanted to point at the documentation.

  • But it's just this small, little library that supports listening for the mouse

  • and then listening for the keyboard.

  • For the purposes of this project, I guess we're not

  • going to be doing much with the mouse.

  • But it does have a way to monitor the keyboard and control the keyboard.

  • And then it handles errors and such.

  • COLTON OGDEN: TheLastKek says, got to go.

  • CS50TV.

  • Love the stream.

  • Cheers.

  • Thanks, Last Kek, for joining us.

  • RODRIGO DABOIN SANCHEZ: Thank you.

  • COLTON OGDEN: See you on the next stream.

  • Andre is saying, JavaScript's "this" is a bit strange.

  • But yeah, it is.

  • In ES6, they made it a little bit more, I

  • think, consistent with other programming languages.

  • And to Andre's point, in C-like languages-- like, for example, Java--

  • this is a bit more like "self" in Python.

  • And then Aerospace Man-- or Aeroman123 was saying,

  • I'm working with a supercomputer in Barcelona

  • running aerospace aerodynamics and CFD simulation using open foam.

  • And then people were saying, oh, that actually makes sense.

  • That's why your name is Aeroman123.

  • JS is lexcially scoped, but when you want

  • something similar to dynamic scoping, "this" gives us that.

  • On arrow functions, there is no "this" defined

  • on the scope, so it goes up the scope and attaches itself with parents "this"

  • definition.

  • I have to reread on all that for the JS stream.

  • That should be coming up in a couple of weeks.

  • And then Putevoditell was a new viewer from yesterday-- says, hello, everyone.

  • Tomorrow there will be a stream because today I

  • will not be able to be on this wonderful channel.

  • Well, I hope you can join us for tomorrow's stream.

  • Glad to have you with us.

  • Yeah.

  • Think we're all caught up now.

  • RODRIGO DABOIN SANCHEZ: All right.

  • COLTON OGDEN: So while I was doing that, you programmed the--

  • RODRIGO DABOIN SANCHEZ: Well, no.

  • It's-- they-- in the documentation, they have, hey,

  • if you want to control the keyboard, for example,

  • this is how you press and release keys or whatever manually.

  • But if you just want to listen for the keyboard, you just copy this code.

  • You have to import the library, I think.

  • I don't think it comes by default in the terminal.

  • I think I had to install it with pip.

  • And then once you have it, you can import the keyboard method.

  • And all that it has is kind of similar to Love2D

  • now, where you're listening for when people press keys.

  • It has a method that fires when people--

  • or when someone-- a user presses a key and one

  • that fires when they release that key.

  • And here's kind of the actual listening portion.

  • And if you read through it, you see that you pass in the methods

  • that you're going to be using.

  • So they're going to be using an onPress and onRelease.

  • And what I did was, I just kind of put this in our file

  • where I imported from py input, the keyboard function.

  • I defined the onPress and onRelease key exactly

  • as they had in their documentation.

  • And then in the main function--

  • in the main method, I started the listener.

  • So that it's constantly listening.

  • And--

  • COLTON OGDEN: It takes the place of like a, while true.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • Yeah.

  • And the only other thing is that in the documentation

  • they say the way you can stop the listener, you can pass it--

  • you can basically broadcast some special codes.

  • But more simply, you can return false.

  • So in this default behavior that they have here,

  • if what the user press was the Escape key, they just return false.

  • And so if we want to just run their code and see what that looks like--

  • I press Enter to execute the file in the program

  • and its realized that I press Enter.

  • So if I press Up--

  • the terminal has this kind of annoying behavior where if you press some keys

  • it gives you this annoying thing.

  • But here's their feedback key.up has been released.

  • If I press a alphanumeric key, a is pressed--

  • and the terminal has this annoying echo, so we're

  • going to want to silence that during our program.

  • Because we won't want it to display what key we're pressing every single time.

  • But yeah, I can just do something as simple as Escape now

  • and it says Escape key has been released.

  • And if we take a look at the code, that is exactly what this does

  • is whenever you print, whenever you press a key, it just tells you such

  • and such key was pressed.

  • If it was alphanumeric, and then if it was not alphanumeric,

  • it tells you that it was a special key.

  • And you know, it just prints which when you press.

  • And when you released, it tells you that you released it.

  • And then if what you pressed the Escape key,

  • it kills the listener, which basically terminates the program

  • because that's the last thing happening and our main method.

  • So yeah.

  • Now what we want to do is adapt this so that we can essentially have moves

  • that we can make in the game.

  • COLTON OGDEN: It's kind of like Love2d, like you're saying,

  • it gives you the ability to like check basically, oh, it's constantly

  • looking for input, sort of almost like behind the scenes, but in this case

  • we have to [INAUDIBLE] to find that behavior.

  • And then if you press-- if it checks for the specific code,

  • and if that code is equal to escape, or whatever,

  • you can decide to quit the game, or you know, do

  • some sort of movement of the-- to change some value of your data structure

  • to actually make the game playable.

  • And also, thanks Putevoditell for the host, much appreciated.

  • RODRIGO DABOIN SANCHEZ: So now we can basically just

  • get rid of some of the stuff that they were doing.

  • And then I don't know, here we can--

  • we want to do something I guess.

  • So we can print, hello for now, just as a placeholder.

  • And what we want, is whenever the user presses the Escape key, that seems

  • reasonable to want to stop the program.

  • So we can also-- we'll probably want to be listening,

  • if we look at the board, we imagine the empty space

  • as kind of what we're going to control moving around.

  • Let's say that we want the behavior where if we press the Left key

  • the empty space swaps with the number to its left.

  • So here we would swap with 15.

  • And then if we press Up, it goes to 12, and so on and so forth.

  • So we haven't actually implemented moves in the board yet,

  • but what we can do for now to make sure that this is working,

  • is just print like left, or print up, and right to make sure

  • that we have something working.

  • So--

  • COLTON OGDEN: Sanity checking.

  • RODRIGO DABOIN SANCHEZ: Right.

  • Sanity checking.

  • So right now I'm going to say, if keyboard. key up is pressed,

  • I'm just going to print, up.

  • And then even though, you know, ideally you're not supposed to copy and paste

  • code, sometimes you just gotta.

  • COLTON OGDEN: Who suggested that up above, I forgot who that was.

  • That was, oh, that was TheKek, TheLastKek, who

  • did that, which is funny.

  • RODRIGO DABOIN SANCHEZ: And here we go.

  • So in theory now, if we press up, right, down, or left,

  • the program will tell us what key we've pressed.

  • And then, later on, we'll replace this with actual behavior

  • of moving in the board.

  • And--

  • COLTON OGDEN: It is an important step.

  • Make sure that you're actually checking for the right things.

  • And that it's triggering that--

  • sort of like penciling in your application.

  • Like filling in, like that, your sketch with the actual color,

  • or the actual paint, or however you want to analogize it.

  • But we do that even when we program games to prevent stream.

  • Like a typing game, we did that.

  • We put all the labels and all the text everywhere with like mock data.

  • And this is something like people in web development do a lot too.

  • They'll make a static-- if they're like trying to make a dynamic web page,

  • they'll put everything that's static, that would represent what

  • the website would look like ultimately.

  • And then actually flesh it out with the JavaScript, or the Ajax,

  • or whatever that they would normally do to make it actually truly dynamic,

  • or whatever.

  • RODRIGO DABOIN SANCHEZ: Did I miss anything in the chat or anything?

  • COLTON OGDEN: No.

  • No.

  • No.

  • No.

  • RODRIGO DABOIN SANCHEZ: OK.

  • Yeah.

  • So, so far we have what we were talking about before,

  • the annoying echo that we're going to have to get rid of.

  • But we see now, that when I was pressing the up key, it was printing up.

  • When I was printing left, it was printing left.

  • Down is pressing down.

  • [BELL DINGING]

  • Right it was printing right.

  • COLTON OGDEN: Sorry, if that was loud.

  • I forgot to mute my phone.

  • RODRIGO DABOIN SANCHEZ: For now, let's go back to the board.

  • And we will probably want to implement.

  • So we have a listener for key keystrokes,

  • now we want a function in the board that will allow us to make moves.

  • So we kind of alluded to this earlier how we want to create moves.

  • If we're taking a look at the board, if I press the left,

  • I'm going to want to swap with the element to my left.

  • If I press up, I'm going to want to swap with the element above me,

  • and so on and so forth.

  • The only tricky thing is, even though this looks like a square

  • this isn't necessarily a square memory.

  • This is, if we recall, and we'd find this, this is a list of lists.

  • So we will have to be careful with what indices we're adding and subtracting

  • when we do this.

  • But I propose that we start--

  • it's going to be very repetitive if we have very similar behavior for making

  • a move to the left, very similar behavior for making move up,

  • and the only thing that's changing is, you

  • know, whether you're adding to the column,

  • or you're adding to the row index.

  • So what I propose is having just a general function

  • for making a move where we're going to have some place

  • holder variables, x and y.

  • So let's do that.

  • Let's create a move function.

  • It's going to have to take in itself again.

  • Ideally-- we could do this in two ways.

  • We could have it refer to self.board every time,

  • but later on, if we want to make a kind of like artificial intelligence

  • solve function, that solves itself, that's

  • going to be annoying because we're going to have

  • to search different possibilities.

  • And so if we start off with an initial composition of the board,

  • we're going to want to basically make four copies of it

  • because we can move up, right, down, left.

  • And if the move function is always referring to self.board--

  • like if we move up, then it'll update self.board for everything.

  • So I propose that we allow a parameter in the move function

  • where we can just pass in whichever board we want to make the move on.

  • And then in the main .py file, we can just pass in the objects board for now.

  • OK.

  • So we'll also want to keep track of the location of the empty space.

  • And then since we know that the way we're

  • going to swap elements in our list of lists

  • is by adding and subtracting to the indices of the list,

  • we'll want to pass in like an x and a y, like you were saying.

  • This seems like it should be comprehensive.

  • And if we want to just test out, you know, how does swapping work in Python?

  • If I open up the interpreter again, and I have--

  • usually what you would imagine is you would have something

  • like, you know, x = 1, and then y = 2.

  • And then, if you want to swap x to be y, you

  • would have to have some sort of temp variable, maybe set to 0.

  • And have something like, temp = x and then let's see--

  • COLTON OGDEN: x = y, y = x.

  • RODRIGO DABOIN SANCHEZ: x = y.

  • COLTON OGDEN: y = temp, sorry. x = y, then y = temp.

  • RODRIGO DABOIN SANCHEZ: And now y = temp.

  • And so what this would do, is now if I see what x is, x has 2, y has 1.

  • But in Python, we actually don't need this middleman.

  • Because we can do something as simple as this--

  • if I have x = 1, and y = 2, we can have something like x,y = y,x.

  • Which is very, very nice.

  • COLTON OGDEN: Yeah in Lua2, which is super cool.

  • RODRIGO DABOIN SANCHEZ: In Lua as well?

  • COLTON OGDEN: Yeah.

  • RODRIGO DABOIN SANCHEZ: So yeah, now we have x having the previous value of y,

  • and y having the previous value of x.

  • So that's just how swapping works in Python, for those who didn't know.

  • That's going to be something that we'll probably want to do here.

  • And let's just go ahead and jump into it.

  • So we know that we're going to be accessing

  • a board that's a list of lists.

  • So we want board@--

  • and when we move--

  • let's go back here.

  • When we move this tile we're starting off at the position--

  • the empty position that we have at which we're passing in here.

  • So let's say-- and the way that we define the empty position

  • is, by default, the board is going to be at 3, 3,

  • this won't matter when we shuffle it.

  • But we were going to have the location of the empty space tract

  • with this variable, so we're going to have--

  • on the x, it's going to tell us what index in the row it is.

  • So like, this is row 0, row 1, row 2, row 3.

  • And the y component it's going to have what index in the columns it is.

  • So this is 0, 1, 2, 3.

  • So we're going to want to refer to the location at position 0 for the x.

  • And then the empty location at position 1 for the y.

  • All right.

  • And this is going to be the empty slot.

  • So this is basically like our first thing.

  • Then the next thing that we want to swap,

  • is either the tile above it, to the left, to the right, or below it.

  • So since we want this to be a general move function where later we'll

  • have something like def move up, and then def move right, and def move down,

  • and def move left, where all these essentially just call the move

  • function with some parameter, some xy.

  • What we want to do, is if we're adding--

  • if we're moving up, we will want to add--

  • or no, we will want to subtract 1 from the rope position.

  • And if we want to move to the left or y, we'll

  • want to subtract or add to the y position.

  • So we can do this--

  • we can do all this logic of whether it's supposed to be minus or plus

  • and which one is supposed to be, in these abstracted out methods,

  • such that in the-- so move up would look something

  • like what we would pass in the board and the e_loc.

  • And then we would pass in something like--

  • if we're moving -1,0 something like this.

  • So here in the actual move function, we would only

  • have to worry about adding x and y, whatever they may be, to the index.

  • So this is going to look something like e_loc 0+X.

  • X could be negative or positive.

  • And then e_loc at position 1 + y.

  • All right.

  • Now we're running out of space.

  • So this backslash in Python, let's us kind of move on to the next line

  • without having to worry about the end of a thought.

  • OK.

  • So here, essentially, we have on the left hand

  • side of the swap, the position of the board that contains the empty space.

  • On the right hand side, we have the position

  • of the board that is, you know, some relative distance

  • from the empty space based on whatever we input to be x and y.

  • So if in like this move up example, we're putting in -1 for x, and 0 for y,

  • that means that moving up this right hand side

  • will be the empty location -1 at the same y.

  • Which if we look at this--

  • if this is empty location 3, 3--

  • empty location -1 will be, and the x component will be 2, so it's a 0, 1, 2.

  • And then, it's same y component.

  • So that'll be the same.

  • That'll be the 12.

  • So yeah.

  • That looks like we have about right.

  • And so now what we essentially want to do, like we did x,y = y,x.

  • Is swap this.

  • COLTON OGDEN: Reverse them.

  • RODRIGO DABOIN SANCHEZ: Reverse the order.

  • COLTON OGDEN: Virani was was saying, "I just learned

  • how to construct dynamic web pages with Express and EJS templates,"

  • That's awesome.

  • We'll probably actually have a stream on that in the near future

  • after we get past the CSS, JavaScript, Bootstrap, jQuery, all that fun stuff.

  • We'll probably go into Node.js, and therefore Express.

  • Bhavik_Knight, in reference to your temp swap example,

  • with saying the temp = 0 line was actually redundant. in way I think.

  • Yeah, because you could just do temp = y or whatever.

  • But I think you were just trying to illustrate that like temp--

  • I guess maybe in reference to other languages

  • where it would have a temp variable, I can see you would usually send it

  • to something by default. And then he was asking,

  • "can we do nested class within the board?

  • Like a class move with up, down, right, left, that inherits from move?"

  • RODRIGO DABOIN SANCHEZ: I don't remember if you would put it inside.

  • I know you can definitely do inheritance.

  • But I don't recall having seen an example of a class written

  • within a class like that.

  • COLTON OGDEN: I think you can.

  • It's been a while since I've actually needed to do that in Python.

  • I don't think I would do it in this example though.

  • I don't think abstracting the idea of a move really saves as much.

  • RODRIGO DABOIN SANCHEZ: OK.

  • So far so good.

  • And then what we did here was we update the position of the empty location.

  • Because if we just swapped it-- so let's pretend this is what we're swapping.

  • We swap position 3, 3 with position 2, 3 If we move up,

  • we want the location of the empty space to be updated as well.

  • We don't want to refer to 12 as the empty location now.

  • So we're also adding to the-- and this is kind of syntax

  • for like updating something.

  • So like if I opened up the terminal again, Python, and then I have x = 1,

  • I could do something like x = x + 1 to get 2.

  • But I could also do x + = 1 to add 1 and update it.

  • So now it's 3.

  • So this + = essentially means add, you know, whatever it is to it,

  • and then update the value.

  • So what I'm doing here now is making sure I also update

  • the position of the empty space with the x and the y.

  • The only other thing that comes to mind-- and then,

  • of course, I'm returning the updated board and the updated location.

  • The only thing that comes to mind, is if we look at this example

  • again, where we're in this configuration, even though it's solved,

  • we could imagine that the users in a corner.

  • So like the empty location is in a corner.

  • And then, say, it's at the bottom right corner,

  • the user tries to move it to the right, or down,

  • and those locations don't exist.

  • So--

  • COLTON OGDEN: We, had that [INAUDIBLE] yesterday with Minesweeper too.

  • When we were doing the pre-calculation for all of the nodes.

  • RODRIGO DABOIN SANCHEZ: It would be an easy thing to miss out.

  • Like to just forget to code it.

  • And then, you know, something breaks.

  • So before we actually do the swapping we should probably check.

  • So yeah, swap update, empty location.

  • And then up here we're going to check legality.

  • You know hashes are how you comment in Python.

  • So the way we can do this is if the empty locations, the x component

  • plus x, because x could be positive or negative.

  • So if this is less than 0, or if, but whoops,

  • you don't have to write, if, twice.

  • If the empty locations, x component plus x,

  • is greater than 3, because 0, 1, 2, 3, that it's the 4,

  • so if it's greater than 3, or if we have something similar for the y component

  • plus the y is less than zero, or it's less or greater than 3 + y.

  • COLTON OGDEN: It's arguable that like a namedtuple might have

  • been appropriate for the location too.

  • So instead of having to index and a 0, you could just do like .x, .y.

  • RODRIGO DABOIN SANCHEZ: True.

  • Yeah.

  • We haven't really used it much yet so you may as well go ahead and do that.

  • We can have this be like--

  • or even a dictionary right?

  • COLTON OGDEN: Yeah.

  • A dictionary would work too.

  • RODRIGO DABOIN SANCHEZ: Be like row.

  • And then this could be column.

  • And then here--

  • COLTON OGDEN: So maybe just replace every 0 with, row, or column.

  • RODRIGO DABOIN SANCHEZ: Ans this will be easier if I just--

  • yeah, this semantically, is probably easier to read as well.

  • COLTON OGDEN: I would've probably done the namedtuple with .x.

  • and you could do .row as well.

  • Just to save like readability.

  • Just because it gets a little bit cluttered here with all these brackets,

  • square brackets.

  • I would've probably just made an empty location and namedtuple.

  • And I have to remember the exact syntax for it.

  • Because I don't find occasion to do it a lot.

  • But there is a--

  • I don't actually remember if they made it a native 3.7 or 2.6,

  • just like part of the core language.

  • Because normally you have to--

  • here it is, namedtuple.

  • So you make a namedtuple, call it, in this case,

  • you could just call it whatever you want.

  • Which takes in and has an x and y, like that.

  • And then from every--

  • every time you want to do that afterwards,

  • you can just say like right here, see how this is p.x and p.y and you would

  • have the same-- that would be e_loc and then e_loc.x and e_loc.y.

  • It might be a little bit too much at this point

  • to go back and retroactively do all that.

  • Especially if you're like--

  • you've mentally already constructed it with the 0,1 index model.

  • But it's a nice thing that they've recently started.

  • It's recently started becoming pretty trendy with Python.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • I can see how that would be pretty nice.

  • Yeah.

  • So we could--

  • COLTON OGDEN: You can revert, if you want, back to the old 0, 1,

  • if that's easier.

  • RODRIGO DABOIN SANCHEZ: I could see the semantic value of doing it this way,

  • but I mean, you know, if we're--

  • COLTON OGDEN: I wouldn't blame you for- I wouldn't blame you.

  • It's kind of like a brand new like, wrench to kind of throw into it.

  • So if you want to--

  • if you want to keep it as it was totally fine.

  • RODRIGO DABOIN SANCHEZ: But I mean-- so here we are again.

  • Wait, I mean, the first location-- so the 0 is referring to the rows,

  • and the 1 is location to the columns.

  • OK.

  • So we're back where we started.

  • And here we have the position of the board,

  • of the empty location here where we're swapping to.

  • And then we're changing the position.

  • We're updating the position of the empty location.

  • We're returning the updated board in the updated, empty location.

  • Here we're checking if the move is legal.

  • So if basically we've checked if adding x or y--

  • x or y to the x and y components of the empty location

  • exceeds, or like goes through an index that doesn't exist.

  • We don't want to do anything.

  • So maybe we just returned the board and the location as it is.

  • COLTON OGDEN: "Guys, are you planning on about explaining

  • advanced concepts in Python, and things like decorators,

  • comprehensions, generators, in one of your future streams?

  • You guys have a great teaching skill."

  • First of all, thank you very much for the compliment.

  • We would definitely like to do a more advanced Python streams.

  • Veronica is, per what Bhavik_Knight said,

  • doing a stream in the near future on and more--

  • well, the stream is called, "A Hundred Cool Things in Python, Part 2".

  • We already did in Part 1, where we covered

  • about 40 different small things.

  • We'll probably do that again with a future stream.

  • No concrete plans on all of those necessarily,

  • but doing a more structured advanced Python stream

  • would be pretty fun and pretty cool.

  • So we'll little different take a look at doing that.

  • So thanks for the suggestion.

  • RODRIGO DABOIN SANCHEZ: Now that we have this general move function,

  • I'm trying to go ahead and update these to look how they should.

  • So if we know the move function is returning

  • the updated board and location, we'll also

  • want to return whatever this returns.

  • And now we'll have to change the x's and y's for this each time.

  • OK.

  • So moving up, that's subtracting 1 from the row.

  • Moving to the right is leaving the row alone, adding 1 to the column.

  • Moving down is adding 1 to the row, leaving the column alone.

  • And then moving left is leaving the row alone, and subtracting 1

  • from the column.

  • So in theory we should have a working way of moving here.

  • OK?

  • So now that we have this, we can probably update in the main .py file.

  • What happens when we release the key?

  • The only other thing, though, is that even if we override this behavior

  • to actually make the moves, we are only ever printing the board

  • at the beginning of the main function.

  • So we wouldn't actually see anything change.

  • So we might want to write a function for the board that just kind of like

  • refreshes the terminal screen and re-displays it.

  • Something like def refresh.

  • And for this, actually, if we remember what this--

  • what the terminal looks like when we were

  • writing the left key, the down key, the up key, it would give us a little echo.

  • So if we actually import up here from OS--

  • let's import system.

  • So that we can clear the terminal screen programmatically.

  • That way we get rid of whatever it was previously.

  • And we can just see the latest version of what we have.

  • We can have in the refresh method that we're going to write,

  • we can have the board class programmatically clear the terminal

  • screen so that in the un-press, instead of printing hello,

  • every time that we press anything--

  • whoops.

  • Let's put this here just for my sake.

  • Any time that we press the key, we will call the refresh method,

  • so that it will clear the terminal, get rid of any

  • echo that the terminal is going to display for us.

  • And then here, after whatever we do, we're

  • also going to call the refresh method so that after we press up, or down,

  • or right, or left, it will re-display.

  • So what this will do, is it will clear the screen,

  • and then we'll want it to display the board itself.

  • So we already have a function that prints the board,

  • so we can just print self.

  • All right.

  • And maybe what we can do since--

  • yeah.

  • This is probably sufficient.

  • So here we have, after we release a key, we're clearing the screen,

  • printing the board.

  • Whenever we press a key, we're clearing the screen, printing the board.

  • I guess we don't need to listen to, print this here,

  • but we'll leave it for now.

  • All right.

  • And now the only thing that's missing is actually writing the moves to the keys.

  • OK.

  • All right.

  • So here, what we'll want to do, is we have--

  • we'll want to-- if we take a look at what our move function does,

  • is it returns the board and the location.

  • So what we want to do is call--

  • and so it does this return the board and location.

  • So we'll want to say b.board, b.--

  • and it's actually kind of confusing because I named this, empty location.

  • So let's just have this be the same name so I don't get confused.

  • OK.

  • So b.e_loc, this is going to take the value of calling b.move up.

  • And it's going to take in the board, the empty location,

  • and I think that's all that it needs.

  • Yeah.

  • Because we took care of the rest.

  • All right.

  • Just for incremental testing, let's see what happens when I run this.

  • All right.

  • And e_loc is not--

  • COLTON OGDEN: And crash.

  • RODRIGO DABOIN SANCHEZ: --defined.

  • Ha ha!

  • Perfect.

  • Where do we have e_loc not being defined?

  • Oh!

  • Where is-- here.

  • I named this just Loc instead of e_loc.

  • So I'm trying to use a parameter that doesn't exist.

  • All right.

  • COLTON OGDEN: That will mess you right up.

  • RODRIGO DABOIN SANCHEZ: Now, we actually have the parameters named properly.

  • And here, I actually specify the right names, I believe.

  • OK.

  • Let's try this again.

  • All right.

  • So we notice when I press Enter, the whole screen was cleared

  • and now we just have the board.

  • So it's the foc--

  • the center of attention.

  • OK.

  • There we go.

  • So we pressed Up key, and we have been able to move.

  • COLTON OGDEN: Nice.

  • RODRIGO DABOIN SANCHEZ: I'll press Escape

  • to quit so that we can finish implementing

  • this in the other directions as well.

  • All right.

  • COLTON OGDEN: It's nice CLI interface, all

  • things considered too, rather than having

  • like, you press a key to say I want to move up, and it has a menu or whatever,

  • and then it like reprints the board below that, refreshing the CLI.

  • RODRIGO DABOIN SANCHEZ: I think the way that the old Pset and CS50 used to be,

  • was that it would prompt you.

  • Do you want to move up, left, down, and right, and then you would type it.

  • And then it would reprint the board below that.

  • COLTON OGDEN: Yeah, exactly.

  • RODRIGO DABOIN SANCHEZ: It was kind of annoying.

  • COLTON OGDEN: A little more of a traditional way of doing it,

  • I think, but also easier to understand.

  • Because you don't have to go through like,

  • you know, refreshing in the terminal, doing asynchronous

  • input, that sort of thing.

  • Right?

  • RODRIGO DABOIN SANCHEZ: We can actually take a look

  • at what it looks like if we don't refresh on key press.

  • So if I, you know, if I just don't include this, I think,

  • pass keyword makes it do something?

  • COLTON OGDEN: Pass keyword will do nothing.

  • Correct.

  • RODRIGO DABOIN SANCHEZ: And so up is up, right is right, down is down,

  • left is left.

  • OK.

  • So if I don't refresh the terminal, we get something like this--

  • COLTON OGDEN: Oh.

  • OK

  • RODRIGO DABOIN SANCHEZ: Where every time that I

  • press a key, you see like down is b, up is a, left is d, and then right

  • is c, for some reason.

  • So the terminal is always printing this if I

  • don't clear the screen on key press.

  • So that's why I wanted to just preemptively do

  • that so we could avoid that.

  • And also, obviously, if I don't clear the screen here--

  • so actually let's just do this.

  • Let's get rid of this comment now.

  • And if, within the refresh method itself, I don't clear the screen

  • and we run it--

  • COLTON OGDEN: Wasn't this easier in the Game of Fifteen,

  • asking for which number you wish to move?

  • There's only one empty field on the board.

  • RODRIGO DABOIN SANCHEZ: That's true.

  • COLTON OGDEN: There's no ambiguity.

  • RODRIGO DABOIN SANCHEZ: That's what it was, which number did you want to move?

  • And so the way this one is going to work,

  • is you just press with the arrow keys.

  • You move the--

  • COLTON OGDEN: I like that because it's nice.

  • You don't have to think too much about--

  • RODRIGO DABOIN SANCHEZ: And you can do it more quickly as well.

  • COLTON OGDEN: Yeah.

  • Much more quickly.

  • RODRIGO DABOIN SANCHEZ: And here, we're not refreshing.

  • They're like, we're not clearing the terminal.

  • So we get all this junk.

  • Right?

  • So that's kind of a headache.

  • So that's why we want to go ahead and clear this anytime that we

  • press a key so that we don't have to see, oh, which key did they press?

  • And also, what did the previous board look like, or whatever?

  • OK.

  • So, so far so good.

  • And just, you know, just to confirm that we have the behavior that we wanted to.

  • Oh, you know what?

  • I don't like that.

  • I don't like how when you run the program--

  • py main.

  • You have that kind of like visual thing where

  • it like the prompt was there, and then the board, and then it was gone.

  • So at the beginning of the main method, let's just go ahead

  • and instead of printing b, let's just call it b.refresh.

  • COLTON OGDEN: Nice.

  • OK.

  • RODRIGO DABOIN SANCHEZ: OK.

  • So now as soon as we run the program it'll clear everything.

  • OK.

  • That looks better.

  • COLTON OGDEN: That looks better, yeah.

  • That looks nice.

  • RODRIGO DABOIN SANCHEZ: We should probably

  • have something like, I don't know, it just seems kind of lonely.

  • Let's say something like, print, welcome to the game of fifteen.

  • And maybe that'll look a little more friendly.

  • OK.

  • COLTON OGDEN: Cool.

  • RODRIGO DABOIN SANCHEZ: We should probably put a space in between.

  • COLTON OGDEN: Yeah.

  • Probably.

  • But it's nice.

  • Nice little touch.

  • If you were really pro, you would have like game of fifteen,

  • and like big ASCII art.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • COLTON OGDEN: You could get like-- you can get--

  • I think there's websites where you can copy and paste

  • ASCII art if you like type it in, they'll

  • give you a text string you can copy.

  • That'd be pretty cool.

  • RODRIGO DABOIN SANCHEZ: So we essentially

  • have a workable version right now.

  • If I'm at the left most corner and I keep pressing left and nothing's

  • happening, if I'm at the right most corner

  • and I keep pressing right nothing's happening, same if I'm down

  • and I'm pressing down, nothing's breaking.

  • COLTON OGDEN: Nice.

  • RODRIGO DABOIN SANCHEZ: And if I'm up--

  • OK.

  • So--

  • COLTON OGDEN: Is the boundary locked?

  • RODRIGO DABOIN SANCHEZ: So far so good.

  • We're locked into our board.

  • We can't move outside of it.

  • We can make moves.

  • So nice.

  • We have basic board function to make moves.

  • You know what I didn't write in the things that we need?

  • We need a way to randomize the board.

  • COLTON OGDEN: There we go.

  • Yeah.

  • Because then they're going to start off every game and it's going to be solved.

  • RODRIGO DABOIN SANCHEZ: It's already solved.

  • Yeah.

  • OK.

  • So that seems like a good candidate for another board function, or board

  • method.

  • You know, functions and methods are essentially the same,

  • except methods are functions inside of class.

  • I think that's the distinction.

  • COLTON OGDEN: Yep.

  • RODRIGO DABOIN SANCHEZ: So what I alluded to at the beginning,

  • is a way that we want to randomize the board such

  • that it's solvable is, we want it to start from a solid configuration

  • and then make n number of moves to randomize it.

  • So let's make another pseudo constant here

  • and call it like, shuffle magnitude or something.

  • And just to keep it simple so that, you know, I can at least still

  • solve the game without having to play for a considerable number of times,

  • let's just self shuffle it like, I don't know, ten numbers.

  • COLTON OGDEN: One time.

  • RODRIGO DABOIN SANCHEZ: Yeah, we have a 50% chance

  • of starting in a winning move because it can be to the right or down.

  • COLTON OGDEN: Well yeah.

  • You could do boundary constraints on your shuffles

  • such that it wouldn't consider it a shuffle if it tries to move--

  • RODRIGO DABOIN SANCHEZ: True.

  • COLTON OGDEN: --outside of the bounds.

  • But--

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • COLTON OGDEN: For the sake of simplicity.

  • RODRIGO DABOIN SANCHEZ: I mean, if we just make it, you know,

  • if we make the magnitude large enough that I

  • don't think it will really matter.

  • COLTON OGDEN: Choose down 100 in a row.

  • RODRIGO DABOIN SANCHEZ: What are the odds, right?

  • OK.

  • So we have the constructor, the printing, let's just--

  • I don't like how it's all blue.

  • I'm kind of like weird about some things.

  • Clear the screen and print the board.

  • There, now there's a nice little separator.

  • See, now I'm thinking about it.

  • Now I've got to do it for all of them.

  • You know?

  • Represent the board.

  • And then here--

  • COLTON OGDEN: There are some streamings where

  • I don't even comment my code because I just completely forget to do so.

  • I try to be better about it.

  • But-- "Just get a linter to remind you of that," says MKloppenburg.

  • Yeah.

  • It's a good point.

  • RODRIGO DABOIN SANCHEZ: Checks.

  • Let's just say, makes legal move.

  • COLTON OGDEN: The linters that are integrated into the text editors too--

  • I can get one for--

  • I think you could definitely get one for Atom and VS Code.

  • It'll actually show you on the left side of the screen, in your file here,

  • if you have issues.

  • You can do like pep8 linters.

  • And you can also do like syntax linters and things like that.

  • It's pretty cool.

  • RODRIGO DABOIN SANCHEZ: OK.

  • So we want this shuffle function method that randomizes

  • board using succession of legal moves.

  • So that way, we know for sure that it's going to be solvable.

  • All right.

  • We'll probably need the random library, I guess.

  • Yeah.

  • So let's go ahead and import that.

  • What's it like from a,b,c, d,e f,g,h,i,j--

  • COLTON OGDEN: I think you just import random.

  • RODRIGO DABOIN SANCHEZ: No.

  • I like having them alphabetized.

  • Right?

  • Wait.

  • Harvard student doesn't know the order of the alphabet.

  • Does r come before or after o?

  • COLTON OGDEN: Comes after o.

  • RODRIGO DABOIN SANCHEZ: Ah-ha.

  • See?

  • We're just human.

  • From random import, random.

  • COLTON OGDEN: I would say because English is your second language.

  • RODRIGO DABOIN SANCHEZ: That's true.

  • COLTON OGDEN: I'll give you a pass.

  • But Spanish uses the same alphabet, don't they?

  • Same order?

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • But it has some different letters.

  • COLTON OGDEN: So you don't get an excuse.

  • RODRIGO DABOIN SANCHEZ: It's a total different thing, you know?

  • COLTON OGDEN: Kind of.

  • Maybe.

  • I'll give you that one.

  • I'll give you that one.

  • RODRIGO DABOIN SANCHEZ: So, from the random library,

  • there's a function called randint, that gives you a random integer.

  • And I think we talked about this in your stream

  • yesterday also, that you should generally seed your random number

  • generator so that you keep getting different results each time

  • that you run it.

  • COLTON OGDEN: Which you want to test specific corner cases, but yes.

  • RODRIGO DABOIN SANCHEZ: True.

  • Good point.

  • OK.

  • So I think, now if we go back to our shuffle--

  • COLTON OGDEN: R.B was asking, "In Ruby, the convention

  • is that you write code such that you don't need to comment.

  • Is there something like this in Python?

  • As far as it goes, writing a lot of comments in Ruby is bad practice."

  • RODRIGO DABOIN SANCHEZ: What?

  • COLTON OGDEN: It's a bit strange.

  • I mean, I'm not too involved in the Ruby ecosystem.

  • What I imagine they're probably referring to,

  • is writing self documenting code, in the sense that your variables are clear.

  • RODRIGO DABOIN SANCHEZ: Oh, yeah, So like I mean--

  • COLTON OGDEN: Function names are clear.

  • RODRIGO DABOIN SANCHEZ: We couldn't name these anything.

  • Right?

  • We can name this like self.tomoato and self.pear.

  • And, you know, it would've worked as long as he kept track of it.

  • Can you tell him hungry?

  • No I'm just kidding.

  • COLTON OGDEN: We just had some awesome curry katsu-- katsu

  • curry, which is pretty good.

  • Yeah, I think, I mean, I wouldn't go so far as to say

  • don't comment your code at all in Ruby.

  • I feel like that's kind of a silly convention.

  • Especially if you're writing in algorithm

  • that's of moderate complexity.

  • I don't think any amount of self documenting code

  • is going to make everything 100% clear.

  • Like, if you're doing, I don't know, like, recursive maze generation

  • algorithm or something in Ruby, I don't think

  • there's any amount of variable naming and convention

  • that's going to save a programmer from knowing exactly what's going on,

  • not knowing exactly what's going on.

  • So I would say don't worry too much about that.

  • In Python, definitely use comments when they make sense.

  • And I think this should apply to most programming languages.

  • And I have to look into Ruby and see why they're

  • saying that because I don't know the ins and outs of the language

  • quite as much as I know Python's as a language,

  • but my instinct is that they're referring to variable names and some

  • of their syntax that sort of makes it clear whether something

  • is a Boolean expression, or a Boolean function.

  • Like the question mark that you can use for function names and stuff like that.

  • But, yeah, I would say use comments but make your variables and functions

  • and lay out of your code sort of obvious what's going on.

  • As much as you can.

  • Right?

  • RODRIGO DABOIN SANCHEZ: Bhavik is asking, "Magnitude of 100

  • won't necessarily mean that we have to do 100 moves to solve the game, right?"

  • So yeah.

  • That's-- I mean you're completely right.

  • The magnitude that I'm referring to, is like how many

  • moves are we going to make before we present the board to the user

  • so that, you know, it's at least not in the solved configuration.

  • COLTON OGDEN: It could theoretically be 0.

  • Because it could theoretically shuffle it,

  • and then, shuffle it all back there and back to the beginning.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • COLTON OGDEN: It's not-- yeah.

  • It's--

  • RODRIGO DABOIN SANCHEZ: Like, I mean, in a shuffle magnitude of 10,

  • it's not that crazy to think that they'll move,

  • you know, up and then left.

  • But then they'll move down and right.

  • And then move up and then back down.

  • And that by the end of the 10 moves they'll

  • end up right exactly where you started.

  • COLTON OGDEN: I don't know how you would compute

  • like, just how many moves it would take from that starting point,

  • that 100 magnitude.

  • Because I can visualize, like, the algorithm kind of going back and forth.

  • And I can imagine there's multiple ways, probably,

  • to move the things to get it back in the same position

  • if it's like, kind of making moves in the same area.

  • I don't know 100%.

  • But I would imagine that that's probably--

  • it probably doesn't map anywhere close.

  • "Self documenting code is code without comments," I wrote--

  • code without comment-- wait.

  • "Self documenting code equals code without comments."

  • I wrote, "nasty spaghetti code equals code without comments."

  • Someone else wrote, "True, true."

  • "Mathematically the game must maintain its invariant to be solvable."

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • That's why we don't want to just randomize the whole list of lists.

  • Because then we might end up with a configuration that can't actually

  • be solved.

  • COLTON OGDEN: Yeah.

  • That's true.

  • RODRIGO DABOIN SANCHEZ: OK.

  • So what I was doing initially in the shuffle method,

  • is first I seeded the random integer generator.

  • And then I thought to myself something along the lines of,

  • OK, for 0, till however magnitude is, I probably

  • want to pick a number between 0 and 3, or 1 and 4,

  • and have that map to one of these functions.

  • Right?

  • So like maybe getting 0 means you move up.

  • Getting 1 means you move right, 2 move down, 3 move left.

  • Then I realized I probably needed some data structure to do that.

  • So I'm going up here and I'm creating a data structure that does exactly that.

  • So the nice thing about dictionaries in Python

  • is that the keys can be anything.

  • That can be like strings or ands or whatever, what have you.

  • So I'm going to have a dictionary called moves,

  • which is going to be like a dictionary of legal moves that I can make.

  • And so if the key is 0, I'm going to have it be self.move up.

  • I don't want to include the parentheses because I

  • don't want it to actually execute.

  • I just want to kind of delay that.

  • COLTON OGDEN: Using function pointers, basically.

  • RODRIGO DABOIN SANCHEZ: Basically, yeah.

  • And then I'm going to have 1.2.

  • And if you're curious about why a mapping like random numbers to this,

  • it's like I think of up, right, down, and left, it's kind of like north,

  • east, south, and west.

  • And so, just in my mental compass, I start up here and then kind

  • of move clockwise.

  • That's why I'm going up, right, down, left, 0, 1, 2, 3.

  • COLTON OGDEN: I go up, down, left, right.

  • RODRIGO DABOIN SANCHEZ: You go up, down, left, right.

  • COLTON OGDEN: Yeah.

  • I think it's because up, down go together,

  • and then left, right go together.

  • And so I just see them--

  • RODRIGO DABOIN SANCHEZ: That's valid.

  • COLTON OGDEN: --sequentially.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • For me it makes sense to go in the cyclical way.

  • COLTON OGDEN: I can I can visualize that too.

  • RODRIGO DABOIN SANCHEZ: Oh, I forgot to refer to the fact this is--

  • COLTON OGDEN: Rabine, I might take a look at that style guide at some point,

  • and then maybe we'll do a Ruby stream in the future too.

  • RODRIGO DABOIN SANCHEZ: Sefl.move down and then 3

  • is going to refer to self.move left.

  • I cheated.

  • OK.

  • All right.

  • So that seems reasonable.

  • 0 self, move up, 1, move right, 2 move down, 3 move left.

  • OK.

  • So now in the shuffle method, I've seeded the generator.

  • I am going from 0 to whatever magnitude I wish.

  • And then choosing a random ends between 0 and 3.

  • And now I'm going to have it do something like--

  • let's see, self.moves--

  • COLTON OGDEN: Add 0 to 3, inclusive?

  • RODRIGO DABOIN SANCHEZ: Yes.

  • Self.moves at i, and now I want to actually execute it.

  • Remember that move up, move right, at all, take in the board and the location

  • that we're going to update.

  • So I'll have to pass in self.board here, and self.e_loc.

  • That's what I named it, right?

  • Yes.

  • OK.

  • COLTON OGDEN: I agree with Andre saying, "Comments aren't necessarily

  • aimed at explaining what code is, but why it's doing it."

  • Yeah.

  • And I agree that no amount of self documenting code can help with that.

  • Like I said, you have to understand what's

  • going on in the programmer's mind and there are

  • algorithmic sort of map mental mapping.

  • Right?

  • Like that could-- you could conceive of a problem abstractly

  • in a way that's not even representative of any programming language construct,

  • but you have to use the programming language to sort of create that.

  • Like creating a data structure, using that data structure,

  • in a particular way.

  • Visualizing a problem in a particular way.

  • The what versus the y, that's essentially it.

  • Yeah.

  • RODRIGO DABOIN SANCHEZ: All I've done now

  • is I've just made sure that the first thing I do is shuffle the board.

  • So when we actually rerun this now, I have a key error, which is great.

  • Not intended.

  • So in line 48 and shuffle, key error.

  • Oh, LOL.

  • I did not mean to do i, I meant to do m.

  • So what I was doing is I was essentially indexing into moves as

  • long as the loop went from 0 to whatever, and what I meant to do

  • was each time that the loop iterates, m is

  • going to take in a random value between 0 and 3.

  • And that's the position that I want index into.

  • OK.

  • All right.

  • So-- I mean, obviously, this is randomized in some way.

  • It doesn't look super random because it's only 10 moves.

  • But if I do this like 1,000 times, then that definitely looks more shuffled.

  • I don't really like that the blank space is starting kind of anywhere.

  • And like it's fine.

  • Right?

  • We know it's solvable.

  • But just like us aesthetically, I like the idea of it

  • starting in the bottom right corner area.

  • COLTON OGDEN: Sure.

  • Yeah.

  • RODRIGO DABOIN SANCHEZ: So I'm going to do something that's

  • not really necessary per say, but--

  • COLTON OGDEN: You mean, like move the underscore to the bottom right

  • no matter where it is.

  • RODRIGO DABOIN SANCHEZ: And so obviously, I

  • don't want to just swap its location with whatever supposition 3,

  • 3, because that could potentially break the solvability of the board.

  • COLTON OGDEN: Right.

  • Yeah.

  • You have to actually move it there, the same way you do it--

  • RODRIGO DABOIN SANCHEZ: Right.

  • So I'm going to just, you know, at most, if we run this again--

  • so at most, I would have to move it down 1, 2, 3 times.

  • And then let's say it started up here, I would have to move 1, 2, 3 down.

  • And then 1, 2, 3, to the right.

  • So we could just write--

  • COLTON OGDEN: Are you just going to call self.--

  • are you going to call move three times to the right, three times down.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • So for i in range, like, max number of rows,

  • I might just do self.moves down is 2.

  • Slef.moves at 2.

  • Self.board, self.e_loc.

  • And then, I'm going to do the same thing.

  • Even though it's syntactically the same thing,

  • semantically, you know, just thinking, I'm going to move the columns.

  • And right is 1, up right.

  • COLTON OGDEN: So this is of like the what versus the y, right?

  • Like this is a good example of why comment would be useful here.

  • Like you know exactly what's going on here, I mean, roughly speaking,

  • it's a little abstract.

  • But it's like, you don't maybe understand

  • the reason for why they're doing this, and so somebody in their comment

  • would be like, we want to make sure that the underscore starts

  • at the bottom right every time for aesthetic purposes.

  • Like I don't know how you're going to communicate that necessarily

  • with just pure syntax.

  • RODRIGO DABOIN SANCHEZ: Mm-hmm.

  • COLTON OGDEN: Like that's a human sort of aesthetic desire more than anything

  • else.

  • So yeah, that's to Andre's point, I think

  • that's an example, a good example as to illustrate using comments that

  • are based on the why, not the what.

  • RODRIGO DABOIN SANCHEZ: Right.

  • And even-- so I I've worked as a TF for CS50, and I had to grade code.

  • And so previously, you know, we have graded

  • on correctness, design, and style.

  • Where correctness is, does the program work?

  • Style, is like, is it formatted properly?

  • Does it contain any sort of comments at all?

  • And design, is you know, how efficiently was it written?

  • Some decisions that went into it.

  • But one of them, is like, how useful are the comments, right?

  • Because the comments could just be cluttering up the code

  • if they're meaningless.

  • And one of the things we say is, if you're writing a comment,

  • don't just restate what you can clearly read in the code itself.

  • Tell us like, what the what the decision making process was behind.

  • Like why are you doing this?

  • So I could have easily written a comment here

  • that says, you know, make three moves down, make three moves right--

  • that's just kind of restating this.

  • But what I'm doing here is, you know, I optionally, I just want to--

  • or maybe, for aesthetic purposes-- for aesthetic purposes,

  • move the empty space to a lower right corner.

  • So even though the code is legible, you might be like, uh, OK, why?

  • But the comment says, oh, this is what the person that coded this wanted.

  • COLTON OGDEN: You got to know what the programmer is thinking when they're

  • writing the application so that you can get into their frame of mind

  • and understand the problem they're trying to solve.

  • RODRIGO DABOIN SANCHEZ: So now we see that the board is shuffled

  • and we're starting in the lower left corner--

  • lower right corner.

  • Yes.

  • English isn't my first language, so.

  • COLTON OGDEN: Yeah, left and right, you know.

  • RODRIGO DABOIN SANCHEZ: OK.

  • Great.

  • And just third time-- three times is a pattern.

  • Is that the saying?

  • COLTON OGDEN: What is it?

  • RODRIGO DABOIN SANCHEZ: If you do something three times it's a pattern.

  • Or like if something happens three times.

  • COLTON OGDEN: Oh, yeah

  • RODRIGO DABOIN SANCHEZ: Like once is an accident,

  • two is a coincidence, three is a pattern.

  • Something like.

  • COLTON OGDEN: Yeah.

  • RODRIGO DABOIN SANCHEZ: I don't know actually

  • if that's the saying in Spanish, or if that's a saying in English.

  • COLTON OGDEN: Is that a saying in Spanish?

  • RODRIGO DABOIN SANCHEZ: I have no idea.

  • I don't know.

  • OK.

  • So we're making some good progress here.

  • We have managed to randomize the board.

  • So all we have left is a function to solve the game, and a game over screen.

  • Solving the game is going to be a little bit annoying, I guess.

  • So we can leave that last.

  • Unless we kind of do like a temporary, kind of

  • like, cheat, where we say, hey, def solve self.

  • All we're going to do is say, like, self.board = deep copy

  • of self.goal right?

  • Like this is kind of like a dumb way to solve it.

  • Right?

  • Right now.

  • COLTON OGDEN: Hey, solved.

  • RODRIGO DABOIN SANCHEZ: Or if we do this, oh--

  • COLTON OGDEN: It would be cool if over, if like,

  • you have a timer that just kind of like does the moves individually

  • for the solve algorithm or whatever.

  • RODRIGO DABOIN SANCHEZ: Well, what I am hoping to--

  • I think we'll have time.

  • Is I want to write--

  • so instead of having this cheap kind of like cheating solve function,

  • is replace this with Breadth-first search algorithm that will

  • search for the correct path to take.

  • And then solve the game for us.

  • I think we'll have time to do that.

  • Because all we have left is, you know, check game over screen.

  • And--

  • COLTON OGDEN: Oh, did you type a self.board with an 'ed'?

  • You know what they're saying?

  • RODRIGO DABOIN SANCHEZ: Not really.

  • COLTON OGDEN: Oh, they were saying something--

  • I think--

  • RODRIGO DABOIN SANCHEZ: Self.bored.

  • COLTON OGDEN: Wasn't sure if they had it--

  • of you had written that as a typo or something.

  • RODRIGO DABOIN SANCHEZ: I guess I can check.

  • Well, I mean, Python will tell me, right?

  • If I'm referring to a variable that doesn't exist.

  • COLTON OGDEN: If you're assigning it to something, though,

  • I wouldn't consider that a syntactical error.

  • Right?

  • RODRIGO DABOIN SANCHEZ: Let me control p.solve.

  • COLTON OGDEN: Or if you're saying something to it,

  • it would just consider that a new variable declaration.

  • RODRIGO DABOIN SANCHEZ: No.

  • I think they're trolling.

  • COLTON OGDEN: I think were trolling.

  • Thanks for the troll, BlueBooger, we appreciate it.

  • RODRIGO DABOIN SANCHEZ: OK.

  • So we are going to test now.

  • So I just arbitrarily mapped the solve function to the Shift key.

  • So now let's see if we rerun this and press Shift.

  • OK.

  • So we have solved the game.

  • COLTON OGDEN: Good job.

  • RODRIGO DABOIN SANCHEZ: All right.

  • So we probably now--

  • it'll be a lot faster to just implement game over than solve.

  • So we can do that ideally by checking whether the goal is

  • equal to the board somewhere.

  • So I'm thinking we can have it be--

  • let's see, let me refer to my notes here.

  • Something that we do pretty often is refresh.

  • So, OK, here's a thought, here's what past me thought of.

  • We can have it check--

  • since we know that the last thing in our main function,

  • right, is the keyboard listener.

  • If we want the program to end we have to return false.

  • We have to give this kind of like signal to the listener,

  • return false, like, OK, stop.

  • So what we can do is, since, what we always

  • do is refresh every time we press a key, we

  • can include in the refresh method, a check for whether the goal is

  • the same as the board.

  • And then have the refresh method return true or false.

  • Where if kind of, you know, counter-intuitively,

  • if the game is over, and like solved.

  • You return false.

  • So that the listener quits.

  • Otherwise, you return true, so that it continues.

  • So let's do that.

  • OK.

  • Let's go to refresh, here.

  • And let's have it do this--

  • after it welcomes you and clears the screen and everything--

  • here, let's just check something like, if self.goal,

  • which is the original list of lists that we created, if this is = to self.board,

  • return false.

  • So that we terminate the listener.

  • Otherwise, just return true.

  • OK.

  • Yes.

  • And here now, what we can do now, is just return refresh.

  • Or if you'd return true to this listener and it doesn't do anything--

  • so here, what we can also do is just return b.refresh.

  • Wait.

  • What am I doing here?

  • Oh, if the game is over.

  • Here, return, b.refresh.

  • Actually, I don't think I need to do this here.

  • I think this would be sufficient.

  • Right?

  • OK.

  • Let's try this out.

  • And now if I solve, OK, it's done.

  • So we might want to give it like a, congrats you won, type of thing.

  • So here we'll say if the board--

  • is kind of like more intuitive for me to ask the question the other way around.

  • I don't know why?

  • If the board is equivalent to the goal, print, Congrats!

  • You won!

  • COLTON OGDEN: Nice.

  • RODRIGO DABOIN SANCHEZ: And maybe like separate it a little bit

  • from the board.

  • Then we fire that message.

  • And here--

  • COLTON OGDEN: Then it will end.

  • Right?

  • RODRIGO DABOIN SANCHEZ: --we will say, py.mean.py if we solve it, Congrats!

  • You won!

  • Game is over.

  • COLTON OGDEN: You can test it manually too.

  • If you were like to it only do like five, or maybe let's

  • three shuffles or whatever.

  • RODRIGO DABOIN SANCHEZ: Let's bring down the shuffle magnitude to like five.

  • It's very likely that we'll have to rerun it a few times in case

  • we automatically win.

  • COLTON OGDEN: Yeah.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • Like see, we just started and won.

  • COLTON OGDEN: See, it doesn't quit there.

  • See that?

  • RODRIGO DABOIN SANCHEZ: That's interesting.

  • COLTON OGDEN: So there's a slight bug.

  • RODRIGO DABOIN SANCHEZ: But that time it did.

  • COLTON OGDEN: Oh, did you rerun it?

  • RODRIGO DABOIN SANCHEZ: Yeah, I just did.

  • This time it didn't.

  • COLTON OGDEN: I'm not sure why that's the case.

  • RODRIGO DABOIN SANCHEZ: This time it didn't as well.

  • Interesting.

  • COLTON OGDEN: Looks like most of the time--

  • are you sure you reran it?

  • RODRIGO DABOIN SANCHEZ: And look, that time I reran it, and it did quit.

  • That's so strange.

  • COLTON OGDEN: Yeah, that is a bit weird.

  • It's doing it every single time too.

  • Like you're winning every time, almost.

  • RODRIGO DABOIN SANCHEZ: Let's increase the magnitude.

  • COLTON OGDEN: Oh, are you hitting shift?

  • RODRIGO DABOIN SANCHEZ: I only--

  • no.

  • I was just--

  • Oh, was I?

  • I was hitting shift.

  • Was I?

  • No.

  • COLTON OGDEN: I don't know.

  • RODRIGO DABOIN SANCHEZ: I don't remember.

  • All right.

  • The chat will tell us.

  • COLTON OGDEN: Now you can try and solve it, right?

  • RODRIGO DABOIN SANCHEZ: It'll be funny if I can't, right?

  • COLTON OGDEN: I mean, it's not an easy game to do, right?

  • RODRIGO DABOIN SANCHEZ: Congrats!

  • You won!

  • COLTON OGDEN: OK.

  • So we know it works.

  • RODRIGO DABOIN SANCHEZ: I'm pretty sure that

  • wasn't the optimal way to solve it.

  • COLTON OGDEN: Probably not.

  • RODRIGO DABOIN SANCHEZ: OK.

  • Good.

  • So our game over screen is working.

  • Right?

  • Now we will implement a more robust solve function

  • that uses Breadth-first search.

  • So maybe people in the stream may not be familiar with Breadth-first search.

  • Maybe what we need to talk about that first.

  • Solves the game using Breadth-first algorithm.

  • Let's just pull up a tree and talk about it.

  • Binary tree.

  • Maybe it doesn't have to binary-- search tree.

  • Search tree.

  • OK.

  • COLTON OGDEN: It's a little hard to see in the chat, or in the stream.

  • RODRIGO DABOIN SANCHEZ: How's this?

  • COLTON OGDEN: Oh, that's good.

  • RODRIGO DABOIN SANCHEZ: So this is just--

  • for those who are not familiar with search algorithms, the purpose of them

  • is if you're trying--

  • in the context of maybe like AI or something--

  • if you're trying to like, for example, in our game,

  • let's say this is the state of the board,

  • and we want like an artificial intelligence to solve the game for us.

  • It's going to take this initial kind of screenshot of the game

  • and then it's going to have to search through different possibilities

  • that it could foresee if it makes certain moves.

  • So obviously, you know, the AI would have four possible moves to make here.

  • If you can move up, left, down, or right.

  • Obviously, if it moves down to right, it's not going to do anything.

  • But it won't know that until it does it and sees the new state of the game.

  • If it moves up, we'll have something like this.

  • And then this will be like a new possibility

  • and from here it can move up, left, right, down,

  • again, and so on and so forth.

  • And so in the context of a search tree we

  • can model the game as a tree, where the root, which

  • is the very first element in the tree, is the initial starting

  • point of the game.

  • And then instead of having only two directions here, maybe it

  • has four branches, one four up, down, left and right.

  • And then if it makes a move up, it's at this new state

  • of the game, where once again, it's faced with, it can move up, down,

  • left, right.

  • And so you can envision this tree with four branches each time, progressively

  • getting larger and larger.

  • And so the way that Breadth-first search works--

  • so pretend that our goal state is to 7, at some point down the line

  • it's going to get to a point where the screenshot of the board

  • is actually 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 whatever.

  • Let's pretend it's the 7.

  • The way that Breadth-first search works is first it starts, it checks the root.

  • Then if that's not the goal, it checks, you know, this node.

  • Every kind of like circle in this tree is called the node.

  • Then it check this node.

  • Then it will check this one.

  • And then if neither of these are the goals,

  • it will move on to the next level of the tree.

  • And check this, this, this, until it checks this, and then

  • finally gets here.

  • That's opposed to another algorithm called Depth-first search,

  • where it just goes all the way down one branch.

  • So like, let's say the AI says, I'm going to move up.

  • And it's going to keep, you know, going down that like, path in the game

  • without even considering what would have happened if it had

  • moved to the left as its first move.

  • Then once it reaches the conclusion, which actually might be really, really

  • long if, you know, in the original state of the game

  • all you have to do to win is move left for some reason, or move up, or down.

  • But if you move in a different direction,

  • you have to like do a bunch more moves or whatever.

  • So Depth-first search could potentially take like a really long time

  • if it goes down the wrong branch.

  • Whereas Breadth-first search is just going to be like,

  • OK, I'm going to try moving up.

  • That wasn't the win.

  • Let me try moving left.

  • That wasn't the win, and so on and so forth.

  • So we're essentially going to just be kind

  • of traversing a tree level by level as opposed to branch by branch.

  • COLTON OGDEN: To that note, Bhavik had said, "Does Breadth-first search always

  • take fewer steps than Depth-first search?"

  • RODRIGO DABOIN SANCHEZ: No.

  • Because what if the goal was--

  • COLTON OGDEN: Number one or whatever?

  • RODRIGO DABOIN SANCHEZ: Well, in this example, it would be.

  • But we can draw, right?

  • I like going to this blank slate.

  • And then, it's for typing, but I have some--

  • so like, oh, this is an old thing that I had.

  • COLTON OGDEN: Wouldn't it funny if there was like something

  • like really blasphemous?

  • RODRIGO DABOIN SANCHEZ: No.

  • I don't-- I don't condone blasphemous activity.

  • Erase all.

  • OK.

  • COLTON OGDEN: You could I was also draw.CS50.io.

  • RODRIGO DABOIN SANCHEZ: Oh, really?

  • COLTON OGDEN: Yeah.

  • Oh, but you have a touch screen too.

  • That's sick.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • COLTON OGDEN: I didn't know that this was touchscreen tablet.

  • RODRIGO DABOIN SANCHEZ: So if we can imagine kind of

  • like a tree where you have a really long branch,

  • and then maybe like, a lot of other branches per level, right?

  • And then these each had like a lot of branches,

  • whatever, blah, blah, blah, blah.

  • Using Breadth-first search, you would have

  • to search this one, then this one, then this one, then this one, then

  • this one, then this one, and this one, this one, and this one, this one,

  • this one, until you got here.

  • Whereas if you use Depth-first search you

  • would just, whoop, automatically get to the end and be like, oh, that's it.

  • But by the same token, if the goal state is over here for some reason,

  • Death-first search would look through this branch,

  • then it would look through this one, then through this one,

  • and through this one, this one, until it finally got here.

  • Whereas Breath-first search would check this, this, this, this, and then

  • find it.

  • So depending on the--

  • COLTON OGDEN: Way the tree is set up.

  • RODRIGO DABOIN SANCHEZ: --on the way that the tree set up.

  • One is faster than the other.

  • So I just arbitrarily was like, OK, let's just

  • use Breath-first search to search.

  • OK.

  • COLTON OGDEN: BlueBooger had mentioned that Red Blob Games

  • website has excellent tutorial on Pathfinding and Python and game

  • programming.

  • I think I actually checked out that once in a long time

  • ago when I was getting more into like procedural generation algorithms

  • for like rougelikes and stuff.

  • They have, I think if it's the same website,

  • they have a lot of really cool resources on that.

  • So yeah, definitely check that out.

  • RODRIGO DABOIN SANCHEZ: All right.

  • So let's give it a crack.

  • Let's try to implement this.

  • Right?

  • Where's my editor?

  • Here it is.

  • COLTON OGDEN: Oh, Bokkengro, "You guys should add a description

  • to your stream."

  • Yeah.

  • That's a good point.

  • We should.

  • Thank you for mentioning that.

  • I will I'll do that soon.

  • "Are you guys just two random dudes doing Python tutorials,

  • or what is this?"

  • Yeah.

  • So this is-- so CS50 is a course at Harvard

  • that has a YouTube channel and Facebook and all this stuff.

  • And we're kind of an extension of that.

  • We're based at Harvard, and Harvard University.

  • And we have access to a bunch of people here that all know a lot of stuff.

  • So, Rodrigo, is a CS student here at Harvard.

  • And he whipped up this Game of Fifteen problem set from a prior year,

  • and he's doing it in Python.

  • I do game programming.

  • We've got David J Malan, who hosts, who sort of lectures CS50, and sort of mans

  • the ship, so to speak, does a whole bunch of other stuff.

  • So, yeah, definitely check us out.

  • Watch some of our prior vlogs.

  • Go to our YouTube channel, youtube.com/cs50 if you're curious

  • about our lectures and whatnot.

  • We do a lot of different stuff.

  • So we're just kind of new to twitch.

  • So growing our presence on this platform.

  • RODRIGO DABOIN SANCHEZ: Also, I want to touch on something that I just

  • saw someone write in the chat.

  • Where let's say we have an example-- so the comment was from Andre,

  • Breadth-first search is exhaustive and it will certainly

  • find the shortest path.

  • So that's a good point.

  • Say we have, like especially in the type of game,

  • where you have multiple ways of arriving to the same state.

  • Right?

  • Like earlier-- do I still have an example

  • here where I could have probably gone left, up, and down, and you know,

  • won the game, but I went in the other direction like a few more times

  • and finally won it.

  • So we have multiple ways of getting to the same state.

  • Some of them will be shorter than others.

  • And so let's pretend that we have multiple goal states.

  • So maybe square is the goal state.

  • And so we can win the game either by making one move, or making three.

  • So Depth-first search will find this solution, which is potentially longer.

  • But Breadth-first search, since it goes level by level,

  • it checks every node at each level.

  • So it will inevitably find the shortest solution.

  • Whereas Depth-first search might find another solution,

  • but it might be longer, for example.

  • And there are certain--

  • what's it called?

  • Possibilities, where one branch might go on indefinitely and so Depth-first

  • search never checks any other part of the tree or something.

  • Another note about Breadth-first search is

  • it'll find the shortest path to victory.

  • OK.

  • Good note.

  • OK.

  • So what we're going to do is since this is

  • going to be probably a more lengthy function,

  • is we're going to map it out first.

  • We're going to write what we're going to do.

  • So we want to have--

  • one thing that we want to avoid is like getting

  • stuck in some sort of infinite loop, where we make a say--

  • we want to remember states we've been in.

  • Right?

  • We don't want to we don't want the AI to start off at some starting state,

  • make a few moves, end up right where it was at the beginning,

  • and then check the same moves that he had checked before,

  • and then, you know, get stuck making the same pattern over and over

  • and over again.

  • So we'll probably want, you know, like a searched list,

  • where we can store configurations that we've been in before.

  • We'll also want what is known as a fringe, which

  • is essentially kind of like a queue of like,

  • nodes that we are waiting to check out.

  • So like in the tree that I drew out, if in the first level

  • there's four different nodes, so like, going up, right, down, or left,

  • will want to just put those in the queue for things that we can do.

  • And then check those, you know, one at a time.

  • So we'll want to actually make this a queue.

  • And we're going to need to import from q that

  • is after, no that is before r, right?

  • COLTON OGDEN: Q is right before r.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • COLTON OGDEN: Q, r, s, t, u, v, w, x, y, and z.

  • RODRIGO DABOIN SANCHEZ: So we're going to import--

  • LOL.

  • We're going to import the queue class from the queue library.

  • And we're going to have our fringe be q.

  • If you wanted to do that first search I think you would use a stack,

  • because then it's last in, first out, right?

  • But anyway, let's not go down that rabbit hole.

  • So we're going to use the q to do Breadth-first search.

  • And I wish I would stop erasing--

  • here we can use this tree.

  • If we use a q, the way that we do this is,

  • we're going to check the current node.

  • We're going to say, is this the goal state?

  • If it is we can just break out, return the path that we took to get there.

  • If it's not, we want to check its successors, right?

  • Or its children.

  • COLTON OGDEN: So every node then, just a copy of the board, basically?

  • RODRIGO DABOIN SANCHEZ: Essentially.

  • It's like a copy of the board, and we're also

  • going to want to store like the current path that we've taken to get there.

  • So that at the very end, we can return that path and then make those moves.

  • And that way we can actually visually see

  • the program solving it step by step.

  • Instead of--

  • COLTON OGDEN: Wow, this could get pretty large, couldn't it?

  • If you're adding a copy of the board every node, every time we make a move.

  • RODRIGO DABOIN SANCHEZ: It'll get large, which will--

  • COLTON OGDEN: What's the mental memory-- have you

  • measured the memory cost for like 1,000 shuffled boards?

  • RODRIGO DABOIN SANCHEZ: So I was actually messing around

  • with that earlier, and originally, before I did this

  • I had to be the shuffle magnitude set to 10,000.

  • And so I was like, man, I am pretty sure I wrote this correctly,

  • but like, it's returning anything.

  • And then I was like, I should print, you know, all the nodes.

  • And so I just see, for like minutes, it's scrolling.

  • Like all this different stuff it's thinking.

  • So I lowered the magnitude to be like five moves

  • and then it just like solved it pretty quickly.

  • COLTON OGDEN: I wonder if you can like discard prior--

  • like set prior nodes of the tree to nothing

  • because you're caching the path.

  • And have that still work.

  • Would that work?

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • So that's what we want to have this searched list for,

  • that I have initialized here.

  • So we can keep track of things that we've seen before.

  • Such that if we see them, we don't look at that successors.

  • We just stop looking at that branch altogether.

  • COLTON OGDEN: Right.

  • RODRIGO DABOIN SANCHEZ: And that should help.

  • OK.

  • So we want to keep track of states of the game that we've seen already.

  • We want to have a queue of like nodes that we're going to check out.

  • Like moves that we can make from the current position.

  • And then we want to have a root for the tree.

  • So like the initial starting point is going

  • to be whatever the current board is.

  • COLTON OGDEN: Yeah.

  • RODRIGO DABOIN SANCHEZ: OK.

  • So now what we want to do is add--

  • COLTON OGDEN: How, what we-- are we using the queue to represent the tree?

  • That's just the current level of the tree, right?

  • The searched for the fringe?

  • RODRIGO DABOIN SANCHEZ: The queue will hold all of the--

  • so like in this example, what we'll do first,

  • is we'll add the root to the tree-- to the queue.

  • And then we'll pop it from the queue.

  • Check whether it's the goal node.

  • If it is, we'll return.

  • If it's not, we will say OK, if we haven't seen the state before,

  • go ahead and add to the list of states that we've seen.

  • And then after we do that, we will find its successor.

  • So we'll see, where can we go from here?

  • Then we'll store all of its successors in the queue.

  • And then for, you know, kind of repetitively for each new successor

  • we'll be like, OK, we'll pop the first one.

  • queue FIFO, q is first in, first out.

  • So this one would be like, OK, we'll pop this from the queue and we'll say,

  • is this the goal state?

  • And if it's not, then we will you know check its successors,

  • add them to the queue.

  • But then since it's a queue, we'll move on

  • to the one that was added after this one.

  • COLTON OGDEN: I see.

  • So it'll never-- so what's hinging on making this work is we will never, ever

  • see the same state again in what we're solving.

  • RODRIGO DABOIN SANCHEZ: Right.

  • COLTON OGDEN: Like, otherwise, this would be impossible.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • COLTON OGDEN: OK.

  • That makes sense.

  • RODRIGO DABOIN SANCHEZ: We will use this list to keep track of things

  • that we've seen.

  • So we don't get stuck infinitely making the same pattern of moves,

  • never making it happen.

  • COLTON OGDEN: I wonder how much--

  • so that I could see taking all our memory too.

  • Like how much memory do you think it takes

  • to store every possible permutation of the board?

  • How many-- first of all, how many possible permutations of the board

  • are there?

  • RODRIGO DABOIN SANCHEZ: So let's see, we have 16--

  • is it like 16 factorial?

  • COLTON OGDEN: I don't know what--

  • I don't know what it would be.

  • RODRIGO DABOIN SANCHEZ: Because it could be--

  • it could be you know--

  • COLTON OGDEN: Because I don't know if you can, strictly speaking, get--

  • you can't get every possible numerical permutation on here

  • because it has to follow a pattern.

  • Like the invariant has to stay consistent.

  • RODRIGO DABOIN SANCHEZ: True.

  • Yeah.

  • So less than 16 factorial.

  • COLTON OGDEN: Yeah.

  • It would be less than that.

  • But I don't know what the number actually would be.

  • But it's interesting.

  • RODRIGO DABOIN SANCHEZ: I'm sure we can-- it's a quick Google search.

  • How many possible configurations of Game of Fifteen?

  • COLTON OGDEN: Or Fifteen Puzzle.

  • It might be known by Fifteen Puzzle, more frequently.

  • RODRIGO DABOIN SANCHEZ: Ah, I can't type.

  • How many different possible combinations are in the Fifteen Puzzle?

  • COLTON OGDEN: [INAUDIBLE].

  • RODRIGO DABOIN SANCHEZ: 10 to the 13.

  • COLTON OGDEN: 10 to the 13.

  • So, OK.

  • So there's 10 to the 13 board positions.

  • Those are all the strings that are two bytes each, right?

  • So this is interesting.

  • Now, what I have the instinct to do is to hash all the potential positions,

  • right?

  • To take that data structure, that list data structure, and hash it.

  • And then store the hashes in a dictionary.

  • And that way you can immediately check to see whether that hash exists

  • in the dictionary.

  • Right?

  • Because how are you checking prior positions now?

  • Are you just going over every single one of them and comparing them?

  • Is it with equals?

  • equals, equals.

  • RODRIGO DABOIN SANCHEZ: I'm saying, like if current board not in search

  • of lists.

  • COLTON OGDEN: OK, so you are doing equals, equals effectively.

  • OK.

  • That's what that essentially--

  • RODRIGO DABOIN SANCHEZ: That's probably why it takes so long for larger.

  • COLTON OGDEN: Yeah.

  • RODRIGO DABOIN SANCHEZ: As it gets longer and longer.

  • COLTON OGDEN: So what you can do is you can

  • hash-- if you hash those lists, right?

  • That data structure, find a way to hash it, and deterministically

  • get it to hash.

  • You could store them in a dictionary and then do constant-time look up of that.

  • RODRIGO DABOIN SANCHEZ: Dictionaries are constant-time right?

  • COLTON OGDEN: Well, are roughly constant-time.

  • Yeah.

  • So that would almost be very fast.

  • RODRIGO DABOIN SANCHEZ: And actually, if we--

  • what's it called?

  • If we used to set for the searched instead of a list, that would be--

  • searched is constant-time look up in Python, I believe.

  • COLTON OGDEN: In a set?

  • Yeah.

  • Yeah, it is.

  • Because they hash it underneath the--

  • RODRIGO DABOIN SANCHEZ: So we could use a set instead

  • of a list, which I have to--

  • COLTON OGDEN: What if--

  • can you-- I don't know if you can-- well, I guess you can hash.

  • That's what I'm saying, the tricky part would

  • be finding a way to hash [INAUDIBLE] like that deterministically.

  • That'll be the tricky part.

  • RODRIGO DABOIN SANCHEZ: You know something we could do is we could--

  • COLTON OGDEN: You could turn it into a string and then hash that string.

  • You could-- by-- if you--

  • because the board is always going to be a different string, right?

  • You could literally just make a string of the board

  • as it is laid out with the brackets.

  • RODRIGO DABOIN SANCHEZ: Like 1, 2, 3, 4--

  • COLTON OGDEN: Yeah, with the brackets.

  • Because then you would ambiguously have 11, and stuff like that.

  • RODRIGO DABOIN SANCHEZ: True.

  • True.

  • COLTON OGDEN: So if you do that, if you flatten

  • the ne-- flatten your list into a string with the brackets,

  • you can hash those strings.

  • Those you can then store in a set, or you can store them in a dictionary.

  • But sets would work fine as well.

  • And then you get almost constant-time look up for those.

  • RODRIGO DABOIN SANCHEZ: And so the only thing

  • that we're going to be changing this algorithm

  • is how we're representing the search list, right?

  • COLTON OGDEN: Yeah.

  • The search is no longer list, it's going to be a set.

  • And every time you get a-- you are looking at a brand new--

  • set is not indexed.

  • Be aware of that.

  • RODRIGO DABOIN SANCHEZ: That's fine.

  • We won't need the check indexes.

  • COLTON OGDEN: What was I going to do?

  • Oh, I was going to check to see what 10 to 13 was.

  • 10 to the 13 is equal to--

  • RODRIGO DABOIN SANCHEZ: More than a trillion.

  • COLTON OGDEN: That's a big number.

  • Yeah, it's like-- what is that?

  • A thousand, million, billion, 10 trillion.

  • RODRIGO DABOIN SANCHEZ: 10 trillion.

  • COLTON OGDEN: So 10, you could have 10 trillion different nested lists--

  • RODRIGO DABOIN SANCHEZ: Here's what I'm thinking.

  • COLTON OGDEN: --that you're doing an if statement on in your thing.

  • RODRIGO DABOIN SANCHEZ: Here's what I think would be fun.

  • Here's what--

  • COLTON OGDEN: Well, I mean--

  • And that's-- is that potential-- that's just for the sake of the Fifteen

  • Puzzle.

  • Right?

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • COLTON OGDEN: That's insane.

  • RODRIGO DABOIN SANCHEZ: Here's what I think would be fun.

  • Let's implement that using a list, see like at what

  • point it starts getting really long, then change the search list to be--

  • COLTON OGDEN: Oh, sure.

  • We could time it.

  • Yeah.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • And then we could just--

  • COLTON OGDEN: That would be sick.

  • Let's do that.

  • RODRIGO DABOIN SANCHEZ: Because we'll have like a working version.

  • And then, you know, once that's done, we can

  • mess around and see like how much of an impact

  • we can make just by changing the search.

  • COLTON OGDEN: Yeah.

  • Yeah.

  • Yeah.

  • RODRIGO DABOIN SANCHEZ: OK.

  • That sounds fun.

  • COLTON OGDEN: That does sound fun.

  • RODRIGO DABOIN SANCHEZ: OK.

  • OK.

  • So like we were saying, we want to have some data

  • structure in which we keep track of all the states that we've searched.

  • We want a fringe to be keeping track of all the different moves

  • that we want to try.

  • And we want to kick off the tree with a root.

  • So the root is going to be the current board.

  • And now what we want to do is we want to add our,

  • you know, our root to our kind of like tree.

  • So the way that I wanted to do this was making a dictionary, where

  • we're going to have a couple things.

  • We're going to have the board that we're keeping track of,

  • and that's going to be the root.

  • Then we're going to keep track of the empty spots location.

  • And that's going to be the current empty spot location.

  • And we also want to keep track of the path

  • that we've taken to reach the current state.

  • So at the root, we're going to have the current board--

  • I guess I don't need to write this out as it's own separate variable, right?

  • OK.

  • So originally, so now this is the root.

  • Because the node isn't just going to be the board itself.

  • It's going to be kind of like a struct containing some information.

  • We're going to store the current board, the current location of the empty spot,

  • and then the path that we've taken to reach this node.

  • The root node, we've taken no steps to reach it so the path is just empty.

  • And here it doesn't matter whether we use a list

  • because we're only going to be adding like some small number of moves

  • to get--

  • we're not going to do like more than probably a couple of hundred moves

  • to solve it, I think.

  • I'm sure this is solvable in a few number of moves.

  • OK.

  • So now we're going to kick off an indefinite loop using, while true.

  • This is where we're actually going to start searching the tree.

  • So the first thing we want is kind of like a base case

  • that we just want to quit if--

  • and let's just write this out so we know what we're doing.

  • Quit if no solution is found.

  • Which we should never have to worry about,

  • but in case, this is important to write when you're writing it

  • for the first time, in case you accidentally introduce a bug

  • into your code, and then your algorithm doesn't work,

  • this way at least you break out of the loop once the queue is empty.

  • So if fringe.empty-- and the fringe is just a native Python q and so instead

  • of like nq, dq, and whatever, what have you the methods are put empty

  • and I think, get.

  • So this checks whether the fringe is empty.

  • And here we're just going to return an empty path like nothing.

  • OK.

  • So that's kind of our base case.

  • So now what we're going to do is we're going to dq to the current node

  • from the fringe.

  • So node is going to be fringe.get.

  • Get is the q function that will return the current first element in that q,

  • And we'll put it in this node variable.

  • All right.

  • And so let's write out the algorithm-- inspect current node.

  • All right.

  • Now we want to check, is the current node the goal state?

  • So quit if node contains goal.

  • All right?

  • Here we'll check if node at the board position is self.goal.

  • We'll return the path that node contains.

  • So ultimately, what we want the solve function

  • to do for us is to return like the list of steps that we need to take.

  • The list of moves that we need to make in order to solve the game.

  • So if we find that the board in the current node matches the goal board,

  • we're just going to return the path that is attributed to that board.

  • COLTON OGDEN: Hey!

  • How's it going?

  • RODRIGO DABOIN SANCHEZ: And we have, David, joining on the stream.

  • COLTON OGDEN: The mystery guest.

  • DAVID: Nice to see everyone.

  • COLTON OGDEN: So we're doing a Game of Fifteen in Python.

  • Currently we're on the solver right now.

  • So where we talked about it earlier-- we're doing a sort of like a Breadth

  • DAVID: Breadth.

  • RODRIGO DABOIN SANCHEZ: Breadth-first search.

  • COLTON OGDEN: Breadth-first search.

  • DAVID: Still hung up on that, huh?

  • Why don't we do a Depth-first search.

  • RODRIGO DABOIN SANCHEZ: Well, don't worry.

  • Earlier I was asking Colton what order the alphabet is in.

  • So there's that.

  • DAVID: Oh, did you go with alphabetical?

  • RODRIGO DABOIN SANCHEZ: I tried to, yeah.

  • DAVID: Nice to see everyone though.

  • I look forward to seeing this.

  • COLTON OGDEN: We're doing an interesting experiment.

  • So right now we have basically a--

  • this whole algorithm hinges on checking prior states of the board

  • because the board can only ever be in one state at a time

  • while we're solving it.

  • And basically, we can, instead of, assembling

  • this massive list of prior states and checking

  • to see if we've already seen that state.

  • We can hash the state of the board as a string and store that in a set

  • and then do constant-time look up of that hash string.

  • And see how that comparison actually ends up [INAUDIBLE] time,

  • how much time we save.

  • RODRIGO DABOIN SANCHEZ: But first, we're restoring everything

  • in the list to see like what the difference in time is.

  • If we start off with the list, versus something

  • that's going to have confidence--

  • COLTON OGDEN: Because this list is going to be massive.

  • Especially if we've done 1,000 steps to get to the permutated board.

  • DAVID: But you're just using these hashes

  • to determine if it's in a one configuration?

  • COLTON OGDEN: If we've encountered this state before while we're

  • going through the actual algorithm of--

  • DAVID: Oh, at which point, you'd--

  • just so you're analyzing the answers that--

  • COLTON OGDEN: We are.

  • Exactly.

  • Yeah.

  • DAVID: Oh, OK.

  • OK that's, good.

  • I a little nervous there.

  • Because if you pre compute all these hashes, that's like infactorial.

  • COLTON OGDEN: Oh yeah.

  • Yeah.

  • No.

  • It's like 10 trillion different ones.

  • No.

  • No we would, no.

  • We would not do that.

  • Actually, we just looked it up on the calculator right there

  • to figure out the exact number.

  • DAVID: Oh, my god.

  • You have to think about where to put the commas there.

  • COLTON OGDEN: Yeah.

  • Nice.

  • DAVID: All right.

  • Well, let me leave you to it.

  • But, good to see everyone.

  • I'll hop on the chat and looking forward to seeing this develop.

  • COLTON OGDEN: Cool.

  • RODRIGO DABOIN SANCHEZ: Sweet.

  • COLTON OGDEN: Thanks for hopping over.

  • RODRIGO DABOIN SANCHEZ: All righty, so, so far we, OK, we

  • have dq'd the root from the q.

  • And we are inspecting whether it is the goal state.

  • If it is, we are returning the path that it contains.

  • Otherwise, if it's not, we want to add the CurrentNode to our search

  • set, which right now is a list.

  • And then put its children in the fringe.

  • So if the root node isn't the goal, we want

  • to add it to the list of search states that we've seen.

  • And then we want to put its children in the fringe

  • so that we can repeat this process again with them.

  • COLTON OGDEN: Right.

  • RODRIGO DABOIN SANCHEZ: So the way we're going

  • to do that is we're going to check, if node board, not in search,

  • which is what we're going to change later.

  • COLTON OGDEN: I mean, we can still-- it's still going to be not in search,

  • right?

  • Because you're doing it through-- you're going to look in a set, though.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • Yeah.

  • We're going to change what search looks like.

  • Which will dramatically--

  • COLTON OGDEN: This will actually be pretty much identical.

  • RODRIGO DABOIN SANCHEZ: Which is nice.

  • Which is why something as simple as what data structure sure you're using

  • can completely change the runtime of your code, or the efficiency.

  • COLTON OGDEN: Oh, yeah.

  • 100%.

  • RODRIGO DABOIN SANCHEZ: OK.

  • So we're going to go ahead and append to the search list

  • the current board that we're seeing.

  • COLTON OGDEN: Also, it's funny that Asli was lurking this whole time.

  • So glad to know that you've been in the chat, Asli.

  • Everyone is saying hi to David.

  • If you use Dijkstra's shortest path alogorthm on a graph with all the edges

  • it just becomes breadth first search.

  • Yeah.

  • I don't know too much about it.

  • I have to reread up on Dijkstra.

  • It's been a long time since I looked at any of that stuff.

  • RODRIGO DABOIN SANCHEZ: All right.

  • So now we're going to want some function to extract the successors

  • from our current node, right?

  • So let's just pretend that we have a successors function.

  • COLTON OGDEN: Are all the successors going

  • to be up, down, left, right, from that one node?

  • RODRIGO DABOIN SANCHEZ: Right.

  • Yeah.

  • OK.

  • So for child and successor, which we have to write.

  • Successor doesn't exist right now.

  • We're going to say, if the child--

  • I don't know, now we're getting into territory

  • where we haven't determined the behavior of successors yet.

  • So actually, let's just go ahead and define it.

  • So that, you know.

  • For child and successors, we want to check whether one of those children

  • is already in the search list so we don't add it to the queue.

  • Otherwise, if the successors of the current node isn't in our search set,

  • we will add them to the queue.

  • Because say for example, that we're starting at the lower right corner.

  • And this is the result of moving to the right.

  • That would be exactly the same as this one.

  • So we don't want to even consider this.

  • And so that will save us the time of putting this in the queue.

  • So we will skip this and go to that next one, which maybe like go up

  • or something.

  • So let's define-- let's define a successor's, maybe

  • like a helper function within here itself, within the solve function.

  • [CHIME ALERT SOUND]

  • COLTON OGDEN: Very interesting to understand

  • most of things those guys are saying.

  • No, it's OK.

  • I mean, we've gotten into a little bit of algorithmic territory

  • and I'm not even that good at algorithms and data structures.

  • I've learned a few things over the years and I

  • should study upon it a little bit more detail,

  • but this is all good stuff to kind of be aware of.

  • Just like using the right data, take that away from the stream if anything.

  • Use the right data for the job.

  • Try to look for it, you know, when you're manipulating data like this

  • and doing thousands upon thousands of potential iterations

  • and all of those things take up data, that's an opportunity to optimize.

  • And, Asli, I totally understand.

  • I have off days, as well, all the time.

  • But thanks for tuning in on the lesson.

  • Being around and still absorbing the material.

  • That's really like a huge thing.

  • And that's something I think that's important,

  • especially in like language learning.

  • It's just absorbing sort of passively, you know, passive media ingestion.

  • Or at least, in this context, like CS, vernacular

  • and just kind of getting input, you know, input sources.

  • It's super important.

  • RODRIGO DABOIN SANCHEZ: All right.

  • So for the successor's function, we know that we're

  • going to want four separate boards.

  • Because one of them we're going to move up,

  • one of them we're going to move left, one of them we're going to move down,

  • one of them we're going to move right.

  • So maybe not like the nicest way possible.

  • I've made four copies of a board and I've stored them in a list.

  • Same thing for--

  • COLTON OGDEN: How large is this queue going to be at max, by the way?

  • Because we're popping off the queue every time we check something right ?

  • Or are we just adding to the queue and never getting rid of the--

  • RODRIGO DABOIN SANCHEZ: No.

  • We're popping-- every time that we inspect

  • a node we're popping it from the cube.

  • COLTON OGDEN: OK.

  • So when might we expect 8.

  • Then we inspect 3.

  • We pop 8 and add 1 in 6, after the 10, in this case?

  • RODRIGO DABOIN SANCHEZ: We do.

  • Pop 8.

  • We add 3 and 10 to the queue.

  • COLTON OGDEN: Then we go to 3.

  • We pop 3, add 1 and 6 to the queue go to 10 and then do that.

  • OK.

  • I see.

  • Got it.

  • RODRIGO DABOIN SANCHEZ: So at most we're only ever

  • having two, less than two levels of the tree.

  • COLTON OGDEN: Yeah.

  • I mean it can get large later, but it's not going to be like insane.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • Nice.

  • OK.

  • So blah, blah, blah. e_loc, and e_loc, and e_loc.

  • So as I kind of referred to earlier, deep copy,

  • helps for recursively copying the list.

  • But if you just if you know you're working with a shallow list that's

  • only one level, you can make a copy just by using the List function in Python.

  • That gives you a list.

  • And OK.

  • So now what we're going to do is we want to say, like, for example, the--

  • and we can clean this up later.

  • But for now just--

  • COLTON OGDEN: I wonder, I wonder if, even here, instead of deep copying,

  • like using the hashes.

  • Like the-- sorry, I didn't mean to do that.

  • --using the string hashes.

  • Because all you're doing--

  • I mean, eventually we'll do the new algorithm, right?

  • Like these-- what we're doing is we're just comparing these, ultimately,

  • to what we've already seen in the thing, right?

  • And comparing it to board, but we can have a hash at the board

  • as well, right?

  • To solve the board, I mean.

  • RODRIGO DABOIN SANCHEZ: True.

  • Yeah.

  • Yeah.

  • The only reason-- the only thing though is

  • that we actually need to make a move.

  • We need a-- well, this is the current state of the board,

  • and so we want to see what it looks like if we move it--

  • COLTON OGDEN: Oh, yeah, you're right.

  • RODRIGO DABOIN SANCHEZ: So the only way we can

  • make a move is an actual list of lists.

  • COLTON OGDEN: Unless you wrote a function that could take the hash

  • and do it on the hash.

  • RODRIGO DABOIN SANCHEZ: Yeah, that would be a little bit more work, I think.

  • OK.

  • So here, what we want to do, is say, self.move up.

  • And we're going to have this be the same.

  • We're passing in the board's move up function,

  • and we're passing in the location of the empty spot to the move up function.

  • So we'll have this be here.

  • All right.

  • And let's clean this up later, but for now, let's just

  • do this for the other ones.

  • Just because I want to have time to mess around with the other ideas

  • that we've had.

  • And this one we'll be moving right, this one moving down,

  • this one will be moving left, and here we

  • have 0, 1, 2, 3, and 0, 1, 2, 3 yeah.

  • A loop might be better for this.

  • OK.

  • And so now, what we'll want to return is--

  • this is going to be the children.

  • So we'll want to return potentially a list of lists where here, we're

  • going to contain the board, position 0.

  • COLTON OGDEN: Bokkengro, thank you very much for the follow.

  • I think I missed somebody else?

  • Apologies.

  • [INAUDIBLE],, thank you very much for the follow as well.

  • Much appreciated.

  • RODRIGO DABOIN SANCHEZ: So I didn't talk about how I want to--

  • how you want to--

  • what's it called I didn't talk much about how

  • I want to represent the path list.

  • And the way that I want to do it is have it be with numbers like we did before.

  • So 0 means up, 1 means right, 2 means down, and 3 means left.

  • So that's what I'm doing here. .

  • I am returning as the kind of like children,

  • I am returning the current board, if you move up or in whatever direction.

  • The look-- the current location of the empty spot,

  • if you go in whatever direction.

  • And then what direction you moved in as an integer.

  • So here I'm saying, board if you move up, empty location if you move up,

  • and the fact that we moved up.

  • COLTON OGDEN: Right.

  • Because that's the information that represents the path

  • we took to get to the actual thing.

  • Because we're going to return that eventually.

  • And how are you returning that?

  • Is it just going to be a data structure that just gives you

  • the list of directions in order?

  • Given the--

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • It's just a list.

  • So then the path will look something like, I don't know, 0, , 3 0,

  • up until it solved the thing.

  • And we'll see-- we're just going to iterate over that list.

  • And kind of how we shuffled the board, we're

  • just going to loop through all those results and refer to this dictionary

  • up here.

  • COLTON OGDEN: And it would be cool if you got the end result of that.

  • And then you have the starting state of the board and then

  • like a function that like performed every step every like 200

  • millisecond or whatever, so you can watch it.

  • Oh, OK.

  • That's good.

  • That's cool.

  • RODRIGO DABOIN SANCHEZ: OK.

  • So now we know that successor's is going to take in a board and the location.

  • So node at board and node at e_loc, which I think is what we called it.

  • Yes.

  • And what is it?

  • Why did it change colors here?

  • I'm curious.

  • Did I close down this list?

  • Wait a minute.

  • This list here closes that.

  • And then this closes--

  • interesting.

  • I think I have some extra brackets that I don't need.

  • OK.

  • So now this is closing that.

  • This is closing this.

  • This is closing that.

  • This is closing this.

  • And then this is closing that.

  • OK.

  • That looks better.

  • All right.

  • So now we know that the node is going to take in--

  • that the successor sticks in a board and the location, which in the node

  • we have a board key and a location key.

  • So now the child is going to be a list containing a board, a location,

  • and then the direction.

  • So we want to check if we've not seen the board in the child.

  • So if child is 0, not in searched, we will add that child to the fringe.

  • So we will put, in the fringe, a dictionary containing board.

  • And then have this be child, deposition 0.

  • And then e_loc look is going to be child at position 1.

  • And we're going to have path be--

  • here's what we've got to remember the parents path.

  • So it's going to have to be the path of the current node, plus child

  • that index 2 in list form so that we can concatenate these lists.

  • So I'm doing essentially something that looks

  • like, if I have x is a list containing 1, 2, and 3, x + 4 will give me 1, 2,

  • 3, 4.

  • And so that's how I'm going to update the paths throughout the tree.

  • So this might be like the current node, and then the children

  • is going to be either 0, 1, 2, 3.

  • And so we're going to add it as a list to the existing path.

  • And that's what is going on here.

  • All right.

  • So now I believe this should return to us the path to victory.

  • So what we've got to do is check in our main function,

  • where we have currently right here, if we

  • press Shift where it's going to solve.

  • We want to store the path.

  • So we're going to potentially store this in a variable called moves.

  • And if we want to be really fancy we can print something like, thinking,

  • because we might take a few seconds.

  • OK.

  • So we're going to have the path right here.

  • We know that we have to return false when we want to stop--

  • when we want to quit the program.

  • So I'm going to preemptively have this variable called persist, which is true,

  • because we we're going to want to refresh the board with each move

  • that we make.

  • So we want to keep refreshing such that we're returning true.

  • But once it's done, we want to quit the program.

  • Actually, do we need to do this?

  • I don't think so.

  • OK.

  • Let's just do this.

  • Let's say for m in moves, so for move, in the moves

  • that we need to make to win, we're going to refer to the moves dictionary

  • that we have in the board, right here.

  • COLTON OGDEN: Shout out to Brenda, by the way, for joining the stream.

  • A little late Brenda, you're all right.

  • But that's OK.

  • Like everyone is saying, better late than never.

  • Glad to have you with us.

  • We're getting to the really cool stuff here

  • in a second where we actually compare running time of a sort of, I would say,

  • naive implementation, just caching prior states of the board in string--

  • in lists and strings.

  • And then memoizing them for when David walked in.

  • That was a much better word than how I was trying to describe it.

  • RODRIGO DABOIN SANCHEZ: So after we make a move, will want to refresh the board.

  • And then we actually have to import from the time library.

  • Important sleep.

  • So that we can have the terminal sleep for just a second,

  • so we can actually see the move being made.

  • Right?

  • And then it'll finish doing this.

  • And it'll return refreshed.

  • OK.

  • Unless we missed something, let's--

  • oh, let's make sure that the shuffle magnitude isn't too big.

  • It's just 10 right now.

  • OK.

  • Let's see what happens if we run main.

  • We automatically won.

  • COLTON OGDEN: Nice.

  • RODRIGO DABOIN SANCHEZ: OK.

  • So here it is shuffled a little bit.

  • Right?

  • And if we press Shift, it's thinking.

  • COLTON OGDEN: So this was-- so it's not, in this case, showing you a like,

  • live figuring out the solution.

  • This is, it knows the solution and then it's doing it.

  • It's actually doing the one solution, that it found.

  • RODRIGO DABOIN SANCHEZ: Right.

  • We could also print the--

  • we could print the solution list, but I mean, it would just look like numbers.

  • So the user wouldn't really necessarily know what it means.

  • COLTON OGDEN: Right.

  • Yeah.

  • Yeah.

  • Yeah.

  • No, this is super cool.

  • RODRIGO DABOIN SANCHEZ: But you'll see now

  • that if we increase the shuffle magnitude to say, even I don't know,

  • 20.

  • COLTON OGDEN: Just to get a little bit lengthy.

  • I mean we can get rid of the-- probably the--

  • RODRIGO DABOIN SANCHEZ: Oh, wow.

  • That was quick.

  • But I don't think it shuffled that much.

  • Some of the moves must have been--

  • actually, it looks almost like the same--

  • the same moves.

  • That was--

  • COLTON OGDEN: That's pretty funny.

  • Yeah.

  • RODRIGO DABOIN SANCHEZ: All right.

  • COLTON OGDEN: This is a little bit shuffled.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • So now like all of a sudden, it's thinking a bit longer.

  • And we can start to play around with changing the searched data

  • structure from the list to something a little bit faster to search.

  • So something with constant-time look up or near there.

  • Because I mean, already you're kind of looking at this like, ah, man.

  • COLTON OGDEN: It's thinking.

  • It's thinking for a while.

  • RODRIGO DABOIN SANCHEZ: OK.

  • So while this thinks, do you want to--

  • COLTON OGDEN: Yeah.

  • Let's do the memoized solution because that

  • sounds like it would be way faster.

  • RODRIGO DABOIN SANCHEZ: So here we are.

  • You we're recommending using a set, right?

  • COLTON OGDEN: Yeah.

  • Set.

  • I mean, I originally proposed dictionary,

  • but somebody wrote and recommended set, and that actually makes more sense,

  • because all we're doing is seeing that it's inside of a container.

  • Right?

  • And they all are unique just per virtue of what they--

  • I mean, I guess it doesn't matter.

  • In the dictionary it would be the same way.

  • But, set, sounds like it would be fine.

  • RODRIGO DABOIN SANCHEZ: We have found sets.

  • COLTON OGDEN: But what we need to do is we need to serialize the string,

  • or I don't know if serializer is the right word,

  • but we need it to take the representation of the list,

  • stringify it, and then use that as the hash or the index into the set.

  • And we need to make sure we preserve the brackets in that string, just because

  • the--

  • like you could have a situation in which you have maybe like--

  • would this be the case necessarily?

  • Yeah.

  • Like 11, 12, versus like 11, 2, 3, 4.

  • Like it doesn't know if that's 1, 12, 3, 4, or 11, 2, 3, 4, you know?

  • So you do need to keep the brackets in there

  • to preserve ambiguity in certain situations, I think.

  • RODRIGO DABOIN SANCHEZ: Right.

  • COLTON OGDEN: So let's definitely do that.

  • RODRIGO DABOIN SANCHEZ: I was just re-familiarizing myself

  • with set notation.

  • COLTON OGDEN: Oh, yeah.

  • Yeah.

  • A lot of the data structures will have kind of a uniform interface.

  • Just because like-- I forget what they call it-- the Python,

  • like they have a term for it.

  • Like all the core like, dunder functions they define that

  • let you have similar behavior across data structures.

  • And you can like define them yourself.

  • RODRIGO DABOIN SANCHEZ: OK.

  • So let's say we have a set based on this list.

  • If we want to add elements to it I think it's s.add, like if we wanted to add 4,

  • and then we can say 4 in s, and that's true.

  • But 5 in s should be false.

  • But if we do s.add 5.

  • and then we do 5 in s.

  • And then s.empty, potentially, is a function?

  • No.

  • I don't remember how to check.

  • COLTON OGDEN: You could just say s is equal to set.

  • RODRIGO DABOIN SANCHEZ: No.

  • I'm checking, like checking, if--

  • COLTON OGDEN: Oh, if it is empty?

  • RODRIGO DABOIN SANCHEZ: But I don't think

  • we actually do this in the algorithm.

  • COLTON OGDEN: No, I don't think we do.

  • No you're only doing that with the queue.

  • Right?

  • RODRIGO DABOIN SANCHEZ: And I believe you can have s2 just be an empty set.

  • Right?

  • COLTON OGDEN: Yeah.

  • RODRIGO DABOIN SANCHEZ: OK.

  • COLTON OGDEN: [INAUDIBLE] .

  • RODRIGO DABOIN SANCHEZ: [INAUDIBLE] is empty.

  • COLTON OGDEN: You can also construct with some--

  • there's another way to do it, I think.

  • RODRIGO DABOIN SANCHEZ: OK so now we have

  • search does a set, which means here, instead of search.append

  • we'll have search.add and we'll have to change the representation of what

  • we're adding.

  • COLTON OGDEN: Yeah.

  • So node board is going to have to be equal to the string or the--

  • yeah, just the string of the--

  • RODRIGO DABOIN SANCHEZ: I wonder--

  • COLTON OGDEN: --representation of the board.

  • RODRIGO DABOIN SANCHEZ: --if we have a list of lists

  • like 1, 2, and then 3, 4 here.

  • If we do str b.

  • That sufficient.

  • COLTON OGDEN: Yeah.

  • That seems pretty good.

  • RODRIGO DABOIN SANCHEZ: OK.

  • COLTON OGDEN: You're going to get some--

  • the extra bytes no matter actually.

  • Yeah.

  • RODRIGO DABOIN SANCHEZ: Let me make sure we're not using--

  • COLTON OGDEN: Yeah.

  • So you could just construct-- you could just do a string of node board there.

  • RODRIGO DABOIN SANCHEZ: Right here.

  • COLTON OGDEN: Yeah.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • str node board.

  • And that means the actual node contains the board, which is good.

  • In case it needs to move it up and stuff.

  • COLTON OGDEN: And I think you need to do if stream node board

  • not it search there too, right?

  • Fuck, sorry, I keep doing that.

  • I just cursed on stream.

  • Sorry.

  • RODRIGO DABOIN SANCHEZ: That's OK.

  • COLTON OGDEN: Bleep.

  • Bleep.

  • Sorry.

  • That was inappropriate-- that was, yeah, that was a slip.

  • RODRIGO DABOIN SANCHEZ: All right.

  • So if node board has a string.

  • It's not in searched.

  • And the same here.

  • If the string format of the child is not in searched, let's see,

  • is there anything--

  • is there really anything else we got to do here?

  • I don't think so.

  • Board-- we are--

  • yeah.

  • I don't know.

  • I think that's it.

  • Right?

  • We just changed them all the strings and put them in a set.

  • COLTON OGDEN: I think so.

  • RODRIGO DABOIN SANCHEZ: So let's try--

  • COLTON OGDEN: I'm curious how much to think--

  • how much-- what was the number that you set it to before when

  • it had to think for a long time?

  • RODRIGO DABOIN SANCHEZ: The one that we did on stream?

  • COLTON OGDEN: We just did, yeah.

  • RODRIGO DABOIN SANCHEZ: I haven't changed it.

  • It is at 20.

  • COLTON OGDEN: It was 20 and it was taking that long?

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • Remember that the first one was pretty quick,

  • but it's because I think the shuffle was nicer, like closure to goal state.

  • COLTON OGDEN: Wow.

  • RODRIGO DABOIN SANCHEZ: So let's--

  • COLTON OGDEN: Is this thinking right now?

  • RODRIGO DABOIN SANCHEZ: No.

  • I was like wait.

  • Did we already win?

  • But no, it's 9, 11, 12.

  • OK.

  • Wow.

  • OK.

  • COLTON OGDEN: That was fast.

  • Instantly.

  • OK.

  • So if we keep bumping it up.

  • RODRIGO DABOIN SANCHEZ: Let's see if we do--

  • COLTON OGDEN: So to be clear, we just took the algorithm,

  • the Breadth-first search algorithm, and we changed it from being sort of I

  • guess not linear--

  • I guess linear search in terms of looking at the data,

  • but we brought it and made it into a set, I guess.

  • So this one's slow.

  • What was the number that you used on this one?

  • RODRIGO DABOIN SANCHEZ: Here it's 40.

  • COLTON OGDEN: OK.

  • RODRIGO DABOIN SANCHEZ: So it's thinking.

  • But I feel like it hasn't yet reached the number of the amount of time

  • that it thought for the one that was 20, when it was still a list.

  • COLTON OGDEN: Mmm.

  • Wait, what?

  • RODRIGO DABOIN SANCHEZ: And if you look at this board,

  • it's actually decently shuffled.

  • Right?

  • 5, 1, 7, 3--

  • COLTON OGDEN: Oh, yeah.

  • RODRIGO DABOIN SANCHEZ: 2, 10, 6, 4--

  • 9, 14, 12, 8.

  • So it's not like-- for the other one--

  • COLTON OGDEN: It's finished now though.

  • RODRIGO DABOIN SANCHEZ: It's done now-- yeah.

  • COLTON OGDEN: That was still reasonably fast.

  • RODRIGO DABOIN SANCHEZ: And that was 40 shuffled moves.

  • Right?

  • And so we can even just see how long it takes

  • to solve it to kind of get a sense for how

  • many moves it's been having to make.

  • COLTON OGDEN: So it'd be cool to do like a--

  • that was even then many moves, but I mean it had to go through the tree

  • and figure that out.

  • RODRIGO DABOIN SANCHEZ: But Breadth-first search always finds

  • the shortest path to victory.

  • COLTON OGDEN: Right.

  • Yeah.

  • RODRIGO DABOIN SANCHEZ: So I wonder if we kick this up even to, I don't know,

  • 80?

  • COLTON OGDEN: Oh, man, that's going to take a long time.

  • I feel like it'd be cool to do like a time before and after, you know,

  • like to see.

  • RODRIGO DABOIN SANCHEZ: True.

  • COLTON OGDEN: Because it feels like, I mean, 40,

  • it solved it in a fraction of the time it took--

  • RODRIGO DABOIN SANCHEZ: To solve it for 20.

  • COLTON OGDEN: --to solve it for 20.

  • Yeah.

  • So I'm not sure what it would be, like, how much time we've actually saved.

  • But it's clear that we've saved a lot.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • We've definitely saved some time.

  • I mean, I guess for comparison, if this, you know, doesn't take forever,

  • we can put it back to a list and see that it basically never finishes.

  • Right?

  • COLTON OGDEN: Yeah.

  • You could do like a 20 one.

  • Spartangtr, thank you very much for following.

  • RODRIGO DABOIN SANCHEZ: What have the people

  • in the chat have been saying while we've been doing this?

  • COLTON OGDEN: There's some conversations going on amongst people.

  • I haven't been following--

  • RODRIGO DABOIN SANCHEZ: Because this is a perfect time to talk to the chat

  • now, while this is thinking.

  • COLTON OGDEN: Yeah.

  • True.

  • True.

  • True.

  • So we shouted out Brenda for coming into the chat.

  • Talking about Coursera courses.

  • And then some folks left.

  • Oh, Bhavik was saying, print the number of the steps in the length of the path.

  • So we could just--

  • we can see actually, how many times it's doing it.

  • Right?

  • RODRIGO DABOIN SANCHEZ: True.

  • COLTON OGDEN: Because that will help us get a better idea of just how

  • long the algorithm is too.

  • RODRIGO DABOIN SANCHEZ: So clearly, even with making this a string in the set,

  • this is--

  • 80 shuffled moves is still--

  • COLTON OGDEN: It's still a long time.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • COLTON OGDEN: Yeah.

  • I'm sure we're saving a tremendous amount of memory though.

  • RODRIGO DABOIN SANCHEZ: For sure.

  • COLTON OGDEN: Because like, if you were thinking

  • about how much memory you needed to store to write those lists of lists.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • COLTON OGDEN: That was probably a lot.

  • RODRIGO DABOIN SANCHEZ: A string would take less for sure.

  • Yeah.

  • Yeah.

  • Yeah.

  • Yeah.

  • COLTON OGDEN: Well, a hash string.

  • It's not even a string that's being stored, it's a hash of a string.

  • Yeah.

  • 0 of 1 versus 0 of n, clearly.

  • Yeah.

  • Not quite 0 of 1, but the actual--

  • that's the look up of the hashed string, but the actual Breadth-first search

  • is still going to take a long time.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • This might be a little bit too much for it.

  • COLTON OGDEN: Virani is saying, "This is just some magic."

  • RODRIGO DABOIN SANCHEZ: It is cool though, to like, just sit back and then

  • watch it figure itself out right.

  • Yeah?

  • But yeah.

  • COLTON OGDEN: It be cool if you could have a counter here.

  • You could keep refre--

  • I mean, I guess I would slow the application down a little bit.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • Like anything where it has to do with printing while you're in the loop,

  • it's going to really slow it down.

  • That's why I waited to do the searching first, so it's as quick as possible.

  • And then do the refreshing the screen after it's figured it out.

  • COLTON OGDEN: That make sense.

  • RODRIGO DABOIN SANCHEZ: Because I mean we could.

  • We could have an updated counter.

  • But then that would just slow it down.

  • COLTON OGDEN: That would skew the performance a little bit.

  • Yeah.

  • Mmm.

  • RODRIGO DABOIN SANCHEZ: But I mean, other

  • than that, that's the Game of Fifteen that I had ready to present.

  • COLTON OGDEN: Yeah.

  • No, it's great.

  • It was cool.

  • It was cool that we got a chance to actually go

  • into like algorithms and data structures a little bit, make it a little bit more

  • theoretical, and actually apply it to something.

  • I got to stretch it a little bit.

  • But yeah, no, it was awesome.

  • RODRIGO DABOIN SANCHEZ: We can probably even see--

  • COLTON OGDEN: Oh, yeah, and they're saying

  • if you can push it to GitHub they want to actually get

  • a chance to tinker with it.

  • RODRIGO DABOIN SANCHEZ: Oh, yeah.

  • I actually already have in my GitHub, the--

  • let's go on my profile.

  • My GitHub is coderigo17.

  • COLTON OGDEN: Good name.

  • RODRIGO DABOIN SANCHEZ: I already have the Game of Fifteen

  • here as one of my repositories.

  • COLTON OGDEN: What's the link?

  • I'll type it in the chat.

  • So that's GitHub.com And this is without the change though.

  • Do you want to commit, or maybe do a branch that has the memoized?

  • I mean, I guess it's easy enough to make the change on the string.

  • Yeah, you could just do that.

  • RODRIGO DABOIN SANCHEZ: I mean, yeah.

  • All I had to do was put str in the two places?

  • No, the three places.

  • Oh, and we changed it to a set.

  • So it's not too bad.

  • COLTON OGDEN: Yeah.

  • That's not bad at all.

  • That's something that if the viewers are going to tinker

  • with the data structures based--

  • RODRIGO DABOIN SANCHEZ: If you follow that does it get to it?

  • COLTON OGDEN: It should, yeah.

  • Let me check and make sure.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • There it is.

  • COLTON OGDEN: Is a public?

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • Everything that I do is public.

  • COLTON OGDEN: Cool.

  • Cool.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • COLTON OGDEN: Everything except the private things that you do.

  • RODRIGO DABOIN SANCHEZ: Well, the only things that are private

  • are things that I don't own.

  • COLTON OGDEN: It's feel thinking, geez.

  • RODRIGO DABOIN SANCHEZ: I don't know.

  • COLTON OGDEN: I mean, even if it does finish, we wont

  • know how many moves it took, necessarily,

  • without watching the whole thing.

  • So yeah, that's unfortunate.

  • RODRIGO DABOIN SANCHEZ: But if it does finish,

  • the fact that the stream is recorded, and then people

  • can go back and watch it, means that if you're really curious,

  • you can skip to whenever this finishes thinking.

  • And then actually count.

  • But yeah.

  • I don't know.

  • COLTON OGDEN: That was awesome.

  • RODRIGO DABOIN SANCHEZ: Is there anything else that people in the chat

  • want to talk about while we wait this out?

  • Or if this takes too long, we may just have to--

  • COLTON OGDEN: Yeah.

  • Well, we might cut it short here, you know, if we don't have any questions

  • and it takes a bit longer.

  • But that was awesome.

  • Thanks for coming onto the stream and putting this together.

  • You know--

  • RODRIGO DABOIN SANCHEZ: It was fun.

  • COLTON OGDEN: It was cool.

  • It was fun for me to participate in.

  • I don't do a lot of algorithmic programming, at least

  • more on academic side.

  • So this felt like an academic exercise, which was cool.

  • And I liked the fact that we kind of took a jump and dived a little bit more

  • into analyzing the performance of the application

  • and figuring out ways to do that using just simple data structures.

  • Not even really going out-- not even changing the algorithm,

  • just changing the fact that we were using a set--

  • RODRIGO DABOIN SANCHEZ: Right.

  • COLTON OGDEN: --instead of a list of lists of lists.

  • Right?

  • RODRIGO DABOIN SANCHEZ: It would have been

  • interesting to see how much longer it takes

  • using Depth-first search, or something.

  • COLTON OGDEN: Yeah.

  • RODRIGO DABOIN SANCHEZ: But, you know, one thing at a time.

  • I mean, I'm hoping to be back on the stream at some point in the future.

  • COLTON OGDEN: Yeah.

  • RODRIGO DABOIN SANCHEZ: Classes are about to start next week.

  • So I don't know.

  • I don't know what that will look like for me.

  • But you know, if I end up doing something for one of my classes

  • that I think is cool, I can kind of take inspiration from that

  • and do something in a similar spirit.

  • COLTON OGDEN: Yeah.

  • Let me know.

  • And then we can get you back up here.

  • And I know, that you're always game for, if we

  • play some Super Nintendo or something.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • If there's games.

  • COLTON OGDEN: [INAUDIBLE] or NES because you seem to be pretty into those.

  • You were there for both of those.

  • MKloppenburg saying, maybe an algorithms stream or something.

  • I mean, it would tie-in to this a little bit.

  • RODRIGO DABOIN SANCHEZ: Yeah.

  • It would be.

  • We could talk more about different types.

  • I'm actually about to take algorithms classes.

  • Because that's what I'm mostly interested in is an algorithms.

  • I do enjoy coding.

  • But the part of coding that I enjoy isn't like, looking up to syntax,

  • and getting the syntax right.

  • Right?

  • It's the actual problem solving portion.

  • COLTON OGDEN: Yeah.

  • That's the most important thing.

  • I mean there's tremendous--

  • I wish this actually was more of a dramatic change in performance.

  • I mean, it might be, ultimately.

  • It might be a dramatic change in performance, relatively speaking,

  • and we just-- it's because it's just so much that we

  • have been able to see it through.

  • We have to time it and we'd have to see.

  • Like the 10 versus the 20.

  • RODRIGO DABOIN SANCHEZ: If someone in the chat is, you know, very into this,

  • they could time this using the list version, which is in the repo.

  • And then maybe-- it won't be much trouble for me

  • to add an additional push, having it be set and on the string,

  • and then compare the two afterwards.

  • And let us know next time or something.

  • Yeah.

  • COLTON OGDEN: That would be awesome.

  • MKloppenburg is saying, your water looks like it's boiling.

  • Green screen magic?

  • Maybe.

  • RODRIGO DABOIN SANCHEZ: I only like drinking 212 degree Fahrenheit water.

  • COLTON OGDEN: Yeah.

  • Boiling water.

  • Bella_Kirs, our pleasure Bella, thanks for tuning in.

  • And to MKloppenburg and thank you Bhavik for the kind words.

  • Appreciate it.

  • Virani, thank you.

  • Yeah, a few minutes, says Bhavik It's taking a little bit of time.

  • Tomorrow we're going to be taking a look at Ren--

  • yeah.

  • is it Render 50, which is a PDF tool, or take source code files,

  • and a lot of text editors don't really let you print, or expert, to PDF

  • from your text editor.

  • But what we needed was a way, I mean David, especially,

  • needed this for lecture, to be able to print source code

  • and be able to look at it while giving lecture,

  • have it nicely formatted on the page, and a few other different cool things.

  • And so just using Python, previously the tool was written in PHP but we took it,

  • we made it in Python, and completely redid it.

  • And so we'll have a little bit of look at that tomorrow.

  • So we're getting more into the Python stuff, which is cool.

  • Today was Python.

  • Veronica will be on stream in the near future with Python as well.

  • And I'm sure we'll have other folks that are

  • on stream for Python related content.

  • RODRIGO DABOIN SANCHEZ: And the stream tomorrow is at 3:00.

  • Right?

  • COLTON OGDEN: Oh, yeah.

  • The stream tomorrow is at 3 PM.

  • It's not at 1:00.

  • So 3:00 PM Eastern Standard time.

  • I'll push an event notifi-- it's already on an event on the Facebook page,

  • but I'll post another post to kind of pub it.

  • And then it'll go on Reddit, Twitter, et cetera.

  • You'll see it.

  • Tune in.

  • It's going to be good time.

  • David is going to be hosting that one.

  • David J Malan.

  • Yeah.

  • Going to be an excellent, excellent time.

  • RODRIGO DABOIN SANCHEZ: This would be a dramatic time for it to finish.

  • But I don't know if it will.

  • COLTON OGDEN: Yeah.

  • I don't know if it will either.

  • It's going to be a long time.

  • RODRIGO DABOIN SANCHEZ: It'll be like the end of Inception, you know,

  • where the coin is spinning, or the totem is spinning

  • and you don't know if it's going to stop.

  • And they end it.

  • COLTON OGDEN: Well, it looks like we have a little bit of content

  • that we can keep going off of.

  • So Bhavik says, you Ubuntu looks dope.

  • Oh, MKloppenburg, you're right.

  • You're right.

  • I don't think we officially ever confirmed the time at 3:00,

  • and so I kept it as a draft.

  • But it'll go up tonight for sure.

  • And then the--

  • I guess when I make it an event, I'll post it

  • to the Facebook group and all that stuff.

  • And then I'll also start creating events for next week streams.

  • We have a few lined up for next week as well.

  • That's going to be a good time.

  • Kareem, next week's going to Flask.

  • I'm going to CSS next week.

  • Dave and I are going to do code reviews next week.

  • Minesweeper-- it's going to be a good week next week.

  • Yeah.

  • It'll be a good time.

  • I was going to look at-- what was this?

  • Bhavik was saying, you're a Ubuntu who looks dope.

  • What desktop are you using?

  • RODRIGO DABOIN SANCHEZ: As in the Ubuntu version?

  • COLTON OGDEN: Yes.

  • I guess the Ubuntu, and if you have a graphical window manager or whatnot.

  • Like what you're using for that?

  • RODRIGO DABOIN SANCHEZ: I'm on 18.10 Ubuntu.

  • And I'm actually, ironically enough, I'm not like a computer person.

  • Right?

  • So like--

  • COLTON OGDEN: That's OK.

  • A lot of people have this, I think, stereotyped perception

  • that all CS people are also like computer technicians.

  • RODRIGO DABOIN SANCHEZ: It's definitely something that I want to improve on.

  • COLTON OGDEN: Yeah.

  • I think it's definitely valuable.

  • I mean, like, computer parts aren't really

  • hard at all to understand, or to use.

  • But I mean, like troubleshooting hardware issues,

  • I think that's something that takes a lot of experience and training

  • and stuff, and so CS people usually do are you familiar with the software

  • side, the hardware side is not really something

  • they necessarily have to interact with.

  • RODRIGO DABOIN SANCHEZ: But I do know that it's 18.10 and I had to configure

  • my bash rc to have it look the way-- that my terminal look the way it does.

  • But other than that, yeah, I'm not too knowledgeable.

  • But--

  • COLTON OGDEN: That's all right.

  • No one is going to hold you accountable for that.

  • I don't think.

  • This is an awesome stream.

  • Appreciate it again.

  • Like part of me wants to keep trying to--

  • RODRIGO DABOIN SANCHEZ: I know.

  • COLTON OGDEN: --prolong it just so we can see if it finishes.

  • RODRIGO DABOIN SANCHEZ: It would be funny if as soon as we cut the stream

  • it ends.

  • Right?

  • COLTON OGDEN: Yeah.

  • That would be pretty funny.

  • Yeah.

  • Asli, our pleasure.

  • Ronnie was excited to see it finished.

  • Ronnie you should take it and run it yourself.

  • Clone off of GitHub and try it out.

  • And then see, maybe time it, use the time function at the command line,

  • or whatever, on a mac or a Linux.

  • I'm not sure what it is PC.

  • RODRIGO DABOIN SANCHEZ: The current version

  • is still using a list for the searched.

  • COLTON OGDEN: Right.

  • Yeah, so you'd have to switch it to the set version

  • in order to see what that performance difference would be.

  • Virani says, too bad it's too late.

  • Maybe I'll watch the VOD, referring it to tomorrow's stream.

  • Yeah, definitely watch the VOD.

  • All these videos go up on to YouTube.

  • I'm going to very tragically transition as back to the full shot here.

  • We're going to say that maybe this won't actually

  • finish by the time the stream is over.

  • Ah, geez.

  • BeastKris, "turned in too late today."

  • Don't worry, the video is going to be on YouTube.

  • So it'll be on YouTube within a couple hours.

  • You'll be able to see, watch it in its entirety as all of our videos are.

  • And what I was going to say was if you are watching this on YouTube,

  • you can tune in to CS50.

  • It's Twitch channel on twitch.tv/CS50tv.

  • Every week we have programming videos from scratch.

  • I do game programming.

  • Rodrigo came in today to do some Python.

  • David's going to come in tomorrow to also show us some Python stuff.

  • And more I guess to talk about making applications using pre-built software,

  • because we did use a lot libraries for that application.

  • But yeah, a pleasure as always.

  • Thanks everybody who tuned in today.

  • We'll catch you tomorrow at 3 PM Eastern Standard time with David for render 50

  • so thanks again Rodrigo you for coming in today.

  • RODRIGO DABOIN SANCHEZ: Thank you for having me.

  • COLTON OGDEN: Much appreciated.

  • We will see all of you later.

  • Have a good rest of your day.

COLTON OGDEN: All right.

Subtitles and vocabulary

Click the word to look it up Click the word to find further inforamtion about it