Arjen Wiersma

A blog on Emacs, self-hosting, programming and other nerdy things

This is a Dutch artcile, there is also an English version.

Dus, jij hebt besloten om te gaan studeren? Misschien wil je jouw HBO- of Masterdiploma halen, of juist dat ene supertechnische certificaat bemachtigen. Het is geweldig dat je deze stap gaat zetten, maar zodra je begint, zul je vrij snel de vraag moeten beantwoorden waar je de tijd vandaan haalt.

Tijd is onze meest waardevolle, niet-hernieuwbare bron. Studeren vergt tijd – en niet zo'n klein beetje ook – dus wil je het natuurlijk goed doen. De meeste studies verwachten dat je wekelijks ergens tussen de 12 en 24 uur investeert om bij te blijven, en dat is flink wat! Als je nog niet studeert, probeer dan eens na te denken over welke dagen en momenten je die tijd kunt vrijmaken. Ga je minder uit eten of juist minder sporten? Vroeg opstaan in het weekend, of juist extra laat naar bed?

De meeste studenten lopen tegen dit probleem aan wanneer ze beginnen met studeren; ik zie het maar al te vaak. Je start vol vertrouwen aan een studie, maar dan realiseer je je dat je niet hebt nagedacht over hoe het in jouw leven past en wat je moet opofferen om te kunnen studeren. Veel studenten proberen dan ook alles tegelijk te doen, met alle gevolgen van dien. Gelukkig is er een strategie die je kunt toepassen. Ik heb deze strategie zelf gebruikt tijdens mijn deeltijd HBO- en Masterstudies, en voor mij werkte het perfect.

De kern van de strategie is het gebruik van je agenda. Om goed de baas te zijn over je tijd, moet je precies weten wanneer je wat gaat doen. Dit klinkt eenvoudig, maar de meeste mensen noteren alleen belangrijke zaken in hun agenda, zoals de tandartsafspraak of de verjaardag van tante Loes.

Op een dag doe je natuurlijk heel veel. Zelf heb ik een baan van 40 uur per week, ga ik naar de sportschool, wil ik tijd doorbrengen met mijn gezin, en nog veel meer. Als ik die activiteiten niet zou inplannen, raak ik al snel het overzicht kwijt. Zonder overzicht wordt het ook moeilijk om effectief te studeren, want dan staat opeens tante Loes op de stoep.

De strategie omvat de volgende stappen:

  1. Gebruik een kalender die je overal kunt raadplegen.
  2. Blokkeer je werktijd en houd je hieraan.
  3. Blokkeer ook tijd voor je gezin en vrienden.
  4. Plan studiemomenten in.

Het maakt niet echt uit welke kalender je gebruikt, zolang deze maar voor jou beschikbaar is. In mijn voorbeelden zal ik de Proton Calendar gebruiken, die is lekker veilig en gevestigd in de EU. Zo heb je geen last van grote techbedrijven die meekijken in jouw planning.

Een lege kalender ziet er zo uit.

{{< figure src=“/ox-hugo/20240715193929screenshot.png” caption=”Figure 1: Een lege agenda, dat is nog eens rustig!” >}}

Zoals je kunt zien, heb ik elk gebied van mijn leven een eigen kleurtje gegeven. Dat is superhandig, want daarmee zie je in één oogopslag waar een afspraak bij hoort.

{{< figure src=“/ox-hugo/20240715194152screenshot.png” caption=”Figure 2: Elke kalender een eigen kleur, helaas ben ik niet goed in kleuren kiezen.” >}}

Als eerste stap plannen we de werkdagen in. Ik heb zelf al mijn werkafspraken in mijn agenda staan, maar ook dan blokkeer ik mijn werktijd met een kalenderafspraak. Op die manier weet ik altijd wanneer ik wel of niet beschikbaar ben op een gegeven tijdstip. Als je ook moet reizen naar en van je werk, plan dan ook die tijd in. Ik doe dat bijvoorbeeld op woensdag en vrijdag.

{{< figure src=“/ox-hugo/20240715195048screenshot.png” caption=”Figure 3: Stap 1, plan jouw werkdagen in” >}}

Dit lijkt misschien een beetje suf, want je weet toch dat je werkt? Natuurlijk is dat zo, maar voor het mentale model van jouw beschikbare tijd is het belangrijk om deze periode te blokkeren. Zo weet je zeker dat je die tijd niet kunt gebruiken om te studeren. En kijk, nu lijkt het alsof er nog heel veel tijd over is, toch?

Tijdens mijn studie vond ik het ook belangrijk om tijd te reserveren voor mijn gezin en om leuke dingen te doen. Studeren moet leuk zijn en mag niet aanvoelen als een straf waardoor je geen plezierige activiteiten meer kunt ondernemen. Laten we nu alle tijd voor gezin en vrienden ook in de kalender zetten.

{{< figure src=“/ox-hugo/20240715195810screenshot.png” caption=”Figure 4: Stap 2, tijd voor het gezin en vrienden” >}}

Dan wordt het al een ander verhaal. Voor mij was het weekend belangrijk. Iedereen werkt hard gedurende de week, dus er is ook tijd nodig waarin we allemaal kunnen ontspannen. Wat meteen opvalt, is dat er dan relatief weinig tijd over lijkt te zijn om te studeren, maar schijn bedriegt. Ik vond het heel fijn om 's avonds te studeren, zo ongeveer van 8 uur tot 12 uur. Dat zijn toch 4 uren op een dag die voor mij goed werkten. Laten we die tijd inplannen.

{{< figure src=“/ox-hugo/20240715200322screenshot.png” caption=”Figure 5: Stap 3, tijd om te studeren” >}}

Dat zijn 4 blokken van 4 uur, plus de zaterdagochtend van 3 uurtjes — in totaal 19 uur die beschikbaar zijn om te studeren. Tijdens het inplannen viel meteen op dat de sportsessie op donderdag niet handig uitkwam, dus die heb ik verplaatst naar de ochtend. Met al deze ingeplande studietijd blijft er ook ruimte over voor familie en vrienden, precies op die momenten dat het voor iedereen goed uitkomt.

Wat nu als je geen avondmens bent? Ik begeleid ook studenten tijdens hun afstudeertraject, en sommigen zijn meer een ochtendmens. Zij staan om 5 uur 's ochtends op en studeren tot 7 uur. Dit doen ze vaak omdat ze kleine kinderen hebben en niet willen dat hun partner met alle zorg achterblijft. Zelf geef ik de voorkeur aan de avond, maar goed, ieder zijn ding.

Wanneer het nodig is, bijvoorbeeld als je dicht bij een deadline zit, kun je natuurlijk altijd tijd van een ander blok gebruiken. Doe dat echter altijd in overleg. Het voordeel van alles uitplannen is dat het duidelijkheid schept, maar daardoor ontstaan ook verwachtingen. Als je dan iets verandert, ook al is het tijdelijk, leg het uit zodat je geen problemen krijgt. Ik paste mijn schema vaak aan door naar de studielast van een module te kijken en een studieplan te maken; daarover zal ik later meer schrijven.

Zelf had ik ook nog bonustijd in mijn schema. De zondagochtend was vaak beschikbaar, afhankelijk van hoe mijn zoon naar een bouldersessie keek. Daarnaast had ik 's ochtends vaak nog een uurtje tijd, tussen het moment dat iedereen naar werk en school gaat en dat ik daadwerkelijk aan mijn werk begin. Die tijd gebruikte ik om papers te lezen en mijn eerste aantekeningen te maken. Maar ook daarover zal ik later meer schrijven.

Het “goed” gebruiken van de kalender om tijd te reserveren is natuurlijk niet revolutionair. Er zijn ook andere methoden zoals de “Trident Method” (uitgelegd door Ali Abdaal), en talloze andere technieken om tijd goed in te delen. Maar dit is de methode die voor mij goed werkte.

Hopelijk begin je jouw studietijd nu met een goed systeem om je tijd in te delen. Dit is de eerste stap naar een succesvolle studietijd!

#writing #learnToStudy

This is an English article, there is also a Dutch version.

So, you've decided to start studying? Maybe you want to earn your Bachelor or Master's degree, or perhaps you're aiming for that highly technical certificate. It's great that you're taking this step, but once you begin, you'll quickly need to answer the question of where you'll find the time.

Time is our most valuable, non-renewable resource. Studying requires time – and not just a little – so you naturally want to use it well. Most programs expect you to invest between 12 and 24 hours per week to keep up, and that's quite a bit! If you're not currently studying, try thinking about which days and times you could free up that time. Will you eat out less or exercise less? Get up early on weekends or stay up late?

Most students run into this problem when they start studying; I've seen it all too often. You start your studies with full confidence, only to realize you haven't considered how it fits into your life and what you need to sacrifice to make it work. Many students try to do everything at once, with predictable results. Thankfully, there is a strategy you can apply. I used this strategy during my part-time Bachelor and Master's studies, and it worked perfectly for me.

The core of the strategy is using your calendar. To manage your time effectively, you need to know exactly when you'll do what. This sounds simple, but most people only note important things in their calendar, like dentist appointments or Aunt Loes's birthday.

You do a lot in a day. Personally, I have a 40-hour workweek, go to the gym, spend time with my family, and much more. If I didn't plan these activities, I'd quickly lose track. Without an overview, it becomes difficult to study effectively because suddenly Aunt Loes will show up at the door.

The strategy includes the following steps:

  1. Use a calendar that you can access anywhere.
  2. Block out your work hours and stick to them.
  3. Also block time for your family and friends.
  4. Schedule study sessions.

It doesn't really matter which calendar you use, as long as it's accessible to you. In my examples, I'll use the Proton Calendar because it's secure and based in the EU. This way, you don't have to worry about big tech companies snooping into your schedule.

An empty calendar looks like this:

{{< figure src=“/ox-hugo/20240715193929screenshot.png” caption=”Figure 1: An empty calendar, that's quite calm!” >}}

As you can see, I've given each area of my life its own color. This is super handy because you can immediately see which appointment belongs to which area.

{{< figure src=“/ox-hugo/20240715194152screenshot.png” caption=”Figure 2: Each calendar its own color, though I'm not great at choosing colors.” >}}

As the first step, let's plan the workdays. I already have all my work appointments in my calendar, but I also block my work time with a calendar event. This way, I always know when I am or am not available. If you also have to travel to and from work, plan that time as well. I do this on Wednesdays and Fridays.

{{< figure src=“/ox-hugo/20240715195048screenshot.png” caption=”Figure 3: Step 1, plan your workdays” >}}

This may seem a bit silly because you know you're working, right? Of course, but for the mental model of your available time, it's essential to block this period. This way, you know you can't use that time for studying. See, now it seems like there's still a lot of time left, right?

During my study, I also found it important to reserve time for my family and to do fun things. Studying should be enjoyable and not feel like a punishment that prevents you from doing pleasant activities. Let’s now add all the family and friends' time to the calendar.

{{< figure src=“/ox-hugo/20240715195810screenshot.png” caption=”Figure 4: Step 2, time for family and friends” >}}

Now it's a different story. Weekends were important for me. Everyone works hard during the week, so time is needed to relax together. What's immediately noticeable is that there seems to be relatively little time left for studying, but appearances can be deceiving. I found it very convenient to study in the evenings, from around 8 PM to 12 AM. That's 4 hours in a day that worked well for me. Let's schedule that time.

{{< figure src=“/ox-hugo/20240715200322screenshot.png” caption=”Figure 5: Step 3, time to study” >}}

That amounts to 4 blocks of 4 hours, plus 3 hours on Saturday morning — totaling 19 hours available for studying. While planning, it immediately became apparent that the workout session on Thursday didn't fit well, so I moved it to the morning. With all this scheduled study time, there's also room for family and friends, at times that are often convenient for everyone.

But what if you're not a night owl? I also guide students during their graduation projects, and some are more morning people. They get up at 5 AM and study until 7 AM, often because they have small children and don't want to leave their partner with all the care. Personally, I prefer the evening, but to each their own.

When necessary, such as when a deadline is approaching, you can always borrow time from another block, but always do this in consultation. The advantage of planning everything is that it provides clarity, but it also creates expectations. If you change something, even temporarily, explain it, so you don't run into problems. I often adjusted my schedule by looking at the workload of a module and creating a study plan; I'll write more about that later.

I also had bonus time in my schedule. Sunday morning was often available, depending on my son's interest in a bouldering session. Additionally, I often had an hour in the morning, between when everyone left for work and school and when I started working. I used that time to read papers and make my initial notes. But more on that later.

Using the calendar effectively to reserve time is not revolutionary. There are other methods such as the “Trident Method” (explained by Ali Abdaal), and many other techniques for good time management. But this is the method that worked well for me.

Hopefully, you'll start your study time now with a good system to manage your time. This is the first step towards a successful study period!

#learnToStudy #writing

So, on Thursday I defended my thesis in front of the graduation committee, and passed! This means that the work I have been doing for the last year comes to an end. From now on there are not long nights and weekends working on my thesis anymore.

Back in 2021 I started my journey of achieving a Master's degree, first with a connecting program and then with the 2 year Master program. Even though I have been in computer science in some form for the last 30 years I still found it to be quite a learning experience.

I greatly enjoyed the track on formal verification of systems and found logic quite enjoyable to work with. My least favorite topic was the security course, mainly due to its reliance on a lot of relatively old literature, but that is only a small “unhappiness”. The courses were well structured and very do-able in the time given.

So happy to be free of the work now. Here is to picking up some fun things again!

So, today I have some news. I will be resigning as Ambassador for Hack The Box after our in-person meetup in June (2024). This means that I will be stepping down from organizing the monthly virtual and quarterly in-person Hack The Box meetups. Let me explain how I got to this decision.

The beginning {#the-beginning}

So, in 2019, I started out building a cyber security curriculum for NOVI Hogeschool. I had the ability to greenfield the courses and create something that is of value to students. In this curriculum I started using Hack The Box for exercises and training next to the regular classwork.

As more and more of my students went through the program I thought it would be cool to get together with the community in a meetup. I contacted Hack The Box and after a little work, the Hack The Box NL meetup was born. This was end of February 2020, and we were aiming for our first meetup in April of 2020. As you all know, the world changed in those days and our plans went into the dumpster. Instead we started hosting a monthly online meetup.

Only when our meetup turned 2 were we able to have our first in-person event. For me and my co-hosts it was a great learning experience to understand how to successfully organize an in-person event, from WiFi to the amount of pizza's that a group of hungry cyber-nerds will consume. For the first event we had our great friends from Hack The Box come over and join us. Check out this after-movie to get a sense of the scale and spot my “psycho”-face somewhere in the video.

The community {#the-community}

Since the early days the community has grown so rapidly. At the time of the blog post we are well past the 1800 members and we are growing to 1900! Of course these are not all people that show up at every meetup, but they come and go. Generally an in-peron meetup will have somewhere between 50 and 100 people attending. Our online meetups will have about 30 to 50 people RSVP-ing to join.

{{< figure src=“/ox-hugo/meetup-christmas-scaled.jpg” caption=”Figure 1: Christmas meetups require a \“foute\” christmas sweater” >}}

The community is full of regulars, people that only swing by for the in-person meetups, and people that just try to figure out if cyber security is a fit for them. I loved meeting every single one of you all. It was such an experience to see friendships grow, skill-sets expand and people step up to actually present in front of a crowd.

Making Friends {#making-friends}

The very first person to ever log into the meetup was @GevuldCookie. She entered the zoom call when I was anxiously waiting for somebody to actually show up. In the same first meetup @DutchPyro joined and after some chatting and exchanging ideas we have been organizing the discord and meetups together ever since. A few years in and @Salp joined as a co-organizer.

Earlier this year we even had our first meetup-baby being born. How special is that?

As the meetup has been online most of the time I have made friends all over the globe, from Egypt to India, from South Africa to Ottowa. It has been quite extraordinary. Charles, from the Texas meetup, dropped by in Utrecht while on holiday in Europe. I went to Lissabon and met up with Pedro and we became such good friends.

{{< figure src=“/ox-hugo/pedro.jpg” caption=”Figure 2: Meeting up with Pedro in Portugal” >}}

The list of people that have meant something to me and the meetup is extremely long, from Hack The Box we have had Soti, Kristi, Stella, Emma, Austin, Shaun, Bran and so many more. We also have had a quite large regular group of people joining every month. I started listing names here, but that entire list would be so long and I would certainly forget specific people. So just know that if you were a regular I loved the time that I spent with you!

The cost of a meetup {#the-cost-of-a-meetup}

As a meetup we were extremely lucky that NOVI flipped the bill for our in-person events. Imagine ordering 40 to 60 pizza's at your favorite place.... But the cost of organizing is much greater then just that, the amount of personal time that I have spent working on getting the meetups together, chasing down guests and getting things organized is quite something and this is exactly the point where it breaks for me.

After more then 4 years constantly worrying and working on the meetup, even planning my own family life around the meetups (I kid you not, we planned our family holidays so that they did not conflict with the meetups), it has been enough.

Being so involved has taken the joy out of Hack The Box for me, a price I have gladly paid, but a joy which I would like to get back. So for me that means stepping back, letting other people pick up a great meetup and giving it a bright new future.

The end {#the-end}

Every beginning must have an end, and an end makes way to new beginnings. So does this step. Yes, the Hack The Box meetups are over for me after the June meetup, but with NOVI I will continue working for our community. I will continue being involved in the Hack The Box community in various ways, just not organizing monthly meetups.

We (NOVI) already host a weekly hacking session on Friday morning where we tackle Hack The Box machines and other types of challenges. Besides that we organize many different types of workshops and events across the areas of our curriculum (cyber security, development and business).

In the next year we will be hosting a quarterly event dedicated to security in a broader sense, and crossing over to the development realm. These events will line up with our starting moments in the school year. You can stay in the loop by registering on our meetup (https://www.meetup.com/workshops-novi-hogeschool/) page or follow me on LinkedIn (https://www.linkedin.com/in/credmp/).

As I am stepping back from my work on the Dutch Hack The Box meetup I am looking forward to exploring new events and opportunities to teach people about this wonderful field.

Last week I was a guest on the Cyber Cafe podcast by rootsec. It was a fun discussion on education and the current xz backdoor story. It is in the Dutch language. It is available on youtube and included below:

This post is just a small note for those of you who also run Microsoft Teams on Linux through their browser and now receive a note “your browser does not meet the requirements for the new Teams”. It turns out that the client is looking at the user-agent string to determine which browsers it accepts, and which not.

So, if you have the message, install an user-agent switcher and select a common browser on a common OS (from the MS perspective) and you will suddenly meet the requirements.

This is a longer form article. I is relevant as of February 18th 2023. If the circumstances of my environment changes I will try to update this article to reflect the situation. You can find the full source code of my dotfiles on Github.

I like consistency and simplicity. I do not like to use many different tools to do different things, I rather spend my time learning to use a few tools very well then to follow the hype on the latest trend of tools for something we have been doing forever.

This philosophy I transfer to pretty much everything in life. I have been using the same laptop bag for ages, I have a small mechanical keyboard, and I run the same version of my OS on all my devices. One device for on the go, the other for at home. They look the same and act the same, courtesy of an Linux distribution called NixOS.

Below you will find 2 screenshots, one from my laptop, the other from my desktop. The only difference is the size of the screen.

{{< figure src=“/ox-hugo/desktop.png” caption=”Figure 1: My Linux desktop on my laptop” >}}

{{< figure src=“/ox-hugo/desktop-large.png” caption=”Figure 2: My Linux desktop on my desktop” >}}

NixOS {#nixos}

I use the NixOS distribution of Linux. NixOS is a wonderful operating system that works by declaring what you want your environment to be and then applying that declaration to the current version of the environment. That sounds difficult, but let me explain.

Suppose you have just installed a Linux distribution and you want to install the wonderful Emacs editor. In most distributions you will go to the package manager, search for Emacs and click on install. A few seconds later, Emacs is installed. With NixOS you edit a file that describes your environment, you will add a line to it saying that Emacs is part of your environment. When you have saved the file you will ask NixOS to create a new version of your environment, to do so it will install Emacs for you.

I say it will create a new version of your environment. This means there is an old version as well, right? Yes! NixOS has a concept of Generations. This means every change happens in its own version of the environment. So, if a change goes wrong, you just revert back to the previous version.

This sounds like a great deal of work, and it is. It is not for the new Linux user, that is for sure. If you spend some time learning NixOS I am sure you will be grateful for it. Just the other day I tried to use the wayland system on Linux, my configuration went horribly wrong and I was left with an unusable system. I rebooted the machine, selected the previous generation, and I was back where I started before the change. It is that useful!

As I share my configuration over multiple machines I split up the configuration into a machine specific version to my desktop, laptop, and the things that should run on both:

The shared configuration contains all the juice, it sets up the graphical user interface, creates users and assigns to groups. This means that when you run this configuration you will end up in a very barren i3 tiling window manager. More on that later.

Most of my applications are courtesy of something called home-manager. This is a user-space application that allows for easy changes to the environment. As none of these changes can actually wreck the environment I kept them outside of the default NixOS configuration.

My home-manager configuration takes care of installing all the user-space tools that I use. It also sets up my shell and configures the Emacs daemon.

You might wonder, do you create a configuration file every time you need a tool? No! When I just need a one-off tool I use something called nix-shell. In the screenshots above you will notice that I run neo-fetch. This program is not part of my normal system as I only use it for screenshots as the one above. Within a terminal I run it as follows: nix-shell -p neofetch --run neofetch. This will temporarily install neo-fetch and run it. Afterwards it can be cleaned up. I also do this for most of the tools, such as unzip. I only install then when I need them. This keeps everything that is installed very clean.

You might also notice that there are not programming language toolchains in my configuration. That is correct. When I have a programming project I use something called direnv, see the direnv webpage for some background.

Whenever I start a new programming project I run the following command in the project root: nix --extra-experimental-features "nix-command flakes" flake new -t github:nix-community/nix-direnv .. This will create a flake.nix file in which I can declare what this project needs as dependencies. As the rest of my environment is extremely clean, I will need to specify precisely what is needed. Take the listing below, it is part of a programming project in which I use Rust, Golang, Python and Java. Whenever I move into this project, all the tools will be installed. This also means that it works exactly the same on every single system where I use this setup.

{
  description = "A basic flake with a shell";
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
  inputs.flake-utils.url = "github:numtide/flake-utils";

  outputs = { self, nixpkgs, flake-utils }:
    flake-utils.lib.eachDefaultSystem (system: let
      pkgs = nixpkgs.legacyPackages.${system};
    in {
      devShells.default = pkgs.mkShell {
        packages = with pkgs; [
          pkg-config
          openssl.dev
          cargo
          rustc
          rustfmt
          clippy
          rust-analyzer
          aoc-cli
          go
          gopls
          gotools
          govulncheck
          pkgs.jdk
          pkgs.jdt-language-server
          pkgs.python311
        ];
        # Environment variable specifying the plugin directory of
        # the language server 'jdtls'.
        JDTLS_PATH = "${pkgs.jdt-language-server}/share/java";
      };
    });
}
Code Snippet 1: A nix-direnv declaration for a polyglot programming project

This might seem like a hassle. It is true, it is more work then just installing Golang on Ubuntu and “just having it”. But once you use multiple systems or work together in groups you will start appreciating it, trust me.

i3 {#i3}

As I like simplicity I tend to not use elaborate windowing environments, such as Gnome or KDE. I try them out every once in a while, but I also go back to i3. Back in the day I ran enlightenment, but now I have been using i3 WM for quite some years. My configuration is quite mature and I generally only change it when I want to add a new tool to my daily use, or when tools get good updates such as polybar. The configuration is part of my dotfiles.

When I boot my system all I have is a top bar that contains the following information:

  • 💻 Active workspaces (each has its own icon and use)
  • 💾 Current fill state of my disks
  • 🛡️ VPN status
  • 🔊 Sound and its volume percentage
  • 🛜 Wifi state (laptop only)
  • 🔋 Battery state (laptop only)
  • ⏰ Time
  • 📥 Tray icons (flameshot, bluetooth and nextcloud)

That is it. After all those years working with computers, that is all I really need. If I could I would write a toggle for the bar as well, to only show up when needed. The very appealing thing about i3 is its tiling feature. I will never have windows that overlap. Everything is neatly ordered in workspaces and within workspaces in columns or rows. As I create dedicated workspaces everything has a specific place:

  1. Terminal (alacritty with tmux)
  2. Emacs
  3. Virtual Machines
  4. Firefox
  5. Chrome

From workspace 6 on I consider them “throw-away” workspaces. The things I will store there will be used only shortly. The exception is workspace 10 (or 0). This contains my Spotify.

To launch applications I use something called Rofi. It is a window switcher, application launcher and menu replacement tool. It is very easy to customize and you can make it exactly what you want. My configuration is available on github.

{{< figure src=“/ox-hugo/rofi.png” caption=”Figure 3: Rofi launching applications in i3” >}}

You can configure your environment exactly as you want. Take a look at r/unixporn for some more extreme versions of customized desktops.

#emacs #development #writing

It has been a little while. I have been swamped with work and the work on my thesis, leaving no room to finish the Advent of Code or much of anything else.

Yesterday I gave my practice presentation for my thesis. This means I am one more step closer to the finish line. During the day there were many interactions with fellow students. One of the topics has been the templates to use at Open Universiteit. So, I thought I would just create a repository of the templates that I use, so that anyone can learn from them.

The repository is here: https://github.com/credmp/ou-templates

The weekend generally is a place to find hard puzzles again, this time not so much. A simple quest to find the next number in a sequence with a fully written out algorithm to follow. They key here is to use recursion.

package main

import (
	"fmt"
	"time"

	"arjenwiersma.nl/aoc/internal/aoc"
)

func NextStep(in []int) int {
	allZero := true

	for _, v := range in {
		if v != 0 {
			allZero = false
		}
	}

	if allZero {
		return 0
	}

	var diffs []int
	for i := 1; i < len(in); i++ {
		diffs = append(diffs, in[i]-in[i-1])
	}

	p := NextStep(diffs)
	return in[len(in)-1] + p
}

func main() {
	content := aoc.AsLines("2023/Day09/input.txt")

	var lines [][]int
	for _, v := range content {
		lines = append(lines, aoc.AsNumbers(v))
	}

	startTime := time.Now()

	var res []int
	for _, v := range lines {
		res = append(res, NextStep(v))
	}

	r := aoc.SumArray(res)
	endTime := time.Now()
	elapsed := endTime.Sub(startTime)
	fmt.Printf("Part 1: %d (%v)\n", r, elapsed)

	startTime = time.Now()

	for _, v := range lines {
		aoc.Reverse(v)
	}

	res = []int{}
	for _, v := range lines {
		res = append(res, NextStep(v))
	}

	r = aoc.SumArray(res)
	endTime = time.Now()
	elapsed = endTime.Sub(startTime)
	fmt.Printf("Part 2: %d (%v)\n", r, elapsed)
}

Somewhat suspicious of 2 easy days we end up at Day 8. A simple map to follow again, from one key follow the instructions until we hit ZZZ. Part 2 had us do it for several keys at once, with the goal to find the spot where they all converge. This can take forever, erhm, a long time.

So there has to be a math type solution to this problem. It turns out to be a Least Common Multiple problem. It is the smallest positive integer that is divisible by two or more numbers without leaving a remainder. To find the LCM of two or more numbers, you can use a method called prime factorization or a simpler approach involving multiples. We can also use the Greatest Common Divisor (GCD) to find the LCM.

LCM(a, b) = (a * b) / GCD(a, b)

Example: Find the LCM of 12 and 18 using their GCD.

Step 1: Find the GCD of 12 and 18.

  • You can use methods like prime factorization or the Euclidean algorithm to find the GCD.
  • GCD(12, 18) = 6

Step 2: Use the formula to find the LCM.

LCM(12, 18) = (12 * 18) / 6 = 216 / 6 = 36

So, the LCM of 12 and 18 is 36.

package main

import (
	"fmt"
	"strings"
	"time"

	"arjenwiersma.nl/aoc/internal/aoc"
)

func LCM(numbers []int) int {
	result := numbers[0]
	for i := 1; i < len(numbers); i++ {
		result = (result * numbers[i]) / GCD(result, numbers[i])
	}
	return result
}

func GCD(a, b int) int {
	if b == 0 {
		return a
	}
	return GCD(b, a%b)
}

func solve(s string, instr string, m map[string][]string, p2 bool) int {
	steps := 0
	for {
		d := 0
		if string(instr[steps%len(instr)]) == "R" {
			d = 1
		}

		if !p2 && s == "ZZZ" {
			break
		}
		if p2 && s[2] == 'Z' {
			break
		}

		s = m[s][d]

		steps += 1
	}
	return steps
}
func main() {
	content := aoc.AsLines("2023/Day08/input.txt")

	instr := content[0]
	m := make(map[string][]string)

	for _, v := range content[2:] {
		n := strings.Split(v, " = ")
		lr := strings.Split(n[1], ",")

		m[n[0]] = []string{strings.TrimSpace(lr[0][1:]), strings.TrimSpace(lr[1][:len(lr[1])-1])}
	}

	startTime := time.Now()

	steps := solve("AAA", instr, m, false)

	endTime := time.Now()
	elapsed := endTime.Sub(startTime)
	fmt.Printf("Part 1: %d (%v)\n", steps, elapsed)

	startTime = time.Now()

	var solves []int
	for k := range m {
		if k[2] == 'A' {
			solves = append(solves, solve(k, instr, m, true))
		}
	}

	// do stuff
	endTime = time.Now()
	elapsed = endTime.Sub(startTime)
	fmt.Printf("Part 2: %d (%v)\n", LCM(solves), elapsed)
}