Easy optimization for part 2 was to return '0' from 'find_mirror' if number of mismatches between 2 lines is >1, if '1' then raise a 'smudge' flag and return '0' if we find more mismatches with raised flag. Even more optimizations would come from not flipping or copying parts of array, just comparing by 2 consecutive lines and moving outwards from a found match (by index) until edge is reached or mismatch found (or 2 mismatching characters for part 2).
With one caveat, that in part 2 the number of mismatches can't be 0, so return the rows (or columns) count only if 'smudge' is raised, got tricked by this rule in my 1st part 2 submission ^^
Damn, my solution in rust was basically the same but took like 100 lines. I'm amazed at how short yet readable some people write code. I'm sure using python also helps haha
Note that all those "efficient" operations in python match to c code most likely resembling your 100 lines of Rust code (as Python really is scripting c code most of the time, especially when it comes to operations on collections) and more. I've seen a lot of unneeded allocations and creations of new lists in the presented python solution, which, when repeated in any decent system programming language, would degrade the performance of the code by 100% each. One can get away with just working on the original input, just using Vec to structure it into fields, in Rust and solve both parts of the AoC challenge in about 50 µs each on a Mac mini M1. You won't get that even with pypy (which does JIT compilation), you will miss by several orders of magnitude. But that is ok: system programming languages like C/C++/Rust are not designed to be most convenient to use, they are designed to produce the most efficient machine code (like a fast Python interpreter) possible. Whereas python or JS are designed to be easy to use, when speed isn't an issue. In this particular problem python3 needs 37 ms to solve part1, whereas Rust needs 50 µs (both measured on a Mac mini M1). That is a factor of 740!. I think that is worth 100 lines of code. And the Rust solution isn't even more complicated - it is just that in Rust you have to hand-code all those comparisons that are one-liners in python (and each of those one-liners explode to a couple of code lines in C within the interpreter and a lot of unneccesary memory allocations). It even turns out that rotating a field to apply the same horizontal reflection algo is the worst thing one can do. The rotation is expensive in execution time (I deemed myself very clever to do so until I found a Rust solution which did not and blowed my solution out of the water then - turns out you do less when comparing columns than you do when rotating the field and then comparing rows, as for all the memory allocations needed to do so).
Hey I'm loving your videos and how you are making the complex problems look so simple. Thank you for the time and effort you are putting into this!!! Would you consider splitting those inline ternaries and loops into multiple lines? It could increase the readability for people just starting with the language, and also it could make your python code more similar to other langues, so we can follow along even if we are not in Python.
I can separate out some of the logic but I intend to keep code still mostly pythonic as I think it isn't useful to teach anti-patterns in python. That said, I can put more time into explaining the language-agnostic approach each segment of code is taking so it can be more easily reimplemented into another language
Dang, that transposing trick is nice !!
Easy optimization for part 2 was to return '0' from 'find_mirror' if number of mismatches between 2 lines is >1, if '1' then raise a 'smudge' flag and return '0' if we find more mismatches with raised flag.
Even more optimizations would come from not flipping or copying parts of array, just comparing by 2 consecutive lines and moving outwards from a found match (by index) until edge is reached or mismatch found (or 2 mismatching characters for part 2).
With one caveat, that in part 2 the number of mismatches can't be 0, so return the rows (or columns) count only if 'smudge' is raised, got tricked by this rule in my 1st part 2 submission ^^
Hi, thank you for your videos. I would like to know what keyboard are you using :)
Razer Blackwidow V4 (not the pro version)
Damn, my solution in rust was basically the same but took like 100 lines. I'm amazed at how short yet readable some people write code. I'm sure using python also helps haha
Note that all those "efficient" operations in python match to c code most likely resembling your 100 lines of Rust code (as Python really is scripting c code most of the time, especially when it comes to operations on collections) and more. I've seen a lot of unneeded allocations and creations of new lists in the presented python solution, which, when repeated in any decent system programming language, would degrade the performance of the code by 100% each. One can get away with just working on the original input, just using Vec to structure it into fields, in Rust and solve both parts of the AoC challenge in about 50 µs each on a Mac mini M1. You won't get that even with pypy (which does JIT compilation), you will miss by several orders of magnitude. But that is ok: system programming languages like C/C++/Rust are not designed to be most convenient to use, they are designed to produce the most efficient machine code (like a fast Python interpreter) possible. Whereas python or JS are designed to be easy to use, when speed isn't an issue.
In this particular problem python3 needs 37 ms to solve part1, whereas Rust needs 50 µs (both measured on a Mac mini M1). That is a factor of 740!. I think that is worth 100 lines of code. And the Rust solution isn't even more complicated - it is just that in Rust you have to hand-code all those comparisons that are one-liners in python (and each of those one-liners explode to a couple of code lines in C within the interpreter and a lot of unneccesary memory allocations). It even turns out that rotating a field to apply the same horizontal reflection algo is the worst thing one can do. The rotation is expensive in execution time (I deemed myself very clever to do so until I found a Rust solution which did not and blowed my solution out of the water then - turns out you do less when comparing columns than you do when rotating the field and then comparing rows, as for all the memory allocations needed to do so).
Hey I'm loving your videos and how you are making the complex problems look so simple.
Thank you for the time and effort you are putting into this!!!
Would you consider splitting those inline ternaries and loops into multiple lines?
It could increase the readability for people just starting with the language, and also it could make your python code more similar to other langues, so we can follow along even if we are not in Python.
I can separate out some of the logic but I intend to keep code still mostly pythonic as I think it isn't useful to teach anti-patterns in python. That said, I can put more time into explaining the language-agnostic approach each segment of code is taking so it can be more easily reimplemented into another language
@@hyper-neutrino I definitely appreciate seeing Pythonic code. Keep up the great work!
today's problem was quite easy. A lot easier then day 5. At this point, I never know what to expect each day
Nice clear explanation. Haven't done today's yet as work got in the way but it looks a bit easier than yesterday's!