■ SEARCH.EXE
    recreational-programming

    Building a Local Voice-to-Text and Rewriting Assistant on Linux

    This article comes from a frustration I had with Discord Web. I didn't have the possibility to directly send a voice message. The only way to send one was to literally record my voice, save the file, and then send it manually. But that was enough to give me an idea: if I had a way to simply speak and immediately send the damn message, that would already be great. And then, imagine having a way to transcribe my voice directly into text and copy it straight to the clipboard; perfect for emails. Even better: a way to reformulate what I've said in different tones! That's the system I scripted yesterday, using keyboard shortcuts in my i3 environment, along with Bash, yad, notify, xclip, jq, ffmpeg, whisper.cpp, llama.cpp, systemd, and…

    journal

    A Look Back at My COVID-Era Home Gym

    During my teenage years, I was quite into weightlifting. When the COVID-19 pandemic hit, I decided to buy some equipment and build my own little home gym. Yes, this is a rather unusual article for my blog! But since I'm about to sell all this equipment, I thought it would be nice to document what I owned and preserve a little memory of that period. There are two common barbell and weight plate hole diameters: 28 mm and 50 mm. The latter is the standard used in most commercial gyms, as well as in powerlifting and Olympic weightlifting. These plates are designed to fit Olympic-style barbells, which typically weigh 20 kg and measure 2.20 meters in length. This type of equipment is generally designed to handle very heavy loads, making…

    journal

    How I Almost Fell for a Leboncoin Phishing Scam

    Yesterday, I was uploading listings for some fitness equipment I bought during the COVID period on the French equivalent of Craigslist (not https://www.craigslist.org/area/paris lol, but leboncoin.com ), which I was using for the first time. So, 13 listings and about four hours later, I received an offer, which I accepted. And boom: in Leboncoin’s rather terrible chat interface, a very professional-looking sales notification suddenly appeared: For someone who doesn’t know how the platform works, someone who has never used it before, or who has only ever been paid in cash during an in-person sale, this can look completely legitimate. After digging a little deeper, you find out that Leboncoin has what is essentially an escrow-like wallet system. The buyer can send the money through Leboncoin, where it is temporarily held…

    maths

    The Trick Is in the Representation

    This article is about several mathematical puzzles which will sharpen your reasoning. There will be several well-known ones, such as the Monty Hall problem, but also lesser-known ones, such as the mechanical scale and the balls. Each answer will be detailed. The lake and the water lily We have a lake and some water lilies on it. We know that the number of water lilies doubles every day and that on the 48th day, half of the lake is covered by water lilies. Copy ----------- |XXXXX | |XXXXX | |XXXXX | ----------- Now the question is: on which day will the lake be fully covered by water lilies? The reasoning is simple, indeed we know that each water lily doubles within a day. Also, doubling half of something gives you…

    linux

    Pacman, APT and dpkg: Under the Hood

    Package managers are often reduced to a few commands: install, update, remove. But behind those commands sits a much larger system involving repository metadata, dependency graphs, local package databases, binary archives, source packages and build tooling. In this article, we will start from the user-facing commands of pacman, APT and dpkg, then progressively move underneath them: how packages are queried, downloaded and tracked, how dependencies are represented, how .deb and source packages are structured, and finally how packages are rebuilt and managed at a lower level. Fair warning: this one goes deep. But if you have the guts to read through it, you should come out with a much stronger understanding of package managers. And that kind of understanding transfers surprisingly well to programming in general: separation of responsibilities, metadata-driven…

    linux

    Installing Gentoo the Hard Way

    In this article, we'll proceed to install Gentoo. This article follows the story of manually installing Linux distros which begins here https://julienlargetpiet.tech/articles/manually-installing-arch-and-void-linux-on-the-same-disk-with-uefi-and-grub.html where non Gentoo relative commands are explained in depth. Indeed, we'll focus on Gentoo specific architecture here. Setup We'll download the ISO here: https://distfiles.gentoo.org/releases/amd64/autobuilds/current-install-amd64-minimal/. Choose the adequat architecture, for me it's amd64. Now, just copy the ISO onto an USB stick, or use Ventoy if you want. For me I just do: Copy sudo dd if=/path/to/iso of=/dev/sdb conv=fsync bs=4M status=progress Where /dev/sdb is of course my USB stick. Now I just plug the USB stick onto my PC and boot onto it. Hmm, you probably won't have this problem, but my screen cropped the tty and no way to fix this at this point, so I'll pipe the…

    linux

    Installing OpenBSD the Hard Way

    In this article, we'll go through the manual installation of OpenBSD and see the differences and similarities with Linux. The setup We'll directly download the latest image of OpenBSD, at the time the version 7.9 and copy it to a USB stick, you can also use Ventoy if you want. In Linux, we have the dd command to copy the entirety of an image to an external disk. Copy sudo dd if=install79.img of=/dev/sdX bs=4M status=progress conv=fsync Replace /dev/sdX by the name of your usb-stick, you can see it with lsblk or sudo fdisk -l. Booting After putting the usb stick to the PC you want to install OpenBSD to, choose to boot from this USB stick on its BIOS. Now, you'll be prompted the following: Copy Welcome to the OpenBSD/amd64…

    linux

    Manually Installing Arch and Void Linux on the Same Disk with UEFI and GRUB

    In this article, we'll deep dive into the manual installation of multi-distrributions in one disk. The Setup We'll install Arch And Void Linux on the same disk. In this case that's an external hard-drive that we'll plug into a computer through USB. So, we'll download the ISOs, wether each one on a separate USB stick or use Ventoy to install the 2 ISOs on the same USB stick. Targeting the hard-drive First, we boot into the Void live environment, here all is oaded into the RAM. So we first need to identify the hard-drive we'll install the 2 distribution into. We run: Copy lsblk -o NAME,SIZE,TYPE,MOUNTPOINTS,PARTUUID,PARTLABEL,LABEL,MODEL,VENDOR,SERIAL,TRAN Output: Copy NAME SIZE TYPE MOUNTPOINTS PARTUUID PARTLABEL LABEL MODEL VENDOR SERIAL TRAN sda 447.1G disk Samsung SSD 870 EVO 500GB ATA S6PXXXXXXXXX sata…

    linux

    I Just Wanted Wi-Fi to Work on Linux

    About a week ago, I needed to set up a laptop for my mum to use while working remotely. The initial plan sounded trivial: install Debian, GNOME, connect it to Wi-Fi, and call it a day. Of course, the Wi-Fi part turned out to be considerably more interesting. The connection provided by the laptop's internal Wi-Fi adapter was slow and unstable, so instead of simply opening Speedtest and accepting whatever number it gave me, I started investigating what was actually happening. That investigation progressively took me through several layers of the Linux networking stack. First, we'll measure the quality of the connection ourselves using curl, ping, Bash and AWK. We'll separate DNS resolution, TCP connection establishment, TLS negotiation, server response time and transfer time, then calculate averages and standard deviations…

    software-computational-architecture

    Where R Data Pipelines Pay Their Cost: data.table, dplyr, fread, readr, and vroom

    My previous article was somewhat polarizing. Most readers responded positively, but some disagreed with the benchmarking methodology I used. That criticism is precisely why this article exists. To fully understand the pipeline architecture I developed, and why I ultimately chose it over the alternatives, I recommend reading the previous article first: data-table-vs-dplyr-in-a-data-pipeline.html In this new benchmark, I use a more rigorous methodology to produce more precise, reliable, and reproducible results. The goal is not only to compare execution times, but also to make the entire process transparent. Every experiment is designed to be reproducible, and the article can also be read as a practical tutorial for benchmarking this kind of data-manipulation pipeline. The entire raw work behind this article is available here: Article_RSHINY Packages version For those benchmarks, I'll use…

    software-computational-architecture

    data.table VS dplyr in a data pipeline

    Recently, I wanted to create an analytical dashboard for the visits on this blog, entirely server-side. This means reading the NGINX /var/log/statix.log file, reducing bot noise as precisely as possible, and outputting useful visualizations. I know that some libraries, like Streamlit in Python, allow this kind of analysis, but at the time, I was way more comfortable with R. My first version was absolutely awful in terms of performance, not only because I used dplyr, which is a good dataframe engine and noticeably better than base R’s dataframe engine, but also because of a completely awful execution order. In this article, I will not only show you the exact performance difference between the dplyr and data.table implementations, but also show you how much execution order matters in a real data…

    journal

    A CV, a Phone Number, and a Data Leak

    The other day, I was searching for the name of a friend on Google, and his personal Curriculum Vitae appeared as the second search result, just after his LinkedIn profile. It was a plain CV. And right in the first pieces of information, his phone number, address, and personal email appeared. So I asked him if he had intentionally uploaded his CV to this website. “Absolutely not!” That is what he answered. In fact, the page where his CV was uploaded was dedicated to static resources, and there was absolutely no way to see the name of the company that had uploaded it, because the domain name shown in the URL was just that of a hosting platform. So I searched for an ID found in the URL, typed it…

    journal

    My Overengineered YouTube Thumbnail Generator

    Following up on my YouTube channel creation from the previous article, on Mon. 25 May 2026 14:02:06 CEST, I wanted to write a program to automate the generation of my thumbnails. Since my face will be shown on my YouTube channel, i've studied YouTubers thumbnails that have their face visible, such as LowLevel. Anatomy of YouTube Thumbnails And I came to the following conclusion: The composition is simple -> arround 3 or 4 elements The Background -> minimalistic enough, just one color tone The upper body with (shoulders + face) -> The viewer sees the creator’s face before clicking, so the video feels less surprising once it starts. In theory, that can help retention. Note that we do not want the PNG of the YouTuber upper body + face beeing…

    journal

    A Practical Linux Setup for Recording Technical Videos

    On Sun May 17 21:35:37 CEST 2026, I decided it was time to start a YouTube channel to promote my articles. Here is the link: https://www.youtube.com/@control-room-11 I already had a (very) messy YouTube experience. I was absolutely brainwashed by the LukeSmith Wave at the time. With my Patched DWM ( larbs config for the initiated ;) ). I had just plugged a cheap webcam into USB 2.0, without tweaking any firmware-level settings to make the image look decent. In this article i will share the evolution of my setup across the ages as a practical guide so you can reproduce and understand each confs according to your needs. This article is aimed at beginner Linux users who want to build a simple but controllable video-creator setup. FFmpeg CLI - Practical…

    software-computational-architecture

    The Cartesian Product Disaster Tour: Haskell, C, and 25GB of Allocations

    In this article, we’ll explore something that looks innocent: computing the cartesian product of several lists. In Haskell, it is almost boring: Copy ghci> sequence [[1, 2], [3, 4, 5]] [[1,3],[1,4],[1,5],[2,3],[2,4],[2,5]] Clean, elegant, one function call. And that is exactly why it is interesting. High-level languages let us treat this kind of operation as obvious. We call sequence, or itertools.product (Python), and move on with our lives. But under the abstraction, there is still a real data structure being built, memory being allocated, indices being advanced, values being copied, and eventually a CPU doing the dirty work. So I wanted to take this simple operation and push it through several implementations. First, we’ll start with my first Haskell attempt: not idiomatic, a bit painful, and honestly quite funny in retrospect.…

    software-computational-architecture

    Why Parsers were invented ?

    A lot of text-processing tools can get surprisingly far without a real parser. For simple patterns, tools like sed, awk, or small ad-hoc string transformations are often enough. You match a fragment, replace it, split on a delimiter, maybe scan left to right, and the job is done. For flat data, it's often the most direct and elegant solution. But this approach starts to break down when the input has structure. As soon as you have nesting, precedence, escaping rules, ambiguous symbols, or context-dependent meaning, the input should not be considered as just a string. It becomes a small language. At that point, continuing to manipulate characters directly means you are building a parser anyway, just an implicit, fragile, and usually inefficient one. This article is about discovering that boundary.…

    blogroll

    Blogs that worth a bookmark

    Gwern.net A huge collection of long-form essays by Gwern Branwen on AI, statistics, psychology, technology, science, economics and plenty of other rabbit holes. Articles are usually extremely well-researched, heavily referenced, and often go much deeper than you initially expect. raphaelouthier.github.io Raphael Outhier’s technical blog, mostly focused on low-level programming: C, assembly, kernels, ARM, memory management and optimization. It is especially enjoyable if you like articles that actually explain what is happening underneath the abstraction layers ( if you are here, that might be the case ;) ). essenceia.github.io/ Julia Desmazes’ blog about chip design, ASICs, Verilog, FPGAs and hardware engineering. The articles often follow real projects from design to tapeout, mixing deep technical explanations with the inevitable chaos of actually building hardware. lukesmith.xyz Luke Smith’s personal corner of the web,…

    journal

    Journal - April 2026

    Days 19 19 First Entry, this is a test. ♥ Support

    latex

    Doom in LaTeX (+Bash)

    This article is a part of my full LaTeX guide here article Here some captions of the game: How did i create the game ? First, the architecture. We have a bash loop script ( loop.sh) that waits for inputs. When it receives input, it updates a state.tex variables. This file is in fact an \input{...} of the main LaTeX file main.tex. We won't focus on the bash file, but here is its code: Copy #!/bin/bash # --- INPUT SETUP --- exec 3</dev/tty stty -icanon -echo trap "stty sane" EXIT # --- STATE --- step=0 scaleval=0.5 shoot=0 demon=0 gameover=0 lst="0,1,2" score=0 # --- SCALE PER STEP --- update_scale() { case $step in 0) scaleval=0.5 ;; 1) scaleval=0.9 ;; 2) scaleval=1.4 ;; esac } # --- DEMON SPAWN --- spawn_demon() {…

    latex

    Traversing a Tree in pure LaTeX

    This article is a part of my full LaTeX guide here article At the end of the article, you'll be able to traverse a tree in pure TeX. First, remember the basics. Copy \def\a{Rémi} \def\b{Julien} Then, use it as: Copy Bonjour \a\ et \b. Bonjour \a{} et \b. Each one outputs the same result. "Bonjour Rémi et Julien." And yess, that is strange that we can call the variable like a comand with empty {}. Speaking of commands, they are in fact, like said before, fancy variables with fancy logic. Copy \newcommand{\hello}[3]{Hello #1, #2 et #3} Used like: Copy \hello{Rémi}{Julien}{Lucas} Output: "Hello Rémi, Julien et Lucas" This stays pure expansions... Now most confusing part of LaTeX. How to reassign a value to a variable ? Maybe, you think this is…

    latex

    Dissecting LaTeX: Revenge, Four Years Later

    When I was a chemist, I wrote my internship report in LaTeX. It was at first a pain in the ass: --> weird syntax with no apparent coherence Especially for drawing objects, graphs, shapes... (cf: PGFPlot, TikZ) Then I moved on and never returned to LaTeX because I did not need it. But I remember the painful hours spent trying to render a good TikZ graphic, and I do not want those hours to be wasted. So 4 years later I returned to LaTeX to learn it, for real. I wanted to build a really coherent mental model by learning all its invariants. And I can say it has been a great success, I even built a mini Doom in LaTeX --> Go to section This is not only an…

    software-computational-architecture

    SAM, the 'other' SED from the 80s

    Prerequisites This article will reference SED syntax that is described here: sed This was also vastly ispired by this comment (user: piekvorst) on HackerNews (a lot of credits go to this user and ressources share in the comment): hn SAM - Installation Because SAM is part of Plan 9, we have to install plan9port: Copy $ git clone https://github.com/9fans/plan9port.git $ cd plan9port plan9port$ ./INSTALL then: Copy $ export PLAN9=$HOME/plan9port $ export PATH=$PATH:$PLAN9/bin $ source ~/.bashrc To make it permanent, write the export down to your ~/.bashrc then source ~/.bashrc Where does it come from SAM was written by Rob Pike at Bell Labs in the late 80s. It comes from the same place as UNIX, but from a later phase where people were already trying to rethink some of its…

    linux

    AWK: The Small Language That Quietly Became a Data Engine

    There is a moment every engineer hits. You're staring at a text file-logs, CSVs, metrics, something messy-and you think: "I just need to extract, filter, compute, group, maybe transform a few columns…" You reach for Python. Maybe Rust. Maybe even spin up a dataframe. And then someone types a one-liner with awk. It runs instantly. It's readable. It's correct. And you realize: AWK is not a tool. It's a streaming data engine disguised as a scripting language. This article is a deep dive—from first principles to advanced patterns—so you don't just use AWK, but start thinking in it. 1. The Core Idea: Pattern → Action At its heart, AWK is built around a deceptively simple idea: Copy pattern { action } Which translates to: "For each line, if the pattern…

    linux

    Sed, a powerfull mini-language from the 70s

    There's a moment when using sed stops feeling like typing weird incantations… and starts feeling like you're programming a living stream of text. At first, it looks like this: Copy sed '1,2p' file And you think: "ok… print lines 1 and 2… neat, but whatever" But if you stay with it — if you push just a bit further — you discover something unexpected: sed is not a command. It is a language. A small one. A strange one. But a real one --> with control flow, memory, and a model of execution. And that's how you end up writing things like: script.sed Copy /./H /^$/ { x /./ { s/\n/ /g s/^ // p } } $ { x s/\n/ /g s/^ // /./ { p } } Copy…

    system-design

    Bash Arrays: From First Steps to Real-World Mastery

    Bash arrays aren't just containers, they're a way to control how data flows through the shell. This guide builds from zero to production-grade patterns, using real examples like file processing and reverse lookups. 1. The Basics (Quick but Solid) Creating arrays Copy arr=(apple banana "cherry pie") Access Copy echo "${arr[0]}" echo "${arr[@]}" echo "${#arr[@]}" 👉 Always use "${arr[@]}" — this preserves elements. 2. The Rule That Changes Everything "${arr[@]}" vs ${arr[@]} Copy arr=("a b" "c d") for x in ${arr[@]}; do echo "$x"; done # broken a b c d for x in "${arr[@]}"; do echo "$x"; done # correct a b c d Without quotes, Bash: splits on spaces expands wildcards 3. Real Data: Reading Files Safely Let's start doing something real. ** Wrong way** Copy arr=($(ls)) Breaks on:…

    recreational-programming

    Building a ChatGPT-like CLI in Bash: a journey through pipes, JSON, streaming, and shell weirdness

    There is something deeply satisfying about building a serious tool with primitive Unix bricks. The mentioned in this article comes from: repo A shell. A while true. A read. A curl. A jq. A pipe. At first, the goal looks almost absurdly simple: "I want ChatGPT, but in my terminal, with Bash." Then the real questions begin. How do we keep a conversation alive if the API is stateless? How do we build valid JSON safely from user input? How do we stream tokens as they arrive? Why does curl | while read ... break variable updates? What exactly is this cursed construct: done < <(curl ...)? And what is Bash really doing when we write IFS= read -r line? This article is the story of building a small but…

    journal

    Statix, llama.cpp, and a Night of Autonomous Blogging

    This article is about this repo: autoBlog There is a particular kind of joy in software engineering that does not come from polished products, investor slides, or framework trend cycles. It comes from taking a few simple parts, each understandable on its own, and connecting them until something unexpectedly alive emerges. That is exactly what happened here. The starting point was not "let's build an AI startup," nor "let's automate content at scale," nor even "let's use a large language model." The starting point was much simpler and much more honest: I already had Statix, my own publishing system, with its own CLI. I had full control over content publication. I had a local machine. I had curiosity. And one evening, a thought appeared that was too tempting not to…

    default

    The Archaeology of a dead .OVA

    "It should be easy to download." Famous last words. The Premise There exists (or existed) a certain .ova file. .ova is a packaged VM - all in one file It contains .ovf metadata (xml like describing the specs, ram, cpu...), .vdmk file(s) (created by VMWare -> contains OS, other files..) Widely used Popular in a very specific niche Distributed officially at some point Then… quietly erased from existence No announcement. No archive. Just... gone. Like it never happened. Phase 1 - Denial Naturally, I assumed: "I'll just Google it." So I searched: Copy "specific ova file name" download Results: tutorials from 2017 broken official links forum threads ending in silence Classic. Phase 2 - Automation (aka coping) At this point, I did what any reasonable person would do: wrote a…

    software-computational-architecture

    How Modern Browsers Render the Web: A Deep Technical Journey

    From HTML bytes to GPU pixels — the complete architecture of a modern browser rendering engine. Introduction: The Browser as a Game Engine There is a useful analogy for understanding how browsers work at a deep level: think of a browser as a real-time 3D game engine. In a game engine: The scene graph defines what objects exist and where they are in the world. The camera defines what portion of the world is visible. The renderer takes the visible scene and converts it into pixels on screen. The compositor combines multiple render layers (HUD, skybox, geometry, post-processing effects) into the final frame. A browser does the same thing — just with HTML, CSS, and JavaScript instead of meshes and shaders. Game Engine Concept Browser Equivalent Scene graph DOM +…

    system-design

    Debugging a “Slow VPS” That Wasn’t Slow

    My VPS suddenly felt extremely slow: pages taking 3–5 seconds TLS handshake hanging random spikes in latency First instinct: server issue. Reality: network path instability. This is how I debugged it step by step. 1. Measure Real User Experience with curl Instead of guessing, start with actual HTTP timing. Copy curl -o /dev/null -s -w "\ DNS: %{time_namelookup}s\n\ Connect: %{time_connect}s\n\ TLS: %{time_appconnect}s\n\ TTFB: %{time_starttransfer}s\n\ Total: %{time_total}s\n" \ https://your-domain.com What each metric means DNS ( time_namelookup) → time to resolve domain → IP Connect ( time_connect) → TCP handshake (network latency baseline) TLS ( time_appconnect) → SSL/TLS negotiation (very sensitive to packet loss) TTFB ( time_starttransfer) → time until first byte from server Total ( time_total) → full request time Example (bad case) Copy DNS: 0.05s Connect: 0.30s TLS: 2.29s TTFB:…

    software-computational-architecture

    From Backtracking to Factorial Coordinates: Understanding Permutations Deeply

    Most developers learn permutation generation through recursion and swapping. It works, it's elegant… but it often feels a bit magical. This article goes much deeper. We will: Fully understand how backtracking actually works Build a precise mental model of recursion Discover that permutations form a structured coordinate space Eliminate recursion entirely using factorial number systems (Lehmer code) Derive efficient, controllable, high-performance implementations 1. The Classical Backtracking Algorithm Here is the standard implementation: Copy template <typename T> void permuteHelper(std::vector<T>& vec, int start, std::vector<std::vector<T>>& result) { if (start >= vec.size()) { result.push_back(vec); return; } for (int i = start; i < vec.size(); ++i) { std::swap(vec[start], vec[i]); permuteHelper(vec, start + 1, result); std::swap(vec[start], vec[i]); // backtrack } } 2. The First Misconception A very common intuition is: "A swap creates a permutation" This…

    software-computational-architecture

    Binary Operations: AND, OR, XOR, NOR - and Their Deep Relationships

    Binary operations are the foundation of computation. At the lowest level, everything reduces to simple operations on bits: true (1) and false (0). In this article, we explore the core logical operations: AND OR XOR NOR XAND (XNOR) We’ll also look at how they relate to each other — and why XOR can be expressed using only NAND-like constructions. 1. Basic Definitions Let’s define the core operations for two boolean values A and B. A B AND OR XOR NOR XAND (XNOR) 0 0 0 0 0 1 1 0 1 0 1 1 0 0 1 0 0 1 1 0 0 1 1 1 1 0 0 1 Intuition AND ( &&) → both must be true OR ( ||) → at least one is true XOR (…

    software-computational-architecture

    Java Deep Dive: Architecture, Memory, OOP & Modern Features

    A comprehensive technical reference — from JVM internals to streams, lambdas, and the philosophy behind Java's design choices. Table of Contents Introduction & Philosophy Everything is a Class Memory Model: Stack, Heap & Metaspace The static Keyword — Java vs C++ Constructors & Method Overloading Encapsulation: Getters & Setters Inheritance, Virtual Dispatch & vtables Overriding toString() — Why It Matters Interfaces, Lambdas & Functional Programming Primitive Types vs Wrapper Classes Comparators as Objects — Everything is a Class Collections, Maps & Sets The Stream API Type Inference in Java Summary Diagram 1. Introduction & Philosophy Java was released by Sun Microsystems in 1995, designed with a clear motto: "Write Once, Run Anywhere". Unlike C or C++, Java programs do not compile to native machine code directly. Instead they compile to…

    system-design

    Statix: A Static Engine That Behaves Like a Dependency Graph

    Most static site generators rebuild everything. Statix doesn’t. It rebuilds exactly what changed — nothing more, nothing less. This article is a deep dive into how Statix actually works internally: Symlink-based runtime theming (no rebuilds) Localized builds driven by implicit dependency graphs The admin pipeline that orchestrates rebuilds The CLI and system integration philosophy 1. Symlinks as Runtime State (Themes & Fonts) Statix treats themes and fonts as runtime configuration, not build-time artifacts. 1.1 Filesystem as Source of Truth Themes are discovered dynamically: Copy func (s *Server) listThemes() ([]string, error) { base := "/var/www/go_blog/assets/css/themes" entries, err := os.ReadDir(base) if err != nil { return nil, err } var themes []string for _, e := range entries { if !e.IsDir() && strings.HasSuffix(e.Name(), ".css") { name := strings.TrimSuffix(e.Name(), ".css") themes = append(themes,…

    system-design

    Go Joining Errors - Learn with Examples

    In Go (since Go 1.20), errors.Join lets you combine multiple errors into a single error while still preserving each individual error inside it. This is especially useful when: multiple operations can fail independently you want to return all errors, not just the first one Basic idea Copy err := errors.Join(err1, err2, err3) Returns nil if all inputs are nil Automatically ignores nil errors The resulting error wraps all the non-nil ones Simple example Copy package main import ( "errors" "fmt" ) func main() { err1 := errors.New("file not found") err2 := errors.New("permission denied") joined := errors.Join(err1, err2) fmt.Println(joined) } Output: Copy file not found permission denied Checking errors with errors.Is This is where errors.Join becomes powerful: Copy package main import ( "errors" "fmt" ) var ErrNotFound = errors.New("not found") func…

    software-computational-architecture

    OpenTelemetry in Go, finally explained: traces, metrics, logs, propagation & middleware

    I spent the day digging into OpenTelemetry in Go and, honestly, a lot of things that look magical at first finally clicked. The code snippet of this article come from my recreational/tutorial repo: TutOpenTelemetry-Go This article is the version I wish I had when I started. It covers: what context.Context is doing in Go HTTP servers how OpenTelemetry plugs into a Go service what traces, metrics, and logs actually are how otelhttp middleware changes request handling why you can have both a middleware-created HTTP span and your own manual span what propagators do and how they work across services why metrics flush in the background what the stdout trace / metric / log output really means field by field how to read the actual JSON output from the OpenTelemetry Go…

    system-design

    Statix - I Built My Own Blog Engine (Because I Refuse to Negotiate with Markdown Toolchains).

    Let me clarify something immediately. First the repo is here lol: Statix, and second This is not a “framework”. This is not a “platform”. This is not “the future of publishing”. It’s just called blog. And it does one thing extremely well: it lets me create, edit, update, and delete articles directly in the browser without negotiating with a build pipeline, a folder structure, or a philosophical manifesto. The Problem With Static Generators (Yes, All of Them) Static site generators are brilliant. Until you actually want to change something. Want to fix a typo? Open your editor → find the file → edit Markdown → rebuild → deploy → commit → push. Want to delete an article? Remove the file → rebuild → redeploy → invalidate cache → hope you…

    functional-programming

    jq as a Stream Calculus and Tree Algebra

    A Deep Semantic and Operational Mini-Book This is not documentation. This is not a tutorial. This is a semantic excavation. We will treat jq as: A stream calculus A purely functional reduction algebra A tree traversal and rewrite system A scoped evaluation engine with explicit rebinding Note To run a jq file do that: Copy Copy $ jq -f test.jq file.json And also some sections will implicitly reference these files file1 file2 1. The Execution Model: Streams, Not Values Every jq filter is: Copy Filter : Value → Stream<Value> Even if it emits one value, it is still a stream. Even if it emits zero values, it is still a stream. Composition: Copy a | b means: Copy for each v in a(input): emit b(v) This is critical: | is…

    linux

    Logrotate for Nginx: Understanding missingok, notifempty, sharedscripts, prerotate, postrotate (and switching to size-based rotation)

    If you run Nginx in production, your access and error logs can grow fast. On most Linux systems, log rotation is handled by logrotate. It periodically renames log files (e.g. access.log → access.log.1), optionally compresses old ones, and (critically) tells Nginx to reopen its log file descriptors so it starts writing to the new files. This article explains the most common directives you’ll see in /etc/logrotate.d/nginx (or similar), why they exist, and how to safely switch from time-based rotation (daily/weekly) to size-based rotation. Where log rotation comes from On Debian/Ubuntu systems, rotation typically runs via a systemd timer (or historically via cron). The timer triggers logrotate, which reads configuration files under /etc/logrotate.conf and /etc/logrotate.d/*. A typical Nginx logrotate config (daily rotation) Copy /var/log/nginx/*.log { daily missingok rotate 14 compress delaycompress…

    system-design

    Streaming a MariaDB Dump from Go: Pipes, Syscalls, Backpressure and the Runtime

    We start from a very simple handler: spawn mysqldump, capture its stdout, and stream it directly to the browser. No intermediate file. No full buffering in memory. Copy func (s *Server) handleDumpDb(w http.ResponseWriter, r *http.Request) { cmd := exec.Command("mysqldump", "-u", "root", "go_blog") stdout, err := cmd.StdoutPipe() if err != nil { http.Error(w, "pipe error", 500) return } if err := cmd.Start(); err != nil { http.Error(w, "start error", 500) return } w.Header().Set("Content-Type", "application/sql") w.Header().Set("Content-Disposition", `attachment; filename="dump.sql"`) io.Copy(w, stdout) cmd.Wait() } What looks like “just stream stdout” is in fact a multi-layered systems pipeline involving: Kernel pipes File descriptors Syscalls Scheduler decisions TCP flow control Go runtime goroutine scheduling Let’s dissect this deeply. 1. What StdoutPipe() Actually Does (Kernel-Level) When you call: Copy stdout, _ := cmd.StdoutPipe() Go performs something conceptually…

    system-design

    Dispatch Responsibility: C++ Compile-Time Power vs Go Runtime Reflection

    When comparing C++ and Go, one of the most interesting differences is not syntax, not performance, and not even generics — it is where the responsibility for dispatch logic lives. In C++, behavior is encoded into the type system itself. In Go, behavior is often encoded into consumers of metadata. Both approaches are powerful. They simply operate on different axes. 1. Compile-Time Dispatch in C++ In modern C++, dispatch logic is typically resolved at compile time. You use templates, if constexpr, traits, concepts, or std::variant with std::visit. The compiler generates the final branching code. There is no runtime inspection. Example: Compile-Time Branching Here, the compiler selects the branch at compile time based on T. Only the valid branch is instantiated. Copy #include <type_traits> #include <iostream> template <typename T> void process(const…

    default

    Designing a Column-Major Matrix Class with Row-Major Multiplication Optimizations (CPU & GPU)

    When I designed my C++ Matrix<T> class for Fulgurance, I deliberately chose a column-major memory layout (Fortran/Eigen style). It fits linear algebra conventions elegantly: columns are contiguous, column vectors are natural, and transposition and determinant routines fall into place. But for heavy multiplications, CPU caches love row-major traversal. This article explains the architecture, shows why/how I compute multiplications using a row-major access pattern (while keeping column-major storage), and finishes with a GPU benchmark using cuBLAS to show how performance scales on modern hardware. 1) Column-Major Storage in a 1D Vector The matrix is stored as a flat 1D vector in column-major order. Element (i, j) (row i, column j) lives at index: Copy index = j * nrow + i Example, for the matrix Copy 1 4 7 2 5…

    default

    Rebuilding the LU Decomposition and Benchmarking It Against My Own Determinant Algorithms

    When I first started playing with determinant algorithms in C++, I wanted to really understand what happens behind Eigen’s .determinant() call. So I decided to reimplement the LU decomposition from scratch — the same method used inside Eigen and LAPACK — and compare it with two determinant algorithms I built myself: A recursive Laplace expansion A non-recursive Laplace expansion (my own invention 💡) But to make benchmarking clean and efficient, I represented matrices as 1D flat vectors in row-major order, so that values in the same row are contiguous in memory — perfect for cache-friendly computations. Here’s the full story, the math, and the code. 1. From Laplace to LU Laplace’s expansion expresses the determinant as a recursive cofactor expansion: $$ \det(A) = \sum_{j=0}^{n-1} (-1)^j a_{0j} \det(M_{0j}) $$ It’s beautiful,…

    default

    Building a New Determinant Engine - An Iterative Combinatorial Approach

    One morning, I decided to compute a determinant from scratch — no recursion, no Gaussian elimination, no library shortcuts. I wanted to understand what really happens behind the determinant and see if it could be expressed as a purely iterative combinatorial process. That exploration became part of my C++ library Fulgurance — a framework for statistics, linear algebra, and data manipulation. Idea: an iterative cofactor traversal (flattening the tree) In the classic Laplace expansion, computing a determinant means recursively removing one row and one column until you reach 2×2 minors. Each recursive branch corresponds to a combination of column indices — but recursion itself isn’t fundamental. The determinant can be computed iteratively by: Enumerating the valid column subsets directly, Computing the sign via permutation parity (number of inversions), Multiplying the…

    default

    Exploring the Power of Metaprogramming in Rust

    Metaprogramming in Rust: Exploring macro_rules! Power Rust offers one of the most expressive and hygienic metaprogramming systems in modern languages. Through declarative macros ( macro_rules!), we can generate functions, handle code repetition, and even emulate control-flow constructs — all at compile time. In this article, we’ll explore Rust metaprogramming from basic macro pattern matching to complex variadic patterns and custom control structures — step by step, with working examples. 1. Macro Pattern Matching and Expression Types Copy macro_rules! macr { () => { println!("Check out my macro!"); }; ($name:ident) => { println!("Hello, {}!", stringify!($name)); }; ($val:expr, $val2:expr) => { println!("2: {}, {}", $val, $val2); }; ($val:expr) => { println!("3: {}", $val); }; } fn main() { macr!(); macr!(7777); macr!(7777, 8888); macr!(Alice); } Output Copy Check out my macro! 3: 7777…

    default

    📊 Building a Flexible Access Log Analyzer in R

    In this tutorial, we’ll walk through the design and implementation of a small but powerful R script that analyzes web server access logs — for instance, NGINX or Apache logs — and produces clean, insightful PDF plots of your website’s traffic patterns. This project demonstrates how to combine dplyr, lubridate, ggplot2, readr, and optparse to build a command-line data analysis tool in R. repo 🧰 Overview The script accepts an access log file, parses and filters it according to date range, regex patterns, and time interval, and then generates a PDF plot summarizing the number of requests per page over time. Example usage: Copy Rscript convert.R \ -l 60 \ -p '^/$--^/all_posts/.*$--^/post_search/0$' \ -i h \ -f access.log This example analyzes the last 60 hours of requests for three URL…

    functional-programming

    The Knight’s Tour in Haskell — From Brute Force to Warnsdorff’s Heuristic

    One of the most fascinating and ancient problems in recreational mathematics is the Knight’s Tour — the challenge of moving a chess knight so that it visits every square of an N×N chessboard exactly once. It’s not just a puzzle: it’s a deep exploration of backtracking, graph traversal, and even heuristic search. In this post, I’ll show how I implemented the Knight’s Tour in Haskell — first using a basic DFS (Depth-First Search), and then improved it with Warnsdorff’s rule, a clever heuristic that dramatically improves performance. The Problem The knight’s movement pattern is unique: it moves two squares in one direction and one in the perpendicular direction. In coordinates, from position (x, y), it can move to: Copy (x ± 2, y ± 1) or (x ± 1, y…

    functional-programming

    Checking Graph Bipartiteness in Haskell

    One of the most elegant problems in graph theory is determining whether a given graph is bipartite. A bipartite graph is one whose nodes can be divided into two disjoint sets such that no two nodes within the same set are connected by an edge. This concept appears everywhere — from scheduling and matching problems to network flow and coloring algorithms. In this project, I wrote a full Haskell implementation to determine whether any graph is bipartite, even if it’s disconnected. 1. The key idea If a graph has multiple connected components (subgraphs that are not connected to each other), we can test each subgraph independently. A disconnected graph is bipartite if and only if all its subgraphs are bipartite. So the problem splits naturally into two steps: Find all…

    functional-programming

    Solving the Eight Queens Problem in Haskell

    The Eight Queens Problem is one of the most famous challenges in computer science and mathematics. The goal is simple to state yet surprisingly rich in structure: Place eight queens on a chessboard so that no two queens threaten each other. In practice, that means ensuring that no two queens share the same row, column, or diagonal. It’s a classical example of a constraint satisfaction problem — and an elegant one to tackle using Haskell’s declarative and recursive strengths. 1. The problem restated We must place 8 queens on an 8×8 chessboard so that: No two queens share the same column. No two queens share the same row. No two queens share the same diagonal (both ascending and descending). We’ll represent each solution as a list of 8 integers, where…

    functional-programming

    Exploring Reachability in Directed Graphs with Haskell

    Exploring Reachability in Directed Graphs with Haskell Graphs are a natural way to represent systems of connections — from flight networks to dependencies in code or social networks. In directed graphs, edges have a direction, and not all nodes may be reachable from one another. This brings up a fascinating question: From which nodes can we reach all others? To explore this, I wrote a Haskell function that recursively discovers all directed paths in a graph, and identifies the nodes that can reach every other node. 1. The problem Given a directed graph represented as a pair ([nodes], [(from, to)]), we want to: Find all traversal paths starting from every node. Keep only the nodes that can reach all others. The function should therefore output a list of path groups…

    functional-programming

    How Do They Display Trees — Three Layout Algorithms in Haskell

    When you visualize data structures in a GUI — such as decision trees, syntax trees, or even neural networks — one key algorithmic problem hides behind the scenes: How do you determine where to draw each node? Many libraries in higher-level languages (like Python’s data science tools or visualization frameworks) rely on carefully designed tree layout algorithms to assign 2D coordinates to nodes. Problems 64 to 66 from the 99 Haskell Problems explore exactly that: how to compute node coordinates for different layout styles. In this article, we’ll go through three classic methods of visualizing trees — each one balancing symmetry, spacing, and readability differently. 1. Layout Algorithm #1 — Inorder Positioning (Problem 64) The first method assigns each node’s position based on two simple rules: x(v) equals the position…

    functional-programming

    Constructing All Spanning Trees in Haskell (Problem 83)

    In graph theory, a spanning tree of a connected graph is a subgraph that includes all the nodes of the original graph, connected with the minimum number of edges (exactly n − 1 for n nodes) and without any cycles. I discovered this concept through Problem 83 of the 99 Haskell Problems series. The goal is to construct, by backtracking, all spanning trees of a given graph, and then use that logic to check if a graph is a tree or if it’s connected. 1. The problem Write a function spanningTree that constructs (by backtracking) all spanning trees of a given graph. Once we have that, we can easily define two related functions: is_tree(Graph) — determines if a graph is a tree. is_connected(Graph) — determines if a graph is connected.…

    functional-programming

    Graph Isomorphism in Haskell (Problem 85)

    Graph isomorphism is one of the classic challenges in graph theory and computer science. It involves determining whether two graphs have the same structure — that is, whether one can be transformed into the other simply by relabeling its nodes. I first encountered this problem through the 99 Haskell Problems, specifically Problem 85. It’s an elegant exercise that brings together recursion, list manipulation, and combinatorics. 1. The problem Two graphs G₁(N₁,E₁) and G₂(N₂,E₂) are isomorphic if there exists a bijection f : N₁ → N₂ such that for any nodes X, Y ∈ N₁, X and Y are adjacent if and only if f(X) and f(Y) are adjacent. In other words, two graphs are isomorphic if they are structurally identical, regardless of how their nodes are labeled. Example Copy λ>…

    functional-programming

    Introduction to Graph Theory in Haskell

    Graph theory is one of the most fascinating areas of computer science and mathematics, forming the foundation for countless real-world applications: from social networks and routing systems to dependency trees in compilers. When learning Haskell, I was first introduced to graph theory through the 99 Haskell Problems — a collection of exercises that gradually expose you to elegant and expressive functional patterns. Problem 81, in particular, focuses on finding all acyclic paths between two nodes in a directed graph. 1. The challenge The problem is simple to state: Given two nodes a and b in a directed graph, return all possible acyclic paths from a to b. For example: Copy λ> paths 1 4 [(1,2),(2,3),(1,3),(3,4),(4,2),(5,6)] [[1,2,3,4],[1,3,4]] λ> paths 2 6 [(1,2),(2,3),(1,3),(3,4),(4,2),(5,6)] [] 2. Representing a graph in Haskell Before diving…

    functional-programming

    Implementing Huffman Encoding in Haskell

    Huffman encoding is one of the foundational algorithms in data compression — elegant, efficient, and entirely based on simple mathematical principles. It converts symbols and their frequencies into binary codes where the most frequent symbols receive shorter codes. The algorithm is used in many compression systems, including ZIP and JPEG, and fits naturally into functional programming thanks to its recursive and tree-based nature. In this project, I implemented Huffman coding in Haskell from scratch. The goal was to explore tree construction, recursion, and symbol encoding rather than optimize for absolute performance. Interestingly, depending on input characteristics, my approach sometimes generates a code table that uses slightly fewer bits than a classic implementation — but that is highly input-dependent. 1. The problem setup Given a set of symbols and their frequencies:…

    default

    The Goldbach Conjecture and Its Recursive Implementation in Haskell

    The Goldbach Conjecture is one of the oldest unsolved problems in mathematics. It states that every even integer greater than 2 can be expressed as the sum of two prime numbers. While no formal proof has been found, the conjecture has been verified by computers for very large numbers. In this post, we’ll explore how to express this idea recursively in Haskell — using an elegant search through the space of prime pairs. 1. Restating the problem For any even number x > 2, find two primes p1 and p2 such that: Copy p1 + p2 = x For example: 4 = 2 + 2 6 = 3 + 3 10 = 5 + 5 or 7 + 3 The challenge is to find such a pair efficiently — and…

    functional-programming

    Understanding Recursion Through Combinations, Permutations, and Trees in Haskell

    Recursion often feels like a mysterious concept when you first encounter it — until you realize that it’s not about doing something repeatedly, but about breaking a problem into smaller, self-similar parts. In this post, we’ll explore how recursion allows us to generate combinations, random permutations, and even manipulate trees and graphs elegantly in Haskell. To begin, here’s how I once described it: “So when my program makes its first recursive call, what does it actually do? Does it launch another recursive call with a different input?” The answer is yes — it destructures the input string, taking its first element, say “a”. If we follow only that first recursive call, it will generate “abc”. But notice that when it took “a”, it also made another recursive call — this…

    functional-programming

    Finding the Optimal Path in Haskell: A Recursive Exploration

    I will explain from my point of view the solution to the following problem here, we explore a recursive approach to solving an optimal path problem — where at each step, multiple paths are possible, and we must decide which route minimizes the total cost. The idea is to think of the problem as a sequence of blocks — each representing a segment of possible movements. Between these blocks, we must choose how to transition optimally while keeping track of cumulative costs along each possible path. 1. The block model and mental picture We can think of the system as three tracks: A, B, and C. Each block of the path has three values representing the cost of traveling along each of these tracks (or switching between them). We define…

    functional-programming

    Understanding the Haskell Type System: From Typeclasses to Data Structures

    In this tutorial — inspired by my video “Structure de données et système de types en Haskell” — we dive into the heart of what makes Haskell so expressive: its type system. This article targets an intermediate audience: you already know what a function or a list is, but now you want to understand why types in Haskell feel so different — and powerful — compared to other languages. 1. Why types matter in Haskell In Haskell, types are not just annotations — they are first-class citizens that define how values behave and interact. The compiler (GHC) uses types to enforce correctness, optimize performance, and even help you reason about your program. Every value in Haskell has a type, and Haskell’s compiler infers those types automatically. But you can (and…

    functional-programming

    Understanding Parenthesis Tokenization in Haskell

    Context Before building a full arithmetic calculator in Haskell, there was one key challenge I needed to solve first: understanding and tokenizing parentheses. Parenthesis tokenization may sound like a small detail, but it’s actually a necessary step for building my own calculator interpreter — the engine that later evaluates nested expressions like (3+(2*(5-1))) correctly, respecting operator precedence and nesting depth. 1. Why tokenization matters In an arithmetic expression, parentheses determine the order in which subexpressions are evaluated. To process them properly, a calculator must: Recognize where every ( and ) occurs Track how deeply nested each one is Know which pairs of parentheses match together Once we have this information, we can safely evaluate the innermost expressions first and work our way out — exactly how human math logic works.…

    functional-programming

    Building a Tiny Reverse Polish Notation (RPN) Calculator in Haskell

    In this project, we’ll build a small expression evaluator using Reverse Polish Notation (RPN) — also called postfix notation. The idea is simple: instead of writing 3 + 4, you write 3 4 +. This lets you evaluate expressions without worrying about parentheses or operator precedence. The project is a fun and compact way to learn about: Recursion Pattern matching List manipulation with foldl Function composition 1. The goal We want a function that can take a string like "3 4 +" and return 7.0. Or more complex ones like "2 3 4 + *" → 14.0. We’ll also add support for basic arithmetic, powers, exponentials, logs, and even a factorial! 2. The full code Copy primitiveSolver :: String -> Double primitiveSolver expr = head . foldl funcNPI [] .…

    functional-programming

    Learning Haskell with Weird Goals

    Sometimes, the best way to learn a language is by using a simple, even slightly “weird” goal as an excuse to explore its core concepts. Here, the goal is to extract the sides (apart from the hypotenuse) from a list of Pythagorean triples—but really, it’s just a reason to learn how pattern matching, recursion, and let blocks work in Haskell. 1. A simple pattern-matching refresher In Haskell, you can deconstruct tuples directly in function arguments. It’s an elegant and expressive way to “take apart” data structures. Let’s define three simple functions to get each element from a 3-tuple: Copy myFst :: (Int, Int, Int) -> Int myFst (x, _, _) = x mySnd :: (Int, Int, Int) -> Int mySnd (_, x, _) = x myThrd :: (Int, Int, Int)…

    functional-programming

    Brute-forcing Pythagorean Triples with Haskell List Comprehensions (up to 100)

    We want all integer solutions (a,b,c) to the equation a^2 = b^2 + c^2 with 0 < a < 100. This is a great place to use Haskell’s list comprehensions: they’re concise, readable, and—when bounded carefully—surprisingly efficient. The goal (and a small symmetry trick) We’re after triples (a,b,c) that satisfy: a^2 = b^2 + c^2 0 < a < 100 to avoid duplicates from swapping legs, we enforce ordering: c < b < a That last line is key: every valid solution has one leg greater or equal to the other, so we arbitrarily choose b to be the larger leg and enforce c < b. This removes mirrored duplicates. Important list comprehension fact In a Haskell list comprehension, a variable can be used only if it’s defined earlier in…

    recreational-programming

    Turning Blog HTML into RSS, the Low-Level Way (in C++)

    If you publish long-form posts on the web, you’ve probably felt the friction of keeping your RSS feed in sync. I did too. So I wrote a tiny command-line tool in C++ that converts a finished blog post page (the raw HTML file itself, not just the body) into a ready-to-drop <item> block for your RSS feed. Because yes—CLI is fun, and C++ is low-level, baby. 🛠️ TL;DR What it does: Reads a full raw blog HTML page (not just the body) → emits a valid RSS <item> XML snippet. Why it’s useful: No separate markdown front matter or duplication. Your source of truth is the rendered page. How to use: ./a.out post.html rss.xml "My Title" "https://example.com/post" "2025-10-04" Where it lives: github.com/julienlargetpiet/automate_rss The Problem An RSS feed wants clean metadata…

    recreational-programming

    A New Way to Explore Your System on Linux

    On Linux, productivity often comes from small but powerful tools. dmenu and rofi are great examples: minimalist application launchers that make your desktop more efficient. But I wanted to go further. Instead of just launching programs, what if I could explore my system, run scripts, and interact with the shell — without opening a terminal? That’s how I created dmenu_all, an extensible, open tool that transforms dmenu into a universal system navigator. What It Does Browse your files: Navigate directories quickly through a dmenu-driven menu. Launch applications: Use it like a classic launcher. Run scripts: Define your own actions and execute them from the same interface. Chain commands: Build workflows without typing shell commands manually. In short, dmenu_all makes dmenu (or rofi) a hub for your daily Linux tasks. How…

    recreational-programming

    Automating YouTube Video Imports into My Website with One Magic Bash Line

    Over the past months I’ve been downloading my own YouTube videos with yt-dlp. It’s a fantastic tool for archiving, and I’ve built up a folder full of .mp4, .webm, and .mkv files. But here’s the boring part: every time I wanted to put those videos on my personal website, I had to manually write <a> tags for each one. Copying file names, escaping spaces, renaming stuff… too much grunt work. So I decided to automate it. And the result is this single, magic line of Bash: Copy $ find . -type f \( -name "*.webm" -o -name "*.mp4" -o -name "*.mkv" \) -printf "%P\0" | xargs -0 -n1 bash -c 'X="$1"; clean=$(echo "$X" | sed "s/ /_/g"); echo "<a href="/assets/common_files/$clean">$X</a><br>"' X1 Breaking Down the Magic find . -type f \(…

    recreational-programming

    Building My Own Parser in R - A Custom Syntax Experiment

    This was one of my older projects, a little bit eccentric but very educational. I wanted to see if I could design and implement a parser from scratch in R, complete with a brand-new syntax and functions to both read and write data. The project is part of my old data manipulation library written in R avaiable on this repo It wasn’t about reinventing JSON, XML, or YAML — it was about learning how parsing works at a low level, handling nested structures, and building a system that’s flexible enough to store and retrieve hierarchical data. The Custom Syntax I invented a compact bracket-based format to represent hierarchical data. It looks like this: Copy (ok(ee:56)) (ok(oui(rr((rr2:6)(rr:5))))(oui(bb(rr2:1)))(ee1:4)) The rules are simple: Each node is wrapped in parentheses (...). A node may…

    system-design

    Building InFoEnd: An End-to-End Encrypted Chatroom in Go

    InFoEnd is my first experiment with building a secure chatroom application in Go. The goal: create a real-time messaging system where messages are encrypted end-to-end, such that even the server cannot read them. To make it feel like a proper client, not just a toy, I added a terminal UI using the tview library and relied on the WebSocket protocol for message transport. The result is a multi-room chat platform that demonstrates encryption, networking, and terminal UI in one place. Architecture Overview The system consists of two roles: Admin (server) and Clients. Illustration images Server (Admin) Responsible for creating chatrooms. For each room, generates a unique 32-byte AES key. Distributes this AES key securely to clients via their RSA public keys. Once all clients of the chatroom have handshaked with…

    default

    Reimplementing diff in C++: A Minimalist Approach

    Why Rebuild Something That Already Exists? The diff command is one of the cornerstones of the GNU/Linux ecosystem. It’s simple in appearance, yet behind the scenes it powers version control, code reviews, and collaborative software development. I wanted to reimplement diff myself — not because the world needs another diff tool, but because it’s a great exercise in understanding how file comparison works at a low level. Writing it from scratch in C++ forced me to think about edge cases, data handling, and performance, even for what seems like a “trivial” utility. Defining the Scope The real diff command is sophisticated. It can produce unified diffs, context diffs, side-by-side comparisons, and even patch-friendly outputs. My goal wasn’t to replicate all of that. Instead, I set out to create a minimalist…

    default

    Automatic Documentation for Any Codebase

    When working with R, I loved how Roxygen lets you generate clean documentation directly from comments in your source code. But I often wished there was something similar for every language, not just R. That’s why I built simple_doc: a lightweight documentation tool that works on any codebase. The Idea Instead of maintaining separate README files, wiki pages, or doc websites, you can write structured comments directly in your code. simple_doc then parses those comments and generates clean, human-readable documentation automatically. How It Works In your code, you add special annotations (inspired by Roxygen style): Copy // @T dcauchy // @U std::vector<double> dcauchy(std::vector<double> // @U &x, double location = 0, double scale = 1) // @D Returns the probability distribution of the Cauchy distribution. // @A x : vector of…

    software-computational-architecture

    Reimplementing Cross-Validation for KNN in R (from Scratch)

    After reimplementing K-Nearest Neighbors (KNN) from scratch, I wanted to take things a step further: build a cross-validation system entirely in base R. This meant re-creating folds, evaluating accuracy across them, and tuning both k (the number of neighbors) and the training proportion. No caret, no external frameworks — just my own code. The Fold Function The first step in cross-validation is creating training/test splits. For this, I wrote v_Rmach_fold, which generates n_fold pairs of train/test datasets. Each sample is stored in a small S4 class sample_Rmach with: train: the training dataframe test: the testing dataframe train_ids: row indices used for training test_ids: row indices used for testing Copy lst_test <- v_Rmach_fold(inpt_datf = iris[1:25,], train_prop = 0.7, n_fold = 4) print(lst_test$sample1@train) # Training set print(lst_test$sample1@test) # Test set This function…

    software-computational-architecture

    Reimplementing K-Nearest Neighbors (KNN) from Scratch in R

    As part of my exploration of machine learning fundamentals, I decided to reimplement classic algorithms from scratch instead of relying directly on existing libraries. One of the first I tackled was K-Nearest Neighbors (KNN), a simple yet powerful classification method. Why KNN? KNN is often one of the first algorithms taught in machine learning because it’s intuitive: To classify a new point, look at the k closest points in your training data. Assign the most common class among those neighbors. No training phase, no model building — just distance comparisons. This makes it perfect for reimplementing from scratch. The Implementation I called my implementation knn_Rmach. It works with R data frames, allowing you to specify which columns are variables and which is the classification column. It also supports both numeric…

    software-computational-architecture

    Optimizing the Exponential Function in Cherubin

    Cherubin is my C++ library for computing very large numbers represented as strings. One of the hardest functions to implement efficiently in this context is the exponential exp(x). A naïve implementation using the Taylor series converges slowly, requires repeated big-number multiplications and divisions, and becomes impractical very quickly. With chexp3, I managed to dramatically reduce the execution time of the exponential function by splitting the input into its integer part and fractional part, and computing them separately. This way, the function avoids huge Taylor expansions and only uses lightweight operations when needed. The Optimization Strategy Here’s the core idea of chexp3: Step 1 — Separate integer and fractional parts: The input x (as a string) is split into partint and partflt. Example: x = "12.34" → partint = "12", partflt…

    software-computational-architecture

    Reimplementing the Cauchy Distribution in Fulgurance (C++ Statistics Library)

    Introduction Fulgurance is my C++ statistics library where I reimplemented several probability distributions from scratch, including the Cauchy distribution. The goal of Fulgurance is to provide flexible statistical tools in modern C++, without relying heavily on external libraries. It’s also a playground to explore how distributions work internally, both mathematically and computationally. Why Reimplement Cauchy? The Cauchy distribution is a well-known heavy-tailed distribution, often used in physics, Bayesian inference, and robustness testing. Unlike the normal distribution, its mean and variance are undefined — which makes it a good candidate to test statistical implementations. Rebuilding it from scratch in C++ was a great exercise in both numerical computation and random number generation. The Four Building Blocks 1. dcauchy — Density Function The probability density function (PDF) of the Cauchy distribution is:…

    software-computational-architecture

    Cheating a Bit: Approximating atan, arccos, and arcsin in the Cherubin Library

    This project is part of my Cherubin library — a C++ library for computing very large numbers represented as strings. Because Cherubin works outside the world of hardware floats and doubles, I couldn’t just call std::atan, std::asin, or std::acos. Instead, I had to invent approximations that made sense within the string-based arithmetic of Cherubin. ( GitHub link) The result is a set of small but clever tricks to approximate inverse trigonometric functions. They’re not mathematically perfect, but they get the job done and are fast enough to work with big numbers. Why Approximate? Standard math libraries are precise and optimized for floats, but Cherubin manipulates numbers as std::string or std::deque. Re-implementing full Taylor series everywhere would be very slow, so I turned to shortcuts: polynomial fits, hybrid methods, and even…

    recreational-programming

    SoundCutr: An Early Attempt at Voice Extraction in Audio Files

    Think of this article as a small time capsule of my programming journey — proof that everyone starts somewhere, and that projects don’t need to be perfect to be fun and functional. Project Overview The goal of SoundCutr was to isolate the human voice from an audio track. This is useful for tasks like: Karaoke (removing or extracting vocals) Speech analysis Audio preprocessing for further machine learning tasks The approach is based on two key principles: Frequency filtering to focus on the human voice range (roughly 300 Hz – 3400 Hz). Block compartmentalization (time segmentation) to distinguish between real continuous speech and short transient sounds. How It Works The pipeline for processing audio files includes both spectral and temporal logic: Read the audio file (typically a .wav format). Apply filters…

    default

    Implementing DataFrames in C++: A Custom Approach for High-Performance Data Manipulation

    Introduction When working with data, Python and Pandas dominate the landscape. They provide an intuitive way to load, transform, and analyze datasets. But what if you need the same capabilities inside a C++ pipeline, without switching languages, and with full control over memory and type safety? That’s the motivation behind Tablo, my implementation of DataFrames in modern C++. This project provides a flexible and performant way to manipulate tabular data directly in C++ — including CSV parsing, type inference, missing value handling, and column/row operations. In this article, I’ll walk you through the architecture, features, and next steps of this implementation. Architecture Overview The core idea of this project is simple: Each column of the DataFrame is stored as a std::vector<T>, where T is the inferred type of the column.…

    functional-programming

    How Haskell (and the Functional Mindset) Rewired the Way I Think About Code

    I didn’t set out to “become a functional programmer.” I stumbled into Haskell after years of imperative and OOP work, mostly focused on getting features out the door. I knew about lambdas and “map/filter,” but those were just utilities, not a worldview. My real journey started with the excellent online book Learn You a Haskell for Great Good!. Its playful style made functional programming approachable, and soon I realized Haskell wasn’t just another language—it was a different way to think about programs: where state is explicit, effects are controlled, and types carry meaning. Why Haskell Was Created Haskell wasn’t born out of industry needs but out of academic curiosity and a desire for clarity. In the 1980s, researchers had designed many lazy functional languages, but the landscape was fragmented. To…

    system-design

    Building an HTTP Server in Rust Without a Framework

    All code excerpts below are highlights of the full implementation. See the complete source on GitHub: julienlargetpiet/HTTP_Server. Why write your own server? When you think of writing an HTTP server in Rust, the obvious choices are production-grade stacks like Hyper, Actix-Web, or Warp. They’re excellent—and in production you should likely use them. But building a server from first principles forces you to understand what actually happens: accepting sockets, parsing a protocol, and coordinating concurrency safely. Beginner-friendly intro: HTTP and Rust in 5 minutes What an HTTP server really does Listen on a TCP port for incoming connections. Parse each incoming byte stream into a structured HTTP request (method, path, version, headers, body). Respond with a valid HTTP response (status line, headers, body). Why Rust helps Ownership & borrowing ensure memory…

    system-design

    Building an Encrypted Terminal Chatroom in C - A Personal Engineering Story

    I built a tiny chatroom that runs entirely in the terminal, written in C, with all messages encrypted. This article is my engineering story: why I did it, how the design evolved, what broke (and why), and the practical lessons I’m taking to my next low-level project. The code lives here: github.com/julienlargetpiet/Chat. It’s a simple, scrappy program that uses sockets, pthread, ncurses for the TUI, SDL for a small “poke” sound, and OpenSSL’s EVP API for AES encryption. Why a chatroom in C, and why the terminal? I like C for the same reason some people like rebuilding engines: it’s brutally honest. If I forget to check a return code, leak a buffer, or mix up a length, I pay the price immediately. A chatroom touches a lot of systems…

    recreational-programming

    Validating JSON Syntax: A Conceptual Approach

    In modern systems, JSON has become the de facto standard for exchanging structured data. Its popularity comes from its simplicity and readability. Yet, beneath this apparent simplicity lies a crucial question: how can we be sure that what we call “JSON” actually respects the rules of the format? Parsing alone is not enough — validation is essential. In this article, I share a way of thinking about JSON validation that goes beyond existing tools. The objective is not to provide a new parser or a piece of software, but to propose a conceptual algorithm for understanding what it really means to validate JSON. The Problem of Validation When we speak of JSON, we often assume that if a parser can read a string without raising an error, then the content…

    software-computational-architecture

    Emulating Binary-Level Operations and Number Representations

    At the heart of every computer lies a simple truth: everything is binary. Whether you are working with integers, floating-point numbers, or characters, all data is ultimately represented as sequences of 0s and 1s. To truly understand how computers operate, developers must go beyond high-level abstractions and study how numbers are represented and manipulated at the binary level. This article covers three pillars of low-level computation: Bitwise operations (AND, OR, XOR, NOT, shifts). Signed integer representations (one’s complement and two’s complement). Floating-point numbers (IEEE 754 standard). 1. Bitwise Operations Bitwise operators act directly on the binary digits of numbers. AND (&) Copy 1101 (13) 1011 (11) ---- 1001 (9) Use case: masking specific bits. OR (|) Copy 1101 (13) 1011 (11) ---- 1111 (15) Use case: setting specific bits. XOR…

    default

    Editing My YouTube Videos the Weird Way: With Nothing but ffmpeg

    Most people edit their YouTube videos with slick GUIs: Premiere, DaVinci Resolve, Final Cut Pro, even OBS + Shotcut for the open-source crowd. Me? I’m allergic to timelines and mouse-dragging. I prefer to edit in the most brutalist way possible: directly from the terminal, using nothing but ffmpeg. Yes, I’m basically editing like a robot with a text editor and command lines. It’s unusual, it’s nerdy, but it works. Let me walk you through my strange ritual. Step 1 — Recording the Chaos I start by summoning ffmpeg to record my microphone and my screen at the same time. One incantation later: Copy $ ffmpeg \ -f pulse -i alsa_input.usb-JMDZ_MICROPHONE_WOODBRASS_UM1_20211207-00.mono-fallback \ -f x11grab -s 1920x1080 -i :0.0 -f pulse tells ffmpeg to grab audio through PulseAudio, my sound system on…

    software-computational-architecture

    Unsolved problem !!!

    Statement and motivation (inspired from pb.93 of 99 Problems in Haskell) This problem originates from the motivation to find all possible results given a formula with `n` values, like: $$ X_1 + X_2 - X_3 \cdot X_4 $$ So here we are given a set of operators and a set of values. Basically there are n - 1 operators, one between each value. So it is trivial to find all possible results, we just have to use a cartesian product of all operators n - 1 times, then put the operators between each value, and calculate the result. In Haskell, to find all operators combinations, it would look like this: Copy sequence . replicate 3 $ "+-*/" But as you know, in each formula, comes the parenthesis. So it will…

    recreational-programming

    Custom Encoding For Integers

    Ok, so i had to encode a structured data, a positive integer in this case representing the space for the server to reserve a byte slice for a file content, image, text... Basically, how to convert any positive integer to a vector of number that accepts value from 0 to 255. Encoding First solution, i just add 256, which will be 255 (from 0) in a vector, and the ending position value will be the rest of the integer minus the previous additions. But that is non optimal, because the vector is too long. Something that reduces more the size of the integer is of course a division, which will reduce a lot the size of the sending byte vector. Ok, so this is it for encoding: Copy func IntToByteSlice(x…

    recreational-programming

    Authentication Without Cookies

    Recently, i've been programming a simple cloud webserver in Go. And of course, it is unavoidable when including accounts, how to make sure a user is who he pretends to be when he connects to a page. Of course, there are authetication and session cookies, but in this blog we like to imagine another way to achive this. So let's implement a custom authentication mechanism that does not rely on cookies at all. Sounds cool. The projetc is available on this website Friendly_Cloud Or here on GitHub repo Method The credentials database consists of 3 columns: username password temp_password The password is only used in the login process, to verify that the users gives the right password. After validation, a randomly temporary password is generated, stored in the third column,…

    system-design

    Simple Compression Algorithm

    I've just finished implementing a simple text compression algorithm in C++, i will talk about its implementation in this article. The programm is available here repo Or on this website as a zip zip Compression overview A function will read the file to compress and will create a std::string of its content. After, it will look for recurrent patterns. Recurrent patterns A recurrent pattern as its name suggests is a sequence of character s that is present multiple times in the scaned std::string of the input file. We can choose the length of the pattern to find. For example a pattern of length 2 is more commun than a pattern of length 3. In a sentence, we more often see "ou" than "oup". Compression level Of course, the patterns frequence…

    default

    Implement Core Operations

    I have just finished developing a library for manipulating numbers so large and/or precise that no conventional datatype can encode them. You can find this library there: repo Or download on this website as zip: zip -Ok so if even a long unsigned int, double... can't represent my number, how do I? I'm not going to use vecteur, see a deque? In fact, if one is obliged, but it requires the complete reimplementation from zero of the fundamental operators ( +, -, *, /, %%, !, exp(x), log(x)...) taking into account the data structure with which we work. Addition For example, we do the addition and then we can do the multiplication and division. Example "12" * "0.4" = "12" + "12" + "12" + "12" then we moove the…

    recreational-programming

    Symetric Encryption Protocol

    How i've implemented an original symetric encryption protocol with combinatorial mathematics repo Or download on this website as zip: zip It starts with this formula: n! / ((n-k)! * k!) It tells how many of k elements combinations can be created in a set of length n. For example, if we have: [1, 1, 0] We notice that the set has a length of 3 there are 2 elements inside. The possible combinations are: [1, 1, 0] [1, 0, 1] [0, 1, 1] It is intuitively made (easy for a set of length 3), but what tells the formula? 3! / ((3 - 2)! * 2!) = 6 / (1 * 2) = 3 We get the number of combinations. Won't be cool to have an algorithm returning the combinations…

    recreational-programming

    A ReGex Dialect

    In this article i'm gonna present you a method to implement RegEx. Link: repo Or on this website: zip Before the explanation, what even is RegEx ? Regular Expressions are in fact a synthax allowing to find any pattern inside a text. A good RegEx dialect is Search Complete if it can, just by its synthax, find any pattern inside a text. I'm not a huge fan of the actual synthax in the majority of the RegEx dialects. I was inspired by these dialects but tried to simplify them, in C++. But first we have to define the characteristics of our dialect sensed to be Search Complete. Allow set definition as a condition This will be built by the introduction of a special character being - which will link the…

    recreational-programming

    An Original Transformation Engine

    In this article i will introduce you, in short, how i've implemented transformation engine XSLT like from scratch (with C++). repo Or download on this website: zip Which means requesting a value using its path in the data structure, the introduction of conditions, loops and sorting algorithms to generate a html page that the user describes inside a file with query instructions. Since i start from scratch, i have to create my own synthax to structure data. I remember of an algorithm i've created 1 year ago now allowing to tokenize pairs of parentheses inside a string. Bingo, for nested data XML, Json or even TOML like, pairs of parentheses design is great to describe their nesting. How it looks: Copy (destination: (restaurant: (menu: (size: (weight:150g) (size:small) ) (size: (weight:200g)…