 I don't know if you saw it, but somebody on the forum, not just somebody, somebody extremely hopeful and kind being Daniel on the forum. He does these summaries of the walkthroughs. And I saw that. I tried to do a little bit, but I think I didn't have time to finish it off. Yeah. Okay, so did you want to maybe share your screen and to get us up to speed with like what the problem is we're solving and where the data is for it and stuff like that. You're muted by the way. Sorry. Yeah, actually, it's just what was in I think it was the 713th live coding live coding which one live coding live coding 13 live coding 13. Yeah, so I basically I kind of had a really janky solution it's not it probably doesn't work but what I was thinking of doing was like putting him in some kind of like a file side by side and then sort of indexing it but I actually didn't do anything because what I did is basically this. At the end. Uh huh. So, so I'm quite sure how to take it any further. I don't even know what it is yet so let me just. So okay so I've got my screen sharing here. And so. Can you guys see that okay. So where do I start so he. I didn't quite understand like. Finish note on the forum. Yeah. Okay, so that's basically like if you get that note. At the end he's got all the images. Yeah. Right. So these are kind of like the. He's got the actual images in that drop down. And what I did was I actually went in there and I looked at the code or what the HTML. And are these going to be in the same order as. Like to have names or. I don't think so. The same order. Let's see. This is. This is called at actually what we could do is if we click at it. Yeah. Oh, I see this is like got off the edge of the screen. And so let's see. So these have. Okay, these have names. Okay. Cool. Like add to class. And then presumably there's an add to class somewhere here. Let's try searching for that. Add. To class. Yes. Yes. Yes. Oh, that's cool. Okay. So the sizes are different a little bit. And this is in double brackets at the end. So I wasn't sure what kind of. Rejects would do that, but I think the one that I got, it kind of, it just kind of captures. So what I did was what I actually did was I went to the bottom. I took all of the ones from the bottom and then I. I just extracted that. And that's about how far I. Let me just start up Jupiter then. All right. So this is our, this is our kind of source images. Okay. So you guys know if you put things in triple quotes, then it creates a multi-line string. Okay. And so then we've got our destination. Okay. I guess which is everything else, right? Destination. Okay. So there's a good start. We've got our data. So like, I guess, like the reason I thought this might be interesting to do. Here is basically. Yeah, people often ask, like, how do you go about actually solving a problem or doing coding or whatever? So I thought, I guess if we do it together, then we can go through the process. Which will work a lot better if you, yeah, ask questions or add comments, you know, as we go, obviously. One thing that does occur to me is in this notebook, actually this is, I find quite, this is quite awkward to have so much data here. So what I might do actually is instead put them into, into text files. So this one is the source, right? In bash, if you type cat and read, and then this means redirect to a file, right? So we could create a file called source.text. It's now reading from standard in. It's reading from the input, right? So I can paste like so. And then to tell basically in Unix to say, I finished this file, you hit control D. Okay. And so if I was to now vim that you can see it's there. Okay. So that's how you can quickly and easily. There's lots of quick and easy ways to create text files. Jeremy, how did you do it? So I got confused with the problem because there was this gift thing and I thought, wow, get the, you know, and it's just the name of the directory I'm in. Yes. Yes. I figured it out to post. All right. So it's just right. Just it was just this less than sign which pipes it to the greater than sign. Yeah. Or greater than sign. Yeah. Right. So the main thing, I guess the main like just to put this together. If I just type cat. Right. And then I type text. It just prints out whatever I type it. Okay. So that's what cat does. The reason it's called cat is actually concatenates things. If you feed it multiple things, it adds them together. If I, I can redirect from a file, which means instead of me typing things in, it'll, it'll get its input from a file. So that would cause it to print it out. Or if I redirect its output, then whatever I type in will go to the file. So one way to copy things, for example, would be to read things into cat and then output things into something else. Wow. Like a really dumb way to copy. But like, you know, it does the job. Right. So yeah, cat, just anything cat bring gets into standard in goes to standard out. Steaded in being the input to a Unix command and standard out being the output for Unix command. So if you do cat greater than filing, it will still let you type in stuff. Right. So that's what I did before. Right. Is I pasted. And then at the end, I hit control D. Right. So now if I cat and take it from that. Yes. There's, but I just typed. Okay. Control D at the end. Control D means end of file in Unix. Yeah. So if I, sorry, let me make sure that you're here. Yeah. So if I hit control D at the end, that's that then it says, oh, you're all done. You might have seen something similar. Like, I think it's like this. Yeah. That thing I know. Okay. And at the end you type whatever you typed. So like, but there's no reason to do that. You can just, cause you could just use control D. Cool. Yeah. If you use this double less than sign, it means keep reading until you see that string. That's quite a hear dog. This is the mystifies a lot. Yes. Yes. All right. So let me show you that again. So let's go to the next station. Right. So let's grab all that. And by the way, knowing how to do things like select to the end of line and select to the end of file and stuff like, you know, using command and control and shift and end and home, that stuff's really important to know. It varies between Mac and PC. So if you don't know how I just selected all that, then it's definitely worth Googling that. Okay. So I've just copied that. So I just want to put that into cat. Redirect the output to destination dot text. Right. Post. Control D. Control D. I don't know why I had to press it twice there. That was strange. Maybe I had to hit. Anyway. Did the job. Okay. So actually. So I guess like my starting point normally is just to kind of like input. Import my like. Standard set of things that I wish Python had, which is called fast for dot utils. So as some folks have pointed out before, some languages have things called a prelude, which is like the. The kind of stuff that. People like to always have available. And this is kind of my version of it with a prelude. And. One of the things that I like to do is import. So I'm going to go ahead and go ahead and go ahead and go ahead and go ahead and go ahead and go ahead and go ahead and go ahead and go ahead and go ahead and go ahead and. One of the things that does is it import some things from the standard library, Python, standard library that I always use. And it also import some things that Fastcore adds to the standard library. So one of the things that adds is. Partly Pat. Pattern. Path. So half, okay? Like so. So how to. And so pathlib.path has a read text. Okay, so that's better. One thing that I don't particularly like is that the standard representation of strings and Jupiter uses backslash n. If you want to replace it with actual near lines, you can say print. Or, you know, like you can just do this. And so just remember curly brackets. So this means do this as a bash command. And curly brackets means read this Python variable and put it into the bash command. All right, so then we can do something similar for destination. One thing that people complain about with my code quite often is my use of abbreviations, like you might reasonably ask, well, why not at least put the E there? And it's just totally fine, you could put the E there. But just to explain, I quite like to have similar things be similar lengths, because it makes it really easy for me to then like have lines next to each other that operate on those two things. And all the bits will be in the same place. And so my eyes can immediately see if there's some unexpected difference or something. So it's not just me being trying to be difficult. It's, you know, there's actually a reason that I quite like doing that. But just not to say everybody has to do that. I just, that's why I quite like to do that. And there's also something to be said for like, having our standard way of coding, that then you just don't think too much about how you code, you know, so like I just have STEM standard way I tend to name things. And then I don't spend time thinking about naming things too much. That's cognitive load I can focus in on solving the problem. All right. So I guess the first thing we might want to do then is we basically, we probably want a dictionary that goes from the name of the thing to the location of the image, right? And so then basically then we'll just go through each type, each one of these here and replace the name with the value of that when we look it up as a key. So there's a thing called find all, which you give it a regex and it finds all the places of that regex. Do you guys tend to use regexes? Is there anybody here who like doesn't really use regexes or not too much? So regexes are what we call it a DSL, a domain specific language. They are, yeah, they're not Python really. Python happens to have support for them but they very much don't look like Python. I actually tend to think of them as a notation and notation is one of my favorite topics. So notation is a way of representing some potentially complex domain in a concise, expressive and flexible way. So for example, a notation that you've definitely used before is this one, right? Which is called math notation. If you play music in the Western tradition then you will have seen the staff-based music notation. If you juggle, you might have come across the juggling notation. If you've done quantum stuff, you might have come across the Feynman diagram notation. So notations are, yeah, they're expressive ways to represent things. And regexes are a notation for finding stuff in text. You know, not many honestly things in computing have got to the point that they're so well understood and studied that we've brought them to the point that they are a notation. But regex is one. And my view is often, most of the time perhaps when something has got to that point we should learn that notation because it's like a way of composing things together very concisely that can solve a wide class of problems. Jeremy, would you recommend learning things like Ork and Sedd also, long term? I wouldn't recommend Ork and Sedd. I would recommend Pearl because Pearl is a superset of Ork and Sedd. And as such, it's more expressive than either because you can combine everything from Ork and Sedd and find and pretty much everything from Python as well. So yeah, at some point in your life it's well worth Googling for Pearl one-liners and diving into that rabbit hole. So another nice thing about regexes is because Pearl's regexes were so good they were built by a linguist, you know, Larry Walls it's not surprising perhaps that they used almost everywhere. So JavaScript, Python, Pearl, C, you know, via the PCRE library, they all use the same regexes. VIMs are slightly different. In VIM you have to add a few more backslashes to things but it's actually possible to turn on a VIM mode which is almost identical to Python and Pearl which is called the very magic mode. So you can turn on very magic mode then VIM basically is the same as everything else. Okay, so. I got a quick question about like 20 minutes into this. I was here last time. So what are we trying to do? Yeah, this is not from last time. This is what we're trying to do is this is something new. So what we're trying to do, thanks, is Daniel creates these nice descriptions of everything in these sessions but this is how his images come out. It's just not very helpful. So I thought it would be nice if we could, for him, make a script or something that would allow him to put the correct images in here. And I don't know why it comes out this way but that's fine. He's got a process he's happy with and in this process the images end up, you know, he can easily paste them all at the end. Right, so here's all the images. And they, so the images, the images in his, that he pasted at the end look like this. Right, so they have names. Right, and then in the forum post they appear like this. So we have to replace this basically with this but with probably with this size would be my guess. In fact, let's just check that. So yeah, that's what he wants, I guess. Fixed test error. I wonder which size he wants. Great for fixed test in source path 690 by 184. And where was that fixed error? Okay, that's at the end. And then in destination path. I wonder if these are the actual sizes. Did he, let's have a look, did he say? I think these are the actual sizes. I'm not sure why it has the 900 standard size or something. It seems to have like... Presumably that's what he wants. That's presumably the size he wants, I guess. Let's have a look. So if I copy that, this post is to test image stuff for Daniel. Paste. Okay, so that's the size that appears there. And then what if it says 900? Oh, it doesn't really make any difference. Well. Try it without this one. I'm not sure if that makes sense. Sorry, say that again. If you were to try it without, it should also work without, it would just... Oh yeah, it would work. I just think like he's, I assume that some of the images he's intentionally trying to resize. Sometimes... Maybe it's notes up. Huh? Maybe this is for his notes up. Well, yeah, I mean, he's got two different sizes. One of them is for his notes up, I assume. And one of them... I'm not gonna assume this is the size he actually wants. Maybe it's already as big as it can show in the bar. Yeah, that would be my guess, I think so. If you right-click and open it in the new tab, would that... Or would that just show the image? No, I think that'll show the image. Let's have a look at some more... Oh wait, does it always say 900? Oh, so I'm at 1200. I see. I think all of the X by Y is the one when he drops them into the interface and it just takes whatever the size. I would say so. So I think this is proper. Let's assume this is actually what he wants. I think that's a reasonable guess. Okay. So you can see sometimes I just judge, grab bash commands when I'm fiddling around just because, yeah, sometimes, I don't know, it's just like an easy way for me to quickly check things. So grep... So actually, grep doesn't take normal red Jaxes, but you can... And I need to get into a habit of doing this. Yeah, you can use minus capital P to use Pell-compatible regular expressions. So when you're looking for, like, can I use normal regular expressions? Specifically, the thing you don't really want to search for is PCI-RE, they're called Pell-compatible. So apparently we can do this. Not that it'll make any difference in this case, but no, this one. Okay, what about eGrip? No? Okay, so that maybe it's in some more recent... Oh, you know, maybe the best thing is not to use eGrip, but instead to use RG, which is rip grep, which I guess I have to install. I noticed that. Is that a different version of grep that you use? Yeah, so RG is like... So basically like for pretty much all the classic Unix tools, somebody's rewritten it in Rust and made it better, or C++ or go, you know, increasingly it's Rust. I don't know what rip grep was written in, but like it's basically like in this kind of general category of like better versions of classic Unix tools. And I try to like get into the habit of using the newer better versions, so even though it takes some retraining. So yeah, RG is the kind of... I meant to ask about that yesterday, because I noticed you were using that, and I thought maybe Nellie is for recursive grep or something. Oh yeah, yeah, no, it's actually a program. Rich, amongst other things, seems to be highlighting the thing I'm searching for, which is cute and showing the right line number. And Jeremy, you find that brew install doesn't mess with your MambaForge installation, are those orthogonal pretty much in your functions? No, it should be fine. Yeah, I mean, I'm not in paper space here, right? So like I wouldn't use... I tried filling with brew in paper space because there is a Linux brew nowadays. It seemed okay, but it uses up a lot of space. So I thought just using Mamba to install binaries like rip grep in paper space is probably the best option, because it doesn't use any more space than necessary. But the two shouldn't get in the way. They'll both add themselves to the path, right? So opt home brew bin and MambaForge bin. So they're just both in the path. Yeah, I can't see why they're getting away with each other. Thank you. All right, so find all. Looks for a patent in a string, right? So I tend to like to create like a really simple version of something just to make sure I understand the command before I dive into it. So I reckon we should be able to find the word fix in our source, right? And there it is, okay? It's appeared more than once. Okay, there it is, right? And so then if we... Generally with regexes, we use backslashes quite a lot to mean certain things, but Python uses a backslash to mean something else, which is that the next character is a control character. So to tell Python that treat backslashes as backslashes, you put an R before the string. So this looks for the backslash F fix test. In fact, if I just show you here, backslash N is normally a new line, but if I put an R there, it's not a new line. Actually, this would be easier if I say print. So that prints new line fix test and that prints backslash N fix test. Okay, so we're gonna look for stuff of this form. That's our source, right? So I would be inclined just to paste it in here, okay? So square brackets have a special meaning in regex, so we can use a backslash to say don't use a special meaning. Ditto with pipe. Ditto with parentheses. Let's get rid of all those, okay? And so this is gonna be the name of something. And so if we want to remember some block of text, we can put it in parentheses, all right? So the thing we're gonna try to find here is basically, I think probably anything that's not white space will be fine. So backslash S means not white space and plus means one or more. I don't think we care about the size, so we'll just skip over this. So we'll just skip over this. And then this is actually something we do wanna keep, which is the actual file name we're gonna end up with. So I'll create parentheses for that and put my backslash S plus there as well, okay? So that's looking pretty hopeful. So what it's done here is found equals, it's found 29 things, which looks something like this. Oh, I put parentheses twice here, which is why it's appearing twice. That's better. Does that make sense? So it's basically showing us each of the parenthesized expressions. And so actually we don't need this bit to be parenthesized because I don't think we care about the original size, okay? And so we should be able to create a dictionary from that because we've now got a list of tuples. I never quite remember how this works, but yeah, there you go. So the list of tuples, if you pass it to dict, it'll create a dictionary. And I think like there's something to be said for programming in an interactive environment, that allows us to like gradually build up a thing that works and then assign it to a variable or stick it in a function or whatever. So now we should be able to search for found add to class and we do. So we've got the dictionary we want to. Does that make sense so far? Yeah. I just have a question about that. You got rid of the size. So if you don't put the parentheses, does that mean it will just ignore that? Yeah, I mean, it has to be there, right? So if we said, oh, look for A, A, A. Well, that's not there, right? So it won't find anything. So it's still searching for it. It's just not storing it. So it's finding an exclamation mark, open square bracket, finding and remembering a bunch of non-white space characters followed by a pipe sign, followed by a bunch of non-white space characters, which it doesn't remember, followed by a closing square bracket, followed by an opening parenthesis, followed by a bunch of non-white space characters that it does remember, followed by a closing parenthesis. So putting parentheses makes it remember essentially keep track. Correct. It does two things. It also groups things, which is a bit confusing that it does two things. But yeah, in this case, the thing we're using for is the fact that it remembers things and will end up in the output of re.findall. Amongst many other things, if you just do re.match or re.search, it'll also remember them. It just returns slightly different things. re.findall is one of the easiest things to use those. So I think it's good. Okay. So now we need to basically search and replace in destination, looking for stuff like this. Okay. So this is our destination. Kind of want to look at the end of it. Okay. Here's two things we want to change, right? So I'm just going to like use the last few characters just so I can see what's going on. So I'm just going to put that in a variable for now. Okay. So there's a thing called re.sub for substitute. That's funny. A lot of Python programmers complain about me using three-letter abbreviations, but Python apparently is allowed to use three-letter abbreviations, re.substitute. So we're going to find a pattern and replace it with something else. And we're just going to search in some string. So for example, if we replace space with star, nd, okay, that's basically how it works. Or you can search for regular expression. So let's search for that. Okay. And then we're going to use r because we're going to use backslashes. We're going to search for a literal square bracket. We're going to search for a literal vertical bar. Okay. And you can see that's been replaced with a star. And so this thing here is a file name. And the bit before the dot is what we're going to look up. So we're going to capture this. And the thing we're going to look for is everything except for a dot. Okay. So to say everything except for a dot, you put in square brackets, you put the things to look for. And carrot means things you don't want to look for. So this is everything except a dot. And this says to capture it. So remembering, I got it remembering, it's actually called capturing. Dot has a special meaning normally, which is anything at all. So that's a literal dot. Let's not assume it's all not, maybe it's not always PNG. So I'm just going to say any three characters. In fact, regardless of whether it's JPEG or PNG. Oh, here we are. Oh, it's also sometimes it's JPEG. Could be four characters. Okay. No worries. Okay. Well, anything could do. Oh, I know we can just do some letters. So backslash w is a word symbol. So basically letters and numbers and stuff. So we'll have a bunch of those. Okay. Now, interestingly, in this case, this has got a pipe 900. This has got a closed square bracket. Okay. So there's a few ways we can do this. I'm going to show you, okay, I've got to show you the more interesting way, which is that, no, let's do it the simpler way. Okay. So the simple way is rather than looking for any word symbol, looks just look for anything that's not a closed square bracket. So this is going to be slightly confusing, but basically this is a rejects that searches for any A's or B's or C's. This is a rejects that search for anything that's not an A or a B or a C. This is a rejects that searches for anything that's not an open square bracket. So we want to find a bunch of things that are not a square bracket. Plus means one or more. And then there's going to be two closed square brackets. Okay. So that didn't work, which is good, because now I can show you how I go about debugging these things. So to debug these things is I would just gradually make this simpler and simpler until it starts working. And that way we'll be able to figure out why it's not working. So I'm going to delete all of this. Okay. So that didn't work. So let's keep deleting. Okay. So that one did delete. Oh, okay. I see the problem. So you can see here, it's just replaced the first letter, which wasn't what I wanted, right? I wanted to grab a bunch of these. So this here says, oh, this here says anything that's not a dot, right? But we actually want one or more things that aren't a dot. That's better. Okay. So one or more things that aren't a dot. So we can go back and now replace that up here with one or more things that aren't a dot. There we go. So that's now successfully replaced all that with a star. So that tells us that we've got our search working correctly. What confused me is the carrot in the square brackets, because I know that the carrot is a symbol for start of line. Oh, yeah. That's true. So I had to Google it and it turns out that if it's inside the square brackets, it means not. But if it's outside, it means start of line. Yeah. No one's going to claim that necessarily this notation is spelt the best. I guess it was made pre-unicode, you know? So it had to rely only on ASCII signs. And so I don't think there's enough ASCII symbols. So it ends up having to reuse ASCII symbols in ways that are entirely incompatible with each other. Yeah, that's correct. So if it's not inside square brackets, it means start of line. If it is inside set brackets, it means the complement of the set, the opposite of the set. The dot. The dot, the dot, which is inside bracket don't mean any character. No special character. Yeah, that just means a dot. And I think in square brackets, except for character is literal. Yeah. So you could do this to make it extra clear. Yeah. In the chat, I shared link to byte.org, which is nice because it has a cheat sheet. So whenever I'm working on a regex myself, I never remember, this is based on Rabular that was very famous in the Ruby world. It's nice for testing your regexes, but also if you expand the cheat sheet, which is, yeah, and then now if you put a string in your test string, it will, and you can put a couple of strings there. It will, you know, show you what it's doing. That's how I figured out the regex. I went to one of these sites. And then the most crucial bit here is the regular expression cheat sheet. When you click on it, it expands. And you have all these things that you can use. Yeah. I think regex 101 is the one I've tried before, which I think has a bit more of an explanation if I remember correctly. It's wrong button. So I like this, so you've got the quick reference, but you've also got this like explanation that matches this character, matches the character. So a capturing group, that's something that remembers is a capturing group, a single character that is not one of these. Oh yeah. Yeah, so the first like, learning a notation is hard, you know, and so like almost any notation people don't, as a matter of course, learn at school. It generally gets categorized into the weird, complicated, annoying thing category. But there's nothing like more or less weird or annoying about regex than basic arithmetic notation. It just isn't something we're learning at school. And it's, yeah, arithmetic takes us some years to learn. Regex, has anybody learnt regex recently? You got a sense of how long it takes to learn, like days, months, weeks? The first time I started using it, I think it was actually last year's FASTI course, where you introduced it. And yeah, I always saw it before and I thought it was kind of like, you know, these weird magical symbols that I'd never understand. And then basically I like got a basic understanding of it, really useful tool. And then basically every few months when I have to come back and use it for something, I just use one of those like online regex tools to kind of like give myself a jumpstart to get back into it. Yeah, I mean, it comes up so much. It's like, I would say it's notation worth mastering, you know, which I wouldn't say about that many things. I mean, mastery requires probably some fairly intentional practice over a period of time. Yeah, but yeah, certainly they're kind of like, use it from time to time and learn a little bit more each time also, also works. So I've got to show you something which I would guess most Python programmers don't know, but which is amazing, which is that this thing here, the thing we're replacing it with, the star doesn't have to be a string. It can be a function. So here's a function that returns star and that does the same thing, right? Or return, we're going to be at past the thing that's being replaced. So, you know, just, I mean, one thing we could just do is just print that out. Okay, so we're getting past an RE.match object. And so you could go ahead and all this. So an RE.match object, we can also get- I would go, I think, or is it only me? Can you guys hear me? I can hear you, sorry. I can't hear anyone, so it must be me. Oh, sorry, my computer did something on its own. It's a bit weird with the audio. Sorry about that. Okay, so I think to play with a match object, we should probably try and create one, which I think if we go RE.search, yeah, we'll get a match object. So let's search for that pattern. In that string. Okay, so there's a match object. So hitting dot and pressing tab isn't a bad idea, just to see what kind of stuff we can do. That looks nice. Groups. That doesn't seem to do anything. Ah, it's a default. Got it. This is confusing with groups because group zero is everything, right? So there's groups in group. So group is something where you give an index or name, and so zero gives you everything that was matched and one gives you the first thing that was captured. So that's actually what we want, right? So if we here did return star x dot group one, star. Okay, you see what's happened there? So again, I'm doing a lot of exploring and exploring, as I go. And so I find using this approach, if I'm working with my code, I basically never get stuck because every step I'm doing is so small and it's from a known place, and it's a small increment and I'm kind of keeping most of the steps along the way. So it's really, yeah, it's very hard to ever get lost or stuck. So, yeah, so now all we have to do is look up the thing in found, right? So found, there we go. Okay, so now we've got to put it in the right format. So actually, yeah, we basically, yeah, this is interesting. We actually want to keep this bit, right? If it exists. So what we can do, yes, we want to keep that bit if it exists. So this thing here where we're searching for anything that's not a square bracket isn't quite what we want. I think we actually need to specifically find the extension. Right, so we're looking for a full stop and then an extension. Okay, so an extension is a bunch of letters, right? Is a bunch of letters, so backslash w plus. Strictly speaking, it should be three or four letters most of the time, but that's okay. We're gonna say backslash w plus, right? And then next after that, there's either gonna be a closed square bracket or there's gonna be pipe followed by a bunch of digits. So in other words, it's gonna be optionally pipe followed by a bunch of digits. And I want to keep that because we want to put it in there if it exists. So we're gonna look for pipe followed by a bunch of digits, backslash d is a digit. Okay, so we're gonna look for all this, right? Now to say that that is optional, you use question mark. And so I'm just gonna change this to zero just so we can print out the whole thing to make sure it's working. Oh, and we don't want to do that anymore. Let's see. Okay, so it seems to have worked, right? And in fact, what we could even do is just say, print out the groups. And that way we'll see, okay, it's got fixed test error pipe 900 and fixed issues none. So you see how the optional thing is coming through as none here, right? So what we want to do is then look up group one, right? Which is this. And then if it exists, we then want to put in the pipe 900, okay? So which is x.group2. Oops, you guys are not inside square brackets. I've found x.group1. Oh, and that's the end of curly brackets there. And start curly brackets there. There we go. Upload blah, blah, blah.png 900, cool. And so then this string is gonna start with exactly the same thing we had before, which is that. And it's gonna end with two square brackets. Okay, so we get rid of our stars. How does that look? We have extra none at the end, which we should remove it. Okay, we do, slightly annoying. So or is a Boolean operator, which returns the thing on the left if it's true and the thing on the right otherwise. And so because none stringifies is the name, the string none, but it also is also considered falsi. So this will turn none into an empty string. Okay, well, let's try that on the whole thing. So one easy way to, when you're doing something on a subset to change it to the whole set is you just go delete. Like, so, all right. So we've got a key error, which is understandable. So we're missing good mix. So let's see if that's actually missing or not. So let's have a look in the source and search for good. Okay, there is not good mix. So what I'd be inclined to do then is change square brackets to dot get because dot get lets us provide a default. So let's use that as a default looks hopeful. Or you know what actually would be nicer. I think this is gonna end up kind of having like just a broken image symbol. I think instead what I'd rather do is grab all this and say if we found it and do that, otherwise return that way, we'll actually be able to see it. There we are, missing image. So let's test it. Ah, okay, so I did that. Oh, okay, so I think I made a mistake. The destination format is not that at all. The destination format is actually this format. It's actually exclamation, it's square bracket. Okay, so that's not correct. If res exclamation mark square bracket doesn't really matter what the name is, but I guess give it a name. And then, oh, and then the size, if there is one. Interesting, size, if there is one, which is this, then close square bracket and then a parentheses and then the file name. Okay, is that right? Oh, I've got an iri.match object, that's not right. Oh, it's, oh yeah, that looks better, doesn't it? Copy, paste. Oh, that looks hopeful. Ha ha! How about that? How about that? Yeah, some of these are too big, but Daniel can easily change. I mean, let's test it actually. So for 33, 33, let's see if we can change the size. 33, 33, sometimes it puts a little percent sign and we can put in, does that work? Discourse image size, oh comma, not right. Was that a bracket in the comma? A bracket in the comma, sorry. Mm-hmm. Yeah, I think it was, because in the next comment they say just by adding. By adding comma 20%. You still have to have the pipe in there. You think so? Yeah, the end button is like a quick, just fiction. Yeah, so at the end. Yeah, the last sentence there. Yeah. So that might be, you could just do just the comma 50%, I assume after a bracket, maybe that would work. Well, in here it's got before the bracket. Oh, not the bar thing. Oh, the pipe. Yeah. Let's try, yes, okay. Maybe take the dimensions out. No, so, oh, here we are, 50%. Okay, so I think we probably shouldn't be putting in his sizes, because they actually want to keep the sizes. So let's change it. So if you press, oh, by the way, it opens and closes the output of a cell, which is quite handy. So I guess we've gonna have two things. We're gonna have the size and the file name. So that's fine. So all we need to do then is to capture this. So it's not a dictionary anymore. Okay, and so then we could say found and we could do a dictionary comprehension. So for name comma size comma file in that, we're gonna go from a name to a tuple of the size and file name, okay. So we're now gonna go x.group. And so that means we don't need this pipe 900 bit anymore. So we don't have to remember that. And instead, we've now got the name and the size. The size and the name are the two things that are gonna be in this tuple. And so we're gonna go pipe, followed by the size. And then, and so. We have clearly brace in the size. Sorry? There's extra curly braces around size. Okay, why did this one not work? Fix issues.png, fix issues, fix issues. Should have worked. Oh, okay. So remember how I told you earlier that parentheses do two things. They both group and capture. So when I removed the parentheses, it stopped grouping, which meant the question mark now referred only to the backslash d plus. So actually I need the parentheses there. Okay, let's fix that. All right. Okay. And so sometimes that's missing. So we'll call that res after all. We'll call that res here. Let's see how that looks. Copy. Ah, cool. So look at that. They've got names. And you can change the sizes. Awesome. I think we're done. Are we done? Okay. So these ones here are too big. Let's fix them now. Just now. Okay. All right. So let's change is. All right. So let's delete that. So next step is to turn this into an app, right? Okay. So which bits do we need? So we don't need this head. Don't need that tail. Don't need the RGs. You can chuck this inside here. Don't need that. Okay. So let's restart the kernel and run it all just to make sure. Okay. So that was just that, I guess. Cool. All right. So a function for this, right? So this is basically replace image. This image. There we go. Jeremy, what? Yeah. What that does, this is seven cell seven. It applies the function to the DST contents basically. It goes to the search through that string. Yeah. Let's kind of look for this regular expression. And then each time it finds that regular expression it'll call this function passing in the match object that the regular expression gets. Thank you. All right. No worries. So this is like a very versatile approach to, you know, doing just about anything you can think of with text really, search for regular expression and replace it with a function. Okay. So if we have, okay. So let's create our function which is going to be fix images. Okay. We're going to be passed in a source and a destination. Okay. And this, if you haven't done this before you might be surprised to discover you can define a function inside a function. And the reason I'm doing that is that the first thing we're going to do is we're going to search for, what's it doing here? We're going to search, we're going to create this dictionary, right? Of things to look for. And then this function here refers to that dictionary. So this is a function that kind of only makes sense inside, inside here. And then we're going to return this, right? So we should now be able to print fix images passing in our source and destination. There we go. Great. So let's install Gradio. Actually, we've got the latest version by using minus U for upgrade. And I haven't used Gradio much at all except when we did that lesson. So I've forgotten everything. So I might need some help with this. Okay. So we import Gradio. Gonna create interface. And the function is fix images. Oh, okay, it's just stuck a while. Okay, now what's this input thing? Inputs is sketch pad, outputs is, oh, I see, we can just say label docs. Is there a different kind of label for like a large bit of text? Should be like a text box or something like that, maybe? Yeah, something, here we are, text box. Great. Here we are, max lines. Yeah. Wait, and then do we, okay. So if we pass a string, it's gonna construct it and like otherwise we construct it manually. Is that how this works? It said that there's a shortcut if you put just text, it would work, I think. If you go, I think I saw it when you were scrolling. I string shortcuts. Oh, text area would have seven lines. I see, I see, I see, which isn't that many. So let's just try to get there away. So input is, output is that. And they've got that new like grid flex boxy thing we might be able to use to like get one under the other because we don't really want them side by side, do we? Okay, so, is there a way to upload a file? An image there is. Oh wait, here's something called file. A bit of file for uploading a generic file. I guess he's probably gonna copy and paste it from the forum. So maybe we should just do it like that too. Yeah, let's just do it here. Can we still run the stuff? We can, it's nice. Cat source.text. Oh, source and output, that's not right. We need two things to pass to fix images. So does that mean we put square bracket here or something or a dictionary string, component, Western strings, natural parameters. All right, okay, so that's our source. That's calls, that's named them, that's nice. That's our destination, yes, submit. All right, that says to be working, doesn't it? So for, all right, so Gradio needs a script. And so I guess we got a spaces first, right? Hugging face spaces, create a space. Okay, and we call it a Daniel image fix, right? It's a Gradio space, okay, clone. You could just create the app file right there if you wanted to. Create the app file. In the UI, I don't know if that might be easier. Oh, can you? How do you, is there some? It says there, hint, create the app.py file right in your browser alternatively. Ah, I didn't know that exists, cool. Yeah, I guess it's kind of like GitHub only, so just everything. Yeah, yeah, absolutely. Okay, so we don't need that stuff. We're gonna need like a requirements.text or something, don't we? So we commit this, does that look right? What is it, is it a requirements.text we need? What is the thing to get? Yeah, I think so, yeah, requirements.text. And I think you just need to put fast core in it. Yes, okay, it automatically have Gradio. Name it requirements.text containing first core. I love doing this stuff just through the web GUI. It's just so wonderfully lazy. Okay, and that should be it, right? Yeah, I think so. Just, yeah, it has to build the app, so yeah. Okay, so it's done, so refresh. It's weird, it says building, but here it says. Because I think it builds for each commits, then you probably built when you committed the app.py and then it's building again when you committed the app. Yeah, I just want to say that, I want to say the latest logs, you know? Yeah, I like the way this stuff, so we're getting kind of standardized now around this idea of just like some key values to all secrets that you can chuck in there. Everything looks pretty similar, doesn't it? This is annoying, runtime error. Okay, so hopefully that means we've got new logs we can see, oh, space not ready. That's not very helpful. Logs is now empty, great. Can you try of rerunning the building process? So like how do you do that? It says you restart the space, it says. Okay. Or I guess I don't know the difference between the factory reboot or the restart. I see that your space could use a GPU, what does that mean? Is that a thing? King face. I don't know, like I think they provide it if you like email them or something like that. It's a custom kind of thing. Oh, no. Case by case basis. Makes me feel like I'm being judged as it's happening, I think. Yeah, it's a little slow, I guess. Yeah. So I want to ask how long do you plan to keep this live coding running? Is it just indefinitely? Yeah, I've got a plan actually. Okay. I hope you guys don't think it's too crazy, but just one moment, important lunch discussions. All right, so why is it still building? So hopefully, I'll get the course out in a couple of weeks. And at that point, I'm thinking of like resetting this as a walkthrough in which things are actually better organized. And so I hope you guys can still join. I mean, it will be stuff you're already familiar with at this point, but certainly be helpful to have a nice to meet, to have familiar faces and people who can help. So hopefully that'll be a lot more people because it'll be open to everybody. And over a period of a few weeks, you know, we'll catch up to where we are now as a group. But for the couple of weeks before that, I'm planning to do a complete change, which is to do two weeks of APL. So I don't know if you guys are aware of APL, but APL is just about the world's oldest programming language that's still widely used. And it's actually, we talked about notation earlier. It's actually a notation. So APL was originally developed as a notation, not as a programming language. And Iverson won the Turing Award, which is kind of like the Nobel Prize of Computer Science for this paper about it, which was written about 20 years after he created the notation. APL is a, let me show you. So the most common, why is this not working? Oh, because they're not using Windows. I have to press that. So the most widely used APL implementation, there's a lot of them, but the most widely used one is called Dialog. And yeah, it's basically math, right? Okay. Okay, looks like math. But imagine if you started with math, which itself has been developed over hundreds of years by very smart people. And then one of the smartest people in the world, being Ken Iverson, then took everything from that and combined it with tensor analysis ideas from physics which had been developed by mainly Albert Einstein and many other people. And then combined that with ideas from computer science. And then have a large group of people continuously work on that from 1960 through to 2022. So it's got a 60 years of continuous development and that gives you APL. And so just to give you a taste, in math, to add up a series, we use capital Sigma, right? And capital Sigma means only one thing. It means add up a series. If you wanna multiply together a series, you have to use something completely different, which is a capital Pi. APL instead has this idea that says, you can take a function like plus and you can modify it using something that they call an operator. So plus is a function slash is an operator. Doesn't mean divide, divided by means divided. And this operator, what it does is it takes a list. That's a list, right? And it inserts this between every pair of things on the list, which is the same as Sigma. In math. And so here's how to do the same thing as capital Pi in math, right? So for example, here's, so then there's a bunch of other symbols, right? So for example, a symbol, which actually finds that way. So lots and lots of ideas from APL have found their way into other programming languages. One of them is a lot of programming languages have something called IOTA, which means the same thing as range in Python. So IOTA six, it means almost the same thing as range. It's range plus one, if you like, rather than zero to five is one to six. And this is how sequences and series are defined in math. In math, we start at one normally. So if I want to do factorial, right? I could do apply time slash, sorry, apply time slash to IOTA six. So that's gonna take one, two, so you actually read right to left in APL. So that takes this series here and sticks times between every pair of things in it. So one times two, times three, times four, times five, times six. You got the idea? And so I'll give you an example of another operator. Backslash is the same as slash, except it basically it's cumulative. It shows me the results as I go. So this is one, one times two, one times two times three, one times two times three times four, one times two times three times four, two times five, one times two times three times four, times five, times six. So it's basically, yeah, it's a notation. It's, you know, built on mathematical notation. Jeremy, can you handle compass number as well? Yes, absolutely. Yeah, absolutely. So complex numbers are written with J. So it's a complex number. And so one of the interesting things about APL is every function, or nearly every function, maybe every function has both monadic and dyadic forms. The dyadic form means it takes two arguments, one on the left and one on the right. So here are the dyadic versions of plus, minus, divide, and times. But there's also monadic versions. And so for example, so if I wave my mouse over any of these, it tells me, so the dyadic version of plus is plus, obviously. The monadic version is conjugate, which is a complex number thing. So the conjugate of real number two is two. The conjugate of the real number 2y plus three is 2i minus three. So yeah, it's, yeah, it's kind of in some ways a superset of mathematical notation. And so yeah, it's not just plus, minus, times, divide, but see all these different things at the top. It's all of these as well. Some of which you'll recognise like epsilon, which as you'd expect means membership as dyadic, but also has a monadic form. So it does a lot more things than normal math notation. And so some of them like are really quite interesting. So for example, there's something called upstyle, which is, looks like this, and it returns the maximum of those two things. Now, where that gets interesting is what if we do maximum slash, what did that do? Well, that did the maximum of four and three. Sorry, the maximum of five and four, and then it was the maximum of that and six, and then the maximum of that and four, and then the maximum of that and three. So in other words, it's five upstyle, four upstyle, six upstyle, four upstyle, three, which when you think about it is the maximum of the list, right? So a lot of the kind of things that in normal math notation, we have to like invent something in the paper as we go or whatever in APO. It's this kind of like natural extension. So yeah, so I thought it'd be fun to have a couple of weeks of exploring this. And it's actually very helpful for PyTorch, TensorFlow and NumPy programmers because those ideas were in a many ways stolen from APL. So for example, just like you can do an APL, a number plus a list, you can do that in APL, but APL invented it, right? And does it in kind of like often more interesting ways. One of the fun things about APL is defining functions. Things tend to be a bit more consistent than a lot of other languages. So in Python, for example, you define a function with like kind of a unique syntax. In APL, to define a variable, you use arrow, and to find a function, you use a variable as well. It's just that the function goes in curly brackets and you can pass one thing to the function in which case it'll be called omega, or you can pass two things to a function which case it'll be called omega and alpha. So if I want to define plus, I would go alpha plus omega, and I can now create my own operator. And you can use any Unicode symbol so you can actually build up your own notation, right? And so it gets kind of pretty interesting because a lot of like, for example, there's an operator called power which repeats a function n times. And so for example, you can define exponent literally as repeat power n times. And so then you can like come up with your own versions of repeating things a bunch of times in ways which aren't necessarily in math but might be quite helpful in whatever you're doing. Anyway, so that's my plan. What do people use APL for nowadays? Honestly, there's two main areas. So APL is one of a class of what's called array languages of which there's three main ones in use, APL, K and J. The array languages are most commonly used in hedge fund trading, which is partly a historical thing. That's where the money is, I guess. And so that's a group of people who don't care about trends as long as they can make money. So when they kind of realize this is a really good way of expressing mathematical ideas, they kind of really dived into it. And in particular Arthur Whitney who helped create APL and went on to create K, he developed kind of a extended version of APL called A plus at Morgan Stanley. So Morgan Stanley did a lot of stuff in A plus. Yeah, so nowadays K actually, there's a whole database built on K called KDB, which is considered perhaps the fastest database in the world for a lot of things. The whole K implementation is so concise that it fits in the cache on a CPU, which is pretty amazing. Because as you can imagine, with this kind of expressiveness, you can often write pretty sophisticated programs in one or two lines of code. Yeah, it's also used in kind of like legacy big business stuff because it's been around a long time, but I don't think that's a very interesting use of it. But then like it's starting to get popular, I mean, popular, niche popular again, just as like people interested in math and notation. So some of the ideas from it have made their way into mainstream math. So for example, something that pretty much any working mathematician will be familiar with is Iverson brackets. This is a type in Iverson, it says Iverson bracket, right? Which is basically the idea that you can put a Boolean expression and make it one or zero. And once you make Booleans ones and zeros, you can manipulate them in mathematical ways, you know? And so that idea comes from APL. And so for example, which of these things is greater than the corresponding thing in, probably all that's been very good. In iota six, iota five, rather. At least on my end, I cannot, okay, because it's here at the bottom, so that it's getting a little bit covered by the, in Zoom. Is it okay? Yeah, okay, I see that in my phone, yeah. Cool, yeah. So once you recognize that you can do things like this and if you return ones and zeros as the truth values, you can be like, oh, like how many times was that true? You know? Stuff like that, you know? Yeah, so anyway, so like some of the ideas have made their way into math and coding and stuff like that. So maybe that's kind of main thing it's used for in some ways, but my interest is- So it's just kind of to look for ideas and things like that, I guess. It's kind of a useful thing. Yeah, a lot of people, including me, who have spent time with the Ray programming feel like it's the most mind-opening thing they've done in computer science, because it's like going to this alien world where they've spent 60 years going in a different direction and suddenly realizing like, and a lot of the smartest people who have worked in computer science were on that path and not our path. And it's like, wow, what have they been doing? So like, I actually find it very enjoyable because you end up reading interesting papers from the 60s and 70s and stuff. And it's just like, oh my God, you know? And so for example, I don't know if you saw it, but Mathematica came out with a new version of Mathematica today, which is not very helpful. So the latest version of Mathematica, which, yeah, came out yesterday or the day before, basically says, oh, we've invented this new thing called Threaded. And anyway, it actually turns out, if you read it, that it's the same thing as what's called the rank conjunction in APL and J, which has been around for decades. So it's like one of these things where it's like, oh, you know, ideas that have decades old are sometimes only just finding their way into modern languages. Yeah, like Mathematica. It's also a really great way to learn math or big parts of math. It's, yeah, because as you go through it, let's say for example, that's our artist question, does it have complex numbers? So as you go through it, my plan is to kind of go through each glyph. And so some of those glyphs are gonna be like, okay, well, this is the conjugate of complex numbers. What on earth does that mean? So it really gives you a chance to explore that. And then in particular, the language called J, which was developed by the developer as APL as a kind of getting all the best ideas from APL over the decades and making them better, actually comes with a whole bunch of, they call them labs, which basically take you through really interesting mathematical ideas like polynomials, you know, and all this stuff, like using J as the notation. And I prefer that to normal math notation because I already always know exactly what it means, you know, and it has a totally consistent meaning. And yeah, so yeah, so that's my plan for the next week. And actually I come across KDB before. My old boss is worked for Morgan Stanley. And I think they still have that free version. Maybe I need to take a run with the memory list and forget they actually have free version as well. They don't have free versions now. And he, last time we tried to do some IoT applications so contact all the different sensors for machinery and they come by and actually better and the performance faster than Panda as well. So he do all the configuration in KDP and then give me the file and then I start doing the visualization. So yeah, but he used to tell me take six months to actually train a person to actually can read it. So you can get us up in one thing cover with them. Yeah, yeah, we'll just get up and running. So I've actually, so like, I don't know much APL at all to be clear. So this is not like teaching you, this is a shared exploration. I've done a little bit of like a little bit of J before and then two or three weeks ago, reached the point in teaching my daughter and so I teach my daughter and her best friend math that tutor them. And we reached the point a few weeks ago where we were up to doing sequences and series, like segment notation. And I started trying to teach them and they had no idea what I was talking about. And I was like, I always thought of segment notation as actually being extremely easy because like if you explain it to me and you just be like, oh, well, it's like this list comprehension with some on the front. You know, it's like, it's a very, it's just like, oh, that's exactly what it is. But of course, they didn't have any of that kind of idea of indexing or anything. So, you know, he's kind of trying to say, like TN equals TN minus one plus one is a arithmetic sequence, you know, or whatever, you know, or like Sigma equals one to six of I. So they're just like, what's TN, what's I, like what's going on? So then we stopped trying, you know, there's like one failed lesson. And it's like, okay, forget all that. I'm gonna teach you APL and NumPy instead. And so we did like three lessons of APL and NumPy. And then I said, okay. So here's that thing, Sigma, you know, I equals one to five of I. That's this, that's plus slash Iota five. And they're like, oh, oh, that's all. Okay, you know, or, you know, in NumPy, and we didn't use MP docs, I use WorldCard import. So sum A range five plus one. Oh, that's all. So yeah, so that's why I've been like re-engaging or engaging more deeply with APL. But I think it's beautiful, you know, I think it's just a beautiful, a beautiful notation. And it reminds me in some ways of like learning Chinese. Like once I started learning Chinese, it was like, oh my God, this is whole culture of thousands of years. Num, you know, APL's like that, but you know, this is whole culture of 60 years. You know, this is whole. And recently I tried to convert things some mathematical formula into Python. That's quite painful for me. Yeah, yeah. Doing some signal processing. Cool. How did our thing, oh look, there's a thing here. So please try it and tell me if you find anything broken, I'll put it in the chat. Oh, why is there an M there? That's better. All right, thanks all. Bye. Thank you for looking forward to being yourself. Oh, hooray. Awesome. Bye.