Wednesday, 3 July 2024

Magical coin

Magical coin

setup

You are traveling home on a gloomy night in the dead of winter. You clutch the edge of your cloak with your frozen fingers, hoping to protect yourself from the hailstorm. Suddenly, a shadowy figure blocks your path. It speaks to you in a low, crackling tone.
“Could I interest you in a magical coin?”
You try to ignore the figure and continue walking, but it stops you.
“Don’t be rude, at least take a look at it.”
You are to tired to argue, so you sigh, and decide to humour the creature. “What does the coin do?” you ask. “What makes it magical?”
The creature grins, revealing a row of crooked teeth. “Whenever you play any game —any game at all— decided by flipping this coin, you have a fifty-five percent chance of winning.”
“Why would I want this?” I frown. “For one dollar, I can buy a coin with heads on both sides. That gives me a one hundred percent chance. This coin is similar but worse.”
The creature chuckles. “To a simple mind, maybe, but a smart man like you should be able to see this coin’s limitless potential.”

How the coin breaks reality

On first glance, the coin appears to be practically useless, or at least as useful as a slightly rigged coin. However, the shadowy figure did claim that the coin was powerful. So the first question we can ask ourselves is, “Is there anything we can do with the magic coin that we can not do with the double-headed coin?”

This answer is easy: “What if we need tails to win?” In other words, “What if we, as the ‘player,’ are not allowed to decide which option (heads or tails) is winning?”

This isn’t reality-breaking yet. With a little practice, a human can consistently throw and catch a coin in exactly the same way. The outcome of the coin flip is only determined by how you hold the coin before flipping. So depending on whether you need heads or tails to win, you just hold the coin differently. It is hard to do it one hundred percent consistently, but beating the fifty-five-percent odds is perfectly doable.

The second question we ask ourselves is, “How does our magical coin differ from this slight-of-hand trick?” What can our magical coin do that the slight-of-hand coin cannot?"

The solution is straight-forward. What if the game is set up in such a way that we do not know whether heads or tails are winning.

Imagine the following game:

Let’s flip a coin. Tomorrow, we will check the lottery results to see if the number 1 was drawn. If so, heads wins. If not, tails wins.

For this game, the rigged coin and the trick do not help (in a way they do, cause tails has a bigger chance of winning, so to maximize the winning chances, rig it to tails). But more importantly, we are not interested in winning this game, but more so in winning the lottery.

Knowing with 55% certainty that a number will appear in the lottery results is an advantage, probably, but we can do better.

We can play this game ninety-nine times and total the number of heads and tails. This is similar to drawing from a binomial distribution with unknown pp.

number of heads head is winning (p=0.55p=0.55) tail is winning (p=0.45p=0.45)
49\leq 49 16 % 84 %
50\geq 50 84 % 16 %

*Note: We chose 99 rather than 100 times because an odd number of coin flips prevents the number of heads and tails from tying.

This gives us an 84% chance of correctly predicting the lottery number.

If we repeat this for all 45 numbers, our chances of correctly predicting all numbers are 0.06%. Which is significantly higher than the 0.0000001% chance you typically have, but still disappointingly low.

We can slightly improve our chances by selecting the six highest numbers rather than 50 as a cut-off point. Doing this will give us a 5% chance of winning. We can improve this probability by increasing the number of coin flips. For example, flipping each number 200, 300, or 400 times results in 28, 59, and 80 percent, respectively.

But then again, do you want to spend five hours flipping a coin?

Rigging it even more

Let us take a look at this game:

Throw ten coins. You win if.

  1. all coins are heads and tomorrow’s lottery results includes a 1
    OR
  2. all coins are tails and tomorrow’s lottery results does not include a 1

As this is indeed a game “that is decided by flipping this coin,” we have a 55% chance to win. This means that the one winning sequence has a 55%55\% chance of failing, while all other sequences have a 45%1023\frac{45\%}{1023} chance.

Note

If you are not convinced that all losing sequences have the same chance of appearing, consider that a non-uniform distribution of losing sequences makes rigging even easier. This is because in our game, we can change the second option as follows:
2. All coins are [whichever sequence had the lowest chance of appearing in option 1] and tomorrow’s lottery results do not include a 1

So, we obtain the following distribution table:

number of heads result contains a 1 result does not contain a one
10 55 % 0.034 %
0 0.034 % 55 %
any other 44.976% 44.976%

Using Bayes’ theorem, if we get ten heads in a row, the probability that our result includes one is 99.3%. Similarly, if we get ten tails in a row, the probability that our result does not include one is also 99.3%.
However, we only have a 55.034% chance of actually getting a decisive result. This is not an issue. If we do not get a definitive answer, we can simply play the game again. On average, we have to play 1.81 games or toss 18 coins before we get our result.

We can improve this concept by changing it to the following game.

Toss a coin 50 times. You win if the coin flips spell out the winning lottery numbers for tomorrow in binary, followed by 14 heads, and lose otherwise.

This method requires only 50 coin tosses to reveal all six numbers, making it more efficient.

Adversarial coins

In the previous chapter, I assumed that if the game was already lost, the coin would have a 50/50 chance of coming up heads or tails. What if that is not true and the coin has an unknown chance of coming up heads or tails? Or worse, what if the shadowy figure actually was the devil and had given us an adversarial coin? A coin that, whenever a game is not decided by our flip, ends up on whichever side we do not want.

Before we actually design a game that fixes this loophole (and actually abuses the fact that this is unspecified), let’s take a look at this simpler self referencing coin game, using a non-magical coin.

Flip two coins.
You win if:

  1. you get heads two times , AND the chance of winning this game is larger than 70%.
    OR
  2. you get tails at least one time AND the chance of winning this game is lower or equal to 70%.

If you try to calculate this, you will quickly realize it is a paradox. If we assume the chance is lower than 70%, it will be 75%, leading to a contradiction. However, if we assume the chance is higher than 70%, it will be 25%, also leading to a contradiction.

So, lets build a game using this pattern.

Flip a rigged coin.
You win if

  1. the coin lands on heads AND The sun always had had a 100% chance of exploding in the next 5 seconds, independent of the result of the coin.
    OR
  2. The chance of winning was not 55%

Lets break this down. The chances depend on three parameters:

  1. itself
  2. whether or not the sun “had had a 100% chance of exploding in the next 5 seconds, independent of the result of the coin.”
  3. chance to toss heads (referred to as hh)

In table form:

sun explodes sun does not explode
p=0.55p=0.55 p=hp=h p=0p=0
p0.55p \neq 0.55 p=1p=1 p=1p=1

There remain two possibilities

  1. You win, independent of the sun and the coin.
  2. You have a 55% chance of winning, the coin has a 55% chance of landing on heads, and the sun has a 100% chance of exploding.

If you play this game with any coin, rigged or not, option one is clearly the outcome. But as the coin the devil gave us is defined to have a 55% chance of winning, the only way to resolve this option 2, which states: “The sun always had had a 100% chance of exploding in the next 5 seconds, independent of the result of the coin.”

Except it does not. Because the devil clearly stated “any game decided by this coin.” If option 2 is false, you automatically win. In other words, the game is not decided by the coin, so the 100% win chance does not violate the devil’s promise.

We can fix this issue by adding an extra condition.

Flip a rigged coin.
You win if

  1. the coin lands on heads AND The sun always had had a 100% chance of exploding in the next 5 seconds, independent of the result of the coin.
    OR
  2. the coin lands on heads AND The chance of winning was not 55%

In table from:

sun explodes sun does not explode
p=0.55p=0.55 p=hp=h p=0p=0
p0.55p \neq 0.55 p=hp=h p=hp=h

There remain two possibilities

  1. You win on heads. independent of the sun. The chance to win is anything but 55%.
  2. You have a 55% chance of winning, the coin has a 55% chance of landing on heads, and the sun has a 100% chance of exploding.

As both options imply the game is decided by the coin flip, the chance to win has to be 55%, which means only option 2 can be true.

Which can only mean the sun explodes with 100% certainty, independent of the actual result.

Back to winning the lottery

Sure, blowing up the sun is nice and all, but lets look back at how we can use this to win the lottery.

Consider the following game:

Toss a coin 50 times
You win if

  1. The coin spells out the winning lottery numbers in binary, followed by 14 times heads.
    AND
  2. The coin always had been rigged (with a 100% chance) such that it had a 45% chance to spell out the winning lottery numbers, followed by 14 tails.

Otherwise, you lose.

If the coin is not rigged as described, you will never win, which would violate the “55% chance to win” condition, so condition 2 must hold true.

This does not work for the same reasons stated above. If condition 2 does not hold, you will undoubtedly lose, indicating that the game is not decided by a coin flip.

We can fix that by always making it decided by coin flip.

Toss a coin 50 times
You win if
open parentheses (
The coin spells out the winning lottery numbers in binary, followed by 14 times heads.
AND
The coin always had been rigged (with a 100% chance) such that it had a 45% chance to spell out the winning lottery numbers, followed by 14 tails.
close parentheses )
OR
open parentheses (
The chance to win is not 55%
AND
Last coinflip is heads.
close parentheses )
Otherwise, you lose.

This will always spell out the winning lottery numbers, followed by either heads or tails.

Thursday, 15 December 2022

Listen to the sea

 

Rockstar is an esoteric programming language that creates code that looks like song lyrics.

I tried to use it to solve this code puzzle: https://adventofcode.com/2022/day/1.

This wasn't that hard, and after puzzling a bit, I ended up with this code that works.

my ship is everything
waves are everything
let my life be waves
let my dreams be waves
Listen to the sea

A pirate wants gold and freedom
If gold is greater than freedom
send gold

give freedom back

While the sea isn't mysterious or the mind isn't mysterious
If the sea is silent
let my life be a pirate taking my ship, and my life
let my ship be waves
Put the sea into the mind
Listen to the sea

If the sea isn't silent
let my love be the sea without waves 
let my ship be with my love
Put the sea into the mind
Listen to the sea


let the sea be my life
shout her

(Full explanation of all the lines follows further below in this blogpost)

You can try it online, and it returns the correct answer if you append two newlines to the bottom of the input. But this could be nicer.

According to the specifications, the expression:
the sea is mysterious

It should return true if "the sea" is null (meaning end of file) and false if "the sea" is an empty string. 

In addition, the expression:  
If the sea is silent

should return true if the sea is an empty string.

But in practice, due to a bug in the interpreter, both mysterious and silent act exactly the same and match both an empty string and a null value. This means we cannot distinguish between the two and need two newlines at the end to ensure the program can detect it.

If we write a program according to spec, we get these lines.

my ship is everything
waves are everything
let my life be waves
let my dreams be waves
Listen to the sea

A pirate wants gold and freedom
If gold is greater than freedom
send gold

give freedom back

While the sea isn't mysterious
If the sea is silent
let my life be a pirate taking my ship, and my life
let my ship be waves
Listen to the sea

If the sea isn't silent
let my love be the sea without waves 
let my ship be with my love
Listen to the sea


let the sea be my life
shout her


When I first made this edit, I accidentally also removed the line "let my ship be waves"  and I actually found that the song flows better without that line, so I decided the keep the "wrong" version. (If you wanna have a singable fixed version, you can move the last "Listen to the sea" one line down, and replace the second "listen to the sea" with "let my ship be waves".)

I also realigned the verses, so each verse has 4 lines. I also broke down long lines into two, and combined some shorter lines.

Both these changes completely break the program as a valid rockstar program, but make it possible to actually sing it.

So then I end up with verses that are close to the working program but not quite.

my ship is everything
waves are everything
let my life be waves; let my dreams be waves
Listen to the sea

A pirate wants gold and freedom
If gold is greater than freedom
send gold, give freedom back
While the sea isn't mysterious

If the sea is silent
let my life be a pirate 
taking my ship, and my life
Listen to the sea

If the sea isn't silent
let my love be the sea without waves 
let my ship be with my love
Listen to the sea

let the sea be my life
shout her


This can actually be sung, so I hired Liliia K  to sing it for me. The result can be seen below




The full song (before I applied a bunch of artistic licences) is equivalent to the following python code. 


myShip = 0
waves = 0
myLife = waves
myDreams = waves
theSea = input()

def aPirate(gold, freedom):
    if gold > freedom:
        return gold
    return freedom

while theSea is not None:
    if theSea == '':
        myLife = aPirate(
            myShip, myLife
        )
        myShip = 0
        theSea = input()
    if theSea != '':
        myLove = theSea - waves
        myShip += myLove
        theSea = input()

theSea = myLife
print(theSea)

There are only two caveats. 

  1. the input function in python blocks when there are no more lines to read, I modified it to return None instead. This matches the behaviour in rockstar
  2. Rockstar uses javascript internally, so a string minus an integer is an integer. In python, this gives an error.
You can add these lines above your script to mitigate both problems.

with open("input1.txt") as file:
    lines = list(reversed(file.read().split("\n")))


def input():
    if lines:
        l = lines.pop()
        try:
            return int(l)
        except ValueError:
            return l

Here follows a line-by-line explanation of all the code:

myShip = 0       | my ship is everything
waves = 0        | waves are everything
myLife = waves   | let my life be waves
myDreams = waves | let my dreams be waves

We initialise a bunch of variables. "everything" has ten letters, so the value of the poetic literal is 0. 
The variable "myDreams" is never used, but it was left over after a refactor, and the song flows better using the variable, so I decided to leave it.

theSea = input() | Listen to the sea

Store the current line from the input into the sea. Rockstar does not have "foreach" nor "do while" loops, so the only way to read the input line by line is to initialize "theSea" to the first line before the while loop. More about that later.

def aPirate(gold, freedom): | A pirate wants gold and freedom
    if gold > freedom:      | If gold is greater than freedom
        return gold         | Send gold
    return freedom          | Give freedom back

Define a function "aPirate" that takes in two arguments ("gold" and "freedom") and returns the larger one. Needs a newline after "Send gold" to close the if block and after "return freedom" to close the function call.

while theSea is not None:  | While the sea isn't mysterious

A while loop. while the input file has unread lines. 

if theSea == '': | If the sea is silent

Checks if we have read an empty line. In the context of the riddle, we start to count the calories of a new elf.

myLife = aPirate(myShip, myLife) | let my life be a pirate taking my ship, and my life

"myLife" is a variable that stores the elf with the highest amount of calories. "myShip" stores the calories of the current elf. This line of code stores the maximum of the calories of the current elf and the already found maximum into the maximum. In python terms, this would be equivalent to myLife = max(myShip, myLife). This changes the variable "myLife" from "the highest number of calories excluding the current elf" to "the highest number of calories including the current elf."

myShip = 0 | let my ship be waves

Resets the "myShip", meaning the "current calory counter" back to zero. This line is missing in the sung version.

theSea = input() | Listen to the sea

Reads the next line of the input

if theSea != '': | If the sea isn't silent

Checks if we have read a non-empty line. This is the alternative (else) branch of the previous if. Although in practice, it can be shortcutted cause the variable "theSea" might have changed since the previous if. This makes no difference to the actual execution of the code.

myLove = theSea - waves | let my love be the sea without waves 


Converts "theSea" to an integer. This is a hack. In javascript -and rockstar by extension- subtracting zero from a string converts it into an integer. So "myLove" ends up with a number of calories as an integer. 


myShip += myLove | let my ship be with my love

Adds the number of calories on the current line to the number of calories of the current elf. 

theSea = input() | Listen to the sea


Reads the next line of the input

theSea = myLife | let the sea be my life
print(theSea) | shout her

Just a poetic version of printing the current maximum stored in "myLife."




Monday, 25 April 2022

Lunar Lockout

 I made a small web applet in which you can play Lunar Lockout. The first 40 puzzles are the official puzzles by the makers of the game, and the following 80 are puzzles generated by an AI. 

The applet can be found here: https://elmosfire.gitlab.io/lockoutpuzzles/

In addition, all solutions to the official puzzles can be found here, nicely animated: https://www.youtube.com/watch?v=35rG8Cl0Hac

The Rules:

The characters can only move up, down, left and right.
You can only move a character on the board if its movement can be blocked by another character.
The red character will pass over the centre square unless a proper block has been made for normal movement there.

Movement:

In order to move the different characters, you must first click the character you would like to move.
This character will stay selected until you click another one or you beat the match.
Upon starting a new level the red character will become selected
Use the number pad or arrow keys to move your character.

Tuesday, 29 March 2022

Light switch puzzle

Thomas has a row of lamps, of odd length. Each lamp has two possible states: on or off. Next to each lamp, there is a switch. If a lamp is on, then pressing the switch next to it will change the state of the two neighbours of the lamp (only one if the lamp is at one of the ends of the row), but the lamp itself will remain on. The switches next to lamps that are off do nothing. At the start, only one lamp was on. At what positions in the row could this lamp have been, given that Thomas managed to turn all lamps on?

The source of this riddle can be found here

This problem can obviously be solved with an invariant. But strangely enough, finding this invariant by trial and error is harder than it seems. And even if you find it, this solution does not give you inside into how the problem works and how you could solve similar problems, so while they work, they are less than helpful.

For example, for the above riddle, I could state:

If we define

A = \left(\begin{matrix}1&0\\0&-1\end{matrix}\right)

and

B = \left(\begin{matrix}1&1\\0&1\end{matrix}\right)

replace each on-lamp with A, and each off-lamp with B, and multiply all matrixes, the end result forms an invariant, and as AnBAm=B is only valid if m=n, the lamp has to be in the centre.

This solution works but is not helpful.

So instead of trying to find a solution, we will describe a semi-structural way to find a solution.

Structural solution.

First, we notice that switches work differently when they are on the first or last lamp. This can be fixed by adding virtual lamps at the start and end of the line. These lamps have a state but not a switch.

We work with a system that is discrete, local, one-dimensional and finite, so it might be a good idea to replace each lamp with a group element, and then multiply the group elements in order.

Let us use the following notation for this group:

a: lamp turned off

x: lamp turned on

Then our invariant has to satisfy the following equations:

\begin{align*}xxx&=axa\\xxa&=axx\end{align*}

Note that every group satisfying this will be invariant, but not every group will be useful. For example, if we take the group

\inline (\mathbb{Z},+)

and define a=1 and x=1, our invariant will be the total number of lamps.

Although, even as "the number of lamps in our final state has to be the same as our initial state" is obvious, the fact that a statement we know is true follows from our math, is a good check to verify if are statements are correct.

The difficult part here is finding a group that is simple enough to actually work with it, but complex enough so it still contains the information we need. This might cause some trial and error, and is very case dependent. Luckily, for this riddle, we can make the statement that we are interested in the position of our lamps, so elements of our group that are central, so that can be moved freely without changing the invariant, are useless. Therefore it might be useful to consider a centerless group.

In addition, we will assume that are group is generated by a and x, there is no reason to complicate our group with other generators.

So first, we notice that x^2 commutes with both x (by definition) and a, (given). Therefore,

x^2 = 1

Using this, we can see that:

\begin{align*}xxx&=axa\\x&=axa\\xx&=axax\\1&=(ax)^2\end{align*}

Now we know that is group contains 2 elements that do not commute and square to the unit element. This means our group is the infinite dihedral group. But if you don’t know the group names from the top of your head, you can just go to Wikipedia: Symmetry groups and pick the one that has the correct properties.

To be fully rigorous, we have to check that x and b=ax do generate the group, but as a=bx, this is trivially true.

Given this group, The initial state can be represented as anxam and the final state as x. Putting both statements to be equal gives us am-n=1 which can only be true if m-n=0. Therefore the final state can only be reached if the centre lamp was on.

If you want to be fancier, you can prove that every state matching the invariant (and the invariant of the number of lamps) can be actually reached, but that is outside of the scope of this blogpost.

Friday, 28 January 2022

Wordle strategy

Wordle is a popular word game similar to mastermind.
If you do not know how to play, the linked website explains it better than I can.

The naive tactic is to guess a random word that you think might be the solution. This tactic might work, and as this game is very luck-based, an optimal tactic will not necessarily do better.

But in practice, this tactic does not bode very well. In essence, the program has the information. You, as a player, are trying to get the information. There is no point in confirming the information you already know to be true.

For example, imagine you picked as the first word “pound”, and the game returned that “o”, “u”, “n”, and “d” are correct. Furthermore, “p” is absent. There are multiple different words you might pick next, like “found”, “sound”, “round”, or “wound”. But if we are unlucky, we will need four guesses. A better guess would be “safer”. We can immediately distinguish between the different words depending on the letter that lights up.

To refine this tactic, we will need to quantify our notion of information. One can easily see that if only a single possible word could be the solution, information is very high. Similarly, if the solution can be any word, information is low. Therefore a good measure for the entropy would be the number of possible words.

This means that we will search the word to guess such that the worst-case entropy is minimal. This means that we partition the set of possible words into subsets for each word depending on the feedback we would get if this word were the solution. We take the size of the most significant subset, and we minimise that. We can keep doing this in a loop.

All the possible guesses can be precalculated, and the solution you can find here:

or in fullscreen view: here

Tuesday, 21 December 2021

Advent of code 2021 day 8, seven segment displays, regex only solution.

I made a video about a specific technique to solve this puzzle using fingerprinting a while ago.

This technique is more efficient and faster than most methods I have seen online, but I still wondered if better, faster or fancier ways were possible.

So instead of building an actually fancier program, I created this:

([a-g ]+) \| ([a-g]+) ([a-g]+) ([a-g]+) ([a-g]+)
$1 | $2 ¶ $1 | $3 ¶ $1 | $4 ¶ $1 | $5
%(`([a-g ]+) \| ([a-g]+)
K`$1¶R`[$2]¶_
~`$-
_
[^_]

(_+)
$.1
%)`

42
0
17
1
34
2
39
3
30
4
37
5
41
6
25
7
49
8
45
9
(\d)¶(\d)¶(\d)¶(\d)
$1$2$3$4
(\d+)¶?
$1*_
_

Try it online

This retina program replaces the input with the solution to the puzzle.

I have tested it on both the example and my own input. And despite being regex, it is really fast. It finishes without a single second on my machine.

How the math works

First, I searched for a fingerprint for each digit. A fingerprint must always have two properties:

  1. It must be unique for the object (in this case, digit)
  2. It must be invariant under changes that we do not know. (in this case, shuffling digits and segments

A fingerprint that does this can be found as follows:

Step 1: Take a specific segment. Count for all digits how many times it is 0.

For example, the top segment is on for the digits 0, 2, 3, 5, 6, 7, 8 and 9. So for that segment, we remember 8.

Doing this for the others yields 6, 8, 7, 4, 9, 7.


Step 2: Sum all the values of the segments which are on.

For example, for 0, almost all digits are on, so 8+6+8+4+9+7=42

We can do this for every number, giving:

1: 8+9=17

2: 8+8+7+4+7=34

3: 8+8+7+9+7=39

4: 6+8+7+9=30

5: 8+6+7+9+7=37

6: 8+6+7+4+9+7=41

7: 8+8+9=25

8: 8+6+8+7+4+9+7=49

9: 8+6+8+7+9+7=45

Efficient calculation

As our data is provided like this:

be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe

We do not have to combine our segments into digits. We can calculate our fingerprint by counting the number of times each of the characters in our output digit appears on the pipe symbol’s left side.

Programming

Now that we have an algorithm, we can write a program as follows:
First, we create a separate line for each output digit:

([a-g ]+) \| ([a-g]+) ([a-g]+) ([a-g]+) ([a-g]+)
$1 | $2 ¶ $1 | $3 ¶ $1 | $4 ¶ $1 | $5

This will change be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe cefdb cefbgd gcbe to

be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe
be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | cefdb 
be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | cefbgd 
be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | gcbe

Then we open multiline mode with

%(`

Then for each line, we craft a new regex. Specifically, we make the first part of each statement a constant and the last part a list of characters.

([a-g ]+) \| ([a-g]+)
K`$1¶R`[$2]¶_

For example our first line

be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb | fdgacbe

will be replaced by

K`be cfbegad cbdgef fgaecd cgeb fdcge agebfd fecdb fabcd edb 
R`[fdgacbe]
_

This itself is a valid retina program
What is does is take whatever the left side of the system was a a constant.
And then replace every character that was on the right side by an underscore.
The next statement

~`$-
_

Will execute the retina program be build before as a retina program (so it is equivalent to an evalute). Notice that this is not injection proof. If we supply a tainted input data, we can execute arbitrary code.

This will replace our first line with

__ _______ ______ ______ ____ _____ ______ _____ _____ ___
__ ____ga_ ___g__ _ga___ _g__ ___g_ ag____ _____ _a___ ___ 
__ _____a_ ______ __a___ ____ _____ a_____ _____ _a___ ___ 
__ _f___ad __d__f f_a__d ____ fd___ a___fd f__d_ fa__d _d_

So every character that has to be counted is replaced by an underscore.
The next peiece of code replaces everything that isn’t an underscore with nothing. This removes everything except the underscores.

[^_]

So our first line becomes:

_________________________________________________
_______________________________________ 
_____________________________________________ 
______________________________

We then count the number of underscores in each line:

(_+)
$.1

So then each line is the correct fingerprint

49
39
45
30

The next two lines just close multi-line mode.

%)`

Then we apply the mapping from our fingerprints to our digits as stated in line one:

42
0
17
1
34
2
39
3
30
4
37
5
41
6
25
7
49
8
45
9

Each two lines is just a replace, so it read

key 
value 
key 
value 
...

Applying this changes our example into

8
3
9
4

The next piece of code:

(\d)¶(\d)¶(\d)¶(\d)
$1$2$3$4

Concatines each 4 lines back into a single number
So we replace our 4 digits with one number

8394

The next three lines sum all numbers

(\d+)¶?
$1*_
_

In essence, it replaces each number with that number of underscores, and then counts the number of underscores. This is a defaulkt way to sum things in unary.

So after doing everything we get the correct answer.

Saturday, 27 November 2021

Corona tests vs symptoms

corona

Who is more likely to have covid? Someone who has a negative selftest,
but has cold-like symptoms, or someone with a positive test but who
has no symptoms?

Define the following:

C: patient has convid
T: patient tested positive
S: patient is symptomatic

We use the following data from the following sources

P(SCˉ)=1/200P(S|\bar C) = 1/200
from: https://www.cdc.gov/mmwr/volumes/70/wr/mm7029a1.htm and https://www.sciencedaily.com/releases/2012/06/120619225719.htm
combined to get symtpomatic common cold cases.
P(SC)=1/2P(S |C) = 1/2
from https://edition.cnn.com/2020/04/01/europe/iceland-testing-coronavirus-intl/index.html
P(C)=367639/11000000P(C) = 367 639/11 000 000
from https://www.worldometers.info/coronavirus/country/belgium/
P(TC)=0.97P(T|C) = 0.97
P(TˉCˉ)=0.85P(\bar T|\bar C) = 0.85
https://covid-19.sciensano.be/nl/procedures/snelle-antigeen-ag-testen-0
And lets assume that the accuracy of the test is independent of the fact of the patient has symptomes
The last to givens can be extrapolated to
P(TˉC)=0.03P(\bar T|C) = 0.03
P(TCˉ)=0.15P(T|\bar C) = 0.15
P(SˉCˉ)=0.995P(\bar S|\bar C) = 0.995
P(SˉC)=0.5P(\bar S |C) = 0.5
P(C)=0.0334P(C) = 0.0334
P(Cˉ)=0.9665P(\bar C) = 0.9665

Law of bayes says:
P(AB)=P(AB)P(B)P(A \land B) = P(A|B)P(B)

If A and B are independant under constant X that
P(XAB)=P(XAB)/P(AB)=P(ABX)P(X)/P(AB)=P(AX)P(BX)P(X)/P(AB)=P(AX)P(BX)/P(AB)P(X)=P(AX)P(BX)/(P(ABX)+P(ABXˉ))P(X)=P(AX)P(BX)/(P(ABX)P(X)+P(ABXˉ)P(Xˉ))P(Xˉ)=P(AX)P(BX)/(P(AX)P(BX)P(X)+P(AXˉ)P(BXˉ)P(Xˉ))P(X)=P(AX)P(BX)P(X)/(P(AX)P(BX)P(X)+P(AXˉ)P(BXˉ)P(Xˉ))=11+P(AXˉ)P(BXˉ)P(Xˉ)P(AX)P(BX)P(X)\begin{aligned}P(X|A \land B) &= P(X \land A \land B)/P(A \land B) \\ & = P(A \land B|X)P(X)/P(A \land B) \\ &= P(A|X)P(B|X)P(X)/P(A \land B) \\ &= P(A\land X)P(B \land X)/P(A \land B)P(X)\\ &= P(A\land X)P(B \land X)/(P(A \land B \land X) + P(A \land B \land \bar X))P(X) \\ &= P(A\land X)P(B \land X)/(P(A \land B|X)P(X) +P(A \land B|\bar X)P(\bar X))P(\bar X) \\ &= P(A\land X)P(B \land X)/(P(A|X)P(B|X)P(X) +P(A|\bar X)P(B|\bar X)P(\bar X))P(X) \\ &= P(A|X)P(B|X)P(X)/(P(A|X)P(B|X)P(X) +P(A|\bar X)P(B|\bar X)P(\bar X))\\ &= \frac{1}{1 + \frac{P(A|\bar X)P(B|\bar X)P(\bar X)}{P(A|X)P(B|X)P(X)}}\\ \end{aligned}

o(XAB)=P(AXˉ)P(BXˉ)P(Xˉ)P(AX)P(BX)P(X)o(X|A \land B) = \frac{P(A|\bar X)P(B|\bar X)P(\bar X)}{P(A|X)P(B|X)P(X)}

This gives

P(CSˉT)=11+P(SˉCˉ)P(TCˉ)P(Cˉ)P(SˉC)P(TC)P(C)\begin{aligned}P(C| \bar S \land T) &= \frac{1}{1 + \frac{P(\bar S|\bar C)P(T|\bar C)P(\bar C)}{P(\bar S|C)P(T|C)P(C)}}\\ \end{aligned}

Filling in the given numbers this has a chance of 10,09%

And
P(CSTˉ)=11+P(SCˉ)P(TˉCˉ)P(Cˉ)P(SC)P(TˉC)P(C)\begin{aligned}P(C|S \land \bar T) &= \frac{1}{1 + \frac{P(S|\bar C)P(\bar T|\bar C)P(\bar C)}{P(S|C)P(\bar T|C)P(C)}}\\ \end{aligned}

Filling in the given numbers this has a chance of 10,87%

So having symptoms while having a negative test gives you the same chance to have covid as not having symptoms and having a positive test.