Anyway, back to the topic. It began to feel clumsy to move the four boxes around. It is time to find a storage solution.

There were many awesome storage solutions available. Some of which involve specially crafted containers, which might be hard or impossible to buy from China. Others involve repurposing the vanilla game box.

One the greatest models is Sumpfork’s Divider Generator. A live version can be found here, and the source code can be found here.

I do have found a few problems however.

First, while the generator comes with myriads of options, hacking any new idea into it is surprisingly hard. The problem is that the generator does not really do all the layout controls. Instead, it relies on `reportlab`

to do so, which works on its own set of assumptions, completely irrelevant for our purposes.

Second, the default background images, while looking good on a low resolution screen, actually looks very pixelated on a high resolution screen and, more importantly, with a decent printer.

The second point resulted in me trying to hack in an alternative design that does not involve raster images. The first point ensured that my attempt was futile.

Instead of continuing trying to modify Sumpfork’s generator, I figured out that it might be easier if I simply typeset the divider cards myself.

Really, once you realize that what you need is just to *typeset* the divider cards, it becomes a much easier problem. As long as I can find a way to typeset a few cards on a page, and another way to control the card contents, I get a generator. What looks like an annoying problem might be in truth two separate easy problems.

For typesetting I use XeLaTeX, which I am not an expert of, but there is nothing you can’t get by randomly hacking a few macro packages and options.

For some reason I decided to do everything in a De Finibus theme…

For the content control, I might have wanted to write a Python program to manage things, but since my goal is only to satisfy myself, LaTeX macro functionality is more than enough for this purpose.

And… for a failure, I will use a different format to described what is the challenge and how exactly I failed at it.

Here is a rough timeline for what I was doing during the competition:

- 00:00 – 00:20: read the four problems, as well as think about them briefly. In the end I concluded that none of them look easy but I should start with the first problem.
- 00:20 – 01:10: solve problem A.
- 01:10 – 01:20: solve the easy case of problem B.
- 01:20 – 02:00: solve the hard case of problem B, but getting a Wrong Answer.
- 02:00 – 02:30: solve the easy case of problem C, while also debugging problem B.

In the end my solutions for both problem A and problem B worked, and problem C easy is never enough for me to enter the top 25.

Zillionim is a turn-based game for two players. Initially, 10^{12} coins are arranged end-to-end in a single line, numbered from 1 to 10^{12} from left to right. During a turn, a player must select 10^{10} consecutive coins and remove them. Two coins that were not originally consecutive do not become consecutive even if all of the coins in between them are removed.

On their turn, a player makes a valid move if possible, and then it is their opponent’s turn. If a player cannot make a valid move on their turn, they lose the game (and the opponent wins the game).

Because our engineers are still hard at work training our machine learning model to play Zillionim, we have created a simple AI that plays Zillionim by making random moves. The AI always gets the first turn. On each of the AI’s turns, the AI determines all valid moves and chooses one of them uniformly at random.

Can you beat this AI… at least most of the time (*499 out of 500 games for the hardest case*)?

The first part of solving this problem involves writing a naïve solution. It involves all kinds of boilerplate code you are going to write anyway, so in some sense a naïve solution is one or two lines of naïve code plus lots of reusable, useful stuff.

A naïve solution also provides a right perspective into the problem. In this problem, the current *state* of the game is a set of intervals with length of least 10^{10}. Each action is to pick a breaking point in an interval, and depending on where you pick and how long the interval is, it might break in two, or shorten, or disappear.

And it is also not hard to see that all intervals with length between 10^{10} and 2×10^{10}-1 are functionally the same: picking anywhere in such an interval would result in eliminating it. Let’s call such an interval “Type I”.

For intervals with length between 2×10^{10 } and 3×10^{10}-2, however, they can either be eliminated, or shortened to an Type I interval. Let’s call such an interval “Type II”.

A key observation is that you can produce short intervals at specific lengths, and the random AI is very unlikely to mess with your plan since it is usually busy with the longer intervals. The end result is when the original long sequence finally turns into a set of short sequences, the length of about half of these sequences is decided by you.

The magic interval length I use is 3×10^{10}-2. What’s special about it? When the AI picks a breaking point in such an interval, it *almost always* shorten to a Type I. On the other hand, I still have both options, meaning that I can still directly eliminate it when I need to do so.

My early game strategy involves pumping as many magical intervals as I can. The middle game strategy involves getting rid of all non-magical Type II intervals, because it results in a simpler situation, making analysis easier.

Now we arrive in a *late game*, already controlled by our early and middle game strategies. In a late game, each interval is either a Type I one or a magical one. Assuming the AI always taking the high probability option when dealing with magical intervals, simple combinatorial game theory tells us that a situation is losing if and only if the number of Type I intervals is even. And as long as there is at least one magical interval remaining, however, we can effectively “cheat” by invoking the elimination option of a magical interval, turning a losing situation for us into another losing situation for the random AI.

All in all, this is a incredibly simple solution because it basically throws all the complexities away and deals with what’s remaining. It turns out to be very reliable: I simulated 5,000 games and it won all of them. This is probably why this problem is the first problem, and why it has the lowest total score.

You have just finished cooking for some diners at the Infinite House of Pancakes. There are **S** stacks of pancakes in all, and you have arranged them in a line, such that the i-th stack from the left (counting starting from 1) has **P _{i}** pancakes.

Your supervisor was about to bring out the stacks to the customers, but then it occurred to her that a picture of the stacks might make for a good advertisement. However, she is worried that there might be too many stacks, so she intends to remove the L leftmost stacks and the R rightmost stacks, where L and R are nonnegative integers such that L + R ≤ **S** – 3. (Notice that at least 3 stacks of pancakes will remain after the removal.)

Your supervisor also thinks the remaining stacks will look aesthetically pleasing if they have the *pyramid property*. A sequence of N stacks of heights H_{1}, H_{2}, … , H_{N} has the pyramid property if there exists an integer j (1 ≤ j ≤ N) such that H_{1} ≤ H_{2} ≤ … ≤ H_{j-1} ≤ H_{j} and H_{j} ≥ H_{j+1} ≥ … ≥ H_{N-1} ≥ H_{N}. (It is possible that this sequence might not look much like a typical “pyramid” — a group of stacks of the same size has the pyramid property, and so does a group in which the stack heights are nondecreasing from left to right, among other examples.)

Note that the sequence of stacks remaining after your supervisor removes the L leftmost and R rightmost stacks might not yet have the pyramid property… but you can fix that by adding pancakes to one or more of the stacks! The *pyramidification cost* of a sequence of stacks is the minimum total number of pancakes that must be added to stacks to give the sequence the pyramid property.

While your manager is carefully deciding which values of L and R to choose, you have started to wonder what the sum of the pyramidification costs over all valid choices of L and R is. Compute this sum, modulo the prime 10^{9}+7 (1000000007).

The annoying fact was that I failed to think of a solution that can work for the hard test case. Instead, I roughly knew the solution for the easy case and that was it.

Before venturing deeper, take notice that the “pyramidification cost” is essentially the same thing as the volume of water that would have been contained by a container of the shape of a histogram of the remaining stacks. They are very different ways to describe the same mathematical stuff, but some people, like me, would find the water metaphor easier to work with than the pyramidification metaphor.

Only when I started to write the O(n^{2}) solution it turned out to be not so straightforward. I split the water volume into two kinds: the first kind is “ascending”, while the second kind is “non-ascending”. They are not exactly symmetric because we need to take account of the cases where there are multiple highest points, but for the sake of describing the algorithm, their difference is minor enough. Therefore, I will only describe the ascending part.

Actually, splitting the problem into two parts is the hard part. Dealing with the parts is easy. First, enumerate all starting points, or, using the terminology in the problem, enumerate L. For each starting point, enumerate all ending point in ascending order, maintaining the maximum point in the current interval as well as the “current water volume” in the interval. The “current water volume” only needs to be updated when the maximum point changes.

Once I had finished the O(n^{2}) solution, it became apparent that there were optimization opportunities. The water volume of the current interval only updates as we encounter a new maximal height. And by “updating” we mean “adding something to it”.

Similarly, lots of computations from different starting points are actually similar.

Taking this perspective, we look at an “ascending lake”. It turns out we know exactly how many times its volume gets counted! If the said lake is between *i* and *j*, then any interval that contains nothing before *i* that is higher than or equal to *i*, and contains the lake in whole, would count the volume of the lake once.

To calculate the total contribution of this lake, we need to find out for each position the leftmost position to its right that is higher than it, and the rightmost position to its left that is not lower than it. Both of which can be calculated in O(n log n) time with the help of an interval tree.

Two companies, Apricot Rules LLC and Banana Rocks Inc., are sharing the same datacenter. The datacenter is a matrix of **R** rows and **C** columns, with each cell containing a single server tower. Each tower contains intellectual property belonging to exactly one of the two companies.

At first, they built walls on the edges between cells assigned to different companies. This allowed orthogonally adjacent cells belonging to the same company to remain connected. Also, two cells x and y are considered connected if x is connected to a cell that is, directly or indirectly, connected to y. With this definition, it was possible that two cells assigned to the same company were not connected, which was unacceptable.

Both companies agreed to build narrow hallways running through cell corners that allow two diagonally adjacent cells to be connected directly. Let us write (i, j) to represent the cell at row i and column j. At most one narrow hallway can be built through any given vertex, which means either (i, j) and (i + 1, j + 1) can be connected, or (i + 1, j) and (i, j + 1) can be connected, or neither pair, but not both. Of course, only hallways between cells assigned to the same company can be built.

Given a matrix where each cell is labeled `A`

or `B`

depending on which company it is assigned to, find a way to add connections through diagonal adjacencies such that all `A`

s are connected and all `B`

s are connected.

I had no idea about the hard test case. The easy test case has the number of rows of at most 4, which enables some contrived dynamic programming where you store the connectivity in your state. Which I tried and failed to get done in 30 minutes.

My thoughts on the problem is that it is probably easier than it looks. That it is a planar grid really keeps its complexity in check. Here is the third sample input:

BBAA BABA BBAA

Funnily, I have been drawing more test cases on paper and none of them are essentially more complex than this one. I think the correct route for this problem is to take this observation and do something with it. The solution should be something like greedy algorithm (in that it always takes one option of the opposite one is obviously useless) and construction (in that after the greedy parts are done, the problem should boil down to a few patterns that can be solved with construction).

I will not write about the last problem since attempting it without finishing problem C would have been a huge mistake, and I did not interact with the problem in any meaningful way to talk about it.

I feel I started incredibly slowly. Reading all the problems and picking one of them is a good strategy when I can solve at least one of them quickly. Otherwise, I might as well just dive at the first problem and solve it while also warm up myself. Of course, there is also the question that whether I should start writing some code *before* the contest, but unfortunately, on the other hand I find myself tire rather quickly in coding competitions. If I have to make a trade off between these, then yes, I still feel I should have warmed up before the contest, as my mental stamina isn’t *that* bad.

I think I used a correct approach for problem A, but it turned out that I spent an incredible 40 minutes between implementing the naïve solution and the final solution. Some of the time was probably spent in thinking about problem B, but that would have been another mistake. I should focus on problem A anyways.

For problem B, it turned out that writing down the solution for the easy case helped me with the hard case. In other words, I knew how to solve the easy case, but I did not think about it *clearly* on paper, and had to think about the same problem again. If I could analyze it on paper as clearly as I did when I wrote the easy case solution, I might have saved valuable time to deal with problem C.

… and it comes to problem C. I should have noticed that solving the easy case is unlikely to help, especially when an easy case only solution is likely to be very contrived and contains little to no code reusable for the hard case.

Instead, I panicked when I realized I wasted so much time on problem A, and went to try hard to grab any point I could. It proved to be futile and detrimental for my overall chance of getting in the top 25. Which is, to be honest, never likely to happen though.

]]>

Upon further inspection, however, it turned out that the problem does not lie in the theme, but my understanding of blockquotes: quoting a problem statement is definitely *not* an appropriate usage for blockquotes.

A temporary fix for those problem statements is that I turned them into plain text paragraphs. It looked much less distracting, but it also made it harder to tell between the problem and the answer.

Further solutions might include a table, a different background color, or an accordion. However, as I am weary of fixing old stuff again and again, I want to take more time to decide on that one.

As making adjustments to the theme will probably become a new normal, it might be useful if I have a benchmark, a unified place to see all the changes to happen. Hence, I started a test page. Since as of now I only concentrate on blockquotes, there are only blockquotes in it at the moment. But in the future I could reuse this page to include more examples.

There is also a page for similar purposes created by the creators of the theme. It includes more stuff, and is part of the inspiration for my creation of the test page. However, seeing the test page in my particular configuration might be useful. And I might some day include stuff not included by the upstream one.

A curiosity I noticed when creating that test page is that blockquotes can have an `<cite>`

field, which usually represents the source or author of the quotation.

In default Kahuna, the quotation itself is in a big, italic and serif font, and the citation is in smaller, upright, all-capital setting of the same font. The kind of serif typeface they have in mind is Georgia or Charter — both featuring strong and even exaggerated serifs, which can probably compensate for the smaller font size nicely.

In contrast, the typeface I am using, Adagio Serif, does not feature very strong serifs. Hence, the smaller letters really look weaker and lighter.

I changed the block quote typeface to slightly lighter, and adjusted letter spacing and font size to balance the citation and the quotation. I feel I ended up with a more interesting kind of contrast than before.

]]>

Muriel is on the path to discovering two new elements that she has named Codium and Jamarium. She has not been able to isolate them yet, but she wants to start investigating some important properties, like their atomic weights, by indirect means. Since Muriel is working with a single isotope of Codium and a single isotope of Jamarium, their atomic weights are strictly positive integers.

Muriel managed to create **N** different molecules, each of which contains one or more atoms of Codium and one or more atoms of Jamarium, and no other elements. For each molecule, she knows how many atoms of each element are present in it. The molecular weight of a molecule is the sum of the atomic weights of all the atoms it contains.

As a first step towards figuring out exact molecular weights for the molecules and atomic weights for the two elements, Muriel wants to sort the molecules by strictly increasing molecular weight. To assess the difficulty of that task, she wants to know how many orders are valid considering only the information she has right now. An ordering of the molecules is considered valid if there exist values for the atomic weights of Codium and Jamarium such that the ordering is *strictly* increasing in molecular weight.

To give an example, we represent each molecule by the ordered pair of the number of atoms of Codium and Jamarium it contains. If Muriel has 3 molecules represented by (1, 1), (2, 1) and (1, 2), there are two possible orderings that can be strictly increasing in molecular weight: (1, 1), (1, 2), (2, 1) and (1, 1), (2, 1), (1, 2). The first ordering is valid for any assignment of atomic weights in which Codium is the heaviest of the two elements, and the second is valid for any assignment in which Jamarium is the heaviest. The only case remaining is when both Codium and Jamarium have the same atomic weight, in which case (1, 2) and (2, 1) have the same molecular weight, so no strictly increasing ordering can be produced for that scenario.

Unfortunately the problems are getting longer and longer…

And I think I spent at least one minute wondering why they are not simply *Codium* and *Jamium*.

Anyway, this problem is essentially asking how many proportions of relative weights for Codium and Jamarium are there for which two atoms have the same total weight. These proportions do not produce legal ordering by themselves, but they are separators of different orderings. Hence the answer is one plus this number.

The Pottery Palace is going to run a lottery featuring some valuable vases by the artist Cody-Jamal. The lottery works as follows:

- 100 people get to play in the lottery. Each player has a unique number between 1 and 100, and is given a single token with that number.
- There are 20 empty clay vases on a table, numbered 1 through 20. The vases have narrow openings that are large enough to accept a token, but small enough that players cannot look inside to see the contents.
- On the i-th day of the lottery, the player with token number i chooses a vase and puts their token in that vase. Since the vases are all identical (apart from their labels), every player will choose one uniformly at random and independently of all other players’ choices.
- On day 100, after player number 100 has inserted their token, the organizers shake the vases to determine how many tokens are inside each one. If there is
*exactly*one vase that has fewer tokens than any other vase, then that one is the “winning vase”. The organizers then pour out all of the tokens in that vase, and every player whose number is written on one of those poured-out tokens wins a vase! If multiple vases have the same minimal amount of tokens, nobody wins anything.

You have been hired to test the security of the lottery, and you will participate in some trial runs. The company will always assign you the number 100 — that is, you replace player 100.

You have found some ways to tamper with the lottery at night, but security is tight, so you can only do so much! Specifically, after each of the first 99 days of the lottery, you may do exactly *one* of the following:

- forge a token with the player number of your choice (between 1 and 100, inclusive), and add it to a vase of your choice. You are a very good forger: if there is a winning vase, any forged tokens in that vase will cause the players with those numbers to win (with one exception; see below).
- use a special camera to see the numbers on all of the tokens in one vase of your choice

You may perform different actions on different nights, and you may choose dynamically: you do not need to decide on all of your actions in advance.

On the 100th day, it is your turn to insert your token into a vase of your choice (you do not need to choose uniformly at random). You cannot perform any other actions on that day.

You know that if there is a winning vase with more than one token for the same player, it will be obvious that cheating has occurred and nobody will win. However, it does not matter if other vases contain more than one token for the same player because the organizers never see those tokens.

Your goal is to be a winner in at least 90% of the test cases.

This problem is, I believe, pretty revolutionary, as it requires you to provide a strategy that works good enough over a given distribution of inputs.

As I did not have many ideas for this question, I decided to start from a toy strategy and gradually improve it.

Since the goal is to ensure the vase with your vote to win, the sub-goals are to have a plan about what vase to vote, and to keep other vases from threatening that vase.

Hence, I mix the two options with a fixed pattern (which ended up in a 3:1 cycle).

For each *peek* attempt, we try to look at something that has greatest uncertainty (as in have not been peeked for long), as well as threat.

What is more weird is the strategy of forging votes. A intuitive strategy is to always hamper the current second placed vase (based on our best effort to predict), since this gives the current best vase a greatest edge over its alternatives. However, this strategy does not work well enough, presumably because we have absolutely no control over the other 99 voters, and they might simply ruin your plan.

A more refined strategy is to hamper the *ninth* placed vase first, then eighth, seventh… as the time goes by. Only for the last few rounds, we focus on the second placed vase to ensure the vase we pick is the winner.

The strategies, especially the one for the forgery operation, involves lots of hyper-parameters. Fortunately, by increasing the number of test cases, we can check whether each potential modification improves the strategy or not with pretty high level of confidence.

My first submissions at a locally measured success rate of 92% failed the official test… which I have to blame my bad luck. But further improvements brought it to 94% and nothing could prevent my code any more.

This problem also brings an interesting question: what if we approach problems like this with reinforcement learning? To be honest, I have not done much reinforcement learning so far, but this is a fascinating opportunity to try fun stuff.

The problem shares the same story with the first problem, so I’ll only quote the actual different parts.

As a first step, Muriel sorted the molecules by strictly increasing molecular weight. Now she wants to find out possible integer values for the atomic weights of both Codium and Jamarium that are consistent with the ordering. Since she is aware there could be many consistent pairs of values, she wants one that minimizes the atomic weight of Codium. If there are multiple pairs in which Codium’s atomic weight is minimum, she wants the one in which Jamarium’s atomic weight is minimum.

It is pretty easy to find a open range to represent all the feasible weight proportions between Codium and Jamarium. The problem is we need both of them to be integers. In other words, we are to find a fraction of smallest numerator that falls within a known region.

I immediately realized that this problem could be solved with a Stern–Brocot tree. Since it is a binary tree, with deeper nodes having both larger numerators and denominators, we only need a binary search to find the first node to fall in the range and output it.

Only after the competition and finding my solution accepted, I realized that the said binary search still degenerates to O(n) for extreme inputs…

Last year, we asked you to help us convert expensive metals into lead. (You do not need to know anything about the previous problem to solve this one.) But your country’s leader is still greedy for more lead!

There are **M** metals known in the world; lead is metal number 1 on your periodic table. Your country’s leader has asked you to use the metals in the treasury to make as much lead as possible.

For each metal (including lead), you know exactly one formula that lets you destroy one gram of that metal and create one gram each of two metals. (It is best not to think too much about the principle of mass conservation!) Note that it is possible that the formula for the i-th metal might produce the i-th metal as one of the products. The formulas do not work with partial grams. However, you can use each formula as often as you would like (or not at all), as long as you have a gram of the required ingredient.

If you make optimal choices, what is the largest number of grams of lead you can end up with, or is it unbounded? If it is not unbounded: since the output can be a really big number, we only ask you to output the remainder of dividing the result by the prime 10^{9}+7 (that is, 1000000007).

I can’t help but wasted another minute or two wondering about the terrible pun about lead and leader.

Anyway, first find out all strongly connected components and sort them from the destinations to the sources. Then for each SCC we can calculate its “optimal lead production per gram” by discussing all the cases (which is more than I initially thought).

A trick that helps a bit is to introduce an extended number type that includes 0, all positive integers modulo 10^{9}+7 and infinity, and build various operations over this type.

Not long after, however, I decided that maintaining a Bazel workspace is not the best use of my time. I worked on other projects, and created an unrelated open source Bazel workspace for my own enjoyment.

This post will be a brief introduction of this project.

In one word, Hermeticity.

Well, Google engineers working on Bazel probably reinvented this word when it comes to building stuff. The word means that the building process is completely reproducible, regardless what environment you use. And by “completely reproducible”, we mean that the output binary stays completely the same, bit by bit. It also means no timestamps and fixed random seeds during compilation, but if they help you locate a really obscure bug, why not?

Since I am also a Gentoo user, there is something I dislike about this. I want to randomly update dependencies and see whether packages break or not. But for more serious projects, maybe a better reproducibility is desired.

Of course, by default Bazel uses the toolchain and libraries in your system. In this case, there is not much hermeticity to talk about, as people with a different system configuration will produce different results than you. However, as long as you do not update your system, your builds will at least be consistent, which is still something not easy to pull off in other build systems.

Other benefits include remote caching. However, while it has been in Google’s version of Blaze for years, last time I checked it was very hard to get Bazel to use that functionality. Hopefully things have improved since then.

Astraeus workspace is a much less ambitious project. I grabbed a few BUILD files from tensorflow and other open source projects, and wrote a few BUILD files myself.

Currently, the biggest applications buildable with this workspace are VIM and Inkscape.

There are also many dependent graphic libraries for Inkscape. Mostly because they are also dependencies of Tensorflow, supporting these is easier than other kinds of packages, which I usually have to manually write the BUILD files.

It can be found here.

To be honest, I don’t know. Building stuff is too much chore, too little epiphany.

The event that triggered me to revisit Astraeus Workspace is that I discovered an Github issue opened in February. Alas, I have been neglecting Github for a few months. It turns out that Bazel itself is rapidly changing, and I should at least catch up.

Another long planned thing is to build a GCC toolchain with Bazel, then write a configuration for the toolchain. I am not sure what is the benefit, but that will make the little workspace an ecosystem on its own. This is the reason why I have been adding compiler libraries like gmp and binutils to the workspace, but progress has been very slow and I am not sure whether it can happen at all.

Another idea was to add a few random applications, then feed them to really nontraditional toolchains like Emscripten, and see what happens.

]]>Anyway, it turned out to be OK for me as the other problems were easy and I was good enough to enter the next round.

Our Battlestarcraft Algorithmica ship is being chased through space by persistent robots called Pylons! We have just teleported to a new galaxy to try to shake them off of our tail, and we want to stay here for as long as possible so we can buy time to plan our next move… but we do not want to get caught!

This galaxy is a flat grid of

Rrows andCcolumns; the rows are numbered from 1 toRfrom top to bottom, and the columns are numbered from 1 toCfrom left to right. We can choose which cell to start in, and we must continue to jump between cells until we have visited each cell in the galaxyexactlyonce. That is, we can never revisit a cell, including our starting cell.We do not want to make it too easy for the Pylons to guess where we will go next. Each time we jump from our current cell, we must choose a destination cell that does not share a row, column, or diagonal with that current cell. Let (i, j) denote the cell in the i-th row and j-th column; then a jump from a current cell (r, c) to a destination cell (r’, c’) is invalid if and only if any of these is true:

- r = r’
- c = c’
- r – c = r’ – c’
- r + c = r’ + c’
Can you help us find an order in which to visit each of the

R×Ccells, such that the move between any pair of consecutive cells in the sequence is valid? Or is it impossible for us to escape from the Pylons?

Basically, you are asked to provide a way to traverse a board of given shape under the constraint that each step consist of two grids that queens on them cannot attack each other.

It’s quick to come up with a few random constructions like repeating variants of knight moves. This kind of naïve construction actually works very well for large **M** and **N**’s. Actually, they are guaranteed to work if you consider two variants and both **M** and **N** are large enough:

- variant 1: keep using (1, 2) knight move, wrapping around the border using modulo. Once you reach the last line, you start in the first line but to one grid to the right.
- variant 2: keep using (1, 2) knight move, wrapping around the border using modulo. Once you reach the last line, you start in the first line but to one grid to the left.

However, the construction starts to fall apart for small **M** and **N**’s! I made the mistake of not having calculated how many special cases I needed, and it cost me lots of debugging time. It turned out the above-mentioned construction needs three special cases:

**M**=**N**= 4**M**= 3,**N**= 5**M**= 5,**N**= 3

Even taking symmetry into consideration, figuring out how the construction would fail for **M** = 3, **N** = 5 was not easy. Hence, a hybrid approach of construction and brute force search could have fared better in another poor day.

Last year, a bunch of pesky gophers took up residence in our orchard. We tried to change our line of work by opening up a miniature golf course, but it looks like the gophers have followed us here! Once again, we need to figure out how many gophers there are, but we cannot observe them directly because they are secretive and nocturnal, whereas we like to sleep at night. We do know there are between 1 and

Mgophers, inclusive.Our mini golf course is famous for having a small electronic windmill on each of its 18 holes. The i-th windmill has 2 ≤

B_{i}≤ 18 blades, which are numbered from 0 toB_{i}-1, clockwise. Each night, before going to sleep, we turn off the windmills and set each one such that blade 0 is pointing downward, which is important so that the windmills can charge up properly for the next day. However, we have noticed that when we wake up, the windmills have been disturbed. Since our mini golf course is in a windless area, we think the mischievous gophers must be responsible!We know that every night, all of the gophers emerge, one by one; each of them chooses one of the windmills independently and uniformly at random and rotates it counterclockwise by one blade. So, for example, for a windmill with 3 blades for which 0 is pointing downward, the first gopher to interact with it turns it so that 1 is pointing downward, and then the next gophers to interact with that windmill make the downward-pointing blade have number 2, then 0, then 1, and so on.

We have devised a plan. We designed our windmills so that we can easily change the number of blades (to modulate the difficulty of our course), and we will now take advantage of this! Each night, before going to sleep, we can choose the number of blades on each of the 18 windmills, within the given limits; we do not have to use the same number of blades on each windmill, or make the same choices every night. In the morning, we will observe the number on each windmill’s downward-pointing blade.

We have

Nnights in which to figure out G, the number of gophers. Can you help us?

Google, we need *more* gopher problems!

Anyway, it becomes apparent that using wheels of different numbers of blades on the same day is asking for trouble: you quickly lose the ability to infer any information. And fortunately we do not need to do that either: just by setting the numbers of blades to a list of preset numbers we can easily solve the problem via the Chinese remainder theorem.

The only caveat here is that the Chinese remainder theorem works when the divisors are **pairwise co-prime**. Some people might forgot that and try using only prime numbers, which will not be good enough to solve the problem. I picked ${7, 8, 11, 13, 15, 17}$ intuitively, and it was probably also the optimal array, in the sense of producing the largest product (2042040) under the given constraints.

During some extraterrestrial exploration, you found evidence of alien poetry! Your team of linguists has determined that each word in the alien language has an accent on exactly one position (letter) in the word; the part of the word starting from the accented letter is called the accent-suffix. Two words are said to rhyme if both of their accent-suffixes are equal. For example, the words

`PROL`

and`TARPOL`

rhyme if the accented letter in both is the`O`

or the`L`

, but they do not rhyme if the accented letters are the`R`

s, or the`R`

in`PROL`

and the`P`

in`TARPOL`

, or the`O`

in`PROL`

and the`L`

in`TARPOL`

.You have recovered a list of

Nwords that may be part of an alien poem. Unfortunately, you do not know which is the accented letter for each word. You believe that you can discard zero or more of these words, assign accented letters to the remaining words, and then arrange those words into pairs such that each word rhymes only with the other word in its pair, and with none of the words in other pairs.You want to know the largest number of words that can be arranged into pairs in this way.

Since we are dealing with suffixes, it is obvious that re-organizing the input data to a trie will help. Traditional tries deal with prefixes but it should be obvious to you that you want to do it backwards and store by suffixes instead.

Once we have that trie, a simple greedy algorithm can be run on the trie to produce the answer. Each node on the trie can produce at most one “rhyme-pair”, and any word in its subtree qualify for such a pair. Furthermore, it is always desirable (meaning it will not make things worse) to create “rhyme-pairs” at the deepest subtrees as possible. Hence, greedy algorithm works, and a simple recursive function defined on the trie will give the answer.

]]>

One can get lazy.

There are many things I think about and want to write something about. From games, to neural networks, to various front-end stuff. There is also pleasure just trying out things that I have not used before.

However, without a definite schedule, one will constantly find excuses to do something else. Procrastination is such a powerful foe, that if action is not taken, even a hobby that’s supposed to be fun will cease being so. Speaking of which, well, I kind of have lampshaded this by naming my blog after a chapter talking about pain itself…

Mondays are too annoying to have extra burdens.

Fridays should not have schedules like this. They should be as empty as they can be.

Weekend time should not be fragmented.

Which means Tuesday, Wednesday and Thursday are my remaining choices. Currently I have bi-weekly Board Game events, so it pushes whatever schedule I want to have towards the other end of the week. Hence, Thursday.

]]>

Someone just won the Code Jam lottery, and we owe them

Njamcoins! However, when we tried to print out an oversized check, we encountered a problem. The value ofN, which is an integer, includes at least one digit that is a`4`

… and the`4`

key on the keyboard of our oversized check printer is broken.Fortunately, we have a workaround: we will send our winner two checks for positive integer amounts A and B, such that neither A nor B contains any digit that is a

`4`

, and A + B =N. Please help us find any pair of values A and B that satisfy these conditions.

Since you can provide any solution, avoiding any carrying in your solution makes things easier. And it is good enough: just design a way to split each digit into the sum of two digits that are not `4`

. An obvious one is to split `4`

into `3`

+`1`

and everything else into themselves plus `0`

.

You have just entered the world’s easiest maze. You start in the northwest cell of an

NbyNgrid of unit cells, and you must reach the southeast cell. You have only two types of moves available: a unit move to the east, and a unit move to the south. You can move into any cell, but you may not make a move that would cause you to leave the grid.You are excited to be the first in the world to solve the maze, but then you see footprints. Your rival, Labyrinth Lydia, has already solved the maze before you, using the same rules described above!

As an original thinker, you do not want to reuse any of Lydia’s moves. Specifically, if her path includes a unit move from some cell A to some adjacent cell B, your path cannot also include a move from A to B. (However, in that case, it is OK for your path to visit A or visit B, as long as you do not go from A to B.) Please find such a path.

It is easily provable that

- an eastward move never coincides with a southward move;
- the
**i**-th move in Lydia’s sequence can only coincide with the**i**-th move of yours; - a path is legal if and only if it has
**N**-1 eastward moves and**N**-1 southward moves.

Hence, even if coming up with a legal path that does not coincide with Lydia’s one is never a hard task, just swapping all `E`

’s with `S`

’s and vice versa is the easiest construction.

On the Code Jam team, we enjoy sending each other

pangrams, which are phrases that use each letter of the English alphabet at least once. One common example of a pangram is “the quick brown fox jumps over the lazy dog”. Sometimes our pangrams contain confidential information — for example,`CJ QUIZ: KNOW BEVY OF DP FLUX ALGORITHMS`

— so we need to keep them secure.We looked through a cryptography textbook for a few minutes, and we learned that it is very hard to factor products of two large prime numbers, so we devised an encryption scheme based on that fact. First, we made some preparations:

- We chose 26 different prime numbers, none of which is larger than some integer
N.- We sorted those primes in increasing order. Then, we assigned the smallest prime to the letter
`A`

, the second smallest prime to the letter`B`

, and so on.- Everyone on the team memorized this list.
Now, whenever we want to send a pangram as a message, we first remove all spacing to form a plaintext message. Then we write down the product of the prime for the first letter of the plaintext and the prime for the second letter of the plaintext. Then we write down the product of the primes for the second and third plaintext letters, and so on, ending with the product of the primes for the next-to-last and last plaintext letters. This new list of values is our ciphertext. The number of values is one smaller than the number of characters in the plaintext message.

For example, suppose that

N= 103 and we chose to use the first 26 odd prime numbers, because we worry that it is too easy to factor even numbers. Then`A`

= 3,`B`

= 5,`C`

= 7,`D`

= 11, and so on, up to`Z`

= 103. Also suppose that we want to encrypt the`CJ QUIZ`

… pangram above, so our plaintext is`CJQUIZKNOWBEVYOFDPFLUXALGORITHMS`

. Then the first value in our ciphertext is 7 (the prime for`C`

) times 31 (the prime for`J`

) =`217`

; the next value is`1891`

, and so on, ending with`3053`

.We will give you a ciphertext message and the value of

Nthat we used. We will not tell you which primes we used, or how to decrypt the ciphertext. Do you think you can recover the plaintext anyway?

This problem is a cautionary tale that how a cryptographically uneducated person could devise something that looks secure but is utterly broken. One might think factorizing a number is hard. However, it is not hard if it is known to share a common non-trivial factor with another number!

Find any two adjacent number that are not the same. The existence of such pair is guaranteed because it is a pangram. Calculate their largest common divisor, which is just their only common prime factor. Use this factor to chain calculate all other primes in the question, and problem solved.

A research consortium has built a new database system for their new data center. The database is made up of one master computer and

Nworker computers, which are given IDs from 0 toN-1. Each worker stores exactly one bit of information… which seems rather wasteful, but this is very important data!You have been hired to evaluate the following instruction for the database:

`TEST_STORE`

<bits>: The master reads in <bits>, which is a string ofNbits, and sends the i-th bit to the i-th worker for storage. The master will then read the bits back from the workers and return them to the user, in the same order in which they were read in.During normal operation,

`TEST_STORE`

should return the same string of bits that it read in, but unfortunately,Bof the workers are broken!The broken workers are correctly able to store the bits given to them, but whenever the master tries to read from a broken worker, no bit is returned. This causes the

`TEST_STORE`

operation to return onlyN–Bbits, which are the bits stored on the non-broken workers (in ascending order of their IDs). For example, supposeN= 5 and the 0th and 3rd workers are broken (soB= 2). Then:

`TEST_STORE 01101`

returns`111`

.`TEST_STORE 00110`

returns`010`

.`TEST_STORE 01010`

returns`100`

.`TEST_STORE 11010`

also returns`100`

.For security reasons, the database is hidden in an underground mountain vault, so calls to

`TEST_STORE`

take a very long time. You have been tasked with working out which workers are broken using at mostFcalls to`TEST_STORE`

.## Limits

Time limit: 20 seconds per test set.

Memory limit: 1GB.

1 ≤T≤ 100.

2 ≤N≤ 1024.

1 ≤B≤ min(15,N-1).## Test set 1 (Visible)

F= 10.## Test set 2 (Hidden)

F= 5.

I wonder how many people have tried to write database puns with “bae”. Admittedly I have also tried that before, so I smiled when I saw the title.

This is the only problem that I included the limits here, because they matter.

For the easy test case, it is easy to design a divide-and-conquer strategy. In the beginning all you know is **N** and **B**. You send a sequence of **N**/2 `0`

’s and **N**/2 `1`

’s, and from the answer you can infer how many of the **B** broken workers belong to the former **N**/2 and how many belong to the latter. Hence, with one query, you divide your question into two smaller ones, which can be further queried *in parallel*. Hence, with 10 queries, you can solve any combination of **N** and **B** as long as **N** is not larger than $2^{10}=1024$.

The hard test case requires to use the fact that **B** is at most 15. The basic idea is the same, but in your first query you send a sequence of alternating 16 `0`

’s and 16 `1`

’s. Since there are at most 15 broken workers, you can still infer how many of the broken workers belong to each of the 16-worker groups. Hence, **N** does not actually matter if **B** is limited to 15.

Google Code Jam has, once again, migrated to a cool new system. While the qualification round is definitely not hard, it offers a good opportunity to get a taste of the upcoming challenges.

I decided to use Python to solve problem 3 since I do not have a C++ library to deal with big numbers. I could have written one, but it would be annoying since I need to cover modulo and division. This has brought my regret during my Code Jam Final session last year: I wanted to use Python but since I have never used it in a competition, I didn’t want to take the risk. I should definitely get myself prepared for situations like this. *And* I should definitely have a C++ big number library ready. This kind of things reduce the frustration when you know the solution, but don’t have the time to type the routines.

This is something that has been bothering me since the first day of Gutenberg.

For the record, when viewing a post, the post title is shown in `h1`

.

`<h1 class="entry-title" itemprop="headline">Title of a Post</h1>`

On the other hand, the same post title is shown in `h2`

in post lists.

`<h2 class="entry-title" itemprop="headline">Title of a Post</h2>`

A weirder thing is that the site title in the main page is also shown in `h2`

, despite occupying the same design space as the post title when viewing the post.

Hence, if the top level heading in a post is `h3`

, Gutenberg will complain, and when you view the post you get a page without `h2`

in the hierarchy. On the other hand, if the top level heading in a post is `h2`

, the post list will be arranged illogically.

There is indeed a compromise between them: if we accept that sub-headings in a post are never importantly enough to belong to a post excerpt, then we should settle with `h2`

’s and there is no logical inconsistency as long as we stick to the premise. This actually makes sense, but it restricts our freedom a bit. We should not decide what to show in the excerpt for this kind of reasons. I can only say that it is a coincidence that we still have a viable solution.

Since the choices of headings outside post content are made by the theme, I blame Kahuna here. I might some day talk to their authors, though I don’t think they are going to adjust for that, since backward compatibility is a good enough reason to stop them from “fixing” the bug that probably only I am going to care.

Classic Editor

Gutenberg Editor

And these are the corresponding code. Of course, I manually changed their dimensions to make for a fair comparison.

```
<a href="https://blog.ahyangyi.org/wp-content/uploads/2018/10/de_finibus-1.png">
<img class="alignnone size-medium wp-image-626" src="https://blog.ahyangyi.org/wp-
content/uploads/2018/10/de_finibus-1-300x300.png" alt="" width="300" height="300" /></a>
```

```
<figure class="wp-block-image"><img src="https://blog.ahyangyi.org/wp-content/up
loads/2018/10/de_finibus-1.png" alt="" class="wp-image-626"/></figure>
```

Again, there seems to be a theme integration problem. The Kahuna extra option for figures are not triggered by Gutenberg-style images despite the latter is also perfect fine HTML code.

The LaTeX2HTML plugin works fine with Gutenberg.

The custom Prism-based plugin, however, is utterly broken by Gutenberg. It insists to convert a regular block into a “preformatted” one, and forcibly strips all classes that I have manually added and replaces them with a useless `class="wp-block-code"`

clause. It makes my current syntax highlighting solution unusable.

I am pretty sure that there are a few Gutenberg-based solutions to the syntax highlighting problem here. However, it disgusts me that it simply breaks my old way without offering any workaround. I used to think that the generic “Paragraph” block is at least a catch-all thing since I can switch to HTML mode and insert whatever code I want. However, this serves as a cautionary tale to think that way: Gutenberg is dirtier than that. It makes wild assumptions and is not really designed for people who know what they want.

This is an early examination of what Gutenberg can bring to this blog. Some of the problems are caused by the theme, usually by making assumptions that no longer hold under Gutenberg. Other problems seem to be caused by Gutenberg’s philosophy. My hope of the existence of easy work around of all problems seems to have been distinguished, and the problems probably need more efforts to fix.

]]>Hence, despite the concerns, here I updates the website.

There are various plugins that can back up the data base. However, after surveying about the various possibilities, I decided to begin with a simple solution — back up the entire database manually. At least there is no intermediate layer and confusing UI between me and the result.

The back up command is just a one-liner:

```
mysqldump -u $USER_NAME -p $DATABASE_NAME --single-transaction \
--quick --lock-tables=false > $DATABASE_NAME-backup-$(date +%F).sql
```

It turns out that the database is just in the scale of about 2MB in plain text. I can casually back up whenever I feel like it, and not take too much disk space. Nice.

So I backed up the database, and the WordPress directory itself. After updating WordPress to 5, I realize that Gutenberg is no longer needed since it is now fully integrated to the system. On the other hand, I need to do something to get back the classical editor. That is, I need to install the Classical Editor plugin.

Thankfully, life with the classical editor plugin is actually easier than before. It used to by default assume I was going to use Gutenberg, since the Gutenberg plugin messed up the priority of the plugins. The current one, on the other hand, offers me choices and allows me to set a default. So I can use the classical editor by default and use the Gutenberg editor when I feel like it. This is how it should have been, but it was not. Anyway, it is an improvement. Surprise.

The classical editor plugin has a shell life of about 3 years. So I need to consider my options before it goes obsolete again.

Let us jump to the simple conclusion. It updates. Nothing breaks. One plugin is no longer necessary but another plugin has to be introduced. Overall, everything is fine, though one wants to start planning for the future from now on.

]]>