« All Episodes

Interview with Mark Engelberg (Part 2)

Published 10/11/2017

In today's episode, I interview Mark Engelberg. Mark creates puzzle games, and most recently created the "CODE" series of games in collaboration with ThinkFun. Mark's insights into learning and teaching are fantastic. I hope you enjoy this episode!

Today's episode is brought to you by Swiftype.

Swiftype is an AI-powered search platform that delivers fast, relevant and customizable search results for websites, applications and businesses. Swiftype's suite of products have revolutionized the way people find information across their organization and on public facing websites. Integrate easily with tools like GitHub, JIRA, Confluence, Dropbox, and more for even better searching power. To learn more about Swiftype Search or for a free trial, visit swiftype.com/developertea today!

Transcript (Generated by OpenAI Whisper)

It's just easier to compare to immutable data structures than mutable ones. So if you want to teach the kids how to test their own code, it's just easier to do that with functional programming. So I love it as a starting point. And then I found that kids who begin with that, later, they don't have any trouble adding in the mutation stuff later. It's just like this becomes this extra spice they sprinkle in where needed. Because it is a more powerful tool. Mutation lets you do some things that you can't do without it. But you learn to use it only when needed. And you already have these years of experience of writing most of your code in this very clean subset that's easy to test and easy to read and easy to understand, easy to verify it's correct. And you're only using the mutation only when it's needed. Whereas people who come the other direction, they're kind of used to using mutation everywhere. Yeah. And so it becomes... It becomes something that they have to train and practice with a lot of exercises to try to learn how to restrain themselves from using this powerful tool that also, unfortunately, has the potential to make the code more fragile and harder to understand if you use it excessively. And so learning to not use it so much is actually... Sometimes it's harder to go that other direction. How can children learn through play? And what can we as adults learn from children? It seems like there's this switch that flips at some point and we go from playing to working. And the overlap there becomes very small and perhaps it is not there at all for some people. So what can we learn from children? That is one of the things that we're going to be discussing. In today's episode, we're talking about puzzle games with Mark Engelberg. And Mark is the creator of a series of puzzle games that helps teach children and really people of all ages how to code, how to think like a coder, a good programmer would think. So these games are teaching excellent fundamental skills in thinking and procedural aspects. We're going to talk more about the specifics of the game in this episode as well. My name is Jonathan Cottrell. My goal is to help you become a better developer each and every day. Even if that's only by a very small percentage. Today, I want you to become better. And if you want to become better, it takes work. It takes sacrifice. Sometimes it takes changing an opinion. Sometimes it takes listening to something and letting it sink in so that later it blooms. In other words, it's kind of like you're putting a seed deep inside of your brain. So that later it will actually grow into something useful. So maybe that's what today's episode is for you. Maybe you are actually interested in expanding the way that you think by not just engaging code directly, but maybe playing some of these games that Mark created. So again, my goal on this show is to help you become better. Help you become a better developer. Help you become a better thinker. And if I've been able to do that for you, I'd love to hear your story. If you'll send me an email at developertea at gmail.com, I read every single one of these stories. And I try to reply to every single one as well. So please reach out. Let me know where you are in your career and how this show and some of the ideas that you've bounced around and maybe the conversations you've had as a result of this show, how that has helped you. I love hearing those stories. It's energizing to me. Thank you so much for listening to today's episode. I want to get straight into interviewing. Mark Engelberg. Some of the most common things that I see, especially in beginning CS tutorials and learn X language is, for example, building up a collection of things using a for loop to iterate over a different collection. And you're adding to, you're appending something to an array. And once you've gone through this for loop, then you have a new array. And, uh, that that's an example of, you know, that that's a very simple and usually a pretty easily controlled example of something that if you use everywhere can become a big problem, right? You know, I've seen, um, if statements that could never be hit, but it's difficult to figure that out. It's difficult to figure out, you know, when you're three or four nested, if statements and you're trying to build up an object or a dictionary inside of these, if statements, based on the presence of, you know, some key or something like that, right? And this happens all the time in, in JavaScript, it happens, uh, really across the ecosystem. Uh, won't focus on any particular language here. Um, but when you, when you have that nested and lots of deep logic and you can't look at it and understand what's going on, you know, really, if you can't look at it and understand what's going on, how do you know that it's right? And the only thing that really tells you whether or not it's right is if you have a very well structured, uh, test, suite, right? The problem is so often we don't write test suites that truly cover every scenario. They don't truly cover every edge case. And in fact, there's some theory that says it's impossible to cover every scenario, every test case. What's not impossible is to write code that will work every time that is actually possible. That is actually possible to do. And when you can reason about your code, uh, when you can look at, uh, what you've written and know, okay, anytime I give it this, it will work every single time. If I pass it this letter or number, if I pass it this structure, this data structure, no matter what I do, this piece of code is going to work, uh, the way that I expect it to. You know, if you write tests, uh, this is for as, as a rails developer, I've seen plenty of tests that have, you know, a hundred lines worth of setup. And the reason that they have a hundred lines worth of setup is because in order to, to test the behavior of a given method, well, you have to have a scenario, right? And that scenario is really all of the data surrounding that method. It's typically found in integration tests or, you know, what are called feature tests. But so much of this code is setting up a scenario. Well, what if the scenario actually goes wrong? Uh, what if one, one piece of data that you have set up in that scenario, what if that actually isn't working that way in production? Or what if something gets corrupted? What if, you know, and there's so many things that you have to look at and test for, for that test to even be, but to be valid in the first place, that you almost feel like you have to write tests for your tests, right? Like it's, it's a very strange and large ends up being a lot of code. Um, and ends up being sometimes more test code than you have in production. On your production code. Yeah. I mean, the latest thing in the, at least in the functional programming community is, uh, a big focus on generative testing. Have, have you talked about that in any of your previous podcasts? No, no, I'd love to hear more. So generative testing is focused on this whole idea of, you know, that, that it's difficult to write exhaustive test cases yourself. So why not let the computer write our test cases for us? And it turns out that's a lot easier to do when you're in a functional programming language than in an imperative one. Cause usually testing in imperative language, it revolves more around trying to think about kind of what invariants have to hold as some data structure is changing over time. And it's difficult to track that value as it flows through multiple things that are changing it. But with, uh, like I said, with pure functions, as long as they're tested in isolation, each one is working the way you expect. Then they're going to compose together the way you expect because nothing's changing something out from under something else. Um, and the way generative testing works is you describe kind of what is the kind of data that's going to be inputted into this function. And you describe some kind of properties of the output that it's going to be put, you know, that's going to come out of this. And then maybe some properties that it has in isolation, maybe some properties, some properties relative to the input. And you describe this, and then the system itself generates, you know, thousands upon thousands of sample inputs, all kinds of crazy stuff that you wouldn't think of yourself. If you were typing it out manually, it's going to check all the weird stuff for you. Just going by your specification of what kind of data needs to be input into it. It's going to generate lots of bizarre examples. It'll generate the, the normal stuff. And then also really strange stuff that fits your specification. It'll pass it into your function and then it'll check that it obeys all these properties that you're saying the output has to hold. And it'll do all that for you. And people routinely find that when they apply this to functions that they, this technique to functions that they thought were pretty solid, it's pretty common to discover new interesting edge cases and things that you just hadn't thought about because you were thinking like who would actually, Yeah. ever do that in real life would pass that kind of input to it. It just didn't cross your mind, but the system will find it generating random inputs. Yeah. Well, and the thing is, you know, this is, this is a bias that I, that I think I talk a lot about cognitive biases on the show, writing code and then assuming it's going to work or writing a limited number of, of test cases and assuming that you've covered things. This is a confirmation bias. Right? Because when you write those tests and they do indeed cover what you thought they were going to cover in your code works as you expected it to in those test cases, then it's easy to believe that you're done. It's easy to kind of check that box and move forward. And the problem is, you know, you're not, you don't have the luxury of seeing the code for the first time. You don't have the luxury of, of recognizing inputs that you had never thought, could be input. Right? And, and so that's, that's a problem. And I love this idea of generating those inputs because then you're not in control. This is actually a good reason to use something like, you know, a random data generating software packages. This exists in, in Ruby testing. I assume it exists everywhere, but fakers, right? So having something that generates first and last names, rather than, you know, deciding your, your static first and last names, that way you get a wide array of inputs into your tests so that after running them a hundred times, you know, you've had a hundred different inputs with the same conceptual data types and that kind of thing. And one comment I've sometimes got from programmers, when I talk about this idea of starting with functional programming, they sort of say, well, you know, what good is it if when they get to the real world, they're not going to be able to use this stuff anyway. And, and what I found is that you, you can use this in the real world. First of all, even in mainstream languages, most people who have spent some time doing functional programming say that it transforms the way they think about regular programming languages as well. And they will automatically find themselves programming in a style with, with more pure functions and, and relying on mutation less making programs that are easier to test. They, they're looking for tools like generative testing in a mainstream language. Like they, it changes the way they think about it and they bring that approach to the regular programming language and it makes the programs better. But on top of that, there's a lot of choices emerging for people who want to use functional programming in their actual jobs. Um, I use on a day to day basis, a programming language called closure and closure is a dialect of Lisp that runs on the JVM. So, it can interoperate with, you know, your existing Java code and it's, it, it's a really wonderful functional programming language that has, uh, sort of the full suite. A lot of the educational programming languages, they only include the barest minimum of data structures because as a, as a learner, you're mostly going to be coding your data structures yourself to kind of learn how they work. But as a working programmer, you want that stuff built into your language. So, closure was one of the first programming languages that took the same suite of data structures that you expect from a modern programming language, uh, you know, and, and give you immutable versions of all of these things that make it easier to write these pure functions. So it comes with something kind of like an array, but when you update an element like it does it in near constant time, but it's, it actually is returning a new data structure, that shares a lot of underlying memory with the original data structure and only, uh, the elements immediately surrounding the one you changed is actually taking up a new slot of memory. So it's very efficient. It's much more efficient than like copying over a whole array and then just changing one element like that would be horrible performance if that was the way it was implemented, but it's not. And so it gives you something like an array. It gives you something like, uh, it gives you a list. Uh, it gives you, um, sets. It gives you hash tables or maps or dictionaries as they're called in different languages, gives you immutable flavors of all these things and, and a really wonderful set of functions for working with these data structures that where the functions kind of consistently work the way you expect on all the different data structures. So, um, you can take those ideas from a functional programming language you learn and you can carry it over to professional life if that's what you want. So that's what you choose to do. Yeah, yeah, absolutely. Uh, there's, there's, you know, I've, I've done a lot of, um, work trying to incorporate some of these ideas into languages that I use that are not enforced. Uh, they're not functionally enforced. Uh, and there's so much, you know, um, for an example, if you have functions, let's say you're writing JavaScript, that's a pretty common language. I don't like to hyper focus on languages, but, uh, you know, sometimes it's, it's worthwhile to, to talk, you know, practically. Uh, with JavaScript, you know, you can write functions pretty much anywhere. They're, they're, they're all over the code, uh, that you write typically. And, um, a lot of the time, uh, I've seen it, a lot of code and I've written a lot of code that has a function that does something rather than returning something. Mm-hmm. And this is kind of a code smell. If you're writing functions that only do something, especially if you're writing a lot of them, then you're probably going to benefit from thinking of ways that you can return a value from those functions and use it moving forward. All right. It's kind of weird. You, you'll see what I mean, kind of thing, right? Uh, once you start writing, uh, that code, you're gonna see how it changes the way you think. Instead of thinking in terms of what steps can I take, you're gonna start thinking more in terms of what transformations am I making? What am I, you know, what, what is this function providing me? How am I using what it is, what it's providing me in the overall structure of what I'm doing? So you don't have to be, you know, you don't have to perfectly, uh, adhere to every single rule of functional programming to start practicing some of the things that functional programming, uh, you can benefit from, right? You can do this in Ruby, you can do it in Python, you can do it in JavaScript, you can do it pretty much every single language. There's so many ways of practicing this stuff. Uh, and, and, you know, I've actually done an episode specifically about that where you can actually benefit from, from functional programming in other languages. Uh, I don't remember what episode number it was, but it's, it's been a while since I did it. But, uh, this is something that I think is really important for people to, you know, if you start thinking about your code in, in new ways, this is one of the ways to start viewing your code. How can I make it better? This is a, an excellent route to kind of take those first steps down the road. So, take those first steps down. Definitely. Today's episode is sponsored by SwiftType. You know, search is not an easy thing. There's a lot to consider when you start thinking about search. Uh, you have to index words and you have to weight them and you have to understand when phrases fit together and there's smart operators. And if you're building your own search engine, uh, for your site, then you're probably doing something wrong and you have a lot that you have to learn to be able to do it. So, uh, I'm going to stop here. I'm going to go back to the chat. I'm going to go back to the chat. I'm going to go back to the chat. I'm going to go back to the chat. I'm going to go back to the chat. At the last minute, you may have taken your name off the title of your search title and you may have taken your name off the title of your search title and you may have taken your name off the title of your search title and you may have taken your name off the title of your search title title and you may have taken your name off the title of your search title and you may have taken your name off the title of your search title and you may have taken your name off the title of your search title and you may have taken your name off the title of your search title and you may have taken your name off the title of your search title and you may have taken your name off the title of your search title and you may have taken your name off the title of your search title and you may have taken your name off the title of your search title and you may have taken your name off the title of your search title and you by giving you AI-powered search that delivers fast, relevant, and customizable search results for websites and applications and for businesses. And Swift's type suite of products have revolutionized the way people find information across their organization and on public-facing websites. And for public-facing data, for example, searching your own website, you can create and deploy a website search experience tailored to your audience in just a few minutes. And for internal organization data, stuff that's not necessarily accessible on a website, you can securely search for your files, your tickets, your pull requests, basically all of the stuff that you already use, like GitHub and Jira and Confluence and Dropbox. All of these services, Swift type is going to allow you to search across all of them. You can customize through APIs as well. So you can customize the search experience through the API. For clients and for content ingestion, querying, and management. Now, Swift type is SOC 2 compliant. SOC 2 is a standard of privacy, security, availability, processing integrity, and confidentiality. And Swift type has gone through all of the measures maybe you didn't even know existed to make sure that your users are safe and that you are providing the most secure search experience as possible. And more importantly, for your website, you can customize the search experience as well. For your business, all of your data is going to be safe. You can start your free trial and you can learn more about what Swift type has to offer with Swift type search by heading over to swift type.com slash developer T. That's swift type.com slash developer T. Thank you again to Swift type for sponsoring today's episode of developer T. So Mark, we've talked about a lot of things. You know, one thing that I would like to do with you is take a step through each of these. These games that you've sent me because I think, you know, each of them has a different aspect that is important to pull out and explain a little bit about these fundamental concepts, fundamental skills. You know, we already mentioned one of them, which is translating, you know, the thing that's in your mind to a computer, encoding that information into a computer. And which game was that, did you say, that best covers that? That was Rover Control. That's the second game in the series. And that's the one where you have the various lines. And that's the one where you have the various lines of different colors, correct? Yes. Okay. And so we have the other games. We have On the Brink and Robot Repair. Let's talk about On the Brink. And if I remember correctly, this is the one where you actually kind of provide instructions for the robot to move throughout a series of tiles. Is that right? Yeah. So On the Brink also involves controlling a robot to kind of move around a maze. In this one, you're moving on a maze of... Yeah. ...coloured squares. And each square determines which procedure you're going to execute, and you have to build those procedures up. So the fundamental instructions are move forward, turn left, and turn right. And you're building procedures just out of two instructions to keep it really manageable. But you're building a red procedure, a yellow procedure, and a blue procedure. And as the robot lands on a space, it's going to then execute that procedure until it's done, and then it's going to look at what colour it's standing on and do that one. And you're trying to find the procedures that are going to get this robot through the maze. And what I was really focused on here is I really wanted to convey to students what I think is one of the core ideas of computer science that I want them to come away with, even if they don't become computer scientists. And that's the idea of procedural abstraction, the idea of making components that are reusable. Because I think that's what makes us able... I think that's what makes us able to build such amazing things in computer science. We start off with assembly, and then we create a language that lets us build on top of that. And then we write some functions, and then we put those functions into objects. And then we use those components to build whole libraries. Then we use those libraries to build these amazing programs. And we keep building layers on top of layers on top of layers. And so that's what this game does. Initially, you're just building the procedures out of the... These simple instructions, the turn left, turn right, move forward. But then in the second half of the game, as you get to the more advanced levels, we give you a whole new set of cards. And the new cards are themselves procedures built out of the forward, left, and right commands. And you're building procedures out of those procedures. And on top of that, you're trying to find procedures that work in multiple locations on the board. At the same time, you may have toension the playersijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijijij things out of things and then building things out of those things. And that's what makes this so fun. Yeah. You know, there's kind of an interesting corollary that I have never actually realized until you mentioned this and kind of recognizing some things that I pull from. You know, the human language, we use a lot of things that essentially they're symbols, right? So the words that we use, they call back into some information that we've encoded in ourselves for that word. And we have various procedures that we think of. You know, I can say test-driven development, and that means 100,000 things, right? And so that word is in a good way, I would say, loaded. It has a lot of information that is communicated there. And so, you know, the idea that I'm thinking of, when I was younger, I played football. This is like little league football. And one of the things that we learned is how to identify a play, right? It's a play that has a name and it has some identifying information. Some of it is important. Some of it is less important. Some of it gives me instruction. And some of it is more like, once again, a signal, a sign that points me. At the same time, you may have evolution, evolution may have evolution, evolution may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may may creating these modules, these repeatable or kind of packaged modules that, you know, they have a single pointer, if you want to call it that. They have a single name, a single way of identifying them, but they mean more than one thing. And if you can compose these things together, then you can look at it and say, okay, I've got these five pointers. I've got these five things that I can put next to each other. And I can organize them in a way that's meaningful. And ultimately, those five pointers can mean a hundred thousand execution things, right? They can mean so much more, but all you have to really do is understand what those pointers mean in terms of the architecture of the application. Does that make sense? Yeah. I mean, I think you're talking about what's a very core skill, which is to kind of think individually. In terms of modularity. Yeah. Yeah. And in terms of abstraction, we can, learning to trust the various levels of abstraction to do what they say they do. And, you know, this goes back to our previous discussion about having code that is reliable and tested and all of that is so important to be able to create reliable abstractions, abstractions you can trust to do the thing that you say they're going to do. Yeah. It's fun for me to watch. It's fun for me to watch kids play on the brink because when they get to those advanced instruction cards that are procedures, they always start out moving their robot and stepping through every single element of the procedure. But a lot of the procedure cards are designed in such a way to have an overall effect that's easy to understand. So like one of the cards is, we call it long turn left. And it's like you move forward a step and you turn left, and then you move forward again. So it's like three components to do this kind of bigger left turn. And what you see is that after the kids have used the procedures for a while, they start trusting, just like you said, they start trusting that the procedure does what they understand it does. It always does this large turn left and they'll stop stepping through the individual steps. They'll start automatically just doing the whole long turn left as kind of one action. And to me, it's always a thrill seeing them have that epiphany right there in front of my eyes that now they can go from, instead of thinking, it's relieved a whole bunch of mental effort from the point where they had to step through everything to where they can now think of it as one big action. Now they can reason about things at a much higher level and it makes the puzzles much more tractable and seeing them go through that is really cool. And that's exactly, that's, the perfect explanation of what abstraction is, is, is being able to say, okay, I, I'm going to trust this thing and I no longer have to, you know, tax myself cognitively to put that robot through every single step, right? I know some patterns now. I can use these patterns reliably to accomplish something. And now I can, I can compose these things a little bit faster. I can do, I can remove the cognitive load a little bit and say, okay, yeah, I, I know that I can do this and I know what that does. And I can move forward and do more complex operations, you know, and, and a really cool part, I'm going to ruin some of the plot twists of the game, if that's okay. Really cool thing that happens in later pages of, of on the brink is you start to see that the, you know, previously you're providing them with, hey, okay, these, these things are what you're going to need to be able to solve this, right? These particular moves or procedures, these, you need to turn lefts and one move forward, right? Or, or whatever the, the particular thing may be. And later on in the book, you remove that and the, the student or the person who's playing the game has to decide what to use. And the, the truth is they may decide to use, you know, there's not only one solution to every single puzzle. Is that true? There, there is. There's a solution to every puzzle in this game. Yeah. In this game. Okay. It's designed so that there's only one. So it feels, I think you're right that it feels very free form. And that was really intentional on my part. One of the criticisms. Well, you fooled me. I guess that's the best way to put that. That's awesome. Yeah. I mean, one of the criticisms I've often heard about other programming games is people say there's something, especially programmers will point out that there's something kind of artificial about it. Because as a programmer, we're never told you have to write this program using exactly two of these function and one of this other function, one of like, like there is an artificial set of constraints that make it a puzzle. And I really wanted to design a system where, uh, you in that expert level, we could say use whatever instructions you want out of, I mean, you're, you're still limited to the cards that we've given you in the set, but it, we're not telling you specifically what to use in it. It feels much more free form. It feels much more like writing a real program. And, uh, the, the maze itself is very carefully, cleverly designed so that it, there is exactly one solution, but it feels very free form solving it. And that is exactly what I was going for. Yeah. And, and what's so interesting, you know, you can draw, uh, these cool parallels to, uh, the kind of the professional, uh, developers job, right. Um, in this case, we have a set of tools like documentation. I know what methods are available to me and it's my job to take these methods and compose them. Right. And it's not, it's not a set of resources. It's a set of things that I can, I can compose together. And I know what tools I have. I have more than enough tools to solve this problem. Now, which ones will I use? And so that, that is a kind of a meta level problem solving, uh, uh, uh, aspect of this that I think is really interesting. So, I want to move on though, uh, to robot repair. Can I, can you kind of give a overarching idea of the narrative of robot repair? Yeah. So robot repair, um, the skill I was focused on there is the idea that logic is something that's very fundamental to computer science. And it's something that isn't given a lot of attention in computer science curricula. Um, we need every day we use and, and, or, and not, and maybe sometimes we'll use more exotic things like exclusive or, or, uh, if you're doing digital engineering, you might use NAND or NOR. Um, we use these things, but we're often left to just use our own intuition from English. Like teachers will say, okay, this programming language, it has and, or, and not, uh, use it the way you think you should go. And it turns out that's not a very effective way to teach those things because, um, a lot of those things are not going to be used. Don't behave quite like what we think of from English, like, or, um, a lot of times in English, we're really using the exclusive or like, if I say, you know, I'm going to dinner or I'm going to a movie that you're, if I, if I did both, you might be very surprised by that because it sounds like I'm saying either this or this, but not both in computer science. Of course, we always mean the inclusive or unless otherwise specific. And, uh, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, So what I wanted to do is I wanted to develop a logic puzzle that would really, uh, stretch players abilities to interpret and understand all the logical connectives. And I think that having that foundation is just very valuable in computer science. But then on top of that, there's this whole, extra level to the game that I think professional programmers will really appreciate. Even though this game is marketed towards kids and young players, this game in particular has this whole other level that I think adults and professional programmers would really get a kick out of. The logic puzzles in there are modeled after a famous NP-complete problem called the satisfiability problem. The Boolean satisfiability problem, the way it works is you're given this really complicated logic formula, and you have to find the truth values for the individual variables to make the overall formula work out to be true. That, it turns out, is an NP-complete problem. It's such an important historical NP-complete problem that computer scientists have spent... Decades coming up with really good heuristics for solving it. Obviously, an NP-complete problem, if you have a large enough problem, it's going to overwhelm your computational resources. But most real-world problems, like hard problems, can be modeled in terms of the satisfiability problem. If you have a good solver with good heuristics, most real-world problems have some kind of structure to them that can be exploited by these heuristics. You can take these hard problems, model them, and then you can solve them. If you have a good solver with good heuristics, model them as a satisfiability problem, as a formula where you're looking for true-false values, pass it into one of these state-of-the-art solvers, and you get back the individual values, and then you translate that back into your original domain of your problem, and you have a solution to your problem. It's a really powerful tool to have in your toolkit to understand how satisfiability problems, how they're structured. As you solve these problems, as you play through this game, you're actually going to learn on your own. You're going to discover yourself a lot of the same strategies that satisfiability solvers use. So you'll get more of an intuition about what kinds of problems can be cracked by these solvers, because you'll understand the processes they go through. Sure. Yeah. Yeah. That's so interesting. And these are things that as a developer, if you're listening to this episode and you're thinking, wow, I've never even touched anything related to NP-completion. I don't even know what that means. Then join the club. Most developers probably have not had the chance to dive into something like that. And I fall into that group. I haven't had a chance to really take time and approach any kind of problem like that in order to solve something greater. Right. Most of the time, the academic things that I do are barely touching the surface on most, of the kind of popular algorithmics, right? Yeah. And so this is, but this is, this is really cool because what it means is, you know, basically you've created this game, this puzzle game. I want to be very clear about that. You've created this puzzle game that introduces concepts that kind of leapfrog into that really high level domain. And so, you know, I think it's really cool. I think it's really cool. I think it's really cool. And what that means, that kind of gives me hope as a developer to think, okay, hey, maybe, maybe the stuff that feels intimidating when Mark is talking about this, you know, he says NP-complete and I, I have a very limited grasp on what that even means. You know, maybe some of these problems are more accessible to me than I expected before I, you know, before I encountered this. Yeah. And one thing I would recommend to people who are kind of intrigued by this and want to see more about what this means in practice, when I talk about modeling one problem in terms of another, I gave a talk at a recent conference. It was actually a Clojure conference. And you can find the video on YouTube. It's called Solving Problems Declaratively. So I gave this talk and the sample code is going to be in Clojure because that's the conference I was at, but I've shown the talk to people who don't understand Clojure and they said they were able to mostly follow the, to the talk even without knowing the details of the Clojure syntax, because I talk about it at kind of a high level. But what I do is I take a kind of a classic puzzle game problem and I demonstrate how to turn it into these, this different models that they're solving engines that already exist to solve these things. And I show how you kind of solve it using the solver and then you translate it and the information backed into kind of the original problem statement to solve that. And I, I work through that for a few different solvers, including the satisfiability solvers. So I would recommend checking that out as a taste of, because if you get a feel for that technique, it's something that can apply to a lot of really interesting, hard problems, things that maybe you're, you're not even sure how you would go about tackling, how you would write a program to solve this thing yourself, but you don't have to worry about that part. If all you have to do is translate it into a model that there already exists a solving engine out there, you can solve it. Can you give an example of a type of problem that that would be good for? Uh, well, the satisfiability solver, for example, um, there is, there are a lot of NP complete problems that come up with certain kinds of resource allocations, routing things through a network optimally, or if you're writing a compiler, uh, the allocating different values to different registers, it turns out that doing that effectively is NP complete as well. And so a lot of these are challenging problems that come up in ordinary things we do and finding the optimal solution is hard, but you can pass it to one of these solvers and it'll do that for you. Oh, okay. Yeah. That makes sense. So this is, this is a problem set that is really, you know, we're talking, we've talked from the very lowest level introductory CS, you know, concepts, uh, in the, in these physical,! Yeah. Yeah. Uh, these kind of foundational ways of thinking all the way up to, uh, really complex and sophisticated algorithms. And what's really cool is these, these games kind of lead people, uh, to, to those spaces. Um, and, and I really respect that about the design of the game. So thank you for, for creating something so cool. Thanks. Yeah. It's, it's been fun for me and, and just amazing to see how much, uh, can be done through a game. I, I think it's, it's not obvious which of these computer science concepts can be turned into something playable. So it's been really fun to explore that space. Yeah. Yeah. It's, I remember a game that I played on my PC when I was younger. Uh, it was called, I believe the incredible machine. I don't know if you've ever played this game. Oh yeah. I love that game. Yeah. So much fun. And, and this concept of components and, and really, you know, I feel like this is kind of a, another generation of a similar concept. Uh, you know, some of, some of the ideas you've, you've, uh, brought to these games is that, uh, but I I'm really, um, you know, perhaps just as impressive to me is the fact that these games are in target, right? It's this, these concepts are becoming popular. They're not just a niche, you know, subject anymore. It's not just a Kickstarter thing anymore. Yeah. If you, if you have listeners in other countries, they might not know what target is, but it's a big, uh, department store that where you can kind of buy a lot of different things, um, here in the United States, but it's one of the big kind of a target in every city that has more than 20,000 people in it or something like that. Yeah. And it's, it's really exciting to have a, a chain like that carry these games. And I think all kinds of people are going to get exposed to this that wouldn't ordinarily. Yeah. Yeah. And I know that I, you know, this is the kind of stuff I just recently had, uh, my wife and I had our first son and I didn't personally, that would be a difficult process, but, um, and, and this is the kind of thing that I'm really excited to see, you know, laying out in front of him and his future, the, the idea that, Hey, you know, for so many years, the professional life was relegated to, you know, you really start thinking about that. You know, you really start thinking about that maybe around the age 16, right. And because we, we, we, and this is a whole different discussion and we don't have time to go into it tonight, certainly, but, uh, you know, thinking about what am I going to do in the world, right. You don't really have that responsibility when you're very young. And, and sometimes you don't even have that responsibility until after college. And a lot of people view that as a burden more than, uh, uh, you know, a gift or an opportunity. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. Okay. This is so cool to me because what we're doing is, you know, with games like the Code Series that you've created, Mark, we're allowing people to start thinking about, hey, what cool stuff is there in the world for me to get involved in? And not just, you know, limited to only the things that you can do in grade school traditionally, right? We've moved past that. It's a new era in thinking. Not that we're saying, hey, you should start thinking about your job when you're five years old. That's, you know, that's ludicrous. But instead, jobs are no longer just intended to bring home money to pay for food, right? Jobs are no longer just about paying bills. We have the opportunity to do really interesting and unique things in the world. And we should share that with our children and with, you know, the people who are in college or who are... They're switching careers way late in their careers. We should share that exciting and inspiring opportunity. So again, Mark, I feel like, you know, the work that you've done with these games is going to do some of that work. And I really appreciate it. Well, thanks. That's sort of my dream. So I appreciate that. Mark, I appreciate your time tonight once again for coming back onto the show, you know, joining me in the evening. It's not an easy thing to do. And I really appreciate your extra effort to make this episode great. I have two questions that I ask all of the people who come on the show. And you happen to have already answered these to me directly. But I'm going to ask them again for the benefit of the people who are listening. The first question is, if you and I were to sit down and have tea and you had never talked to me before, what would you wish that I would ask you about? Well, as a parent, I always love it when people ask me about my kids, of course. And in the context of computer science, also, because my big focus is on trying to start computer science to start kids on these concepts as early as possible, you know, because I homeschooled, I think it also makes a lot of sense for someone to ask me, how did this work out with my own kids? Because I started them very young on this material. And so slightly different answer. For both my son and my daughter, my son really took to this really quickly and just loved it. And I started him on these kind of computer science concepts really as early as eight. We got, I mean, before that, he was kind of dabbling in playful programming kind of things. But by eight, kind of got more serious about it and made programming part of his everyday routine. Made, tied his math curriculum to that. And it worked out fantastically. And he became really expert at this stuff really early, as you might imagine. And by the time he turned 16, he realized he had the skills to go out and get a professional software engineering job. And so that's what he did. My daughter, I did a lot of the same things with her from a very young age. And she also was really good at it. And in. Enjoyed it, but not quite in the same way. It wasn't the kind of thing she wanted to be doing every day. And that's okay too. She's going a different direction. She's going off to college this year, going to be studying stage management. She loves theater. That's her passion. But what I have seen over the years is that those early years that I spent working on these foundational math and computer science concepts have really just made her a significantly better problem solver. Yeah. A really strong thinker, and it's really helped her in every other thing she's done. So I'm really glad she has that experience in her background, and I can see that it's going to help her, even though that's not the kind of career she wants to go into. And that is perfectly okay, too. Yeah. And that goes back to that discussion we were having earlier, you know, having these skills, it goes beyond programming. And it really is about becoming a better thinker. And, you know, a more strategic thinker. So I totally agree. I hope to pass on some of the same thinking skills to my children and really kind of espouse that on this show. So the second question I like to ask everyone who comes on the show is if you only had 30 seconds worth of advice to give to developers who are listening, and they come from all different backgrounds, all different experience levels, what would you tell them? Well, we spent some time talking on this show about functional programming languages. And I would say, I would recommend to developers to spend some time learning a different programming language than what you use every day. Maybe a functional programming language, maybe something different. The point is it should be a programming language that forces you to think in a different way than you're used to thinking every day. And the reason is because that's going to give you a whole new expanded tool set, a new way of thinking about problems. And it will give you more when you face new problems, you'll have a new way of thinking about it that will allow you to solve things that maybe you hadn't solved before. That's excellent advice. And you actually stayed under 30 seconds. You know, I don't know that anybody who comes on the show has actually stayed under 30 seconds. You know, every once in a while I'll have somebody who says, you know, be nice to people, right? And that's a great answer. There's plenty of advice in that, but you kind of hit that mark right on 30 seconds. So that's kind of impressive. Mark, thank you so much for coming on the show. Thank you. For coming on the show, for doing something great and for being so accommodating with tech issues and, you know, overall being an excellent guest for Developer Tea. Well, thank you very much. I know I'm going to continue to explore this space of creating puzzle games that teach programming. And so there's some new things coming in the pipeline down the line, and maybe we'll have an opportunity to have another conversation about that stuff in the future. Yeah. Top secret stuff. And things that actually, you know, you and I have discussed off the record that are worth paying attention to and following Mark, especially if this episode has intrigued you. Mark, where can people find you and follow you and know about this stuff in the future? My Twitter account is Mark underscore Engelberg. That's M-A-R-K underscore E-N-G-E-L-B-E-R-G. And I use that as a way mainly to tweet out things relating to like new games I have coming out or new talks that I've done. You know, videos out or something. So it's pretty low bandwidth. If you want to sign up for that to follow me on Twitter, I would promise not to spam you with too many random things. It'll just be kind of updates about what I'm up to. Excellent. Mark, thank you so much for coming on the show. And thank you again for all that you've done for the community, the community of developers who want to inspire, especially young students in this, in this field. Thank you so much. Thanks. Bye. Thanks so much for listening to today's episode of Developer Tea. And thank you again to Mark Engelberg for joining me on this episode. I had an excellent time interviewing Mark. He was so kind and gracious to do the interview a second time after we ran into some technical difficulties. So I really appreciate his patience with me. And thank you so much for listening. And of course, go and check out Mark's awesome games. You can find them in Target. You can find them online as well. Thank you to Mark. Thank you for listening. And thank you to SwiftType for sponsoring today's episode of Developer Tea. SwiftType Search is a fast, reliable, safe, and AI-powered search system that you can get set up on your website in just a few minutes. Head over to swifttype.com slash developer tea to learn more about SwiftType and to start your free trial today. Thank you so much for listening to Developer Tea. Make sure you subscribe if you don't want to miss out on future episodes, just like this one, and also different than this one. We've covered tons of topics. We've three episodes a week. And it's so important that you subscribe if you don't want to miss out on topics that are relevant to you. So subscribe on whatever podcasting app you're using. It takes just a second, pretty much a single button click. Most apps don't even require you to sign up for an account. So go and subscribe to Developer Tea now. Thank you so much for listening. Until next time, enjoy your tea.