Posts by Philip Pham

One of my seemingly incongruous hobbies is reading classics, particularly, Victorian era novels. Although, I'd like to think that if you really take the time to get to know me, it's not that strange as I can be a bit of a hopeless romantic. In this lonelier chapter of my life, I have found much solace in books.

I've just finished Far From the Madding Crowd by Thomas Hardy. It was a rather difficult read with all the pastoral vocabulary and allusions from the Bible and Greek mythology. My perseverance rewarded me with Hardy's poetical English and an enchanting story.

In the story, Bathsheba Everdene is courted by three different suitors in three different ways. First, there is Gabriel Oak, who shows a steadfast love. Second, there is Mr. Boldwood, who, being a well-established farmer, himself, offers the most practical marriage, both in terms of money and social status. Thirdly and finally, there is Sergeant Troy, who displays a most passionate love. He flirts so well that I found myself being charmed by his wit and eloquence.

I won't ruin the surprise on whom she picks, but I do find it interesting how little modern love has changed. Today, given online dating, women even moreso than back then hold the power of choice. The so-called friend zone is alive and well being present in Vanity Fair, with Captain Dobbin and Amelia, and A Tale of Two Cities, with Sydney Carton and Lucie, too. Men are still losing their minds over women. One very forward-thinking quote I found was

The good-fellowship — camaraderie, usually occuring through similarity of pursuits, is unfortunately seldom super-added to love between the sexes, because they associate not in ther labours, but in their pleasures merely.

It does seem that this ideal of love is more a reality in today's world now that women are part of our workforce. This love is claimed to be "strong as death." Perhaps, I'll start looking out for this "similarity of pursuits."


A classic programming problem is to find all the primes up to a certain number. This problem admits a classic solution, the sieve of Eratosthenes. Here it is in Java.

/**
 * @param upper bound exclusive
 * @return a list of primes strictly less than upper
 */
public static Deque<Integer> findPrimes(int upper) {
    Deque<Integer> primes = new ArrayDeque<Integer>();
    if (upper <= 2) return primes;
    primes.add(2);
    boolean[] isPrime = new boolean[(upper-2)/2]; // index 0 is 3
    Arrays.fill(isPrime, true);
    for (int p = 3; p < upper; p += 2) {
        if (isPrime[p/2 - 1]) {
            primes.add(p);
            // only need to start from p^2 since we already checked p*m, where m < p
            for (long q = ((long) p)*((long) p); q < upper; q += 2*p) {
                isPrime[((int) q)/2 - 1] = false;
            }
        }            
    }
    return primes;
}

The problem is with the isPrime array. This solution is $O(n)$ in space and computation. We may only be interested in finding large primes from say 999,900,000 to 1,000,000,000 as in this problem PRIME1. It doesn't make sense to check numbers less than 999,900,000 or allocate space for them.

Hence, we use a segmented sieve. The underlying idea is that to check if a number $P$ is prime by trial division, we only need to check that it is not divisible by any prime numbers $q \leq \sqrt{P}$. Thus, if we want to find all the primes between $m$ and $n$, we first generate all the primes that are less than or equal to $\sqrt{n}$ with the traditional sieve. Let $S$ be the set of those primes.

Then, let $L$ be some constant number. We work in segments $[m, m + L)$, $[m + L, m + 2L)$, $\ldots$, $[m + kL, n + 1)$. In each of these segments, we identify of all the multiples of the primes found in $S$ and mark them as not prime. Now, we only need $O(\max(|S|, L))$ space, and computation is $$O\left(|S| \cdot \frac{n-m}{L} + (n-m)\right),$$ and we can set $L$ to be as large or small as we want.

By the prime number theorem, $|S|$ is not typically very large. Asympototically, $$|S| = \pi(\sqrt{n}) \sim \frac{\sqrt{n}}{\log \sqrt{n}}.$$ For $L$, we have a tradeoff. If we have large $L$, we may need a lot of space. If we have $L$ too small, our sieve is very small and may not contain many multiples of the primes in $S$, which results in wasted computation. Here is the code with some tweaks to avoid even numbers.

/**
 * Find primes in range
 * @param lower bound, inclusive
 * @param upper bound exclusive
 * @param sieveSize space to use
 * @return list of primes in range
 */
public static Deque<Integer> findPrimes(int lower, int upper, int sieveSize) {
    if (lower >= upper) throw new IllegalArgumentException("lower must be less than upper");
    int sievingPrimesUpper = (int) Math.sqrt(upper);
    if (lower <= sievingPrimesUpper || sievingPrimesUpper <= 2) {
        Deque<Integer> primes = findPrimes(upper);
        if (!primes.isEmpty()) while (primes.peekFirst() < lower) primes.removeFirst();
        return primes;
    }                
    if (sieveSize < 5) sieveSize = 10;
    Deque<Integer> primes = new ArrayDeque<Integer>();        
    if (lower <= 2) primes.add(2);
    Deque<Integer> sievingPrimes = findPrimes(sievingPrimesUpper + 1);
    sievingPrimes.removeFirst(); // get rid of 2
    while (!sievingPrimes.isEmpty() &&
           sievingPrimes.getLast()*sievingPrimes.getLast() >= upper) sievingPrimes.removeLast();
    if (lower % 2 == 0) lower += 1; // make lower odd
    boolean[] isPrime = new boolean[sieveSize]; // isPrime[i] refers to lower + 2*i
    /** 
     * Find first odd multiple for each sieving prime. lower + 2*nextMultipleOffset[i]
     * will be the first odd multiple of sievingPrimes[i] that is greater than or
     * equal to lower.
     */
    int[] nextMultipleOffset = new int[sievingPrimes.size()];
    int idx = 0;
    for (int p : sievingPrimes) {
        int nextMultiple = lower - (lower % p); // make it a multiple of p
        if (nextMultiple < lower)  nextMultiple += p; // make it at least lower
        if (nextMultiple % 2 == 0) nextMultiple += p; // make sure it's odd
        nextMultipleOffset[idx++] = (nextMultiple - lower)/2;
    }
    while (lower < upper) {
        Arrays.fill(isPrime, true);
        idx = 0;
        for (int p : sievingPrimes) {
            int offset = nextMultipleOffset[idx];
            for (int j = offset; j < sieveSize; j += p) isPrime[j] = false;
            /** 
             * We want (lower + 2*sieveSize + 2*(nextMultipleOffset[idx] + k)) % p == 0
             * and (lower + 2*sieveSize + 2*(nextMultipleOffset[idx] + k)) % 2 == 1,
             * where k is the correction term. Second equation is always true. 
             * First reduces to 2*(sieveSize + k) % p == 0 ==> (sieveSize + k) % p == 0
             * since 2 must be invertible in the field F_p. Thus, we have that
             * k % p = (-sieveSize) % p. Then, we make sure that the offset is nonnegative.
             */
            nextMultipleOffset[idx] = (nextMultipleOffset[idx] - sieveSize) % p;
            if (nextMultipleOffset[idx] < 0) nextMultipleOffset[idx] += p;
            ++idx;
        }   
        for (int i = 0; i < sieveSize; ++i) {
            int newPrime = lower + i*2;
            if (newPrime >= upper) break;
            if (isPrime[i]) primes.add(newPrime);
        }
        lower += 2*sieveSize;
    }
    return primes;
}

Perhaps the funnest part about this blog was writing the commenting system. One may want to comment on a comment. I found a way to support this behaviour with recursion.

In the layout, using Jade mixins, we have something like

mixin commentView(comment)
    - var children = comments.filter(function(child) { return comment.id === child.commentId; })
    .wmd-preview!= comment.bodyHtml
    .children
        .inner-children
            each child in children
                +commentView(child)

We need the inner-children div to create the smooth transitions when you expand the sub-comments. Apparently, CSS transitions only work when the height is specified, so you can calculate the new height of children with inner-children.

We can also expand comments recursively with JavaScript:

function expandParent(node) {
    if (node.classList.contains('comments')) return; // we've reached the top level
    if (node.classList.contains('children')) {
        node.parentNode.querySelector('.reply-expander').classList.add('expanded');
        node.classList.add('expanded');
    }
    expandParent(node.parentNode);
}

I've left some sample comments below to show off the features. Apparently, transitions are only smooth in Chrome and Internet Explorer. Leave a comment below and try it out!


Photo URL is broken

Welcome to my new blog! After about 6 weeks, I've managed to reinvent the wheel in Node.js and have created my own blog. There are a couple reasons why I've decided to do things the hard way instead of using something like WordPress.

  • I failed to find an internship this summer, so I have ample time. I figured that it would be a good learning experience.
  • I'm very particular about my editor, so I wanted complete customization. Specifically, I wanted my Emacs keybindings that are so deeply ingrained in me.
  • Code highlighting and $\LaTeX$ with live preview were a must, too.
  • I wanted the ability to save drafts of comments and posts, either because I want to keep them private as a diary, or to write them in pieces.

Writing this blog took me far longer than anticipated, which I mainly attribute to my lack of experience. I perhaps went overboard with testing, and I wrote hundreds of unit, integration, and functional tests. I must say that using Mocha for my test driver and Selenium for my functional tests was a very pleasant experience, however. Customizing Ace with buttons and keybindings and tying it all together with MathJax and marked was not easy, either, but I'm mostly satisified to have it working to my liking. There are a few improvements to make still like adjustable height.

I probably made a mistake in sticking to a low-level framework like Express for a straight-forward create, read, update and delete (CRUD) application and pure JavaScript for much of the front end—jQuery not even once. I had a really hard time with CSS and design, too. My stylesheet is a mess and needs refactoring. Thinking about security hurt my head, too. On the plus side, I was very excited to be able to use recursion for the commenting system. I also loved being able to share server-side and client-side code. For instance, using Browserify, I can use

var Markdown = require('lib/markdown.js');

in both my server-side and client-side code. Thus, if I don't trust the client, I can do the conversion myself on the server. Also, converting Markdown server-side may reduce page loading time for the client.

All the code for the blog can be found here on GitHub. Here are some cool features of the editor, which you can try with comment box below.

Math and SVG

I'm probably the only person in the world that writes in raw SVG. If you do, too, you can draw diagrams like

a b c d e f

Now, we can prove the Pythagorean theorem. Note that $c = f + e$. By similar triangles we have that $$\frac{c}{a} = \frac{a}{f} \Rightarrow a^2 = cf,$$ and likewise, $$\frac{c}{b} = \frac{b}{e} \Rightarrow b^2 = ce.$$ Thus, \begin{align*} c^2 &= c(f+e) \\ &= cf + ce \\ &= a^2 + b^2. \end{align*}

The code for the SVG diagram is

<svg class="centered" width="230" height="130">
    <defs>
        <g id="right-angle-mark">
            <path d="M 12 0 L 12 12 L 0 12" style="stroke: black; fill: none;"></path>
        </g>
    </defs>
    <g transform="translate(15,15)">
        <g style="stroke: black">
            <line x1="0" y1="0" x2="0" y2="100"></line>
            <line x1="0" y1="0" x2="200" y2="0"></line>
            <line x1="0" y1="100" x2="200" y2="0"></line>
            <line x1="0" y1="0" x2="40" y2="80" style="stroke-dasharray: 5 5"></line>
        </g>
        <g>
            <use xlink:href="#right-angle-mark"></use>
        </g>
        <g transform="translate(40,80) rotate(243.4349)">
            <use xlink:href="#right-angle-mark"></use>
        </g>
        <g style="font-style: italic; text-anchor: middle">
            <text x="100" y="0" dy="-3">a</text>
            <text x="0" y="50" dx="-7">b</text>
            <text x="100" y="50" dx="5" dy="10">c</text>
            <text x="20" y="40" dx="7">d</text>
            <text x="20" y="90" dy="-5" dx="-3">e</text>
            <text x="120" y="40" dy="-5" dx="-3">f</text>
        </g>
    </g>
</svg>

I had to some basic trigonometry to calculate the coordinates, which mainly involved noting that $\theta = \tan^{-1}(2)$, where $\theta$ is the lower-left angle. Note that you can add a centered class to center your diagram. One of the annoying things about Mathematics Stack Exchange, from where I drew much inspiration is the lack of ability to center diagrams.

The $\LaTeX$ is $$\frac{c}{a} = \frac{a}{f} \Rightarrow a^2 = cf$$ and

\begin{align*}
c^2 &= c(f+e) \\
&= cf + ce \\
&= a^2 + b^2.
\end{align*}

Code

Code is automatically highlighted. See this implementation of binary search in C++ using iterators:

#include <iostream>     // std::cout
#include <algorithm>    // std::sort
#include <vector>       // std::vector
#include <iterator>     // ForwardIterator

namespace phillypham {
    template <class ForwardIterator, class T> ForwardIterator 
    binary_search (ForwardIterator first, ForwardIterator last, const T& val) {
        auto mid = first + (last - first)/2;        
        while (*mid != val && first < last) {        
            if (*mid > val) {
                last = mid; // new upper bound
            } else {    
                first = mid + 1; // *mid < val
            }
            mid = first + (last - first)/2;
        }
        std::cout << *mid << std::endl;
        // loop ends when val or first and last are equal
        while (mid != first && *(mid - 1) == *mid) --mid;
        return mid;
    }
}

int main (int argc, char *argv[]) {      
  std::vector<int> v{10,20,30,30,20,10,10,20}; // size 8
  std::sort (v.begin(), v.end()); // 10 10 10 20 20 20 30 30

  std::vector<int>::iterator it1, it2, it3, it4;
  it1 = phillypham::binary_search(v.begin(), v.end(), 20);   
  it2 = phillypham::binary_search(v.begin(), v.end(), -10);
  it3 = phillypham::binary_search(v.begin(), v.end(), 30); 
  it4 = phillypham::binary_search(v.begin(), v.end(), 1000); 


  std::cout << "found " << *it1 << " at position " << (it1 - v.begin()) << std::endl; 
  // 20, 3
  std::cout << "found " << *it2 << " at position " << (it2 - v.begin()) << std::endl;
  // 10, 0
  std::cout << "found " << *it3 << " at position " << (it3 - v.begin()) << std::endl; 
  // 30, 6
  std::cout << "found " << *it4 << " at position " << (it4 - v.begin()) << std::endl; 
  // undefined, 8  

  return 0;
}

Languages are auto-detected, but you can also use a hint to help hightlight.js like this

```cpp
// your code here
```

You can also insert code by highlighting your text and clicking the code button or indenting with 4 spaces.

Tables

There is support for GitHub-flavored markdown. You make this table

Item Value Qty
Computer $1600 5
Phone $12 12
Pipe $1 234

with

| Item      | Value  | Qty  |
| --------- | -----: | :--: |
| Computer  | $1600  |   5  |
| Phone     |   $12  |  12  |
| Pipe      |    $1  | 234  |