- Mm-hm. Aha! So that was fake. Welcome to, it was already solved, welcome to coding challenge
on the coding train. (blows train whistle) Rubik's Cube. So today, a while back in April 30, 2018, nilsweb suggested a Rubik's cube solver using a neural network. By the way, this is the green
side, not the white side. See? Eh. And I'm really interested in this. I actually picked up a
Rubik's Cube over the weekend, I've been learning to solve it, it takes me at least a half an hour, but I do do it, I don't
have to watch a video while I'm doing it. I did have to watch a bunch
of videos to figure it out. Getting off topic. But I really want to explore this idea. What types of AI machine
learning algorithms can I apply to solve a Rubik's Cube? This will be interesting to try. And to put on the channel. But there's a lot of steps I need to get to before I can get there. So what I'm going to start with today, is just creating a
Rubik's Cube simulation. Simon-tiger also posted an issue showing all the different
kinds of Rubik's Cubes configurations that are out there. Apparently there's this 28 by 28 one. I have some of these at home, they're super fun to play with. Anyway, but, so. So let me close all this stuff out. I should also reference Code Bullet. Code Bullet is a YouTube channel that has many different coding, exciting, adventurous topics, and Code Bullet has a video using a particular algorithm to solve a Rubik's Cube then
makes a giant Rubik's Cube. So if you want to get the 16 minute version of everything that is going to take me the next 700 days to figure out in
one video and be entertained? I would definitely recommend
the Code Bullet one. So closing that out, I'm going
to start here in processing. Processing, if you're not familiar, is a Java-based development environment for creative coding, images,
animations, all sorts of stuff. I use it a lot on my channel. I'm pretty sure that's
what Code Bullet used for his Rubik's Cube. I'm going to add the
setup and draw functions. I'm going to add a
window that's 400 by 400 and I'm going to put in P3D. So P3D I definitely need
to use a 3D renderer because I'm going to
represent the Rubik's Cube in three dimensions. Let's make a. Let's make a class called box. I'm going to call each one of these little cubes inside the larger cube each cell of this three by three grid, just going to call it a box. So I need a constructor. And I need to know where is it, I need to know it's index in some type of, maybe, multidimensional array. But for drawing it I
really just need to know where it is in the virtual 3D space. When I create it let's
give it an X, a Y, and a Z. And then also, I need a side length. So I don't know whether I need the full side length or a half length. That's definitely going to be
something that's going to come up. But let's just assume right now, that I initialize it
with a full side length. And then I'll use a
Pvector, a vector object for the position and a
float for that side length. Let's just call that side. Oh, I'll call that length. And I'll use an underscore here to make this a different variable name. So now, I'm going to say
position is a new Pvector. X, Y, Z. And the, this needs a semicolon here. And the length is equal to this. So then I'm going to write
a function called show. And I'm just here, I'm going to say, pushMatrix, which saves
the transformation states. PopMatrix which restores
the transformation state. Oh, my god, what's a transformation state? You might be asking. So I'll tell you what it is. What I need to do is I
need to say translate to position dot X, position
dot Y, position dot Z. This is basically positioning
what I'm about to draw. This box with this
length at this position. I have a feeling people
who are watching this live in the chat are telling me
this isn't going to work. Because I need to color the
different faces differently. I'll get there, I mean, I have
to get there at some point. But let me just use the
processing box function which will just put a box right there. So in order for each box's translation to not affect the others, that's what pushMatrix and popMatrix does. I'll put something in
this video's description to more about matrix transformations if that is new topic for you. Let's just say a fill 255. Stroke zero. Stroke weight eight. And then I have this box class. So now I need to make a cube object. It's not really a cube object,
I'm making it right now. I could make a cube
class, I probably should, but just for simplicity right now let me make a three dimensional array for rows, columns, and what's
the other one? (laughs) I don't know, if you have a third one, it's the Z axis, I suppose. And this is going to be, let me make a variable
called dim for dimensions. 'Cause in theory, if I do this right, we could just change that one variable and have a much bigger cube. Equals new, box, which is dimension. Ah. Dimensions by dimensions by dimensions. Then I'm going to say, I'm going
to do a triple nested loop. With I, J, K. I, J, K, I, J, K, I, J, K, and then, I am going to, say cube index I, J, K, is a new box at some X, Y, Z, with some side length. How do I figure this out? If this is going to be
at zero, zero, zero, this is going to be at one, zero, zero. If I go down here I'll be
at like one, one, zero. Back, maybe the last row, anyway, you get the idea. It's like a grid but
with another dimension. I think I'm doing this right. But I need a side length. Let's just make that up right now. Length is, let's say it's 10. So the X would be length times I. The Y would be length, and
I might have my axes wrong, but whatever I call X, Y, and Z axis, eh, whatever, they're
all just different axes. I, J, K. So I'm going to say box X, box Y, box Z. X, Y, Z, and then length. And then, I mean, there's no way this is right. (laughs) Like, how could I possibly get, oh, I need another curly bracket. And then, now, if I grab this four loop and I put it in draw, but all I say now, is cube I J K, show, I almost want to keep these
in another array that's just a one-dimensional array for simplicity. But let's see how this goes. Hey, look! That's kind of like the Rubik's Cubey thing up there in the corner. So one thing I want to do,
I definitely want to do, is I want to add, well. (laughs) I want to first give it a background. Background 200. I'll use my number 51. And then I'll probably
want the side length to be much bigger and
let's just run this again. And you can see it's sort of up there. I think I need a larger space here. So I need to position it in the center so I can actually see it. And there's a variety of ways to do that. I could just translate to the center. But I'm going to use a library,
I think I have it installed. Import library, I don't, this is great. I'm going to use a
library called PeasyCam. And I'm going to hit install PeasyCam. For processing easy camera is a way, a library that allows you to very quickly get a mouse-camera interaction. Where I can spin around a
3D scene and processing. I've used it in other videos before. So I think if I just say PeasyCam cam. And then if say something
like cam equals new Peasy. Thank you to Jonathan Feinberg who created this library PeasyCam. This, I forget, this is
something to do with like how zoomed out or zoomed in it is. Oh, import. I need to import the library. Which I can do automatically like this. Import library PeasyCam. Was it there and I just didn't see? (laughs) There, ah, there we go. Look, hey, (rings bell)
coding job finished, thank you. (laughs) No, there's a lot more to do here. But look at this, that kind
of looks like a Rubik's Cube. Now it's rotating around
it's little corner there. I want it to rotate around the center. So what I need to do, I
need to have an offset. And the offset is going to
be half of the full width. So the full width is
dimensions times length and then if I divide that by two. So if I then subtract out the offset. That should give me our
nice little cube, no. That's not right. Oh, because. I think this is my off by, I think the box function is
probably using the half width. But then that'll be off now. No, ah, that's not right. What I have done? I think I have this
off by dividing by two. Alright, here's the issue, I actually just made a little diagram. If the box, these are just
two-dimensional rectangles, were drawn from the
corner like they are in, two D rectangles in
processing, this would work. Because I've just shifting everything over and the middle one is, but, the middle one is now
placed in the center. 'Cause I'm shifting over
by the total width is 30. I'm shifting over by 15, we've
got half here half there. But they're not, they're
actually drawn from the center. So by shifting them over I end up with the first two on one side and the other. So I actually need to shift it. There's a half of a
length that's incorrect. So there's probably a smarter
way to fix this formula. But right now I'm just going to
add another half length here. Or the offset, actually, that's silly. I should really add it in the offset. So length divided two plus this. And now we should have. (laughs) Eh. Oh, no, minus! I need to shift it over but it's in the offset, the offset
is a little bit less. Dimensions minus one, that's the issue! Hold on, everybody. This is so silly. Change this to point five. And this is actually dimensions minus one. Times length and then half of that. And now. We should have it, there we go. There's my Rubik's Cube in the center. Alright, phew, and I'm
being told, by the way, that these are called cubies. So I'm going to change that. Class, Cubie. Cubie. Cubie, Cubie. And Cubie. Step one is complete. But as you'll see, if
we look at this, whoops. If we look at this Rubik's Cube, each face has a different color. There are only six colors. There's white, red, so white on the top, yellow on the bottom, and then red, blue, orange, and green. So let me make an array with those colors. I think what I can do is just say. Oh, there's a datatype in
processing called color. It's actually just a integer. And I'm going to, let's
come up with an order. I'm going to say top,
bottom, I don't know if this is a good order to do. But top, bottom, I'm going to think of
the top as always white. So top, bottom, and then
right, left, front, back. Right, left, front, back. And I know there's actual
Rubik's Cube notation and I'm probably getting
that a little off. I think it's actually not
top, bottom, it's up, down. Up, down, right, left,
front, back. (rings bell) Okay, I'm back, I finished off the colors for this array and I'm using the order up, down, right, left, front, back, and I'm just right now,
using the convention as white being on the top. But I know there's some different ways of looking at the cube. You can think of yellow as the
top and white as the bottom. But I'm going to use, yellow's
the top and green as the front. So I have these colors. So how do I, then, apply these colors to the different faces
of these little Cubies. I love that they're called Cubies. It's like, that's like the
greatest thing I learned today. Unfortunately I will not be able to use this box function anymore. However, I can use my
own beginShape, endShape. So what I really want to do, instead of just using the box function to draw the full three-dimensional Cubie, I just need to use quads. I can use four quads, I
can probably use rectangle function or different things, but, I can do one quad, well
it's more than four. I need to do six. One quad, another quad, another quad, another quad, and another quad. Now, of course, if we look
at the actual cube itself, each of these corner pieces,
you can only see three faces. These other pieces on
the middle and the top you can only see two faces. But I'm just going to do all the faces. For each Cubie. We can optimize later, if need be. So let's just do one. So in other words, if I say, beginShape quads, then I can create the,
and let me just say, the R equals length divided by two. So now I'm going to take that side length and divide it by two because I want to set the vertices offset from the center. Negative R, plus R, negative R, plus R. So I should be able to
do, for the first one, vertex, negative R, negative R, zero. And I'm going to keep the Z
at zero for this first one. And then. So let me just diagram this, right? If this is what I'm doing. This is negative one, negative one. This is one, negative one. This is one, one, and this
is a negative one, one. So basically I just need to set all of these vertices to draw that quad. And a negative R, R. (laughs) What did I say it was? R, negative R, R, R, negative R, R. And now if we run this. We should see, oh, whoa. What did I just do? So first of all, oh,
you know what I'm doing? I'm still drawing the box. Yeah, take out that box,
thank you very much. And there we go, we can see now I just have those front faces. So all I need to do is do
exactly the same thing. I just need to do six of these. So with different axes. So if I put zero, zero,
zero, zero, zero, zero, zero, zero, and take the
zero off of the Z now. I have got, oh, wait a second. This is not right. (laughs) Oh! (rings bells) Oh, I'm so silly, this isn't zero. This is either at negative R. This is one side. And then the same face,
so comment this one out. Would be, at R, right? These don't cross the
center of each little Cubie, they go along the edges. So the Z has to be. So now we can see, now this is right 'cause it's a three by three cube. Looks like, why is there four? But these are the front and back or the left and right
or the top and bottom, every one I consider it. And so now if I do this. With negative R, of course, and then the same thing with positive R. There's six faces. There we go. Now I have my Rubik's Cube but without the left or right or top or bottom. (laughs) I have no idea
what the orientation is. But the Y axis needs to be fixed. So this is Z being fixed. This first one was Z being fixed. This one is X being fixed. So I'm going to say a Z fixed. X fixed. And now I need to do one that's Y fixed. And that, is going to be. So this one, I copied, what did I copy? I copied Z fixed. So all I need to do is fix Y. So negative R, negative R, negative R. R, R, R, and then this should be
negative R, negative R. R, negative R, R, R, negative R, R. And same thing here,
negative R, negative R. R, negative R, R, R, negative R, R. Look! There it is again! There's our cube but all different faces. So I have no idea. Let's just make a total guess here. What if I say, just for this. So let me do a fill on all of these. Fill 255. Fill 255. Fill 255. Fill 255. Ah, fill 255, fill 255. So now they're all white. But I can say, remember I have my colors. And what I'm actually going to do. Let's make some variables
that just keep these. Let's do top, no, let's do up. Well these are key words in processing. Let's do them all three letters. Up is zero. Down is one. I just want to keep
track of these constants. Final, is that a thing? I don't know. I don't know how Java works. There's probably like an enumerable. Down, right, left, front, and back. This might, I mean, this
is sort of unnecessary, but let's do that. So now, up, down, right,
left, front, back. So in theory, I want to say fill. If this is the top, I
have no idea if it is. (laughs) Whatever the top is. Fill colors top. Up, (laughs) up. Yes, that's the top, it's facing, whoa. Oh, yeah, it's white. (laughs) I shouldn't pick white as
the first one. (laughs) Fill colors, they're already white, down. Alright let's find where that is. Is it going to be on the bottom? No, it's facing us, but that's fine. Because the way I drew it, this is really the top over here, I think. So that's fine. Whatever, the point is I
just have to be consistent. Colors, so this would be if Y is fixed, if Y is fixed we're doing, oh, no. If Z is fixed. (laughs) Z is fixed, it's front and back. Behind is back, this is front. And then if Y is fixed,
it's not really fixed, then we have top. That's actually bottom. And then this, would be, and it's down and this is up. Boy, this is taking a crazy
amount of time. (laughs) I can't believe how much
time this is taking. And this, everybody in
the chat is going crazy with better solutions than this. X, this is left. And this is right. Alright, let's see. Oh, hold on. (laughs) Let's look here. I have white, green, red,
orange, yellow, blue. Ah, red and orange are in the wrong place. Red and orange are in the wrong place. So, actually, drawing it is correct, I just have the colors
swapped incorrectly here. This should be orange on the left and red should be here on the right. Let's check it, here we go. Alright, so I'm looking at
green with yellow next to it. So I'm now holding it the same way. Green with yellow next to it. So if I go orange, red, white, and on the back, blue. I have now drawn the Rubik's Cube. I have made some of you
happy who think that the top is yellow because
the top is yellow here. 'Cause I drew it with the Y axis flipped. Even though it says top
is white in my code. Who knows, I'll figure that out later. Something that would really improve this would be using e-nums, enumerables, instead of these list of constants. It's a little tricky to
do that in processing because of the way that
processing wraps Java. Maybe I'll fix that up
when I refactor this later. In the next video I'm going to work on actually trying to figure
out how to do a rotation. How to turn and move the stuff around. And actually have all
the data move, as well. So that I could shuffle the Rubik's Cube. If at least in this first part, if I can now then make the moves, then I can do another part
where I can shuffle it and then play the shuffle back in reverse to make it look like it's
being solved, that'll be fun. Another thing that's really missing here is that you'll notice on
an actual Rubik's Cube, that the faces that you can't see are actually colored black. Whereas, once I start rotating these, all those other colors are
actually there internally and in fact, there's
like a cube in the center you'll never see, it has
the colors on it in mine. But eh, I think I've done enough. I will see you in the
next video. (rings bell) (upbeat music)
Just came here to post it :D