Frenetic Array

A canvas for logic and imagination.

A Curious Shebang

If you've ever written a shell script, you might top your script with your interpreter (i.e. #!/bin/sh or #!/bin/bash). What you might not have known that rm is also a valid interpreter. So the following shell script:

#!/bin/rm
echo "Hello, world"  

would simply interpret to be removed. Useful? No. Hilarious watching someone trying to debug? Definitely.

C++ Syntactic Peculiarities

After using a fairly large, matured language for a reasonable period of time, find peculiarities in the language or the libraries is guaranteed to happen. However, given it’s history, I have to say C++ definitely allows for some of the strangest peculiarities in it’s syntax. Below I list three that are my favorite.

Ternaries Returning lvalues

You might be familiar with ternaries as condition ? do something : do something else, and they become quite useful in comparison to the standard if-else. However, if you’ve dealt with ternaries a lot, you might have noticed that ternaries also return lvalues/rvalues. Now, as the name suggests suggests, you can assign to lvalues (lvalues are often referred to as locator values). So something like so is possible:

    std::string x = "foo", y = "bar";

    std::cout << "Before Ternary! ";
    // prints x: foo, y: bar
    std::cout << "x: " << x << ", y: " << y << "\n"; 
    // Use the lvalue from ternary for assignment
    (1 == 1 ? x : y) = "I changed";
    (1 != 1 ? x : y) = "I also changed";

    std::cout << "After Ternary! ";
    // prints x: I changed, y: I also changed
    std::cout << "x: " << x << ", y: " << y << "\n"; 

Although it makes sense, it’s really daunting; I can attest to never seeing it in the wild.

Commutative Bracket Operator

An interesting fact about C++ bracket operator, it’s simply pointer arithmetic. Writing array[42] is actually the same as writing *(array + 42), and thinking in terms of x86/64 assembly, this makes sense! It’s simply an indexed addressing mode, a base (the beginning location of array) followed by an offset (42). If this doesn’t make sense, that’s okay. We will discuss the implications without any need for assembly programming.

So we can do something like *(array + 42), which is interesting; but we can do better. We know addition to be commutative, so wouldn’t saying *(42 + array) be the same? Indeed it is, and by transitivity, array[42] is exactly the same as 42[array]. The following is a more concrete example.

    std::string array[50];
    42[array] = "answer";

    // prints 42 is the answer
    std::cout << "42 is the " << array[42] << ".";

Zero Width Space Identifiers

This one has the least to say, and could cause the most damage. The C++ standard allows for hidden white space in identifiers (i.e. variable names, method/property names, class names, etc.). So this makes the following possible.

    int n​umber = 1;
    int nu​mber = 2;
    int num​ber = 3;

    std::cout << n​umber << std::endl; // prints 1
    std::cout << nu​mber << std::endl; // prints 2
    std::cout << num​ber << std::endl; // prints 3

Using \u as a proxy for hidden whitespace character, the above code can be re-written as such:

    int n\uumber = 1;
    int nu\umber = 2;
    int num\uber = 3;

    std::cout << n\uumber << std::endl; // prints 1
    std::cout << nu\umber << std::endl; // prints 2
    std::cout << num\uber << std::endl; // prints 3

So if you’re feeling like watching the world burn, this would be the way to go.

Painting Gabriel's Horn

There are many things in the world of mathematics and physics that are really quite unintuitive — however, I am not sure there will be anything more unintuitive to me than Gabriel's Horn.

Gabriel's Horn is thus: suppose you have the function $y = \frac{1}{x}$ where $x \in \mathbb{R}^+, 1 \leq x \leq \infty$, rotated around the $x$ axis; not too difficult to conceptualize, it looks like a horn of sorts. But here's the paradox.

Suppose we want to calculate the volume. Simple enough, using solids of revolution, we can show the volume to be:

$$V = \pi \lim_{t \rightarrow \infty} \int _1 ^t \frac{1}{x^2} dx = \pi \lim _{t \rightarrow \infty} ( 1 - \frac{1}{t} ) = \pi $$

A simple, elegant solution; we can expect the volume to be exactly $\pi$. So, let's see about the surface area.

We know the general definition of the arc length to be $\int _a ^b \sqrt{1 + f'(x)^2}$, so combining this with our solids of revolution, we should get

$$A = 2\pi \lim _{t \rightarrow \infty} \int _1 ^t \frac{1}{x} \sqrt{1 + \left( -\frac{1}{x^2} \right)^2 } dx $$

However, this is not a trivial integral; however, there is a trick we can do. Suppose we take the integral $$2\pi \lim _{t \rightarrow \infty} \int _1 ^t \frac{dx}{x}$$ instead, and we can prove this integral will always be equal to or smaller than the former integral (because of the disappearance of $\sqrt{1 + (-\frac{1}{x^2})}$). So, taking this rather trivial integral, we can see that

$$ A \geq 2\pi \lim _{t \rightarrow \infty} \int _1 ^t \frac{dx}{x} \implies A \geq \lim _{t \rightarrow \infty} 2\pi \ln(t) $$

Wait a minute; it's divergent! So we know the volume $V = \pi$, but the surface area $A \geq \infty$. This is no mistake, the math is valid. And that is one of the most counter-intuitive things I have ever ran into.

A horn you can fill with paint, but you can't paint the surface.

Calculus II & III Notes

I have decided to post my Calculus II and Calculus III notes.

Note that these notes are heavily based on Calculus for Scientists and Engineers by Briggs, Cochran, Gillett, and Schulz. I do not own the material and no copyright infringement is intended.

They can be found in projects, under notes.

The Monty Hall Problem

You've seen it in the movies or read about it in the books: the Monty Hall Problem. The premise is such: you are on a game show. There's three doors, behind one is a prize. Behind the other two is nothing besides disappointment. You pick an arbitrary door. The game host, Monty Hall, opens one of the other doors and reveals that there is no prize behind it. Keeping the other two doors closed, he asks you if you would like to switch your choice or remain with your original pick. What should you do? Benc Campbell has a solution.

You're meaning to tell me that if I switch mid-game, an offer by the man who set up all the doors and the respective prizes, I would have a better chance of winning? How is this possible? Seems a bit counterintuitive. Seems almost wrong. Fortunately, we can test this with a simple program.

import Darwin // for arc4random_uniform

func random(from from: Int, to: Int, except: Array<Int>? = nil) -> Int {  
    let number = Int(arc4random_uniform(UInt32(to - from + 1))) + from // produce bounds, +1 to make inclusive

    if except != nil && except?.indexOf(number) != nil {
        return random(from: from, to: to, except: except) // recursively call until you find the a number that doesn't contain the value
    }

    return number
}

// returns if you won when you stayed and switched, respectively
func montyHall(doors: Int) -> (Bool, Bool) {  
    let originalDoor = random(from: 1, to: doors) // Your original choice
    let correctDoor = random(from: 1, to: doors) // The winning choice.

    let revealedDoor = random(from: 1, to: doors, except: [correctDoor, originalDoor]) // The door the judge reveals
    let switchedDoor = random(from: 1, to: doors, except: [revealedDoor, originalDoor]) // Supposing you switched, you woudl

    return (originalDoor == correctDoor, switchedDoor == correctDoor)
}

let testValues = [100, 1_000, 10_000, 100_000, 1_000_000, 1_000_000]  
let actualNumberOfDoors = 3

for value in testValues {  
    var stayingCounter = 0, switchingCounter = 0

    for _ in 0...value {
        let (stayedWon, switchedWon) = montyHall(actualNumberOfDoors)
        if stayedWon { stayingCounter += 1 }
        if switchedWon { switchingCounter += 1 }
    }

    print("Test Case: \(value). Staying Won: \(stayingCounter), Switching Won: \(switchingCounter)")
}

There's no tricks in the code. No gimmicks. So, the results?

Input Staying Won Switching Won
100 42 58
1000 344 656
10000 3289 6711
100000 33203 66797
1000000 333178 666822
10000000 3335146 6664854

It appears that Ben1 was right. Taking the limit as the input get higher, switching won roughly 66% of the time — compared that to the original 33% you got before you were given the option to switch doors. So, how is this possible? I'll explain.

For simplicity, suppose the prize is behind door A out of doors {A, B, C}. The argument can be made for any initial door, but A makes it easier. At this point, you have $\frac{1}{3}$ chance of picking the prize no matter what you pick. If you pick door A, the door which contains the prize, the host will definitely want you to change so he will offer you either door B or C. Now suppose you choose a door without the prize, either door B or C. The host has no choice but to eliminate the door without the prize. Meaning if you switch, you have the winning door.

So, why 66%? Computationally, if you always switch and you picked the wrong door initially, your switch will win every time. There's two incorrect choices out of three, meaning $\frac{2}{3}$ of the time you will win.

You've just had your first lesson in conditional probability.

  1. 21 main character, played by Jim Sturgess