diff options
| Commit | b961355d65aba669976c93792c2e5779ca7e5c32 (patch) | |
|---|---|---|
| Author | 2022-12-13 14:24:59 +0200 | |
| Committer | 2022-12-13 14:24:59 +0200 | |
| Files | ff7dea53213aabbc6324fd619e2dd719efa7136b | |
| syndamia.com-b961355d65aba669976c93792c2e5779ca7e5c32.tar syndamia.com-b961355d65aba669976c93792c2e5779ca7e5c32.tar.gz syndamia.com-b961355d65aba669976c93792c2e5779ca7e5c32.zip | ||
| Parent | e23b4d32ad13ad1ba6fa6476edd73414fe2be2b6 (diff) | |
[blog] Added the When a language forces simpler thinking blog post
4 files changed, 110 insertions, 66 deletions
| -rw-r--r-- | src/blog.md | 3 | ||||
| -rw-r--r-- | src/blog/index.md | 3 | ||||
| -rw-r--r-- | src/blog/when-a-language-forces-simple-thinking/index.md | 66 | ||||
| -rw-r--r-- | src/blog/when-a-language-forces-simpler-thinking/index.md | 104 |
diff --git a/src/blog.md b/src/blog.md index bbf8220..62c8a6f 100644 --- a/src/blog.md +++ b/src/blog.md @@ -6,6 +6,9 @@ Articles detailing personal experiences or exploration of certain topics. #### *2022* +&&gb [When a language forces simpler thinking](/blog/when-a-language-forces-simpler-thinking) +: `Shallow dive` `Advent of Code` `Common Lisp` + &&gb [Taming The Fun-too](/blog/taming-the-fun-too) : `Story` `Linux` `Gentoo` `Funtoo` `packages` diff --git a/src/blog/index.md b/src/blog/index.md index bbf8220..62c8a6f 100644 --- a/src/blog/index.md +++ b/src/blog/index.md @@ -6,6 +6,9 @@ Articles detailing personal experiences or exploration of certain topics. #### *2022* +&&gb [When a language forces simpler thinking](/blog/when-a-language-forces-simpler-thinking) +: `Shallow dive` `Advent of Code` `Common Lisp` + &&gb [Taming The Fun-too](/blog/taming-the-fun-too) : `Story` `Linux` `Gentoo` `Funtoo` `packages` diff --git a/src/blog/when-a-language-forces-simple-thinking/index.md b/src/blog/when-a-language-forces-simple-thinking/index.md deleted file mode 100644 index 457ce82..0000000 --- a/src/blog/when-a-language-forces-simple-thinking/index.md +++ /dev/null @@ -1,66 +0,0 @@ -# When a language forces simpler thinking - -[Article Source]() - -**Created: 11 December 2022** || **Edited: 11 December 2022** - -<br> - -Recently I was reminded of the idea that a programming language can force you to think of a simpler solution to a problem by making your initial idea unecessarely difficult to implement. -This has happened a couple of times to me, so I decided to share those experiences. -By the way, all code examples are most probably incredibly unoptimal to a highly skilled programmer. I'm not, so don't get too heated! - -<br> - -This year I decided to join the [2022 Advent of Code](https://adventofcode.com/2022) event. -The exercise [on the 7th day](https://adventofcode.com/2022/day/7) involved storage of a folder structure: each folder would have a name, files, and other folders in itself. -For the task itself, you don't actually need to store the files, just sum their size and the size of all files in subfolders, so a name, a number and multiple other folders. - -My solutions are written purely in [Common Lisp](TODO): a programming language where everything is represented as a list of values, where a value might be another list or a non-list value, like a number. -So I thought I could represent each folder as a list, where the first item is it's name, second is file size sum and everything else are subfolders, something like this: - -``` -Name File size sum Subfolder "e" in "a" - | | | - v v v -("/" 48381165 ("a" 94853 ("e" 584)) ("d" 24933642)) - ^ ^ - | | - Subfolder "a" in "/" Subfolder "d" in "/" -``` - -Now, after getting a file, you'll need to update the file size sum in the current folder and in the **parent** folder. -To do such a thing, you would either need to - -- iterate from "/" to that folder, find/store all folders in between, and update them, or -- store some way to access the parent folder, and just travel upwards - -I decided to go with the second option, since it seemed more elegant and potentially more efficient. -It is important to note that, for the past year and a half, I've extensively studied C++ in university, so my first though was for each folder to store some sort of pointer or reference to the memory address of the parent folder. - -Here is where Common Lisp slaps me on the wrist: you cannot do such a thing. -I mean, you can kinda store a reference to the parent folder object, but that will include the subfolder itself, resulting in an endless self-referncing loop, making the list unuseable. - -After thinking for a long long time, trying to force this idea to work, I had a revalation: what if, instead of trying to have lists in lists in ..., I just flatten everything and store indecies to parents? - -``` -Index of parent folder name (doesn't exist) - | -Name | File size sum - | | | - v v v -("/" -1 48381165 "a" 0 94853 "e" 3 584 "d" 0 24933642) - ^ ^ ^ ^ ^ ^ - | | | | | | - Name | Name | Name | - | | | -At index 0 is parent "/" Parent is "a" Parent is "/" -``` - -Now this solution worked great! With this I was able to [solve](https://gitlab.com/Syndamia/advent-of-code/-/tree/main/2022/Day07) both tasks![^day7] - -<br> - - - -[^day7]: A potential improvement would be to use CLOS to store each folder as it's own object, but this worked fine and I really wanted to try a structure without CLOS. diff --git a/src/blog/when-a-language-forces-simpler-thinking/index.md b/src/blog/when-a-language-forces-simpler-thinking/index.md new file mode 100644 index 0000000..86e0ec0 --- /dev/null +++ b/src/blog/when-a-language-forces-simpler-thinking/index.md @@ -0,0 +1,104 @@ +# When a language forces simpler thinking + +[Article Source](https://gitlab.com/Syndamia/syndamiadotcom/-/blob/master/src/blog/when-a-language-forces-simpler-thinking/index.md) + +**Created: 13 December 2022** || **Edited: 13 December 2022** + +<br> + +This year I decided to join the [2022 Advent of Code](https://adventofcode.com/2022) event. +The exercise [on the 7th day](https://adventofcode.com/2022/day/7) involved storage of a folder structure: each folder would have a name, files, and other folders in itself. +For the task itself, you don't actually need to store the files, just the sum of their (and of those in subfolders) size, so a folder can be represented as a name, a number and multiple other folders. + +My solutions are written purely in [Common Lisp](https://en.wikipedia.org/wiki/Common_Lisp#Syntax): a programming language where everything is represented as a list of values. A value might be another list or a non-list value, like a number. +So I thought I could represent each folder as a list, where the first item is it's name, second is file size sum and the rest are subfolders, something like this: + +``` +Name File size sum Subfolder "e" in "a" + | | | + v v v +("/" 48381165 ("a" 94853 ("e" 584)) ("d" 24933642)) + ^ ^ + | | + Subfolder "a" in "/" Subfolder "d" in "/" +``` + +Now, after parsing a file, you'll need to update the file size sum in the **current** folder **and** in the **parent** folder. +To do such a thing, you would either need to + +- iterate from "/" to that folder, find/store all folders in between, and update them, or +- store some way to access the parent folder, and just travel upwards + +I decided to go with the second option, since it seemed more elegant and potentially more efficient. +It is important to note that, for the past year and a half, I've extensively studied C++ in university, so my first though was for each folder to store some sort of pointer or reference to the memory address of the parent folder. + +Here is where Common Lisp slaps me on the wrist: there is no such thing as a pointer. +You can kinda store a reference to the parent folder object, but that will include the subfolder itself, resulting in an endless self-referencing loop, making the list unusable. + +After thinking for a long long time, trying to force this idea to work, I had a revelation: what if, instead of trying to have lists in lists in ..., I just flatten everything and store indices to parents? + +``` +Index of parent folder name (doesn't exist) + | +Name | File size sum + | | | + v v v +("/" -1 48381165 "a" 0 94853 "e" 3 584 "d" 0 24933642) + ^ ^ ^ ^ ^ ^ + | | | | | | + Name | Name | Name | + | | | +At index 0 is parent "/" Parent is "a" Parent is "/" +``` + +Now this solution worked great! With this I was able to [solve](https://gitlab.com/Syndamia/advent-of-code/-/tree/main/2022/Day07) both tasks easily.[^day7] + +#### Appendix + +In the exercise, you have commands for navigating between folders. +Going up a folder is trivial, but folders can have duplicate names if they're inside different parent folders, so going to a sub folder requires to search by it's name *and* parent index. + +Surprisingly enough, in my solution [(lines 15-17)](https://gitlab.com/Syndamia/advent-of-code/-/tree/main/2022/Day07/part-one.cl#L15-17), I just search from the end to the beginning of all parsed folders for a name. +This works fine for this exact task and exact inputs, however in general this isn't correct. In a structure like this: + +``` +/ (dir) +- a (dir) + - file1.txt (file, size=1) + - file3.txt (file, size=3) +- b (dir) + - a (dir) + - file2.txt (file, size=2) +``` + +with an input like this: + +``` +$ cd / +$ ls +dir a +dir b +$ cd a +$ ls +1 file1.txt +3 file3.txt +$ cd .. +$ cd b +$ ls +dir a +$ cd a +$ ls +2 file2.txt +$ cd .. +$ cd .. +$ cd a +``` + +The last `$ cd a` actually puts you into `/b/a/`, not `/a/`. +The main thing that saves us (me) is that you can only change directory and list structure (in current directory), so you would only ever be visiting a folder once. +If a folder's contents were `ls`'d more than once, or they could change (for example having an `mkfile`[^mkfile] command), a proper search would be required. + + +[^day7]: A potential improvement would be to use CLOS to store each folder as it's own object, but this worked fine and I really wanted to spare reading on CLOS at that time. + +[^mkfile]: `mkfile` is like `touch`, but you could specify a size and the file will be filled with that many zeroes. It seems to exist solely in [Solaris](https://docs.oracle.com/cd/E26502_01/html/E29031/mkfile-1m.html) (as a system administration command) and [MacOS](https://ss64.com/osx/mkfile.html). I mentioned it and not `touch`, since the latter only creates empty files, which wouldn't contribute to the total file size sum. |