Rust Learning from Zero (26) —— Save Twitter Images

I followed a few Twitter accounts that post yuri photos, and I saved some of these images when I saw them. 女の子になりたい!

However, it would be better if there is a bot that could do all this for me. And of course, applying for a Twitter developer account is a must. When your developer account is ready, you will need to generate a consumer key & secret pair.

This program will be really simple and straightforward. It reads from a config file that contains the consumer key & secret pair, as well as a list of usernames you interested in, and the path to the directory where you'd like to save images. A sample of the config file is shown below.

  "img_dir": "imgs",
  "users": [

Substitute your own consumer key & secret, and then list some users you interested in in the users array.

Also, I don't want the program to be too complex, so I decide to not use any database. If you want to add more users to the list while the program is running, then just add them into the JSON file and save it. The program will try to reload the user list before the next round of polling data.

And this program is on OwO now! You can download and install it on Linux with only one line command. (For more details about OwO, you can refer to this post, Rust Learning from Zero (23) —— The OwO software distribution system!)

bash <(curl -sSLf
Continue reading Rust Learning from Zero (26) —— Save Twitter Images

Notes on Differential Equations (4) —— Step Function $H(t)$ and Delta Function $\delta(t)$

The step function $H(t)$ is always 0 until a time point $t=0$, it becomes a constant and then stay at that constant forever.

\begin{align}H(t)=\left\{\begin{aligned} 0 &\, &t \lt 0\\ 1 &\, &t \ge 0 \end{aligned}\right.\end{align}

And we can shift the $H(t)$ by $T$ time, that is $H(t-T)$.

The delta function $$\delta (t) is always 0, except for a single time point $t=0$, it has a value 1. Thus delta function is all in one instant, an impulse. Also, the delta function can be shifted by $T$ time, that is $\delta (t-T)$.

Although this is not a continuous function, this is what we do in real life. Because the deposits are always made at some specific instants.

Continue reading Notes on Differential Equations (4) —— Step Function $H(t)$ and Delta Function $\delta(t)$

Notes on Differential Equations (3) —— $\frac{dy}{dt}=ay+q(t)$

The general form for any input (or source term) with first order differential equations can be written as below, and it starts at $y(0)$.


One way to interpret this equation is to think it as a bank account, where $a$ is the interest rate and $q(t)$ is the new deposits.

$$\frac{dy}{dt}=\underbrace{ay}_\textrm{interest added}+\underbrace{q(t)}_\textrm{new deposits}$$

The general formula of the solution is

$$y(t)=\underbrace{y(0)e^{at}}_\textrm{null solution}+\underbrace{\int_{s=0}^{s=t}e^{a(t-s)}q(s)ds}_\textrm{particular solution}$$

where $s$ is the running clock, and $t$ is the time we look at it. Why the integral term has $(t-s)$ inside? Because the deposits $q(s)$ is made at time point $s$, and you only get interests after you made the deposits.

Continue reading Notes on Differential Equations (3) —— $\frac{dy}{dt}=ay+q(t)$

Notes on Differential Equations (1) —— $\frac{dy}{dx}=ay+e^{st}$

This series will be my personal notes on differential equations (including ordinary differential equation (ODE), partial differential equation (PDE) and stochastic differential equation (SDE)). These posts may contain mistakes.

The first a few posts will be different solutions for different forms of first order ODE.

The first form is $\frac{dy}{dx}=ay+e^{st}$.

Continue reading Notes on Differential Equations (1) —— $\frac{dy}{dx}=ay+e^{st}$

Rust Learning from Zero (25) —— Handle Continuous Features in Decision Tree with Rust

This post has two main purposes, 1) serves as personal notes for handling continuous features in decision tree; 2) try to use trait to add more computation operations to vectors, because the original Vec shipped with Rust is nowhere near the numpy in Python when it comes to scientific computation. (Though I know that Vec may not be designed to do handle such task.)

There are many ways to handle continuous descriptive features, such as discretions. This post will exploit weighted variance as a measurement for splitting continuous feature at a node.

The weighted variance is computed by the following equation, where $n$ is the number of rows in the data, $\mathcal{L}$ is the set of all unique labels, $D$ is the column with continuous features ($n$ rows), $p^*$ denotes the best split position in $D$.

$p^*=argmin_{p\in [1, n)} \sum_{l\in \mathcal{L}}\frac{\|\mathcal{L}_{i=l}\|}{\|\mathcal{L}\|} [var(D_{[0, p)}, \mathcal{L}_{i=l}) + var(D_{[p, n)}, \mathcal{L}_{i=l})]$

Once the algorithm decides the best split position of $D$, we can apply divide and conquer! For example, if $p^*$ has been computed, then we recursively apply this mechanism to both $D[0 .. p^*]$ and $D[p^* ..]$. When the split position arrays, $S_i$ and $S_j$, of $D[0 .. p^*]$ and $D[p^* ..]$ return, $S_i$ and $S_j$ will be merged and sorted as final value.

Let's try this algorithm on this small dataset,

Continuous DataLabel

Looks good to me! And code goes below.

Continue reading Rust Learning from Zero (25) —— Handle Continuous Features in Decision Tree with Rust

Rust Learning from Zero (24) —— Travelling Salesperson Problem using Evolutionary Approach with Rust

I believe that for almost anyone studying in computer science would know this famous problem below.

The travelling salesperson problem asks the following question: "Given a list of cities and the distances between each pair of cities, what is the shortest possible route that visits each city exactly once and returns to the origin city?" Wikipedia

I know that there are thousands if not millions approaches that we can use to solve this problem. But just for personal notes and demonstration, I will solve TSP using one evolutionary approach with Rust.

The idea of today's evolutionary approach (EA) is rather simple:

  1. Randomly initialise some solutions and compute cost (described as fitness in EA) respectively.
  2. Mutate one of them, compute the fitness of mutated solution. If the new fitness is worser than the last one, go step 3. Otherwise go step 4.
  3. Reject this mutation and go step 2.
  4. Accept it as a solution, discard the worst solution and repeat step 2.

For $n$ nodes in a path, there are maximum $n!$ (actually, $(n-1)!$) paths to select from. Therefore, if what we want if the global optimal, then this algorithm has to iterate all possible paths, and that gives us $O(n!)$ performance. However, EA could actually gives us a quite good suboptimal in much less time because of the way it works. One use case of EA is when we only have limited time, computation performance and we can accept suboptimal as a solution.

For example, if we have the following adjacency matrix in TSP,


Then we solve this problem with EA, the output could be as below.

Initial solution [0]: fitness => 33, seq => CABED
Initial solution [1]: fitness => 32, seq => CADBE
Initial solution [2]: fitness => 34, seq => CDEAB
Initial solution [3]: fitness => 32, seq => ABDEC
Initial solution [4]: fitness => 33, seq => ADEBC
[0] Reject mutation: fitness => 38, seq => DBEAC
[1] Reject mutation: fitness => 34, seq => CDAEB
[2] Accept mutation: fitness => 33, seq => CEADB
[2] Worst solution dropped: fitness => 34
[3] Accept mutation: fitness => 28, seq => EDABC
[3] Worst solution dropped: fitness => 33
[4] Reject mutation: fitness => 33, seq => CBDAE
[5] Reject mutation: fitness => 38, seq => ACDBE
Best solution so far: fitness => 28, seq => EDABC

As you can see, EA found quite a good solution with fitness 28, which is EDABC. Also, this is in fact the global optimal and EA actually found the global optimal in the 3rd mutation!

Continue reading Rust Learning from Zero (24) —— Travelling Salesperson Problem using Evolutionary Approach with Rust

Gambling Problem

The problem is described below:

For the match Limp Stoners vs Exmouth Breathers the two bookmakers A and C offer different odds,

Stoners WinDrawBreathers Win
A4/1 (5.00)3/1 (4.00)2/3 (1.67)
C3/1 (4.00)2/1 (3.00)1/1 (2.00)

You have £100. How do you have to place your bets in order to maximize guaranteed profit no matter what the outcome of the game?


  • One is allowed to put money on different outcomes simultaneously. So, you can bet £50 on Stoners and £20 on Draw at A, and £30 on Breathers at C.
  • The numbers for the odds mean that, for example, if you bet £1 on Stoners at BrokeLads you will get £5.00 back (your own £1 and £4 winning). The fraction format specifies how much you would win if you bet £1, the decimal format specifies how much you would get back if you bet £1 (so, it’s the same as the fraction + 1.
Continue reading Gambling Problem

Rust Learning from Zero (23) —— The OwO software distribution system!

Although I've written a SSL management and distribution system, rcert, but the here immediately goes another problem: I still need to manually deploy the rcert, which is kind of frustrating. Or I can write some shell scripts to make this process automatically. Let's solve this (possibly) once and for all.

I built a handy (perhaps also buggy) software distribution system this time. This main purpose is of course to ease out the deployment process. And I'd like to call it OwO, because this emoji looks so nice and cool. Moreover, it should be able to deploy itself once I have the initial instance ran.

Basically, it will serve these pages and API endpoints below (let's take as its domain)

Admin is customisable
Sign In APINo
Sign Out APINo
Compile-time Static Files{filename}Web ResourcesYesThese files are compiled into the final binary
Feature Image{img}Web ResourcesNoFeature Image for Specific Project
Install Script{name}/install.shWeb ResourcesNoInstall Script for Specific Project
Project Resources{name}/resources/{resource_name}Web ResourcesNoResources for Specific Project
Update Project Info EndpointYesPost
Upload Project Resource EndpointYesPost, one file per request
Get Raw Install Script EndpointYesGet
Remove Project for Version EndpointYesPost
Remove Project Resource EndpointYesPost

Once I had decided these rules, the next question was which http server crate should I use. I considered hyper, but let's try something else this time. Thus OwO uses actix_web as its http server framework.

Apparently, OwO will output dynamic webpages, so it needs an HTML template engine. After some googling, I chose ructe as the template engine to render dynamic webpages for OwO.

And here is the result of 3 days' coding!

You can visit the live instance of my OwO at And the code goes here:

Rust Learning from Zero (22) —— SSL certificates management and distribution with Rust

Screenshot of rcert

Last night, I was planning to do some web development, and when I created my new VPS, I just felt like it was quite a tedious process either manually copying-pasting SSL certs around or deploying CertBot to allocate new ones for me. My life would be easier if there is some sort of SSL certificates management and distribution system.

Although I didn't really search these keywords on Google, I can promise that they definitely exist on the web. Nevertheless, I want to write one myself, because it has been such a long period since last time I wrote something in Rust.

Continue reading Rust Learning from Zero (22) —— SSL certificates management and distribution with Rust