building an adding machine in a prison building game

[ linkstandalone ]

Building an adding machine in a prison building game

As of late, I really got into Prison Architect. It’s a fantastic game - you get to plan your own prison just the way you like, decorate it and then see how it fares when ‘actual’ prisoners are living there. Also, its DLCs are somewhat fair-priced, which isn’t usually the case with Paradox’s games. I wanted to do something unique to express my appreciation of the game, so I built a simple calculator in it.

The plan

Luckily, the game features a logic gate system, so we don’t need to figure out how to simulate one using game mechanics. There’s also a ‘status light’ object which lights up when it receives a signal, so we’ll use that as a building block of a display. There’s no way of cloning logic gates etc. with its connections to other utilities, so since I don’t really want to spend eons on connecting magical boxes in a video game (yet?), we’ll limit our calculator’s capabilities to adding two numbers with two binary coded decimal digits. That means our calculator will be able to add 99 and 99 at most, so we’ll actually need three digits on the result display (something I’d figured out way after I built the displays and connected them…).

I picked BCD as the encoding, because the only way of displaying plain binary numbers in decimal I could figure out was to connect each possible combinations of bits to AND and NOR gates, then connect the NOR gate to the AND gate, to then connect the AND gate to the display in a proper way. That means I’d have to mindlessly map about 99 + 99 + 198 = 396 possible outcomes onto the displays. With BCD, the number of possibilities goes down to 10 + 10 + 10 + 10 + 1 + 10 + 10 = 61, since I only need to connect each digit representation with its display and the first digit of the result number can only be either 1 or 0.

You can add BCD digits with conventional binary adders, but you might need to convert them later by adding six to the result and sending the carry bit to the next digit’s adders (if that makes sense). Since each BCD digit uses four bits, in order to add the digits, we’ll need four full adders connected together forming a ripple carry adder (I think). Although four adders is enough, our big adder will consist of five small adders, since if the last adder outputs a carry bit, we will have an integer overflow. The additional circuit allows us to incorporate the bit into the computation’s result. Later, we’ll setup a bunch of NOR gates connected with AND gates, which will be connected to the output of the big adders, that will output signal to another set of two big adders that will preform the conversion, if required.

Normally we’d need some-kind of a flip-flops to build a keyboard with, but the game features an object that emits signal constantly, so we’ll just use it.

Adders

We can easily implement a full adder with the game’s logic gates. We can then place four more adders underneath it, connecting them together to form the big guy. Since, for some reason, most in-game emitters send a high signal by default, we should also connect a turned off lever to the first adder’s carry input gates, and two turned off levers to the ‘screw overflow’ adder’s input. We also connect each adders output (the XOR gate) to a corresponding light at the bottom. We could directly connect the outputs to the next part, but I think it would make the build less clear (click the image to rotate)


how the adders look in-game


Next, I connected the lights to a bunch of NOR and AND gates, and these to an OR gate, so that the ‘circuit’ outputs signal only if the output lights form a binary number that is greater than nine. The signal then turns on the switches that are connected to a next big adder that adds six to a digit only when a high signal is emitted. However, these adders are different from the previous ones, because the final adder of the first big adder passes its carry bit to the first full adder of the next ripple carry adder. And the last full adder of the second big adder passes its carry bit to the leftmost bit of the output.


how the converter looks in-game


Screen

The display is a straightforward beast: the rows of lights under the BCD converter are appropriately mapped to a bunch of NOR and AND gates, the NOR gates are inputted into the appropriate AND, so that when the AND gate emits a signal, lights corresponding to the appropriate digit light up:


the screen, displaying number 57


The light that corresponds to the hundreds digit of the sum is directly connected to the display, since it doesn’t need this kind of a dashboard.

Demonstration



birds view of the construction


Since I don’t really know much about electronics, feel free to contact me if you think there’s an error in the article or if you feel like something is badly worded.

simple code generator

[ linkstandalone ]

simple code generator

Last semester I was taking a mandatory "Programming 101" course, aka. drawing stairs made out of stars and watching my classmates struggle with basic tasks, the course - a time truly well spent. Even though the course problems weren’t too enlightening, the silliness of one of the tasks’ requirements gave me a chance to write a simple code generator.

Problem

Without using an associative table (they weren’t covered in class), write a program that encodes a message using morse code. The characters should map as follow (yes, a picture; who needs copy-paste anyway?):


ASCII to morse mapping


Implementation

First, I looked online for the table in a text format, downloaded it and, using a vim macro, formatted it so that each line would contain one of the ASCII symbols and its Morse representation separated by a space. Since I wanted to use envsubst, I created a file like so:

    else if (morse_representation == "${CASE}") {
        return '${VALUE}'
    }

Then, I wrote a script that reads each line from the ‘translation file’, and places the Morse representation inside the if’s condition and the ASCII symbol next to the return statement:

    #!/usr/bin/env sh
    while read line; do
        line=($line)
        export CASE=${line[1]}
        export VALUE=${line[0]}
        truncate -s-1 from_morse_code.cc
        envsubst < switch_case.cc >> from_morse_code.cc
    done < morse_code.txt

I ran it, ran it again with the values of the CASE and VALUE variables switched as to generate the other way translation, removed the unneeded elses at the bottom, copy-pasted the big if chains into the file where I would write the wrapper code... and voila! An hour of time was just saved (if you’re not counting the hour it took me to write this lol)!

website update 2

[ linkstandalone ]

website update 2

  1. the site’s layout was completely overhauled, see for yourself
  2. there’s fancy, new, CSS only ‘slider’ on the bookmarks page
  3. added a table of contents to the rolling blog page
  4. added a light and a dark theme throught CSS, how to enable dark mode in Chromium
  5. fixed RSS’ date attribute on posts
  6. broke RSS - old posts may appear as new
  7. website’s RSS will be moved to here
  8. the ‘link’ buttons on the blog page now takes you to the article’s title
  9. the posts are now written in markdown and then converted with pandoc to HTML so you can read them in plain markdown under /files/markdown/posts/POST-NAME, here’s this post If you really want, you can even read them in PDF, assuming pandoc and zathura are installed:
    pandoc -o - --to pdf --from markdown https://jacadzaca.github.io/files/markdown/posts/website_update_2.md | zathura -
  1. reworded the dark mode article
  2. there’s a donation page now

Criticism or ideas are welcome.

generating a maths worksheet

[ linkstandalone ]

generating a maths worksheet

Inspiration

When you get a maths worksheet, it usually comes with the answers to the problems from each section, so you can check your work - pretty nifty. However, it turns out that’s not the way they do it at my university. Passing semester, I had to trudge through a ton of answerless worksheets, which made studying much more time-consuming, since I had to spend extra minute or two per example inputting the equation into Symbolab, or googling for the solution. Let for minor annoyances, when I couldn’t input some problem into Symbolab or when it spouted out gibberish, I finished the semester less than unharmed - I got inspired. Leaving the question of whether not handing out answer-sheets was just a big psyop by my instructors to to force students into creating study groups for another time, I decided I would generate my own worksheets (without blackjack and hookers... sadly).

How?

Wolfram’s Problem Generator claims to be using AI to generate the problem sheets, mathsbot probably uses some database of predefined questions. Shouldn’t writing a maths worksheet generator be complicated? or at least time consuming? Also, don’t you need someone to handout answers? With the right software and mindset - no, no and no. If we think about it, maths worksheets are just permutations of different symbols. We can generate these just fine, for example with python’s itertools or random module. Now, since a worksheet usually comes with an answers section, we will also be needing a way of evaluating the generated expressions, luckily there’s a whole bunch of software that dose this, for example, sympy. To present the worksheets we can generate a LaTeX document via jinja and then compile it with, for example, pdflatex.

Implementation

For simplicity, we’ll write a quadratics worksheet generator. First, we’ll need a function that spouts out quadratics, we would like the generator to:

  1. differentiate quadratics on basis of the number of solutions, because a worksheet with, for example, only two solutions quadratics would be boring/incomprehensive,
  2. ensure that the quadratic’s coefficients are not to crazy - in the end it’s humans that will be solving the equations.

To achieve the first goal, we’ll split the function into three. Second one will require making some simple observations:

  1. it’s more difficult to randomize fraction coefficents, so random coefficients will only be integers,
  2. coefficients should be bounded,
  3. it’s easier to generate positive integers and then to pick a sign
  4. we know that a quadratic has two solutions, if and only if its discriminant is positive, so given a quadratic of the form: ax2 + bx + c ∧ a ≠ 0, with two different solutions, we can write: b24a > c. Since we are looking for an integer upper-bound for a and c, lets set c > 2, therefore b28 > a,
  5. for a quadratic to have one solution, it’s discriminant must equal zero, so if we pick a and c, b = √4ac, since this could produe complicated coefficients, let’s require a and c to be perfect squares.

Figuring out bounds for no-solutions quadratics is left as an exercise for the reader. Translating the observations into python code:

    import math
    import sympy
    import random

    SIGN = [-1, 1]

    def generate_quadratic_two_solutions(max_coefficient=20):
        b = random.randint(3, max_coefficient)
        a = random.randint(1, (b**2)//8)
        c = random.randint(1, (b**2)//(4*a))
        return sympy.sympify(f'{a}*x**2 + {b}*x + {c}')

    def generate_quadratic_one_solution(max_coefficient=20):
        sign = random.choice(SIGN)
        a, c = sign * random.randint(1, max_coefficient)**2, sign * random.randint(1, max_coefficient)**2
        b = int(math.sqrt(4*a*c))
        return sympy.sympify(f'{a}*x**2 + {b}*x + {c}')

    def generate_quadratic_zero_solutions(max_coefficient=20):
        sign = random.choice(SIGN)
        a, c = sign * random.randint(1, max_coefficient), sign * random.randint(1, max_coefficient)
        b = math.sqrt(random.randint(1, math.floor(math.sqrt(4*a*c))))
        b = sympy.Rational(str(math.trunc(b * 10)/10))
        return sympy.sympify(f'{a}*x**2 + {b}*x + {c}')

Wait a minute, problems in a worksheet are usually ordered by difficulty - the further the problem, the more difficult it is. I couldn’t come up with any solid way of evaluating a quadratic’s difficulty, based on it’s coefficients, so I went with:

    def quadratic_difficulty_comperator(x):
        return sum(x.as_coefficients_dict().values())

Now onto generating a LaTeX document. Luckily, sympy has a built-in LaTeX converter, so we’ll only need to instiate jinja and put toghether a template:

    #!/usr/bin/env python3
    import math
    import random
    import collections

    import sympy
    from jinja2 import Environment, FileSystemLoader

    #...quadratic generating code ommited for breviety...#


    Task = collections.namedtuple('Task', ['instruction', 'problems', 'awnsers'])

    ENV = Environment(
        loader=FileSystemLoader('.'),
        trim_blocks=True,
        lstrip_blocks=True)

    def main():
        # generate diffrent kinds of quadratic equations
        zero_solutions_quadratics = [quadratics.generate_quadratic_zero_solutions() for _ in range(10)]
        one_solution_quadratics = [quadratics.generate_quadratic_one_solution() for _ in range(10)]
        two_solutions_quadratics = [quadratics.generate_quadratic_two_solutions() for _ in range(6)]
        # sort them according to 'difficulty' - the greater the sum of quadratic's coefficients, the more difficult it is
        zero_solutions_quadratics.sort(key=quadratics.quadratic_difficulty_comperator)
        one_solution_quadratics.sort(key=quadratics.quadratic_difficulty_comperator)
        two_solutions_quadratics.sort(key=quadratics.quadratic_difficulty_comperator)

        # arrange the problems in random order, but try to keep the problems' difficulty incremental
        problem_lists = [zero_solutions_quadratics, one_solution_quadratics, two_solutions_quadratics]
        problems = []
        for _ in range(len(zero_solutions_quadratics) + len(one_solution_quadratics) + len(two_solutions_quadratics)):
            choice = random.choice(problem_lists)
            problems.append(choice.pop())
            if not choice:
                problem_lists.remove(choice)

        # generate the awnsers with sympy https://docs.sympy.org/latest/index.html
        awnsers = (sympy.printing.latex((sympy.solvers.solveset(quadratic, domain=sympy.S.Reals))) for quadratic in problems)
        # convert into LaTeX
        problems = map(sympy.printing.latex, problems)

        #output latex code
        latex = ENV.get_template('problem_sheet.jinja.tex').render(tasks=[Task('Find the roots of function $f$, given by expression:', problems, awnsers)])
        print(latex)

    if __name__ == '__main__':
        main()

To compile and view the document, we can use:

    ./worksheet.py | pdflatex --jobname worksheet --output-directory /tmp && zathura /tmp/worksheet.pdf

More

Slightly modifed version of this script can be found here, along with scripts generating worksheets on differentiation, integration and limits. Example worksheet generated with the script can be found here. If you write a simillar script on some other math topic, for exmaple function graphing or trig equations, feel free to issue a pull request :). I will also gladly accept links to simillar repositories and include them in zadanko’s README.

website update

[ linkstandalone ]

website update

  1. there’s a link to my Codeberg account on my homepage now
  2. all contact info was moved into the ‘Contact’ drop-down menu on the
  3. I’ve replaced the ‘webring’ page with a ‘Links’ drop-down menu on my homepage
  4. images’ backgrounds now fit the blog’s color scheme (e.g. they’re black)
  5. nearly all images were converted from PNGs into AVIFs
  6. images on the blog page are now loaded lazily
  7. I’ve changed my avatar (I still have a copy of the silly badger - don’t worry)
  8. I’ve added an favicon
  9. mathematical equations are now rendered with an SVG image
  10. code snippets are now syntax-highlighted with pygments
  11. ‘long’ code line are now wrapped
  12. I’ve added OpenGraph, favicon [1] and some other metadata tags. There’s also a manifest.json file now (this means you should be able to add this blog to your smartphone’s home-screen)

hacking a warcraft 3 map

[ linkstandalone ]

hacking a Warcraft 3 map

I’m a big Warcraft fan. Actually, I consider Warcraft 3 to be the best video game of all time. I like the story, the voice-acting (polish voice-over was great until Reforged), and the music fits game-play. But what’s best about Warcraft 3 is its universal game engine that combined with the powerful game editor would lead to creation of many unique mods. Of course, I have my favorite: a polish modification called Alchemicy - a combination of a hero defense and a crafting game. Although the mod is loads of fun, one aspect of it always bugged me: there are characters that you can only play as after either making a donation to the author or if you know him in-game. What’s more, the donation service was shut-down in 2012 with the guy quting the game. Since the map is protected, meaning nobody can open the mod file in the editor, the characters seemed to have been lost to the sands of time... Until I figured out a way to produce a patch that removes the paywall.

Protections, how do they work?

First, a brief introduction to the Warcraft map file format (w3x). For my purposes, every Warcraft 3 mod is basically an archive (see here for proper docs) that contains a few files, each relating to different aspects of the mod. Certain files (from now on - header files) only carry data that’s required by the game editor to open up the map, other files are mandatory (for example, the map file), there also might be some auxiliary files; most probably custom models, icons or sounds. What’s crucial is that each file contains information that allows a human to identify it (e.g, the file defining custom units contains units’ names, hitpoints etc.)

All map protection software dose is remove the header files, therefore making the editor crush each time you try to open a protected map with it. It also removes the MPQ’s (name of the archiving format) listfile, therefore obfuscating files’ names.

The plan

Since I’m familiar with the Warcraft ecosystem, a glance at the map in-game revealed that there must be a certain upgrade that is granted to all ‘premium’ users. Since all of the custom upgrades are in the war3map.w3q file, I figured that all I need to do is:

identify the .w3q file

byte patch the mod-file directly or:

  1. convert the file into editable form
  2. make applicable changes
  3. convert the file back and patch the mod-file using an editor

Sadly, this approach doesn’t work, because:

  1. files in the MPQ are somehow compressed, so you cannot byte-patch them directly
  2. the MPQ’s listfile is gone, so you cannot add new files. You cannot replace a file without adding a file
  3. the .w3q files only cotains the upgrade’s definition (ID, description etc). The correct place to apply the patch is in the war3map.w3u file

Luckily, the new insight allowed me to conjure an approach that works:

  1. acquire a Warcraft map with a listfile - a template
  2. extract and identify the files inside the Alchemicy mod file
  3. make applicable changes to the war3map.w3u file
  4. replace the files inside the template with the ones extracted

We are going to need:

  1. the MPQ editor (it runs under Wine) to both extract, and overwrite files found in a .w3x file
  2. this w3x parser to identify the files
  3. Alchemicy map file
  4. a 128 by 128, Cityscape tileset, Warcraft map to use as a template

The implementation

First, I downloaded one of my old, unfinished maps for a template. Then, I created two directories: identified-files and unidentified-files and extracted all files from the map (save for .blp and .mdx files) into the second one. Second, I noticed that it’s possible to identify few of the files just by either looking at them or by opening them in your favorite text editor:

  1. since File00000000.w3e has an extension, it’s probably the war3map.w3e file
  2. by comparsion with your template map, File00000001.xxx is the war3map.w3i file
  3. since File00000002.xxx is fillied with strings, it must be the war3map.wts file
  4. since File00000003.xxx looks like computer code, it must be the war3map.j file
  5. since File00000007.wpm has an extension, it’s probably the war3map.wpm file
  6. the File0000000008.doo is either the the war3map.doo or the war3mapUnits.doo
  7. by comparsion with your template map, File00000015.xxx is the war3mapMisc.txt file
  8. by comparsion with your template map, File00000016.xxx is the war3mapExtra.txt file

I renamed the identified files and moved them into the other directory. I also ran this example script that is provided by the parser to figure out that the .doo file is the war3Map.doo file. Nearly all other files can be identified using this script, after applying this ‘patch’ inside the WC3MapTranslator/examples/warToJson directory:

find . -name '*js' -exec sed -i -e 's|fs.writeFileSync(jsonPath, |console.log(|g' {} \;

File00000004, File00000006 and File00000012 couldn’t be parsed into anything sensible. I would later figure out that (using a method of trail and error) File00000004 is the .shd file and that File00000006 is the .mmp file. I couldn’t figure what File00000012 is.

Thirdly, I would convert both the .w3q and the .w3u file into JSON and compare them:


a side-by-side comparision of JSON representation of the .w3q and .w3u


I figured that the simplest solution would be to blank-out the value record with:

sed -i -e 's|R000||g' units.json

Then, I would convert the edited JSON back into a .w3u file and continue as planned.

Conclusions

Although the patch works (see [1]), it’s somehow rough around (points [2-5]) the edges:


a side-by-side comparison of original Alchemicy map and its ‘hacked’ version


I also think it’s also worth mentioning that:

although my way of identifying the files works, it turns out that MPQ Editor automates this process.

although the patched map can be opened in the editor, the game crushes when I try to launch the map

there exist a program that can automate the whole process, but:

  1. it’s literally a sketchy, Russian program from the internet
  2. I’ve never seen any explanation of it’s inner workings

I later used the MPQ Editor’s Name Scanner feature to fix issues [2-5], it turns out that:

  1. File00000016 is actually war3mapSkin.txt - renaming the file fixes [2] and [4]
  2. one of the .blp files was the wa3mapMap.blp - including this file in the patch fixes [3]
  3. other .blp and .mdx files were custom models/icons - including them in the patch fixes [5]

warcraft3mapUnit.doo is a header file

are landlords cringe

[ linkstandalone ]

are landlords cringe?

I’ve noticed that the contempt for landlords (example in polish) has recently reached a new level - landlord being are equated with social parasites, who are going to cause an overpopulation crisis in literal hell. Surely, behind such brutal rhetoric stands some merit?

Landlords bad!1!1!

Landlords are said not to do any work - they just siphon others’ efforts. If you and your landlord earn a similar wage and you’re both saving for a new flat, it’s going to be your landlord that can buy it first, although they already have a place of their own. Albeit, a landlord makes sure your apartment is a decent place to live (e.g they call in a plumber once in a while) it doesn’t lessens their parasitism, because then they become a redundant middleman (it’s not rocket science to call a plumber). Some might claim that becoming a landlord actually requires much effort - you must take risk, familiarize yourself with the appropriate laws, go around searching for a property etc. but why someone should bother with it all? Can’t we organize into housing cooperatives or establish a government monopoly on rentiership and thus socialize the trouble?

Landlords bad?

Imagine you’re moving into city of Ekslandia - let’s say you’ve landed a job opportunity there. You’re pretty sure that you won’t stay in Ekslandia for more than N years. Sadly, all of the established housing cooperatives are already full (they provide high quality housing, so nobody want to leave) and the ongoing initiatives either will take more than N years to provide you with a quarter (establishing an organization is not a timely process) or are not welcoming of total strangers that hardly have a job in the city housing coops are allowed to select who’s to live with them). You try applying for social housing, but it turns out that it favors people with turbulent past. Running out of options (and since people on the internet told you that all landlords do is exploit), you want to take out a loan and buy an apartment. You meet up with your financial adviser and he tells you that the loan over the N years that you plan to stay in the city will cost you X, however he also mentions that due to the growth of available housing alternatives, the typical rent has fallen drastically and it wouldn’t be hard to find a similar apartment that over the next N years will only cost you (X - 1). Since everyone can subtract, you quickly figure out that by renting you could actually save one unit of value… Since when does being exploited saves you money?

Landlord good???

Although the above story lays down a rather specific scenario (all ‘better’ options are unavailable, renting is cheaper etc.) and thus is not very convincing, it’s still a scenario that seems to presume most of the skeptics’ propositions, while allowing a landlord to contribute to a society. Basically, what a landlord does is allowing the tenant not to buy an apartment; if we were to let go of some skeptics’ tenets, e.g that housing coops are always more economically efficient, we could ask whether the landlord doesn’t produce value by elevating the tenant from the chore of attending coop’s board meetings? Surly, if someone is attending a board meeting they are not, for example, spending time with their family. Summarizing, we cannot conclude whether landlords are cringe and useless ex offico - when a landlord grants you affordable accommodation they are not cringe otherwise they probably are.

other way to find sin of 18

[ linkstandalone ]

other way of finding sin of 18 degrees

It turns out that you can find the value of sin(18°) by the following method:

Notice that by the sin addition formula: Also: Moreover, by the double cosine formula: Now use the Pythagorean identity like this: Now equate the right-hand side of equation 2° with the right-hand side of statement 1°, and substitute for cos(36°): Notice that for t = 1 the equation is satisfied, so: Now notice that 1 > t > 0, because sin(x) is an increasing function when 90 > x > 0 and sin(90°) = 1 > sin(18°) > sin(0°) = 0, so t = sin(18°) = (-1 + √5)4 , since that’s the only solutions that meets the criteria

While this method works, it’s not easy to come up with the first equation. I stumbled on it by pure coincidence. I personally prefer the geometrical way of finding the value of sin(18), because it strikes me as the more obvious way of doing it.

how sin is computed

[ linkstandalone ]

how sin is computed?

I can recall the first time I wrote a program that used a trigonometric function - it was back in secondary school. I was making a game and wanted to make some object float around another. Back then, I didn’t know what trig functions were and how they worked, so I copied some code from the web and, to my astonishment, it worked. I got curious how these functions worked, so I pressed F3 in my IDE and tried to look for the source code of Math.sin. I can’t remember whether I found the code and didn’t understand it or whether I couldn’t find the implementation at all. It doesn’t really matter. What dose, is that back then I swore to myself that one day I will implement my own sin function. Two days ago, I’ve learned about Taylor Series.

Taylors, how do they work?

Taylor series is a tool to express some function as a polynomial, using its nth derivative. Since sin(x) and its derivatives are differentiable, we can express f(x) = sin(x) as:

In this case, we can’t add infinitely many terms in a finite amount of time, so we have to approximate. Since this is a toy implementation, we will just compare it with python’s math.sin implementation and call it quits when they will converge good enough.

Implementation

First, we need some way of obtaining the nth derivative of sin, evaluated at some center a. By writing down sin’s first fifteen derivatives, we can see that the odd derivatives are either 1 * cos(x) or (-1) * cos(x), while the plural ones take the form of 1 * sin(x) or (-1) * sin(x). What is more difficult to see, is that derivatives with an ordinal that yields a reminder of two or three when divided by four are the derivatives with and minus sign. I don’t know how to formally prove it... yet, but you need to trust me on this one. Translating into python code:

    def nth_sin_derivative(n, a=math.pi/2):
        if n % 4 in (2,3):
            sign = -1
        else:
            sign = 1
        if n % 2 == 0:
            function = sin
        else:
            function = cos
    return sign * function(a)

Second, we need to actually be able to evaluate both cos(x) and sin(x) at our center. Since we are implementing sin(x), we should deal with cos(x) first. We don’t have to implement cos(x) separately - notice that sin(π2 - x) = cos(x):

    def cos(x):
        return sin((math.pi/2) - x)

Great. That solves the cos(x) part. Now, we can finally implement sin(x):

    def sin(x, center=math.pi/2, term_count=5):
        if x == math.pi/2:
            return 1
        elif x == 0:
            return 0
        else:
            values = (((x - center)**i / math.factorial(i)) * nth_sin_derivative(i, a=center) for i in range(term_count))
            return sum(values)

We specify two special cases: x = π2 for evaluating sin derivatives that require to compute sin(x) at center, and x = 0 for evaluating sin derivatives that require to compute cos(x) at center. Else, we compute the Taylor series.

Is the implementation any good?

Well, it sure can compute sin(x)! With term_count=19 the approximation is nearly as good as the python’s math.sin:




However, assemblies actually provide an fsin instruction, so computing sin(x) in software when speed matters is kinda cringe. On the side note, CPUs don’t actually use a Taylor series to compute trig functions - they use CORDIC.

Code that generates the graphs

transfer files with netcat

[ linkstandalone ]

transfer files with netcat

As I don’t use my arch laptop that much, I’ve figured that I can use it as a backup storage for my collections - collections of memes and movies.

Rsync is bloat?

Using some kind of a USB as an intermediary wouldn’t do the trick, because my meme collection is 14GB big (pathetic), whereas my movies take 139GB. My first though was to use rsync. I’ve never used rsync before, so I perused its man page and quickly found out that you can use:

    rsync -vzP /some/path user@remote:/some/other/path

to sync the files. Then... I got a ssh error. I couldn’t be bothered to install a ssh server on my laptop, because that would only bloat my precious Arch Linux install. I continued the search.

Rsync is bloat, so let’s pipe stuff into some program

I’ve stumbled on this StackOverflow answer. Not only does this guy have a method that would allow me to transfer my movies without installing a ssh server, but he also claims that it’s faster (rsync shines more when it comes to syncing files that are ‘similar’). It turns out that you can compress the files with tar and then use netcat to send them over the network with:

    tar -cpv --atime-preserve=system /path/to/ | nc -q 10 -l -p 45454

on the source machine, and

    nc -w 10 X.X.X.X 45454 | tar -xpv

on the destination computer. The traffic isn’t encrypted at all, but that’s not a problem over LAN (e.g sending movies to my laptop). Albeit, encryption can be provided with ssh or with a VPN.

I think this method is very linux-like, because it combines two programs in some unusual fashion to create something new. I might consider replacing scp with the ssh version of this trick.

my calendar system

[ linkstandalone ]

my calendar system<

TL;DR: I spend too much time on the Internet, should find some frens and go out more lol?

Over the past three years, I’ve developed this odd habit of writing down everything I do in my calendar. I’ve developed the habit mostly out of curiosity: I wanted to know how much time I spend on the Internet, playing video games, programming etc. Besides, I’m rather sentimental.

Last week, I realized that having one calendar doesn’t actually allow me to do that, because each event has a unique name (e.g if a play some video concrete game I write down that I’m playing concretely it). That means that running some simple script, on the calendar, to sum the events’ durations would not be plausible (just imagine the regex!). I should have several calendars, so that I could sort each event in to its proper category.

Categories

Coming up with the categories turned out to be more difficult that I’ve anticipated. They should be both not too specific, yet not too broad, so the ‘time spent on X statistic’ wouldn’t be complete bullocks. Should working out be considered its own category, or should I just put it under the ‘necessary, cannot live without it, but boring’ label? Is distro-hopping programming related? Should competitive programming be considered as studying or as programming? In the end, I’ve converged on these ten different categories:

Splitting the calendar (nearly 10k events) proved to be impossible by hand; wrote a script for it. I concur that some events that should be in the ‘chores’ category landed in the ‘life’ category, but only pedants would notice that.

Results



Basically, over the last three years I’ve spent around 36.8% of my time on mindless Internet browsing, while allocating about 2.3% of it to being ‘off the grid’ (relaxing + social). On the other hand, I’ve used about 37% of my time on doing useful stuff (i.e programming, studying/reading and chores; the number goes down to 22.7%, if doing chores would NOT to be included).

Conclusion

Well, it’s kind of problematic to draw conclusion from my ‘experiment’, because... I have no clue what the average might be. How can I tell if I’m doing ‘good’, whether I’m spending too much (or too little?) time on the Internet, studying etc? Besides, the antecedent (that’s literally the fanciest word I know) presupposes that the average even exist or is possible to ‘compute’! Nonetheless, I surely should try leaving my basement more often, because with that 2.3% staying constant I will either lose eyesight or die from vitamin D deficiency - not going outside is surely not lindy. I also like how calendaring makes me think about my life - when you go on to write down yet another five hour long mindless Internet browsing session, you kinda start to doubt your life decisions lol. It kinda functions like Benjamin Franklin’s 13 Virtues [sample chart]

btw i use arch

[ linkstandalone ]

btw i use arch

I’ve finally got around to installing Arch Linux on my laptop. Installing Arch was simple enough, the only problem that I’ve had was understanding the difference between a boot partition and a ‘boot partition’. A BIOS boot partition is a type of a partition, whereas a ‘boot partition’ is a partition you create for your /boot/ directory - you don’t actually need a ‘boot partition’, while a boot partition is more or less required - manually telling your boot loader (most likely GRUB) where everything is located is way too tedious.

Programs I run

The first thing that I installed was GNOME3. I run GNOME on my Ubuntu desktop and it works just fine, I especially like the DE; it looks nice out of the box and the Activities tab is amazing. But that’s mutter36 (mutter is the GNOME DE). mutter40 is nothing like it. As of now I run xfce4 on my laptop and it’s alright, albeit a little retro. Actually, xfce’s so vintage that it might be the best desktop environment for an eldery person, but that’s neither here or there. I’m actually thinking of switching to dwm or i3, but I’m yet to decide which one is better. For the login manager I’ve chosen LightDM - it just worked.

I don’t run NetworkManager, because I have no need for it - just connecting to wi-fi with iwd and running a dhcpcd daemon in the background works for me. I also installed an iwd frontend program, because some normal person might have to input a wi-fi password into my laptop someday.

I use udisks with udiskie for automating USB mounting. I also run gvfs, so I can have a Trash bin (which is less useful than I’ve thought). gvfs also seems to provide an alternative to insync, but it remains unclear whether you can actually use gvfs effectively without all the GNOME bloat.

I use CUPS directly for printer manging. I even have a desktop shortcut to a chromium app that starts the CUPS web gui.

I also considered installing a cron-like program (most probably anacron) and running a simple pacman update script, but after a little research, I’ve decided to postpone creating such cron job. If after a while of updating nothing breaks, I will surely consider it.

Final thoughts

As of now, Arch Linux is my favourite distro; it boots faster than Ubuntu, it eats a lot less RAM (which is cool, becouse now I can brag on the internet about how little memory my setup needs) and the package manager seems to be full of useful programs, especially compared to apt. Also, there’s AUR, which looks like a both more managable and faster version of snap,

psa use vimium

[ linkstandalone ]

psa: use vimium

Aren’t you tired of having to use your mouse in order to click a link? Of course you are, but worry no more - there exists a remedy.

Vimium is a browser (download for Chrome, download for Firefox) extension that binds all the functionality that you would need to some key combination. You can go to the previous/next page, you can look through your bookmarks, you can even copy the URL of the page you are looking at.



What’s also great is the fact that you remap Vimium’s key-binds how you like.

While being able search your bookmarks etc. is all fun and games, all Vimium’s feature pale in comparison to link hints. By default, pressing ctrl-f will make little boxes with letters (called link hints) appear next to all the links on the web-page. You now are only (at most) two key-strokes away from clicking that link! You can customize the boxes’ look with CSS, however the feature seems to be a little clunky - CSS sometimes only loads after refreshing a page.

By the way, I’ve brought back a ridiculously random site about red pandas. I think it was supposed to be a fan-fiction about Killian, but I can’t really remeber.

browser dark mode

[ linkstandalone ]

browser dark mode

It turns out that you don’t need fancy JavaScript to have your webpage change the color theme based on user’s preference.

You can access system’s color theme preference with @media (prefers-color-scheme dark). Now your you only need to write two separate CSS styles and you’re good to go.

Sadly, most pages don’t seem to use the feature. It’s good to know about it, but for a dark mode conesouir (like myself) would yern for something better.

Inside of chrome (and Chromium based browsers, I assume) you can got to the chrome://settings/appearance page, and set the theme there to a some dark one. This only changes the looks of your start page and the window’s border, but it’s a start.

We need to dig deeper.

A moment of browsing the internet, reveals the chrome://flags/ page, where you can the Auto Dark Mode for Web Contents option which, when enabled, forces every page to render in dark theme. It breaks some pages a little (especially the ones making extensive use of fancy CSS animations):




but it surly doesn’t render them unusable. Great stuff.

What if I don’t use Chrome?

You’re probably stuck with using Dark Reader then. It works with every popular browser, although it in my opinion it produces worse looking webpages than the native Chromium’s feature. If you’re a using an extensible browser like surf there’s probably a script or even a CSS file that does the same. Although, the kinds of people that use browsers like surf probably have known about since before I was born or something (I’m bad at role-playing a boomer, sry)

welcome!

[ linkstandalone ]

welcome!

I’ve decided to take up blogging. I’m mainly going to write about programming, but from time to time I will write a piece about some cool math fact that I’ve learned or a book review. I plan to keep the site bare-bones (no js!), because I believe that the web should be faster.
To build this website, I’ve rolled out my own static site generator (e.g. a few python3 scripts and some jinja templates), which you can find here.

             (•_•)
            <)  )╯[Always](https://www.alwaysownyourplatform.com/)
             /  \
            \(•_•)
            (  (> [Own](https://www.alwaysownyourplatform.com/)
            /   \
             (•_•)
            <)  )> [Your Platform](https://www.alwaysownyourplatform.com/)
             /  \