diff options
author | eug-vs <eugene@eug-vs.xyz> | 2022-04-21 15:04:56 +0300 |
---|---|---|
committer | eug-vs <eugene@eug-vs.xyz> | 2022-04-21 15:04:56 +0300 |
commit | 24639575c32e48a3db46e06be6a3a25cd80e8991 (patch) | |
tree | c8d86d84ce9581a65471d0d4aa6720b4506fe6ae /blog | |
parent | 0b7bc99af62aa53148b7fcede648e5dfb6e2ca22 (diff) | |
download | eug-vs-xyz-24639575c32e48a3db46e06be6a3a25cd80e8991.tar.gz |
refactor: change prject structure
Diffstat (limited to 'blog')
-rw-r--r-- | blog/2021-07-02.md | 17 | ||||
-rw-r--r-- | blog/2021-07-03.md | 98 | ||||
-rw-r--r-- | blog/2021-07-15.md | 141 | ||||
-rw-r--r-- | blog/2021-08-14.md | 80 | ||||
-rw-r--r-- | blog/2021-08-18.md | 81 | ||||
-rw-r--r-- | blog/2021-09-10.md | 22 | ||||
-rw-r--r-- | blog/2021-09-21.md | 24 | ||||
-rw-r--r-- | blog/2021-10-06.md | 17 | ||||
-rw-r--r-- | blog/2021-10-27.md | 34 | ||||
-rw-r--r-- | blog/2021-10-28.md | 11 | ||||
-rw-r--r-- | blog/2022-02-26.md | 5 | ||||
-rw-r--r-- | blog/2022-03-17.md | 14 | ||||
-rw-r--r-- | blog/2022-03-24.md | 14 | ||||
-rw-r--r-- | blog/2022-03-26.md | 62 | ||||
-rw-r--r-- | blog/2022-04-02.md | 83 | ||||
-rw-r--r-- | blog/2022-04-17.md | 51 | ||||
-rw-r--r-- | blog/2022-04-18.md | 48 | ||||
-rw-r--r-- | blog/index.md | 43 |
18 files changed, 0 insertions, 845 deletions
diff --git a/blog/2021-07-02.md b/blog/2021-07-02.md deleted file mode 100644 index 48ef972..0000000 --- a/blog/2021-07-02.md +++ /dev/null @@ -1,17 +0,0 @@ -# My plans for this website -Welcome to [eug-vs.xyz](https://eug-vs.xyz)! This is my personal website where I plan to set up a bunch of cool things, namely: - - SearX instance - - Email server (*already up and running!*) - - [TaskWarrior](https://taskwarrior.org) server - - This blog - - Knowledge base - -I decided that I will write content for this website in `Markdown`, since it's the way of writing I am already so used to. -I use [vimwiki](https://github.com/vimwiki/vimwiki) for writing and then I just pipe my `.md` files into `pandoc` which gives me nice static web pages. No bullshit, ads, trackers or client-side JavaScript here. - -# Structure -Vimwiki provides a very good notes structure out of the box: you have your **main wiki** and **diary**: - - **Main wiki** will be represented as a knowledge base, where I'll put things that I consider important and worth being indexed - - **Diary** will form this blog - where I'll put everything that does not fit into the main wiki but still worth sharing - -This way I can keep my writing workflow the same, I don't have to switch to the new patterns or anything else. diff --git a/blog/2021-07-03.md b/blog/2021-07-03.md deleted file mode 100644 index 7b97329..0000000 --- a/blog/2021-07-03.md +++ /dev/null @@ -1,98 +0,0 @@ -# What's wrong with Numerology -Numerology is a strange thing you may encounter at some point in your life. While you can believe into anything, it's of course -important to not take it too serious as some people do. You should be able to detect if something completely random is trying to mimic the science. - -<p align="center"> - <img src="https://i.pinimg.com/originals/2b/9c/57/2b9c57e9d98fdb853f863ecb224aac27.jpg" width="512px"> -</p> - -# Background -Lately I've been on the party where I met a girl who was making money by doing numerologic predictions for people. I've never had a chance -to have a conversation with such people, and I was very excited when I finally got it. One of the first questions I asked was a sanity check: "*you know that you are tricking people, right?*" - -She seemed pretty intelligent to me and I thought that it's just a way to make money for her - it's of course bad to trick people -into such things, but well, we are not judging here. - -Surprisingly, she turned out to be **strong** believer and she really thought that she's making world a -better place by doing this. -I thought, well, maybe she's right, let's find out! We had a long conversation, let's jump straight into key points. I will express some parts of our dialogue as shortened Q&A's. - -# Do numbers matter? -Basically as she explained, they convert everything into numbers in numerology (pretty much like we do in programming). I have no problem with, for example, converting -my name into some number and than working with it. So, according to this theory, numbers have special meaning. - - Is it the number that matters, or the digits it consists of? - - The number itself - -This absolutely makes sense - since we can have an infinite amount of numeral systems. E.g 11 is eleven in base 10, but at the same time these digits can express number three in binary (base 2). - -So, ultimately this theory must be a subset of [determinism](https://en.wikipedia.org/wiki/Determinism) - numbers affect our life in a specific way - they produce more numbers and the cycle continues. -She agreed with that, and since there's no way to prove this deterministic aspect - I'm ok with that. If we know we can't prove it - you can only believe it (or not). Who knows, maybe numbers really have -special meaning. But the problem isn't here... - - -# Which numbers matter? -Everything above is perfectly valid, but the question naturally arises: - - How do we choose, which numbers matter? - - There are special numbers in your life! E.g your name/surname/etc, your birthday, your [*try not to laugh*] **passport number**! The time of specific events also matters. - -<p align="center"> - <img src="https://i.imgflip.com/3tzba8.jpg"> -</p> - -As soon as I heard that, I was 100% sure it's a total bullshit, but how do I prove it? I've started with simple things. - - What if I change my name? - - Your destiny changes along with it! - - Ok, what if I don't have a name? What if I live in the woods and don't know what the passport is? - - In this case only date of your birth matters! - -Ok, first of all, she seems to not understand that passport is a thing that only exists in a specific context: civilized society, jurisdiction, ability to print - just to name a few. - - There were no passports back then, did people not have destiny? - - But they had names! - - Well, let's go back to cavemen - they didn't have names. So... Numerology didn't work in those times, did it? - - It does not matter! If no one could speak or even had a name - they didn't care about numerology so it could not work. But it works now! Or there was a different Numerology... - - This last argument is pretty interesting. The problem is - well, if your science (or any set of laws) works - it works every time. If you have **Numerology v1** for ancient people and - **Numerology v2** for a modern society - it's not a one science - it's two! - -# A "proof" - Here's somewhat formal proof that such form of Numerology can't exist: - - We'll define Numerology as a *mapping* which maps the space of **numbers in your life** into the space of **possible outcomes** - - Assume there only exists one valid Numerology. If there are more valid "Numerologies" - it means we can choose any of those as we need and make up any result. - - Assume we can only account for finite amount of **numbers in our life**. If it's not true, such Numerology is useless - we can't make any predictions if the amount of factors is infinite! - - Consider some point in one's life. It can be described with the finite amount of **N numbers** - e.g current time, current passport name, amount of money in bank account, etc. - - Let's go back in time to the point where this person had no bank account - it means now there are only **N-1** meaningful factors - - Go back further to the point where the person didn't have a passport (maybe he was just born). It's **N-2** now - - We can keep decreasing N as much as we want, all the way to 0. Even the most "abstract" concepts, such as time, were invented by humans and we can go back where they didn't know how to measure time, it means there were no origin (or no one has defined it). As a number, time only exists as an interval - from `START` to `END`. If there's no single `START` - we can take any point and choose arbitrary number! One can argue that we can take *BIG BANG* as a `START`. But well, in this case, what unit do we use to measure time? Do we use seconds, minutes or what? - - We have now **N** different valid versions of Numerology! It contradicts with our assumption that there's only one valid Numerology. - -The "proof" above is of course not 100% correctly formulated, but hopefully you get the idea and reasoning behind it. The better and shorter version might be: - -*For any given outcome `S` for the person `P`, there exists a "version" of Numerology `V` that picks a finite amount of specific factors for that person, such that `V(P) = S`* - -It basically means that since we have infinitely many factors to measure in our life (and we can make up infinitely many measuring units) - we can generate any sequence of numbers to **make up** specific result. Of course, we can not make any predictions based on that - this is a complete bullshit. This is also backed up by the fact that there's no single "repository" or "sourse of truth" for Numerology. Everyone just comes up with their own version! Even if there is some hidden secret knowledge base it's also totally made up and as invalid as any other. - -# Why she thinks she's right - - How do you know which parameters to account? - - It's **statistics** and **high-level maths!** [*Here she started explaining me how they accumulated huge amount of data and analyzed that etc. etc.*] - -Yes, she may understands the **math** that transforms the numbers into results. The problem is - math is only doing the mapping! If the source of mapping is incorrect, the result can't be correct too! Information follows this path: - 1. Reality - 2. Numerology picks [arbitrary] N factors - 3. Super-advanced math functions - 4. Resulting prediction - -She knows that step 3 and 4 work, but what she doesn't understand is that step 2 can give arbitrary results! Therefore steps 3 and 4 do not matter as they act on the results of step 2. This is exactly what **misleads** people and makes them trust the system! They are so focused on verifying steps 3 and 4, they completely forget about step 2! - -# Few words about statistics -They may gather as much data as they want. There's such thing as the [Law of large numbers](https://en.wikipedia.org/wiki/Law_of_large_numbers). It's usually enough to debunk any sort of fraudelent predictors - and this is not the exception. - -# PS -These guys always sound so convincing because usually they believe the theory themselves. Always make sure to perform a "sanity check" on such things. Some of them require deeper thoughts, but usually you can "smell" the trickstery (or foolishness) right away. A *common sense* is all that you need in order to avoid getting tricked by them. - -<p align="center"> - <img src="https://www.memecreator.org/static/images/memes/5188399.jpg"> -</p> - -Fun fact: **almost all** numbers are *normal* yet *uncomputable* - in practice it means we can't even write them down! If you, for example, measure something (except for counting instances of objects) in real world with a fixed unit of measurement - it's almost never going to be rational number. Do you think every single one of those uncountably infinitely many numbers has its own "special meaning"? See [this video](https://www.youtube.com/watch?v=5TkIe60y2GI) for detailed explanation. There are of course more inconsistencies to it that I missed. - - diff --git a/blog/2021-07-15.md b/blog/2021-07-15.md deleted file mode 100644 index 2ea0bd5..0000000 --- a/blog/2021-07-15.md +++ /dev/null @@ -1,141 +0,0 @@ -# CircleCI :circleci: in daily life: how I improved Matrix stickerpicker - -[CircleCI](https://circleci.com) is a great tool that everyone seems to skip and I don't know exactly why. -I'm gonna quickly show you how I've automated adding stickers to the [Matrix](https://matrix.org) messenger. - -## What is CircleCI? -`CircleCI` is a cloud platform that can run automated jobs when different events occur. The most common use-case is -running tests in the cloud when you push a commit to the `GitHub` repo. But the possibilities are endless, -you can literally automate everything with it - I even used it to compile `.exe` file **in the cloud** and include -a **zipped binary** into the release package. Don't ask me why I had to compile `.exe`, better ask why the guys from my -University **made a deal with** [**the Devil**](https://microsoft.com). - -## Matrix -[Matrix](https://matrix.org) is a messaging protocol which I'm currently trying to replace **Telegram** with. -It's in itself a separate topic for discussion, but what's important for today is that **Matrix** lacks such -a huge collection of stickers as there is in **Telegram**. I'm a big fan of **Wojak** stickers and many other ones, -so I had to do something about it. - -![stickerpicker](/public/stickerpicker.png) - -# Matrix Stickerpicker -Stickers work in a slightly weird way in **Matrix**. Basically you have to deploy your own sticker "server" -(*don't worry, it's just a static site*) where you can add your stickers - it will be used as a widget inside your client. - -There's an amazing tool for that - [stickerpicker](https://github.com/maunium/stickerpicker). It's written in `Python` and the author -of course took care of the import feature - you can provide a link to a **Telegram** sticker pack - it will re-upload it -to your `Matrix` server and then generate a web UI using GitHub Pages that you can integrate as a widget in your client. Your friends -can use it too. - -The problem is that each time you want to add new sticker pack to your collection you have to run a `Python` script. -I'm lazy and I don't wanna do that - so let's automate it! - -## Automation -Main idea of my solution is to have a single plaintext file `telegram-packs.txt` which will contain links to all -sticker packs I import from **Telegram**. Then every time I update it `CircleCI` will run a job that will run this `Python` script for me. Deadly simple. - -This approach ships with few bonuses by default: - - You can edit the file from anywhere (even from phone :laughing:) - - If someone from your friends uses your stickers collection and wants to add a new pack, they simply have to open a PR which adds the pack URL to `telegram-packs.txt`. - -There are two problems of running this `Python` script automatically: - - You have to log into your `Matrix` account - - You have to log into your `Telegram` account - -## Config -Here's my fork of the repo: https://github.com/eug-vs/stickerpicker - -`CircleCI` is fully controlled by a config file `.circleci/config.yml`. It uses `YAML` which is really picky about indentation, so be careful with that. - -Ok so let's start outlining our job, we'll be using default CircleCI `Python` image: -```YAML -defaults: &defaults - working_directory: ~/repo - docker: - - image: cimg/python:3.9.5 - -jobs: - upload_stickers: - <<: *defaults - steps: -``` - -The `defaults` part might look scary, but you could just move everything from defaults directly under `upload_stickers` job. -Defaults are useful when you have multiple jobs, and I planned to have 2 initially. Let's now move to the `steps`: -```YAML -- checkout - -- run: - name: Install python dependencies - command: pip3 install . -``` -Obviously we checkout our code first, and then install all the dependencies for our `Python` script. - -Now let's solve the first problem we found. Instead of logging into `Matrix` manually, you can supply a `config.json` file with your credentials. So I prepared a template for this file (`config.template.json`): -```JSON -{"homeserver": "$HOMESERVER", "user_id": "$USER_ID", "access_token": "$ACCESS_TOKEN"} -``` -You might think how am I gonna put the actual variables in here? Well, there's a tool for that called `envsubst`. It does exactly what you think - substitutes environment variable names with the actual values. -We will put the actual values of `$HOMESERVER`, `$USER_ID` and `$ACCESS_TOKEN` in our `CircleCI` environment (as secrets), and the template can be safely pushed to the GitHub repo. - -There's a little problem - `envsubst` is not installed in the image that we use (`cimg/python:3.9.5`). Solution to it is [orbs](https://circleci.com/developer/orbs) - basically plugins for your CircleCI needs. -Let's add `envsubst` orb at the top of our config: -```YAML -orbs: - envsubst: sawadashota/envsubst@1.1.0 -``` - -Now back to the steps. Let's install the tool and use it to generate our `config.json`: -```YAML -- envsubst/install - -- run: - name: Create config.json from template - command: envsubst < config.template.json > config.json -``` - -Ok so we can now login into `Matrix`, but what about `Telegram`? The script uses `Telethon` package under the hood which works with a `sticker-import.session` file. This is basically an `SQL` database, and I don't really -wanna mess around with creating it from scratch (*although I could!*). Instead, I will just encrypt it with `GPG` and push to the repo. That's just me being lazy, but you know, that is what automation is about! -Of course, someone could try to decrypt my `Telethon` session since it's now publicly available, but I can just revoke it at any time. I will probably improve this at some point, but now it's not a big deal for me. - -Our next steps in config will be to decrypt the session and finally pipe our `telegram-packs.txt` to the script using `xargs`: -```YAML -- run: - name: Decrypt telethon session - command: gpg --batch --passphrase $PASSPHRASE --decrypt sticker-import.session.gpg > sticker-import.session - -- run: - name: Reupload and install stickers - command: cat telegram-packs.txt | xargs sticker-import -``` - -At this point, the stickers are uploaded to the server, but the UI is updated via it's own `.json` file which contains information about uploaded stickers. It's already updated by the script, we just have to push it to our repo. -For that I've created a new SSH key and added it to `CircleCI` secrets so that it can push commits to my repository. So the final steps would be: -```YAML -- add_ssh_keys - -- run: - name: Add github to known_hosts - command: | - mkdir -p ~/.ssh - ssh-keyscan github.com >> ~/.ssh/known_hosts -- run: - name: Commit stickerpack JSON's - command: | - git config --global user.email "eug-vs@keemail.me" - git config --global user.name "eug-vs" - git add . - git commit -m "feat: add stickerpacks with CircleCI [ci [skip](skip.md)]" - git push -u -``` - -The `[ci skip]` flag tells Circle to avoid running on this commit, otherwise it would have to run once again since we pushed a new commit with it. - -One thing that I didn't mention is that I did not actually -need to check the **new** packs in the `telegram-packs.txt` - the script is actually smart enough to skip already existing ones. Otherwise I would have to use `git diff` to find only the new ones. - -And that's it! Now every time I add new URLs to the `telegram-packs.txt`, they will automatically appear in my widget within a minute or so. Enjoy your stickers! - -![wojak-brain-chair](/public/wojak-brainchair.png) - -You can find full version of the config here: https://github.com/eug-vs/stickerpicker/blob/master/.circleci/config.yml diff --git a/blog/2021-08-14.md b/blog/2021-08-14.md deleted file mode 100644 index e98d78f..0000000 --- a/blog/2021-08-14.md +++ /dev/null @@ -1,80 +0,0 @@ -# Using imagemagick :imagemagick: to crop soy faces -I'm pretty sure everyone knows that sometimes finding a good **PNG** can be very hard, while there's always a bunch of the same **JPEG** images with the white background. -After searching for 10 minutes, you decide to remove background yourself - using [GIMP](https://gimp.org) or something like `Photoshop` or `PAINT.NET` if you are on Windows. **Forget about it!** I'm gonna show you how you can use [imagemagick](https://imagemagick.org/) to automate basic tasks like removing background and cropping images. - -# Telegram sticker pack -Every time I use Telegram stickers, I feel tired scrolling through many different packs trying to find the sticker I want. Sometimes, you just want them all to be in one place. That's why I created **Based Wojak** - a sticker pack which is automatically generated from random source images that I find on the internet. - -![based-wojak](https://user-images.githubusercontent.com/51545008/129426994-2a787714-772d-4010-b295-6ae00346bdbc.png) - -It doesn't matter if the image has a white background or wrong resolution, I just put it in the `src` folder and then magic :imagemagick: happens. For example, these are the source images used to generate the stickers above: - -![based-wojak-sources](https://user-images.githubusercontent.com/51545008/129427152-e01bc830-06e4-441a-9d8c-3dccbfb4d025.png) - -The collection itself is very small right now as you can see, but I plan to extend it as I need more stickers. Add this pack: - -https://t.me/addstickers/BasedWojak - - -# Imagemagick -Now, let's see how I've done that. Here's the GitHub :github: repo so you can follow: - -https://github.com/eug-vs/telegram-based-wojak - -You know, I love Makefiles. I use them everywhere (where they're appropriate), even this website is generated by a `Makefile`. Let's have a look at the `Makefile` for `telegram-based-wojak`: - -```Makefile -# Makefile -SOURCES=$(wildcard src/*) -OUTPUTS=$(patsubst src/%.png, out/%.png, $(patsubst src/%.jpg, out/%.png, $(SOURCES))) - -SIZE=512x512 -FUZZ=50% - -VIEW_COMMAND=sxiv -t - - -all: $(OUTPUTS) - -view: all - $(VIEW_COMMAND) out - -viewsrc: - $(VIEW_COMMAND) src - -out/%.png: src/%.* - @mkdir -p out - magick $< \ - -fuzz $(FUZZ) -fill none \ - -floodfill +0+0 white \ - -floodfill "+%[fx:w-1]+0" white \ - -trim +repage \ - -resize $(SIZE) $@ - -clean: - rm -rf out -``` - -On the first two lines I just create variables for input and output images. Then I define the `SIZE` - Telegram expects sticker's largest side to be `512px`. The value of `FUZZ` determines the sensitivity of removing the background - I use `50%`, but that's just something you can play with. - -Now let's have a closer look at the recipe for creating `out/%.png` from `src/%.*`. I use `magick` on the input file (denoted by `$<`), then pass a whole bunch of parameters to it, and finally provide the output file (`$@`). If you are confused by `$<` and `$@`, check out [Makefile cheatsheet](https://devhints.io/makefile). - -![imagemagick-logo](/public/emoji/imagemagick.png) - - -## Removing the background -To remove background, I use `-floodfill`, here's how [imagemagick wiki](https://imagemagick.org/script/command-line-options.php) describes it: -> -floodfill {+-}x{+-}y color -> -> Floodfill the image with color at the specified offset. -> -> Flood fill starts from the given 'seed point' which is not gravity affected. Any color that matches within -fuzz color distance of the given color argument, connected to that 'seed point' will be replaced with the current -fill color. - -I use it two times: one in the top-left corner and one in the top-right. Top-left corner pixel obviously has a coordinate `+0+0`. To get the X coordinate of right-most pixel I have to use this expression: `+%[fx:w-1]`, Y coordinate stays at `0` of course. Since I already supplied `-fuzz` and `-fill none`, both operations will replace the white background with `none`, starting from two top corners of the image using the supplied fuzziness value. - -## Cropping the image -After we removed background, most of the time we can trim a lot of extra space so that our image size corresponds to its content. Simple `-trim +repage` does the trick. - -## Adjusting the size -All we have to do now is to make sure the sticker respects the size with `-resize` option. It will resize it in a way so it fits into `512x512` box without changing the aspect ratio (largest side will always be `512px`). - diff --git a/blog/2021-08-18.md b/blog/2021-08-18.md deleted file mode 100644 index f048106..0000000 --- a/blog/2021-08-18.md +++ /dev/null @@ -1,81 +0,0 @@ -# Python :python: in real life -Recently I had a chance to solve an accounting problem. And as always, Python saved me some time and nerve cells. - -## The problem -In accounting you sum things up a lot. And sometimes, you forget what were the terms you used to compute the sum, especially when there are a lot of them. This is exactly the scenario I faced recently: - - There's a price list for certain items - - There's a total sum that was made up from **some** of these prices - - You have to find out what prices were used to calculate total sum - -And this problem appears many times, same price list but different totals. I immediately knew I am not gonna do this manually, so first thing I did was creating a new script and writing my first two lines with the input data: -```python -prices = [561.6, 134.24, 561.6, 345.6, 2292, 22.08, 61.2, 87.41, 37.08, 37.8, 25.44, 246] -totals = [271.01, 1078.61, 3333.44] -``` - -## Thinking -Now, let's analyze the problem a bit. There are **12** prices in the list. Let's suppose our total was made up from 2 prices. It could be any 2 numbers from the list, in fact there are a lot of possible pairs. To be precise, there are **66** of them! Luckily Python has an amazing package `itertools` which allows you to work with combinatorics. We can now list all these pairs: - -```python -from itertools import combinations - - -prices = [561.6, 134.24, 561.6, 345.6, 2292, 22.08, 61.2, 87.41, 37.08, 37.8, 25.44, 246] -pairs = list(combinations(prices, 2)) -print(pairs) -``` - -Output: -```python -[(561.6, 134.24), (561.6, 561.6), (561.6, 345.6), (561.6, 2292), (561.6, 22.08), (561.6, 61.2), (561.6, 87.41), (561.6, 37.08), (561.6, 37.8), (561.6, 25.44), (561.6, 246), (134.24, 561.6), (134.24, 345.6), (134.24, 2292), (134.24, 22.08), (134.24, 61.2), (134.24, 87.41), (134.24, 37.08), (134.24, 37.8), (134.24, 25.44), (134.24, 246), (561.6, 345.6), (561.6, 2292), (561.6, 22.08), (561.6, 61.2), (561.6, 87.41), (561.6, 37.08), (561.6, 37.8), (561.6, 25.44), (561.6, 246), (345.6, 2292), (345.6, 22.08), (345.6, 61.2), (345.6, 87.41), (345.6, 37.08), (345.6, 37.8), (345.6, 25.44), (345.6, 246), (2292, 22.08), (2292, 61.2), (2292, 87.41), (2292, 37.08), (2292, 37.8), (2292, 25.44), (2292, 246), (22.08, 61.2), (22.08, 87.41), (22.08, 37.08), (22.08, 37.8), (22.08, 25.44), (22.08, 246), (61.2, 87.41), (61.2, 37.08), (61.2, 37.8), (61.2, 25.44), (61.2, 246), (87.41, 37.08), (87.41, 37.8), (87.41, 25.44), (87.41, 246), (37.08, 37.8), (37.08, 25.44), (37.08, 246), (37.8, 25.44), (37.8, 246), (25.44, 246)] -``` - -Here we converted the result of `combinations(prices, 2)` to a `list`, but that's actually only to be able to `print` it. In fact, the original result was a [generator](https://wiki.python.org/moin/Generators) - it wasn't storing the whole list in memory, only the instructions how you should iterate over it. And that's exactly what we want to do - iterate over this list, taking the sum and see if it matches the result, something like this: - -```python -for prices_combination in combinations(prices, 2): - if sum(prices_combination) == total: - return prices_combination -``` - -# The solution -Of course, our `total` doesn't have to be a sum of 2 terms, it can be 3, 4, 5 or more. Also, `total` might not exactly equal the sum, there can be a slight difference due to rounding or human error. Let's say this difference is no more than `0.01`. This will be the final solution: -```python -#!/usr/bin/python -from itertools import combinations - - -prices = [561.6, 134.24, 561.6, 345.6, 2292, 22.08, 61.2, 87.41, 37.08, 37.8, 25.44, 246] -totals = [271.01, 1078.61, 3333.44] - -def decompose(total, terms): - for count in range(1, len(terms)): - for combination in combinations(terms, count): - if abs(total - sum(combination)) < 0.01: - return combination - -for total in totals: - combination = decompose(total, prices) - print(f'{total} = sum{combination}') -``` - -Which will produce a nice output in less then **0.03** seconds: -```python -271.01 = sum(22.08, 61.2, 87.41, 37.08, 37.8, 25.44) -1078.61 = sum(561.6, 22.08, 61.2, 87.41, 37.08, 37.8, 25.44, 246) -3333.44 = sum(561.6, 134.24, 345.6, 2292) -``` - -Notice that the only list stored in memory was the original one. Each combination only appeared in memory when it was needed to calculate the sum, and immediately disappeared after that. That's why it's (relatively) fast! - -# Takeaway -Of course this script isn't by any means optimal! Essentially it's a brute force, we are just checking all the possible combinations. But we are doing it in a **clean and efficient way** (credit to generators). - -When you are solving real-life problems, you are not in algorithms class and you don't have to write a hardcore algo, you just have to correctly utilize amazing toolkit that this language has. I've spend no more than 5 minutes writing this and I already have the answer to my problem - that's the beauty of Python :python:! - -## Now imagine writing and compiling a C++ program for that! -I can only describe it with this image: - -![meme](/public/brainlet-dreams-big-brain.png) - -Programming languages are tools, and different situations require different tools. diff --git a/blog/2021-09-10.md b/blog/2021-09-10.md deleted file mode 100644 index de1d7a0..0000000 --- a/blog/2021-09-10.md +++ /dev/null @@ -1,22 +0,0 @@ -# Summer 2021 - retrospective -This summer was one of the greatest I ever had! - -# Achievements -During this summer I have: - - [X] Set up a Raspberry Pi :raspberry-pi: - - [X] Created this website - - [X] Configured personal email server - - [X] Configured personal TaskWarrior server :taskwarrior: - - [X] Passed some university exams - -# Productivity -Here's my TaskWarrior burndown: -![burndown](/public/summer-2021/burndown.png) -I'm pretty happy with how it looks, definitely can spot some progress going on. - -# Lifestyle -It was very active! I got into kayaking which was unforgettable :fire:, big thanks to my friends! - -![bonfire](/public/summer-2021/bonfire.jpg) - -![kayaking](/public/summer-2021/kayaking.jpg) diff --git a/blog/2021-09-21.md b/blog/2021-09-21.md deleted file mode 100644 index d3a5f8f..0000000 --- a/blog/2021-09-21.md +++ /dev/null @@ -1,24 +0,0 @@ -# I'm back on Carnivore! :meat_on_bone: -This weekend I bought a new high-quality pan and now I just can't resist going back to carnivore diet. - -![pan](/public/pan.png) - -You really see the difference in the cooking process - the surface is big, heat is distributed evenly, it produces less smoke - it all adds up to a much better cooking experience :fire: - -![meat](/public/meat.png) - -I've been thinking of going back to carnivore for a long time already, but this pan finally pushed me to do it. I'm not going **full carnivore** though, this is the list of the food I'm planning to eat: - - All sorts of meat :meat_on_bone: - - Liver (~1-2 times a week) - - Fish (~once a week) :fish: - - Eggs :egg: - - Coffee :coffee: - - Diary: - - Cheese :cheese: - - Cottage cheese - - Butter :butter: - - Sour-cream - - Bananas :banana: - - Lemon :lemon: - -This is of course not a perfect list, ideally I would remove bananas and diary from here, but I'll start with this because I already used it for ~3 months before. I find lemon really important to support the levels of vitamin C. But that's what works for me, it might now work for you of course. diff --git a/blog/2021-10-06.md b/blog/2021-10-06.md deleted file mode 100644 index 4611853..0000000 --- a/blog/2021-10-06.md +++ /dev/null @@ -1,17 +0,0 @@ -# You should start using `ssh-copy-id` now! -Over the last couple of weeks I had to simultaneously manage up to 4 virtual machines in the Cloud. Holy shit, I've lost so much time just trying to log into them - picking up the correct server IP, then finding the password for it, and then finally `ssh`-ing into it. That's such a painful process, especially when you have to repeat it over and over again. - -Luckily, there's a solution! Simply run `ssh-copy-id username@password` (the same way you would do with `ssh`, just replacing it by `ssh-copy-id`), enter your password and it will remember it. Of course you gotta have your keys set up, but I think everyone has. - -Well, as a bonus, to not mess with the IPs, you can also use `~/.ssh/config` like that: -```bash -Host <alias> - HostName <server ip> - User <username> -``` -You might guess what it's doing: running `ssh <alias>` will now expand to `ssh <username>@<server-ip>`! - -Of course you can add as much hosts as you want to your config. Combined with `ssh-copy-id`, you get a perfect solution for managing multiple web servers. - -## PS -If you are familiar with `tmux`, I highly recommend installing it right away on your server, and doing everything in a session. Even simple `tmux new` / `tmux a` will make your life even more easy! diff --git a/blog/2021-10-27.md b/blog/2021-10-27.md deleted file mode 100644 index 06b9a0d..0000000 --- a/blog/2021-10-27.md +++ /dev/null @@ -1,34 +0,0 @@ -# Ray marching in Rust :rust: ! -I'm currently learning Rust for fun and re-writing my [ascii-renderer](https://github.com/eug-vs/ascii-3d-renderer) from Python :python:. I'm using Ray Marching this time, here's how it looks (if you are on mobile, use desktop version of the site): - -[![asciicast](https://asciinema.org/a/jsDqGeMkRwLeYhVIMqNbaec0M.svg)](https://asciinema.org/a/jsDqGeMkRwLeYhVIMqNbaec0M) - -You can see that Ray Marching allows for some cool stuff like smooth surface blending and proper shadowing. - -# Ray marching -Usually 3d renderers use a triangular mesh to describe objects in a scene. In Python version of `ascii-renderer` I defined each object as a set of points -(i.e object is defined by a function `__contains__` that determines whether the given point is in this object). It allowed me for some cool Ray Tracing stuff, but that was just me toying around. - -Behold - Ray Marching! It's a cool rendering technique where you describe your scene with a *Distance Field* - each point in this field contains a distance from that point to the scene. -Well, actually it's a *Signed Distance Field* - the distance to the object is considered negative *inside* the object, and positive *outside*. - -What's cool about Ray Marching is that since the whole scene is defined with mathematical expression, I can apply any mathematical transformations to it. For example I can make an object wavy -using a `sin`, or make it repeat forever with `%` operator. Also, `SDF` allows for different ways to combine objects - I can find a `union`, `difference`, and `intersection` for free! - - - -## Performance -Currently it's rendering 4 shapes at ~19 FPS, which is pretty bad. That's probably due to my dirty and inefficient code :laughing: - I'm nowhere near a good understanding of Rust :rust: patterns. - -My goal is to render 8 shapes at 24 FPS: - - 24 FPS is OK for a human eye - - 8 distinct shapes is usually enough to create a complex scene (ray marching allows for cool tricks that can multiply amount of your shapes without performance decrease) - - -# Plans - - Cleanup the code and increase performance - - Build an actually usable API - - Use `ncurses` instead of just printing to `STDOUT` - - Create an `ncurses` GUI for building a scene - - Allow importing/exporting scenes in `JSON` - - Do some magic :star: and expose API to the browser using `WebAssembly` diff --git a/blog/2021-10-28.md b/blog/2021-10-28.md deleted file mode 100644 index aece45f..0000000 --- a/blog/2021-10-28.md +++ /dev/null @@ -1,11 +0,0 @@ -# Pistol :gun: - yet another ASCII renderer -In [previous blog post](./2021-10-27) I've shown you my beginnings with Rust :rust: - today I wanna share some progress! -The project is now officially called **Pistol** :gun: - -## Showcase -Thanks to `NCurses` it supports camera navigation using `VIM`-keys. Here's how it looks: - -[![asciicast](https://asciinema.org/a/Wo3mWNQUTYAeZkAYob2gKzv4h.svg)](https://asciinema.org/a/Wo3mWNQUTYAeZkAYob2gKzv4h) - -# Source code -Project source is now available [on GitHub](https://github.com/eug-vs/pistol) :github: diff --git a/blog/2022-02-26.md b/blog/2022-02-26.md deleted file mode 100644 index bd759f2..0000000 --- a/blog/2022-02-26.md +++ /dev/null @@ -1,5 +0,0 @@ -# Слава Україні! :ukraine: - -Russian government is doing terrible things to Ukraine. No excuse. - -Russian citizens, do not fall for propaganda! diff --git a/blog/2022-03-17.md b/blog/2022-03-17.md deleted file mode 100644 index 59d9e71..0000000 --- a/blog/2022-03-17.md +++ /dev/null @@ -1,14 +0,0 @@ -# Жыве Беларусь! :belarus: - -Belarus citizens meet a lot of hatred outside the country. But are not the same as our government! - - -## Current situation -Most people in Belarus are against the regime. Actual support of Lukashenko in 2020 was ~3%. - -Elections were stolen! Our freedom is stolen! People were fighting against it, but [the protests were brutally stopped by a bloody regime](https://en.wikipedia.org/wiki/2020%E2%80%932021_Belarusian_protests). - -## Goergia :georgia: -And here I am, writing this from T'bilisi, Georgia :georgia: , **forced** to leave my country. - -Belarussian government supports Russia's war. But no citizen in Belarus does, and no one wants to fight against our brothers in Ukraine :ukraine:, myself included. If you are Georgian, please think about it when blaming random people on the streets. diff --git a/blog/2022-03-24.md b/blog/2022-03-24.md deleted file mode 100644 index 7359978..0000000 --- a/blog/2022-03-24.md +++ /dev/null @@ -1,14 +0,0 @@ -# Here comes my git server :fire: -I've mirrored all of my important projects from GitHub :github: (along with some unpublished ones) to my personal git server: https://git.eug-vs.xyz - -It includes: - - My [dotfiles](https://git.eug-vs.xyz/eug-vs/dotfiles/) - - My builds of [suckless sotftware](https://suckless.org) - - [Source code](https://git.eug-vs.xyz/eug-vs/eug-vs-xyz/) for this website - - My [homelab infrastructure](https://git.eug-vs.xyz/eug-vs/infrastructure/) (subject for the upcoming blog post) - - And [more](https://git.eug-vs.xyz)... - -![git remote meme](/public/git-remote-meme.png) - -I'm using [cgit](https://git.zx2c4.com/cgit/) as a web fronted to it. There still is some misconfiguration here and there, but it works. Check it out! - diff --git a/blog/2022-03-26.md b/blog/2022-03-26.md deleted file mode 100644 index 1bc09b2..0000000 --- a/blog/2022-03-26.md +++ /dev/null @@ -1,62 +0,0 @@ -# Agent-less infrastructure management with Ansible :ansible: -As I explore new things and grow my homelab :raspberry-pi: infrastructure things start to get a little messy. I've reached the point where I should start using more advanced deployment strategy than just manually setting up servers via SSH or `rsync`-ing a bunch of files into them. The goal is to reach [Infrastructure as Code](https://en.wikipedia.org/wiki/Infrastructure_as_code). - -# But what about Docker? :whale: -[Docker](https://www.docker.com/) is an amazing tool that solves particularly nasty problem - isolating your application from environment and **reliably** running it on any platform. You just pack your application into the container and ship it anywhere you want! It makes your app **scalable**! - -I use Docker on my daily job and I can't imagine it otherwise. But here, in my tiny homelab (which is just one RaspberryPI :raspberry-pi: at this point), this is not world-class production problems, so it might be an overkill. - -Docker requires your servers to run a *daemon* - e.g extra software layer (and it's dependencies) between your applications and the metal. It will run in the background and make your fan work a bit louder :helicopter: in the upcoming summer nights to compensate for those extra couple degrees. - -![meme](/public/docker-on-rpi.jpg) - -# Introducting Ansible :ansible: -[Here it comes](https://ansible.com) - **agent-less** deployment tool that doesn't require your server to run anymore bullshit than good old Python :python: and open SSH port. - -In Ansible you define so called playbooks - `YAML` specs of your tasks. Then you just feed the `YAML` to `ansible-playbook` and voila! It's already SSHing into your machines and doing your job now! - -Ansible is not the tool you should learn, it's so simple that you can use it right away! - -# Examples from my infrastructure :raspberry-pi: -Ansible has a bunch of built-in convenience commands that make your life even more enjoyable. - -![meme](/public/pepe-smug.png) - -This is how easy it is to setup a cron-job: -```YAML - - name: Setup auto-renewing certificates - become: true - cron: - name: "Auto-renew certificates" - minute: "0" - hour: "12" - job: "/usr/bin/certbot renew --quiet" -``` - -Transferring files: -```YAML - - name: Copy nginx configuration - become: true - copy: - src: ./files/nginx/website - dest: /etc/nginx/sites-available -``` - -Installing packages: -```YAML - - name: Install build tools - apt: - pkg: - - gcc - - make - - cmake - - gnutls-dev - - uuid-dev -``` - -...and many many more. Check out source code of my playbooks here: - - https://git.eug-vs.xyz/eug-vs/infrastructure/ - -The notable ones are: - - Installing [taskd](https://git.eug-vs.xyz/eug-vs/infrastructure/tree/taskd.yaml) (migth be worth a separate post) - - Installing [git server along with cgit](https://git.eug-vs.xyz/eug-vs/infrastructure/tree/git-server.yaml) diff --git a/blog/2022-04-02.md b/blog/2022-04-02.md deleted file mode 100644 index 6f8a9a2..0000000 --- a/blog/2022-04-02.md +++ /dev/null @@ -1,83 +0,0 @@ -# DWM - useless gaps are useless! -Many people in Linux community spend too much time *"ricing"* their desktops. Here are few points I came to after using minimal window managers for 2 years: - - Screen real estate **matters** - - Gaps are **useless** (unless you care about your wallpaper) - - Wallpapers draw too much of your **attention** - - You **don't need** to constantly see your CPU temperature, battery percentage etc. - - **Less** windows is **better** - -And from that I can derive an advice on how to stay functional, productive and efficient with minimal window managers: - - **Get rid** of gaps - - **Stop** caring about your wallpaper - - **Don't** put many windows on your screen at once. You probably only need one. Two is ok, sometimes three. More windows = less focus - - Try **removing** window borders (or using `1px black` border). You won't be able to see which window is focused this way, and that will naturally encourage you to keep less windows on the screen - - **Decrease** the number of available workspaces / tags - - **Hide** your status bar when you don't need it - -Following these steps leads you to super-productive no-distraction fullscreen experience. You still get all the advantages of your window manager though. - -**Try it!** (you can always switch back) - - -# Evolution of my desktop -Here's my journey to my current WM philosophy - represented in random screenshots with a couple of comments. - -If you want to replicate a setup on the screenshot - lookup it's date and checkout the corresponding commit of my [dwm build](https://git.eug-vs.xyz/suckless/dwm/). - -## i3 -I've been happy user of `i3` with a lot of "ricing" for a long time. I liked transparent windows, blur and shadows: - -![screenshot](/public/desktop-screenshots/2020-12-08_01-49-30.jpg) - -![screenshot](/public/desktop-screenshots/2021-01-06_18-57-32.jpg) - - -## DWM -But then I decided to switch to suckless `dwm`. The functional approach was so much better then manual window management in i3 - as a perfectionist I always spent extra time arranging windows "in a cool way". DWM solved this problem entirely, but I still couldn't live without beautiful wallpaper and gaps. - -![screenshot](/public/desktop-screenshots/2021-03-10_21-14-09.jpg) - -![screenshot](/public/desktop-screenshots/2021-03-27_01-26-27.jpg) - -![screenshot](/public/desktop-screenshots/2021-04-26_00-06-32.jpg) - -![screenshot](/public/desktop-screenshots/2021-06-04_08-52-16.jpg) - -![screenshot](/public/desktop-screenshots/2021-06-25_16-19-05.jpg) - -![screenshot](/public/desktop-screenshots/2021-06-28_19-12-39.jpg) - -![screenshot](/public/desktop-screenshots/2021-07-15_14-20-16.jpg) - - -## Fuck gaps! -After ~4 months of `dwm` (and ~year of using minimal window managers) I realized - gaps are just taking too much of my screen real estate! Let's try removing them entirely: - -![screenshot](/public/desktop-screenshots/2021-07-22_09-50-48.jpg) - -As a bonus you stop caring about your nice wallpaper because you only see it once - when you first boot your machine. You can also get rid of your composite manager now. Finally, get rid of that bright orange: - -![screenshot](/public/desktop-screenshots/2021-08-14_02-29-30.jpg) - -![screenshot](/public/desktop-screenshots/2021-10-07_13-11-59.jpg) - -![screenshot](/public/desktop-screenshots/2021-10-17_16-17-55.jpg) - -![screenshot](/public/desktop-screenshots/2021-11-06_15-24-35.jpg) - -![screenshot](/public/desktop-screenshots/2021-12-05_21-38-36.jpg) - -That setup was untouched for 4 months! Finally rollback some patches to get that beautiful default status bar (that color though!): - -![screenshot](/public/desktop-screenshots/2022-03-21_20-01-58.jpg) - - -## Current state -That lived for 3 more months and now I use gray as the accent color and all my borders are black! Also I decreased the number of available tags. - -![screenshot](/public/desktop-screenshots/2022-04-02_14-59-33.jpg) - -Most of the time I hide status-bar anyway. - -![screenshot](/public/desktop-screenshots/2022-04-01_18-44-17.jpg) - diff --git a/blog/2022-04-17.md b/blog/2022-04-17.md deleted file mode 100644 index d6ca637..0000000 --- a/blog/2022-04-17.md +++ /dev/null @@ -1,51 +0,0 @@ -# Running Gentoo :gentoo: on multiple workstations -Last week I've migrated my daily-driver laptop :computer: from [Artix Linux](https://artixlinux.org/) to [Gentoo](https://www.gentoo.org/). I also have Gentoo-powered PC for a ~half a year already, so some experience has accumulated. -I always wanted to do that, but there was a fear of unknown: - - Is my CPU performance sufficient for compiling packages? - - What if I don't have time to compile a package (e.g at work)? - - How am I gonna manage the USE flags? - -Of course, none of that shit can stop me! - -# My CPU is weak :cry: -My laptop has a pretty weak CPU (**Intel i3**) compared to flagship models. My PC has **Intel i5**, so obviously compiling packages on laptop will be even slower. That is definitely gonna be a problem... - -But wait, why don't we use **both CPU's** for compilation? :thinking: - - -## Introducing `distcc` -From [Gentoo wiki](https://wiki.gentoo.org/wiki/Distcc): -> Distcc is a program designed to distribute compiling tasks across a network to participating hosts. It comprises a server, distccd, and a client program, distcc. Distcc can work transparently with ccache, Portage, and Automake with a small amount of setup. - -Installation and usage is of course covered in the wiki along with instructions on bootstrapping new machine. Thanks to `distcc` installing Gentoo on my laptop was even faster than on more performant PC. - -Basically my PC runs a `distccd` server in my **LAN** and my laptop connects to it, sending compilation requests. Now every time I want to compile some heavy packages I just wait to come home and do it at almost twice the speed. There are more optional benefits: - - I can bring my RaspberryPI :raspberry-pi: to the compilation network (not without some cross-architecture magic) - - I can pull up some more old rusty metal, connect it to my **LAN** and have my packages compiled *even faster* :fire: - - I can setup [ccache](https://wiki.gentoo.org/wiki/Ccache) and share compilation cache within my network, making heavy package updates finish in seconds - - -# What if I'm outside and don't have time for compilation? :scream: -Actually turns out it's a very hypothetical situation. Most of the time you already have your toolkit installed anyway. It's only annoying if you want to try something new - for that I recommend remote or virtual machines (yes, `docker` still exists). - -In any case, if such an urgent situation occurs, **you can just get a binary!** There are also ways to setup your own [binary package server](https://wiki.gentoo.org/wiki/Binary_package_guide). - -# Managing portage configuration across workstations :hammer_and_wrench: -[Portage](https://wiki.gentoo.org/wiki/Portage) is **the best** package manager I ever used. The obvious benefit is an ability to split your packages into [sets](https://wiki.gentoo.org/wiki/Package_sets). I can define as many sets as I want, for example here's my `/etc/portage/sets/base`: -```bash -app-admin/doas -app-admin/stow -app-editors/neovim -app-shells/dash -app-shells/zsh -dev-vcs/git -app-misc/vifm -net-misc/ntp -``` - -I can install everything from this set with `emerge --ask --verbose @base`. Or if I want to install everything development-related, I can just install `@development` set. As easy as it gets! - -This way I can categorize my packages by purpose, compilation time, shared libraries, *etc*. Each package can belong to many sets. And most importantly, package set is **just a plaintext file**! You can manually edit it, you can store it under `git`, and you can share it across your workstations. - -Since portage is fully configurable via plaintext files, the same works for USE flags, keywords, accepted keywords and licenses. - diff --git a/blog/2022-04-18.md b/blog/2022-04-18.md deleted file mode 100644 index 4f817a8..0000000 --- a/blog/2022-04-18.md +++ /dev/null @@ -1,48 +0,0 @@ -# Patching Gentoo :gentoo: packages in the wild -Everyone who has ever used **st** - [suckless terminal](https://st.suckless.org) - has experienced [weird crash](https://github.com/LukeSmithxyz/voidrice/issues/284) when trying to render some very specific unicode characters. In this short post I'm showing how easy it is to solve this problem on Gentoo with the help of patches. - -# libXft -The original problem is solved by installing a couple of fallback fonts and a **patched version** of `libXft`. Guys from Arch Linux can just install patched version [libxft-bgra from aur](https://aur.archlinux.org/packages/libxft-bgra), why don't we have something similar on Gentoo? :thinking: - -We don't need it! Here's the process *of me* solving this problem in a matter of 5 minutes: - -1. Find patched version from comments on GitHub - https://github.com/uditkarode/libxft-bgra -2. Find upstream source code - https://gitlab.freedesktop.org/xorg/lib/libxft -3. Clone the patched repo and pull tags from upstream: - ```bash - git clone git@github.com:uditkarode/libxft-bgra.git - git remote add upstream git@gitlab.freedesktop.org:xorg/lib/libxft.git - git pull upstream --tags - ``` -4. Checking `git log --oneline` on `master` branch, looks like we are only interested in commit `72e54c0` (the actual *PATCH*). The latest tag before the patch seems to be **2.3.3**. - ```bash - 072cd20 (HEAD -> master, origin/master, origin/HEAD) README: instructions i guess - 72e54c0 [PATCH] Add support for BGRA glyphs display and scaling - 6e7da3c Remove call to FcNameRegisterObjectTypes - 26a3a49 Skip 'render' pattern elements with invalid type - 972fa05 build-fix for c89 - 86c2355 minor typography fix - ed8bb96 fix most type-conversion warnings from gcc-normal, without obje - ct-file changes - a266847 (tag: libXft-2.3.3) libXft 2.3.3 - fab5adf Add description of libXft to README.md - b397ffb Update configure.ac bug URL for gitlab migration - ``` - -5. Create patches from the diff: `git format-patch libXft-2.3.3` -6. Move the generated `.patch` to `/etc/portage/patches/x11-libs/libXft` -7. Reinstall libXft: `emerge -av libXft` -8. Profit!!! - -Well, actually, I did something on top of that - I *rebased* patched branch to the latest **2.3.4** tag to make sure that the patch still works with the latest version of the library. If it wasn't the case - I could just pin the version when emerging: `emerge -av "=libXft-2.3.3"` because we know that the patch is working on that version. - -From now on, I will keep receiving updates to my `libXft` from Portage and each new version will be patched (hopefully successfully) until the fix is released to the upstream. - -# Grab the patch -Well, everything above was "head-on" way. Taking a closer look to the upstream repo, there's already a [merge request](https://gitlab.freedesktop.org/xorg/lib/libxft/-/merge_requests/1) with our fix, so we don't have to do git magic and we can easily grab the raw diff by appending `.patch` to the URL: - -https://gitlab.freedesktop.org/xorg/lib/libxft/-/merge_requests/1.patch - -# See also - - [Running Gentoo :gentoo: on multiple workstations](2022-04-17.md) - - [DWM - useless gaps are useless!](2022-04-02.md) diff --git a/blog/index.md b/blog/index.md deleted file mode 100644 index d9c72fe..0000000 --- a/blog/index.md +++ /dev/null @@ -1,43 +0,0 @@ -# Blog - -## 2022 - -### April - -- [Patching Gentoo :gentoo: packages in the wild](2022-04-18.md) -- [Running Gentoo :gentoo: on multiple workstations](2022-04-17.md) -- [DWM - useless gaps are useless!](2022-04-02.md) - -### March - -- [Agent-less infrastructure management with Ansible :ansible:](2022-03-26.md) -- [Here comes my git server :fire:](2022-03-24.md) -- [Жыве Беларусь! :belarus:](2022-03-17.md) - -### February - -- [Слава Україні! :ukraine:](2022-02-26.md) - -## 2021 - -### October - -- [Pistol :gun: - yet another ASCII renderer](2021-10-28.md) -- [Ray marching in Rust :rust: !](2021-10-27.md) -- [You should start using `ssh-copy-id` now!](2021-10-06.md) - -### September - -- [I'm back on Carnivore! :meat_on_bone:](2021-09-21.md) -- [Summer 2021 - retrospective](2021-09-10.md) - -### August - -- [Python :python: in real life](2021-08-18.md) -- [Using imagemagick :imagemagick: to crop soy faces](2021-08-14.md) - -### July - -- [CircleCI :circleci: in daily life: how I improved Matrix stickerpicker](2021-07-15.md) -- [What's wrong with Numerology](2021-07-03.md) -- [My plans for this website](2021-07-02.md) |