<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.8.5">Jekyll</generator><link href="http://coollog.me/feed.xml" rel="self" type="application/atom+xml" /><link href="http://coollog.me/" rel="alternate" type="text/html" /><updated>2019-07-30T02:08:44-04:00</updated><id>http://coollog.me/feed.xml</id><title type="html">coollog.me</title><subtitle>Blogging about things I like to think about.</subtitle><author><name>Qingyang Chen</name><email>qingyang.chen@gmail.com</email></author><entry><title type="html">Taxes now or taxes later</title><link href="http://coollog.me/personal-finance/taxes-now-or-taxes-later/" rel="alternate" type="text/html" title="Taxes now or taxes later" /><published>2019-07-29T14:10:11-04:00</published><updated>2019-07-29T14:10:11-04:00</updated><id>http://coollog.me/personal-finance/taxes-now-or-taxes-later</id><content type="html" xml:base="http://coollog.me/personal-finance/taxes-now-or-taxes-later/">&lt;p&gt;&lt;em&gt;Disclaimer: I am not a financial professional and this information is only general in nature. Individuals have different financial circumstances and should consult a professional.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are many different retirement plans to choose from and it’s sometimes hard to determine which one is best for you to choose to reach your retirement goal. I won’t go into the details and rules of all the potential plans in this post. Instead, I’ll consider a specific question: should you pay taxes now or later? Specifically, we’ll compare the future value of contributing the same amount to a traditional 401(k) vs a Roth 401(k).&lt;/p&gt;

&lt;p&gt;A traditional 401(k) contribution is tax-deferred. This means that if you put in $100 now, you don’t have to pay taxes on $100 of your income this year. However, when you retire and withdraw that money (take a distribution), you will have to pay income tax in the year of withdrawal. This means that for a $100 contribution, it 1) starts in full, 2) grows tax-free for however many years it sits in your retirement account, and then 3) has your future tax rate reduce the future amount.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/401k_future_value_model.png&quot; alt=&quot;401(k) future value model&quot; class=&quot;align-center&quot; style=&quot;max-width: 600px;&quot; /&gt;&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;em&gt;401(k) future value model&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let’s put the traditional 401(k) growth model in equation form so that we can analyze it.&lt;/p&gt;

&lt;p&gt;Let &lt;script type=&quot;math/tex&quot;&gt;x&lt;/script&gt; be the initial contribution amount. The Contribution portion is just &lt;script type=&quot;math/tex&quot;&gt;x&lt;/script&gt;.&lt;br /&gt;
Let &lt;script type=&quot;math/tex&quot;&gt;r&lt;/script&gt; be the expected annual growth rate and &lt;script type=&quot;math/tex&quot;&gt;y&lt;/script&gt; be the number of years to grow. Assuming compounding annual growth by &lt;script type=&quot;math/tex&quot;&gt;r&lt;/script&gt; for &lt;script type=&quot;math/tex&quot;&gt;y&lt;/script&gt; years, the Growth portion is &lt;script type=&quot;math/tex&quot;&gt;x(r^y-1)&lt;/script&gt;.&lt;br /&gt;
Let &lt;script type=&quot;math/tex&quot;&gt;t_1&lt;/script&gt; be the future tax rate. The tax rate is applied on the total of the Contribution and Growth. The total Future taxes paid is thus &lt;script type=&quot;math/tex&quot;&gt;t_1(x+x(r^y-1))&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;Adding these terms together gets us the Future value for the 401(k) model:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;x+x(r^y-1)-t_1(x+x(r^y-1))&lt;/script&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;=x+xr^y-x-t_1x-t_1xr^y+t_1x&lt;/script&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;=xr^y-t_1xr^y&lt;/script&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;=xr^y(1-t_1)&lt;/script&gt;

&lt;p&gt;Just for the sake of illustration, let’s plug in some numbers. Let’s say we contributed $100 initially and left it to grow with 5% annual returns (a 1.05 annual growth rate) for 30 years, and our future tax rate is 25%, the Future value is:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;$100 \times 1.05 ^ {30} \times (1-.25) = $432 \times .75 = $324&lt;/script&gt;

&lt;p&gt;From this equation, we can see that, ideally, we would want our future tax rate as low as possible to maximize the actual amount we withdraw. This is why most retirees do not withdraw the entirety of their traditional 401(k) in a single year, as much of that withdrawal would fall under high tax brackets. This is also why there is a minimum distribution limit so that retirees don’t just let the money sit untaxed forever.&lt;/p&gt;

&lt;p&gt;Let’s compare this to the same amount, &lt;script type=&quot;math/tex&quot;&gt;x&lt;/script&gt;, except grown outside of a traditional 401(k) (or any other tax-advantaged account). This means that for an $100 initial contribution, the current tax would have been taken away, and then the amount would have grown over the years. However, this growth rate would be lower than &lt;script type=&quot;math/tex&quot;&gt;r^y&lt;/script&gt; since gains outside a tax-advantaged account can be taxed as long term capital gains or as ordinary income.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/no_tax_advantage_model.png&quot; alt=&quot;no tax advantage model&quot; class=&quot;align-center&quot; style=&quot;max-width: 600px;&quot; /&gt;&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;em&gt;No tax advantage model&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let’s put this in equation form too.&lt;/p&gt;

&lt;p&gt;We’ll define &lt;script type=&quot;math/tex&quot;&gt;t_0&lt;/script&gt; to be the current tax rate and &lt;script type=&quot;math/tex&quot;&gt;r^t&lt;/script&gt; to be the growth rate with taxes.&lt;br /&gt;
The Contribution is still &lt;script type=&quot;math/tex&quot;&gt;x&lt;/script&gt;.&lt;br /&gt;
The Taxes now is just &lt;script type=&quot;math/tex&quot;&gt;t_0x&lt;/script&gt;.&lt;br /&gt;
The Growth (taxed) is &lt;script type=&quot;math/tex&quot;&gt;x(r_t^y-1)&lt;/script&gt;. Note that we are applying the growth to the full initial contribution. The alternative would be to apply the growth to the contribution amount after Taxes now are applied. However, this would make it an unfair comparison since a lower amount is allowed to grow. The solution is to bring the taxes out into its own term like we have here and then include another cost, which is the lost potential growth on the amount that went to taxes. This lost growth is &lt;script type=&quot;math/tex&quot;&gt;t_0x(r_t^y-1)&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;Adding these terms together gets us the Future value for the non-tax-advantaged model:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;x-t_0x-t_0x(r_t^y-1)+x(r_t^y-1)&lt;/script&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;=x-t_0x-t_0xr_t^y+t_0x+xr_t^y-x&lt;/script&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;=xr_t^y-t_0xr_t^y&lt;/script&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;=xr_t^y(1-t_0)&lt;/script&gt;

&lt;p&gt;Note, however, that if we had just taken the tax out and let the after-tax portion to grow, the resulting Future value would actually still be the same here.&lt;/p&gt;

&lt;p&gt;Here, the tax is first taken out from the initial amount at the current tax rate. Compared to the model for the tax-deferred (traditional) 401(k) contribution, the tax-deferred 401(k) contribution is worth it if:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Your future tax rate &lt;script type=&quot;math/tex&quot;&gt;t_1&lt;/script&gt; is lower than your current tax rate, or&lt;/li&gt;
  &lt;li&gt;Your future tax rate &lt;script type=&quot;math/tex&quot;&gt;t_1&lt;/script&gt; is higher than your current tax rate, but only up to however much is lost from having a lower growth rate (&lt;script type=&quot;math/tex&quot;&gt;r^y/r_t^y&gt;(1-t_0)/(1-t_1)&lt;/script&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the event that your future tax rate is the same as your current tax rate, the traditional 401(k) contribution becomes more worth it as time goes by (since the difference between &lt;script type=&quot;math/tex&quot;&gt;r^y&lt;/script&gt; and &lt;script type=&quot;math/tex&quot;&gt;r_t^y&lt;/script&gt; increases exponentially as &lt;script type=&quot;math/tex&quot;&gt;y&lt;/script&gt; increases) - so contribute early. Also, the tax that you save at present by contributing to your traditional 401(k) is your marginal tax rate, and the tax you pay at withdrawal time would likely be your effective tax rate (that is, if your traditional 401(k) distributions are your main source of retirement income). This means that, most likely, your current tax rate would be higher than your future tax rate for the traditional 401(k) contribution. Unless your future tax rate is significantly higher than your current tax rate or the taxes on growth is just too miniscule, it seems &lt;strong&gt;always better to put the money in the traditional 401(k) than just leaving it without tax advantages&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now, let’s take a look at the Roth 401(k). Roth 401(k)s have tax-free growth, which means that once you put money into a Roth 401(k), that money can grow tax-free, and you’ll never have to pay tax on that money again. When you withdraw that money in retirement, you’ll also pay no taxes.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/roth_401k_model.png&quot; alt=&quot;no tax advantage model&quot; class=&quot;align-center&quot; style=&quot;max-width: 600px;&quot; /&gt;&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;em&gt;Roth 401(k) model&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Individuals contribute to a Roth 401(k) with after-tax money. For these contributions, the future value of the Roth 401(k) is the same as the non-tax-advantaged case except that it can enjoy the higher non-taxed growth rate, making it strictly better than leaving money outside. (As a side note, Roth IRAs act the same as Roth 401(k)s, except that normally, only individuals under a certain income threshold can directly contribute to them. This is why direct Roth IRA contributions have a very low limit and individuals with incomes over a certain threshold are not allowed to contribute directly. However, there are a few ways for individuals above the income threshold to contribute a significant amount, including backdoor and mega-backdoor contributions. These methods essentially take after-tax money from different sources and place them into a Roth IRA, and are equivalent to doing a direct contribution. Alright, back to Roth 401(k)s.)&lt;/p&gt;

&lt;p&gt;Let’s put the Roth 401(k) model in equation form.&lt;/p&gt;

&lt;p&gt;The Contribution is &lt;script type=&quot;math/tex&quot;&gt;x&lt;/script&gt;.&lt;br /&gt;
The Taxes now is &lt;script type=&quot;math/tex&quot;&gt;t_0x&lt;/script&gt;.
The Growth (tax-free) is &lt;script type=&quot;math/tex&quot;&gt;x(r^y-1)&lt;/script&gt;. Here, we have to subtract the lost growth on the portion paid as taxes as well, which is &lt;script type=&quot;math/tex&quot;&gt;t_0x(r_t^y-1)&lt;/script&gt;. Note that we use the growth with taxes here since the portion paid to taxes would have grown without tax advantages.&lt;/p&gt;

&lt;p&gt;The Future value for the Roth 401(k) model is thus:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;x-t_0x-t_0x(r_t^y-1)+x(r^y-1)&lt;/script&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;=xr^y-t_0xr_t^y&lt;/script&gt;

&lt;p&gt;This is quite similar to the non-tax-advantaged case except that we have the positive term as &lt;script type=&quot;math/tex&quot;&gt;xr^y&lt;/script&gt; instead of &lt;script type=&quot;math/tex&quot;&gt;xr_t^y&lt;/script&gt;. Even though this seems like a small difference, the difference can be huge as the number of years &lt;script type=&quot;math/tex&quot;&gt;y&lt;/script&gt; gets large. For instance, a $100 contribution with 1.05 tax-free growth rate would grow to $704 in 40 years, but only $480 with a 1.04 taxed growth rate. In other words, the 20% annual tax on long-term gains turns into a 32% overall tax after 40 years. (As a side note, if you’re following modern portfolio theory, don’t rebalance too often even with long-term gains. Having a 1.04 growth rate compared to a 1.05 growth rate every year is a lot less than just paying 20% tax one time.)&lt;/p&gt;

&lt;p&gt;Now, let’s compare the Roth 401(k) to a traditional 401(k). Let’s take a look at the traditional 401(k) model (with the tax cost split out into its own term) alongside the Roth 401(k) model:&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;script type=&quot;math/tex&quot;&gt;xr^y-t_1xr^y&lt;/script&gt; traditional 401(k) vs. &lt;script type=&quot;math/tex&quot;&gt;xr^y-t_0xr_t^y&lt;/script&gt; Roth 401(k)&lt;/p&gt;

&lt;p&gt;Now we can compare the traditional 401(k) to Roth 401(k) easily. As you can see, both share a common term &lt;script type=&quot;math/tex&quot;&gt;xr^y&lt;/script&gt;, the initial amount with growth. The only difference is in the tax cost term. For Roth 401(k), the tax cost is &lt;script type=&quot;math/tex&quot;&gt;t_0xr_t^y&lt;/script&gt;, whereas for traditional 401(k), the tax cost is &lt;script type=&quot;math/tex&quot;&gt;t_1xr^y&lt;/script&gt;. These have a common term &lt;script type=&quot;math/tex&quot;&gt;x&lt;/script&gt; that can also be disregarded. We have simplified the comparison between traditional 401(k) and Roth 401(k) to just:&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;Traditional 401(k) vs Roth 401(k)&lt;br /&gt;
&lt;script type=&quot;math/tex&quot;&gt;t_1r^y&lt;/script&gt; vs &lt;script type=&quot;math/tex&quot;&gt;t_0r_t^y&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;This looks familiar doesn’t it. This is just like comparing the traditional 401(k) model to the no tax advantage model, except here the Roth 401(k) is like the traditional 401(k) and the traditional 401(k) is like the no tax advantage. Comparing the models, the Roth 401(k) contribution is worth it if:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Your future tax rate &lt;script type=&quot;math/tex&quot;&gt;t_1&lt;/script&gt; is higher than your current tax rate, or&lt;/li&gt;
  &lt;li&gt;Your future tax rate &lt;script type=&quot;math/tex&quot;&gt;t_1&lt;/script&gt; is lower than your current tax rate, but only up to however much is lost from having a lower growth rate (&lt;script type=&quot;math/tex&quot;&gt;r^y/r_t^y&gt;t_0/t_1&lt;/script&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, for young people with many years to compound growth, the Roth 401(k) can be a better option than the traditional 401(k). Just using our &lt;script type=&quot;math/tex&quot;&gt;r^y=1.05&lt;/script&gt; and &lt;script type=&quot;math/tex&quot;&gt;r_t^y=1.04&lt;/script&gt; from above over a 40 year period, the ratio becomes about &lt;script type=&quot;math/tex&quot;&gt;r^y/r_t^y=1.47&lt;/script&gt;. It would generally not be the case that &lt;script type=&quot;math/tex&quot;&gt;t_0/t_1&gt;1.47&lt;/script&gt;. Using some more aggressive growth rates like &lt;script type=&quot;math/tex&quot;&gt;r^y=1.1&lt;/script&gt; and &lt;script type=&quot;math/tex&quot;&gt;r_t^y=1.08&lt;/script&gt;, we get an even larger ratio like 2.08. It would be quite unlikely to have the current marginal tax rate be more than double the future effective tax rate. However, as one gets older, there will be less time for a contribution to grow, and one would favor the traditional 401(k) more and more over the Roth 401(k). &lt;strong&gt;The recommendation is to favor contributions to the Roth 401(k) more when you are young (like before 30) and then exponentially decay that contribution to favor more towards traditional 401(k) as you get older (like after 30).&lt;/strong&gt;&lt;/p&gt;

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;</content><author><name>Qingyang Chen</name><email>qingyang.chen@gmail.com</email></author><summary type="html">Disclaimer: I am not a financial professional and this information is only general in nature. Individuals have different financial circumstances and should consult a professional.</summary></entry><entry><title type="html">My favorite protocol that makes the Internet useful</title><link href="http://coollog.me/computer-science/my-favorite-protocol-that-makes-the-internet-useful/" rel="alternate" type="text/html" title="My favorite protocol that makes the Internet useful" /><published>2018-06-18T20:12:11-04:00</published><updated>2018-06-18T20:12:11-04:00</updated><id>http://coollog.me/computer-science/my-favorite-protocol-that-makes-the-internet-useful</id><content type="html" xml:base="http://coollog.me/computer-science/my-favorite-protocol-that-makes-the-internet-useful/">&lt;p&gt;I remember when I was first dabbling in making online multiplayer video games. I ran into many issues of people “hacking” my game and stealing players’ passwords. Of course, this was a major issue, but I at the time had no clue how these “hackers” could get ahold of the passwords. It was later that I realized that all data sent over the Internet is public. Anyone could see the data that my game’s server sent to the players and vice versa. Whenever a player logged in, their game would send their password to my server for verification. This data was sent over the Internet, and anyone watching would be able to see the password.&lt;/p&gt;

&lt;p&gt;So, I had a question.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If anything sent on the Internet could be seen by anyone, how are we able to do anything secure?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;How are we able to log in to websites without others seeing our secret information? How are we able to read our emails without others being able to read them as well? How are we able to process financial transactions over the Internet?&lt;/p&gt;

&lt;p&gt;At the time I had no clue. I vaguely remember reading some articles about &lt;a href=&quot;https://www.google.com/search?q=secure+sockets+layer&quot;&gt;SSL&lt;/a&gt; and something about public and private keys, but I didn’t really understand how it all worked. It was not until I took a cryptography course in college that I discovered the protocol behind it all - the Diffie-Hellman key exchange.&lt;/p&gt;

&lt;p&gt;To explain this protocol, I’ll present it as a puzzle.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Let’s pretend there’s 3 people - Alice, Bob, and Eve - sitting at a table. Alice and Bob want to agree on something without Eve knowing. Since they are all at the same table, anything Alice communicates to Bob and vice versa, Eve gets to know as well. Each person can also turn their backs to do things in secret, which no-one else can see. How can Alice and Bob achieve this?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/table_alice_bob_eve.png&quot; alt=&quot;table with Alice, Bob, and Eve&quot; class=&quot;align-center&quot; style=&quot;max-width: 400px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Of course, neither Alice nor Bob would have any prior agreement Eve does not. This means that this is a symmetric system, where all participants are equal in terms of information. However, the goal is to have a protocol that can achieve informational asymmetry.&lt;/p&gt;

&lt;p&gt;At first, this might seem impossible. How can Alice and Bob agree on something only they know when Eve can listen in on their whole conversation? Wouldn’t that mean that Eve would always have the same information as Alice and Bob? And thus there’s no way of breaking the information symmetry?&lt;/p&gt;

&lt;p&gt;But there is a way. The key is that Alice and Bob can do things in &lt;em&gt;private&lt;/em&gt;. The private actions break the overall information symmetry of the system.&lt;/p&gt;

&lt;p&gt;For example, let’s say Alice, Bob, and Eve all start with no information. Then, Alice says “TRIANGLE!” Now, Alice, Bob, and Eve all know triangle. If Bob says “SQUARE!”, then Alice, Bob, and Eve now all know square as well.&lt;/p&gt;

&lt;p&gt;This is still information symmetric. But, if Alice secretly thinks to herself “circle…”, then this breaks the information symmetry of the system. Alice now knows something that neither Bob nor Eve knows.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/alice_bob_eve_knowledge_diagram.png&quot; alt=&quot;Alice, Bob, and Eve knowledge diagram&quot; class=&quot;align-center&quot; style=&quot;max-width: 400px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Okay, great. Now we’ve broken the information symmetry. But, this is not enough for what we need though. What we need is that both Alice and Bob share some piece of information that Eve doesn’t have. Therefore, Alice and Bob need to somehow leverage the secret information that they each have to create some secret information that Eve does not have.&lt;/p&gt;

&lt;p&gt;The way we do this is Alice and Bob both choose their own secret number. Alice chooses 3 and Bob chooses 4. Alice then announces some number, say 5, to the table, meaning that everyone knows this number. Then, Bob multiplies his secret number 4 with the 5 that Alice announced to get 20. He then announces 20 back to the table. Alice multiplies her 3 with the public 5 to announce 15. Alice then multiplies her secret 3 with the 20 Bob announced, getting &lt;strong&gt;60&lt;/strong&gt;. Bob’s secret number was 4, so he multiplies that with the 15 Alice announced and gets &lt;strong&gt;60&lt;/strong&gt;. And there we have it, both Alice and Bob have the number &lt;strong&gt;60&lt;/strong&gt;, and Eve does not.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/diffie_hellman_example.png&quot; alt=&quot;Diffie-Hellman example&quot; class=&quot;align-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Eve does not know 60 because the numbers that were announced were 5, 15, and 20. No matter how you multiply these numbers, you can’t get 60.&lt;/p&gt;

&lt;p&gt;Oh wait.&lt;/p&gt;

&lt;p&gt;Eve can actually guess 60 very easily. All she needs to do is divide 15 by 5 to get 3 and 20 by 5 to get 4, and now she can multiply 5 times 3 times 4 to get 60. We’ll need to do something further. Hmm.. how do we make it harder for Eve to guess… How about every time we multiply two numbers, we only take the remainder after it divides by 9.&lt;/p&gt;

&lt;p&gt;This time, Alice still announces 5 to start, but instead of sending 20, Bob sends the remainder of 20 divided by 9, which is 2. Alice sends the remainder of 15 divided by 9, which is 6. Bob then multiplies his secret 4 with 6 and divides by 9 to get a remainder of &lt;strong&gt;6&lt;/strong&gt;. Alice then multiplies her secret 3 with the 2 from Bob to get 6, which, when divided by 9, gets a remainder of &lt;strong&gt;6&lt;/strong&gt; as well. Now, Eve has a much harder time finding this common secret (I explain more in &lt;a href=&quot;#remarks&quot;&gt;Remarks&lt;/a&gt; below). Of course, this gets even harder when Alice and Bob use much larger numbers. Try finding what two numbers produce 893498529201 as a remainder when multiplied and divided by 2182841020912383.&lt;/p&gt;

&lt;p&gt;Now that I’ve thoroughly confused you with all these numbers, let’s take a step back and see what really happened here. What really happened is that Alice and Bob &lt;em&gt;combined their asymmetries&lt;/em&gt; with each other. This process of combining asymmetries produced a symmetry between just Alice and Bob and maintained asymmetry with Eve.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/combining_asymmetries.png&quot; alt=&quot;Combining informational asymmetries&quot; class=&quot;align-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Diffie-Hellman is essentially the same protocol, except that it uses exponentials rather than multiplication and large primes with primitive roots rather than just some small integers. In my example, I used a multiply-divide-get-remainder function, but this protocol works with any function that has these properties:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The function takes two inputs and produces an output&lt;/li&gt;
  &lt;li&gt;The function is commutative and associative, meaning that applying it many times in any order produces the same output&lt;/li&gt;
  &lt;li&gt;The inputs are hard to find if given an output&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We can see that these properties help us because 1) and 2) help us combine the asymmetries of Alice and Bob, and 3) prevents Eve from doing the same.&lt;/p&gt;

&lt;p&gt;To illustrate this protocol in a generic form with an example, let’s say the function is &lt;script type=&quot;math/tex&quot;&gt;f&lt;/script&gt;. Alice chooses &lt;script type=&quot;math/tex&quot;&gt;x&lt;/script&gt; as her secret and Bob chooses &lt;script type=&quot;math/tex&quot;&gt;y&lt;/script&gt; as his secret. The publicly announced value is &lt;script type=&quot;math/tex&quot;&gt;z&lt;/script&gt;. Alice announces &lt;script type=&quot;math/tex&quot;&gt;f(x, z)&lt;/script&gt; and Bob announces &lt;script type=&quot;math/tex&quot;&gt;f(y, z)&lt;/script&gt;. Then, Alice gets the secret from &lt;script type=&quot;math/tex&quot;&gt;f(x, f(y, z))&lt;/script&gt; and Bob gets the secret from &lt;script type=&quot;math/tex&quot;&gt;f(y, f(x, z))&lt;/script&gt;. These are the same value S (because &lt;script type=&quot;math/tex&quot;&gt;f&lt;/script&gt; is commutative and associative), which Eve is not able to get. All Eve has is &lt;script type=&quot;math/tex&quot;&gt;z&lt;/script&gt;, &lt;script type=&quot;math/tex&quot;&gt;f(x, z)&lt;/script&gt;, and &lt;script type=&quot;math/tex&quot;&gt;f(y, z)&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;So, now that we have such a protocol, how does this enable secure communications over the Internet? Well, the shared information that Alice and Bob create can be a key for encryption. After the protocol, Alice can use the key to encrypt messages she sends to Bob, only send the encrypted message over the Internet, and when Bob receives the encrypted messages, he can use the key to decrypt them and read the original messages. Anyone without this key would not be able to see the contents of the messages. When you are browsing your favorite website, you are essentially going through a similar protocol to generate a key that only you and the website’s servers share. All the communications between you and the website are encrypted with this key. Just make sure the website uses HTTPS and has a valid TLS certificate, but that’s probably for another post.&lt;/p&gt;

&lt;p&gt;And there you have it - the protocol that lets you do the useful things on the Internet, like posting to your Facebook wall or ordering that late night delivery from Grubhub.&lt;/p&gt;

&lt;h2 id=&quot;remarks&quot;&gt;Remarks&lt;/h2&gt;

&lt;p&gt;In the example with Alice, Bob, and Eve, why did taking the remainder make it harder for Eve to know what Alice and Bob’s secret numbers were?&lt;/p&gt;

&lt;p&gt;Well, first, it’s trivial for Eve to find the secret numbers when the protocol involves just multiplication. Let’s say &lt;script type=&quot;math/tex&quot;&gt;z&lt;/script&gt; is the publicly announced number, &lt;script type=&quot;math/tex&quot;&gt;x&lt;/script&gt; is Alice’s secret, and &lt;script type=&quot;math/tex&quot;&gt;y&lt;/script&gt; is Bob’s secret. Alice sends &lt;script type=&quot;math/tex&quot;&gt;x\times z&lt;/script&gt; and Bob sends &lt;script type=&quot;math/tex&quot;&gt;y\times z&lt;/script&gt;. Eve can calculate x by just doing &lt;script type=&quot;math/tex&quot;&gt;\frac{x\cdot z}{z}&lt;/script&gt;, and likewise for &lt;script type=&quot;math/tex&quot;&gt;y&lt;/script&gt;. This is because there can only be one &lt;script type=&quot;math/tex&quot;&gt;x&lt;/script&gt; that could give &lt;script type=&quot;math/tex&quot;&gt;x\times z&lt;/script&gt; and only one &lt;script type=&quot;math/tex&quot;&gt;y&lt;/script&gt; that could give &lt;script type=&quot;math/tex&quot;&gt;y\times z&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;Now, taking a remainder changes this. Let’s represent taking the remainder after dividing by a number with the symbol &lt;script type=&quot;math/tex&quot;&gt;\%&lt;/script&gt;. If you were to take any integer &lt;script type=&quot;math/tex&quot;&gt;x \% 3&lt;/script&gt;, for example, the result can only be one of 3 values - 0, 1, or 2. This means that many &lt;script type=&quot;math/tex&quot;&gt;x&lt;/script&gt;’s could result in a remainder of 0, and likewise for 1 and 2. This is essentially what in cryptography you’d call a hash function, where the function has a large domain but a small range. Of course, just taking the remainder is not a cryptographically secure hash function, but it increases the difficulty by which Eve can find the inputs - the secrets of Alice and Bob. This is because, given a divisor &lt;script type=&quot;math/tex&quot;&gt;d&lt;/script&gt;, Alice would send &lt;script type=&quot;math/tex&quot;&gt;x\times z \% d&lt;/script&gt; and Bob would send &lt;script type=&quot;math/tex&quot;&gt;y\times z \% d&lt;/script&gt;. With just &lt;script type=&quot;math/tex&quot;&gt;x\times z \% d&lt;/script&gt; and &lt;script type=&quot;math/tex&quot;&gt;y\times z \% d&lt;/script&gt;, Eve would have a harder time finding which &lt;script type=&quot;math/tex&quot;&gt;x\times z&lt;/script&gt; and &lt;script type=&quot;math/tex&quot;&gt;y\times z&lt;/script&gt; produced those remainders.&lt;/p&gt;

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;</content><author><name>Qingyang Chen</name><email>qingyang.chen@gmail.com</email></author><summary type="html">I remember when I was first dabbling in making online multiplayer video games. I ran into many issues of people “hacking” my game and stealing players’ passwords. Of course, this was a major issue, but I at the time had no clue how these “hackers” could get ahold of the passwords. It was later that I realized that all data sent over the Internet is public. Anyone could see the data that my game’s server sent to the players and vice versa. Whenever a player logged in, their game would send their password to my server for verification. This data was sent over the Internet, and anyone watching would be able to see the password.</summary></entry><entry><title type="html">I made a mistake in a concurrent program</title><link href="http://coollog.me/debugging/i-made-a-mistake-in-a-concurrent-program/" rel="alternate" type="text/html" title="I made a mistake in a concurrent program" /><published>2018-05-25T10:42:30-04:00</published><updated>2018-05-25T10:42:30-04:00</updated><id>http://coollog.me/debugging/i-made-a-mistake-in-a-concurrent-program</id><content type="html" xml:base="http://coollog.me/debugging/i-made-a-mistake-in-a-concurrent-program/">&lt;p&gt;I was working on the concurrency part of my main project at work today. The program executed a series of steps in order to accomplish its task. Many of these steps could run in parallel, but some steps could only run after certain other steps.&lt;/p&gt;

&lt;p&gt;I organized these steps into a dependency graph. Each step defined previous steps it needed to wait on before running. Steps with no dependencies could run immediately. With this structure, many steps could run at the same time, but no step would run before they were supposed to.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/execution_dependency_graph.png&quot; alt=&quot;execution dependency graph&quot; class=&quot;align-center&quot; style=&quot;max-width: 300px;&quot; /&gt;&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;em&gt;Example of an execution dependency graph with steps A…F&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Each step would submit itself to an execution manager to either run immediately (no dependencies) or run after some other steps (after its dependencies). Upon submission, this step would receive a &lt;a href=&quot;https://en.wikipedia.org/wiki/Futures_and_promises&quot;&gt;future&lt;/a&gt;. Other steps would then use this future to retrieve the result of that step after it finishes. I decided to be a bit fancy and lazily initialize these futures, where the step would only submit itself to the execution manager if another step required it to run.&lt;/p&gt;

&lt;p&gt;All seemed well. I added a check to make sure that a future is always finished before another step retrieves its result. This makes sure that I defined the dependencies for the steps correctly. This was important because if I did not define the the dependencies correctly, steps might unintentionally block threads from executing useful work. Unintentional blocking would decrease the efficiency of the parallel execution.&lt;/p&gt;

&lt;p&gt;After running the tests a few times, the check failed. I must have set up the graph incorrectly somewhere. I must have forgotten to define some dependency… So, I went down a rabbit hole for a few hours, auditing each step to make sure I had all the necessary dependencies set. But, every so often, the check still failed.&lt;/p&gt;

&lt;p&gt;I thought for a long time. And then it suddenly hit me. I figured it out. This whole time I had set up the dependency graph correctly. The problem lied not in my dependency graph, but rather in my lazy initialization.&lt;/p&gt;

&lt;p&gt;The lazy initialization worked like this. Each step has a “future” variable and a “get future” method. The “future” variable is initially undefined. When another step calls the “get future” method the first time, the method submits the step to the execution manager and sets the “future” variable. Further calls to “get future” returns that submitted future.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/get_future_method.png&quot; alt=&quot;&amp;quot;get future&amp;quot; method&quot; class=&quot;align-center&quot; style=&quot;max-width: 600px; width: 100%&quot; /&gt;&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;em&gt;“get future” method&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Each step calls its dependencies’ “get future” method to get the futures to wait upon. Therefore, this initialization design builds the dependency graph from the last step backwards.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/backwards_initialization.png&quot; alt=&quot;backwards initialization&quot; class=&quot;align-center&quot; style=&quot;max-width: 600px; width: 100%&quot; /&gt;&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;em&gt;Illustration of how the dependency graph is built backwards&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;From this, I noticed the flaw in this initialization method - it had a blaring race condition. For example, let’s take a look at a scenario where two steps depend on a single step:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/race_dependency.png&quot; alt=&quot;dependency with race condition&quot; class=&quot;align-center&quot; style=&quot;max-width: 200px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Let’s say B and C happened to call A’s “get future” method at the same time. B’s call has A submit future 1 to the execution manager. C’s call has A submit future 2 to the execution manager. This causes A to set its “future” variable to future 1 and then change it to future 2. Later, B calls A’s “get future” method again. B receives future 2, and not future 1 as it had expected.&lt;/p&gt;

&lt;p&gt;So, how do we solve this problem? By not doing this backwards initialization. Each step should just initialize itself. Each step would submit itself to the execution manager upon creation. This means that each step would only ever create one future. Each step’s “get future” method would always return the same future.&lt;/p&gt;

&lt;p&gt;I made this fix, and the problem disappeared.&lt;/p&gt;

&lt;p&gt;In essence, the real issue is that I had mutable state. All concurrent objects should be immutable. I ran into this problem here because I had concurrent objects (the steps) be able to mutate state (set a “future” variable). By setting the “future” variable upon construction of each step, I made each step immutable and therefore immune to any parallel execution problems.&lt;/p&gt;

&lt;p&gt;So, yeah, make sure all your concurrent objects are immutable. And don’t try to do fancy stuff before thinking it through completely.&lt;/p&gt;

&lt;h2 id=&quot;remarks&quot;&gt;Remarks&lt;/h2&gt;

&lt;p&gt;This problem wouldn’t exist with the original initialization method had the dependency graph been a tree. This is because in a tree, each node has only one parent, and therefore each “get future” method could only be called at most one time. But, our dependency graph is a directed acyclic graph and, in practice, many nodes have several parents.&lt;/p&gt;</content><author><name>Qingyang Chen</name><email>qingyang.chen@gmail.com</email></author><summary type="html">I was working on the concurrency part of my main project at work today. The program executed a series of steps in order to accomplish its task. Many of these steps could run in parallel, but some steps could only run after certain other steps.</summary></entry><entry><title type="html">The 25 Horses Problem</title><link href="http://coollog.me/problem-solving/hard-google-interview-question-25-horses-problem/" rel="alternate" type="text/html" title="The 25 Horses Problem" /><published>2018-05-20T00:42:30-04:00</published><updated>2018-05-20T00:42:30-04:00</updated><id>http://coollog.me/problem-solving/hard-google-interview-question-25-horses-problem</id><content type="html" xml:base="http://coollog.me/problem-solving/hard-google-interview-question-25-horses-problem/">&lt;p&gt;I recently came across a video titled &lt;a href=&quot;https://www.youtube.com/watch?v=i-xqRDwpilM&quot;&gt;HARD Google Interview Question - The 25 Horses Puzzle&lt;/a&gt;. I don’t think Google asks any brain teaser problems so I decided to check it out. Although the problem was formulated like a brain teaser, I found it to actually be a very well-designed technical problem. I could actually apply various technical problem-solving techniques to solve this problem - although it involved no coding. The problem describes a scenario with a “real-world” setting, but it could be modeled nicely with graph theory and topological ordering. The video presented a nice intuitive explanation of the solution, but I want to show how certain techniques can be used to approach this problem step-by-step - techniques that could be applied to problems of all sorts.&lt;/p&gt;

&lt;p&gt;So, the problem goes as such:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;You want to find the fastest 3 horses in a group of 25 horses. You can only race 5 horses at a time. You don’t have a stopwatch, so you can only know the ranking of each horse within each race. How many races do you need?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/25_horses_puzzle.png&quot; alt=&quot;25 horses puzzle&quot; class=&quot;align-center&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I enjoyed this problem since it wasn’t one of those brain teasers where there’s some trick to solving it that wasn’t presented in the original problem. The solution didn’t involve adding elements of manipulation to the scenario (like you give steroids to horses to make them faster). There wasn’t some wisecrack answer like “just one race if we are lucky!”. The solution formulates itself completely within the scope of the problem. In fact, the problem could be reduced into a raw representation such that it could be modeled in a mathematical format.&lt;/p&gt;

&lt;p&gt;To re-formulate the problem in a technical sense:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;There are 25 elements that have some ordering from fastest to slowest among them (a &lt;em&gt;strict&lt;/em&gt; ordering).&lt;/li&gt;
  &lt;li&gt;You can perform some computation called &lt;em&gt;race&lt;/em&gt; that can give the &lt;em&gt;relative&lt;/em&gt; ordering of any 5 of those elements.
How many times do you need to run &lt;em&gt;race&lt;/em&gt; in order to find the first 3 elements in the ordering?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The intent of the problem isn’t for us to give a number of races needed, but rather to provide a &lt;em&gt;proof&lt;/em&gt; as to the number of races. This proof is like one of those classic two-sided proofs where the goal is to prove an equality. In these proofs, to prove that the solution is exactly some value, you prove that the solution is at least that value and also at most that value - and therefore the solution must be exactly that value. However, in this case, the two proofs are 1) that a solution exists for some value and 2) that the solution must be at least that value - therefore, that value is the minimum possible value.&lt;/p&gt;

&lt;p&gt;So, for this problem, I needed to prove that:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;I can find a small number of races that works, and that&lt;/li&gt;
  &lt;li&gt;The minimum number of races needed is that number&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I started with a naive answer to prove the first lemma (&lt;em&gt;there exists some number of races that works&lt;/em&gt;). Since there are 25 horses, if I race every pair of horses, I can rank each of the horses in their exact order. Therefore if I race the 25 horses 25 times each, I have the exact ordering - this is 25&lt;sup&gt;2&lt;/sup&gt; races. Then, I realize that there are a lot of duplicate races. Eliminating these duplicate races I find the actual number of pairings:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The first horse has 24 other horses to pair.&lt;/li&gt;
  &lt;li&gt;The second horse has 23 other horses to pair. The pairing for the first horse is already covered.&lt;/li&gt;
  &lt;li&gt;The third horse has 22 other horses to pair…&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;…&lt;/p&gt;

&lt;p&gt;  24. The 24th horse has 1 other horse to pair.&lt;/p&gt;

&lt;p&gt;  25. The 25th horse has no other horses to pair.&lt;/p&gt;

&lt;p&gt;This linear summation can be easily expressed as &lt;script type=&quot;math/tex&quot;&gt;\frac{25(24+0)}{2}&lt;/script&gt;, or 300. That’s quite a few races still.&lt;/p&gt;

&lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;

&lt;p&gt;So, then I tried to look for what other races I could eliminate (don’t take this out of context) - which ones did not need to happen - what &lt;em&gt;inefficiencies&lt;/em&gt; my algorithm had. The two main inefficiencies were that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I was not utilizing the full potential of the &lt;em&gt;race&lt;/em&gt; function. I am discarding useful results by just looking at the ordering for the first two of each &lt;em&gt;race&lt;/em&gt; result, and that&lt;/li&gt;
  &lt;li&gt;I am finding the full ordering of all 25 horses, whereas I only need the ordering for the first 3.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One technique I like to use is to represent the problem in a model I have worked with extensively before - one that I am familiar with and have solved other problems in. Doing so would helps me to apply techniques I’ve learned from working with that model. In this problem, we are trying to find the (ordering) relationship between pairs of horses. What better model to represent this than a graph.&lt;/p&gt;

&lt;p&gt;For those unfamiliar with graphs in discrete math, a graph is just a bunch of nodes and edges that connect them. In other words, it is the colloquial equivalent of a network (like a social network, or a network of highways).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://upload.wikimedia.org/wikipedia/commons/5/5b/6n-graf.svg&quot; alt=&quot;graph example&quot; class=&quot;align-center&quot; style=&quot;max-width: 300px;&quot; /&gt;&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;em&gt;An example of a graph&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In our case, the nodes are the horses, and each edge represents a pair of horses. We can have our graph be a “knowledge” graph. We start with 25 nodes with no edges. Then, every edge we add between two horses represents knowledge of the ordering between the two horses - knowledge of which horse is faster. That means that each race could add new edges to our graph.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/25_dots.png&quot; alt=&quot;25 nodes&quot; class=&quot;align-center&quot; style=&quot;max-width: 300px;&quot; /&gt;&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;em&gt;A 25-node graph with no edges&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With this model, the original approach of running 300 races is equivalent to adding an edge between every node. In fact, there are exactly 300 edges if we were to connect all the nodes with edges (see &lt;a href=&quot;https://en.wikipedia.org/wiki/Complete_graph&quot;&gt;complete graph&lt;/a&gt;). Many of these edges are not necessary. In fact, we only need two edges to know the fastest 3 horses - the edge between the fastest and second fastest, and the edge between the second fastest and third fastest.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/first_second_third.png&quot; alt=&quot;first second third&quot; class=&quot;align-center&quot; style=&quot;max-width: 300px;&quot; /&gt;&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;em&gt;We win if we find these edges&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;However, this does not mean that we only need one race. We could get lucky and have our top 3 horses be in the one race we hold, but the problem is asking for a solution that could work in &lt;em&gt;all&lt;/em&gt; cases.&lt;/p&gt;

&lt;p&gt;Now, it made sense to start building the solution from the bottom up and tackle the second lemma (&lt;em&gt;the number of races needed is at least some number&lt;/em&gt;). The initial graph is 25 nodes with no edges. So, the first thing I realize is that no matter what, when we connect the nodes up no node can be left out (the graph needs to be &lt;a href=&quot;https://en.wikipedia.org/wiki/Connectivity_(graph_theory)#Connected_graph&quot;&gt;connected&lt;/a&gt;). This is because any horse that is not connected to the others means that we don’t have any information about its ordering. Therefore, first, we must run at least 5 races to get some edge for each of the 25 horses. However, this results in 5 disjoint graphs.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/5_races.png&quot; alt=&quot;5 races&quot; class=&quot;align-center&quot; style=&quot;max-width: 300px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We still need to connect these 5 disjoint graphs by picking &lt;em&gt;some&lt;/em&gt; horse in each graph for another race (the 6th race). One way is to pick the fastest from each group. In fact, this will give us one of the key information that we need - the fastest horse overall.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/6_races.png&quot; alt=&quot;6 races&quot; class=&quot;align-center&quot; style=&quot;max-width: 300px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;However, we still need to know the second and third fastest. If we look at the current knowledge graph, the fastest horse is connected to two horses. Either of these horses could be the second fastest. Therefore, we need an edge between these two horses in order to know who is faster. We need a 7th race.&lt;/p&gt;

&lt;p&gt;What if we didn’t pick the fastest horse to race from each group? For instance, let’s assume we raced the fastest horses from only 4 groups. In that case, we would not know if the horse we left out is the fastest overall unless we had some edge between that horse and the fastest of the other 4 we raced. To have that information, we need at least another race.&lt;/p&gt;

&lt;p&gt;In both cases, we proved that there needs to be some number of races 7 or higher (lemma 2). So then, I tried to find a way to solve this with just 7 races.&lt;/p&gt;

&lt;p&gt;After we raced the horses 6 times, we got this knowledge graph:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/6_races.png&quot; alt=&quot;6 races&quot; class=&quot;align-center&quot; style=&quot;max-width: 300px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We can see that the only horses that could be the second fastest are the ones that are directly connected to the fastest horse. Likewise, we know that the only horses that could be the third fastest are the ones that are directly connected to the contenders for second place.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/6_races_highlight.png&quot; alt=&quot;6 races highlighted&quot; class=&quot;align-center&quot; style=&quot;max-width: 300px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;We are left with 6 horses that are still in the running for first, second, and third. Since we already know which horse is fastest, &lt;em&gt;we just need to race the 5 other horses to find the second and third fastest&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/7_races.png&quot; alt=&quot;7 races&quot; class=&quot;align-center&quot; style=&quot;max-width: 300px;&quot; /&gt;&lt;/p&gt;

&lt;p style=&quot;text-align: center&quot;&gt;&lt;em&gt;Another race gives us the four edges we need&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And there we have it, we found a way to solve the problem with 7 races and proved lemma 1 as well.&lt;/p&gt;

&lt;p&gt;Therefore, the minimum number of races needed is 7.&lt;/p&gt;

&lt;p&gt;The framework I used in solving this problem can be used to solve many other types of problems:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Reformulate the problem to remove the cruft&lt;/li&gt;
  &lt;li&gt;Define what we need to prove&lt;/li&gt;
  &lt;li&gt;Model the problem to break it down and see what we actually need to solve&lt;/li&gt;
  &lt;li&gt;Start easy and gradually engineer the solution by:
    &lt;ol&gt;
      &lt;li&gt;Removing the unnecessary parts, and&lt;/li&gt;
      &lt;li&gt;Building from the ground up&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;remarks&quot;&gt;Remarks&lt;/h2&gt;

&lt;p&gt;This problem is also recognizable as a topological ordering problem, but I decided not to present it in that way since I wanted to explain it in a more intuitive “knowledge graph” manner.&lt;/p&gt;

&lt;p&gt;So, I’ll present the topological ordering model here. Let’s take the original “knowledge graph” and make it into a directed graph. For those who are unfamiliar, this just means that each edge points from one node to the other. In this case, we can point from the faster horse to the slower horse for each edge. Going back to the diagrams we had, after the 6th race, the edges would look like:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/6_races_directed.png&quot; alt=&quot;6 races directed&quot; class=&quot;align-center&quot; style=&quot;max-width: 300px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Here, we can see that a path from horse A to horse B means that we know horse A is faster than horse B. A path is just a way to get from one node to another by only following edges in the direction they point.&lt;/p&gt;

&lt;p&gt;The final 6 contending horses would look like:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/../../assets/images/posts/7_races_directed.png&quot; alt=&quot;7 races directed&quot; class=&quot;align-center&quot; style=&quot;max-width: 300px;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;After the 6th race, we have a path from the fastest horse to any of the contenders for 2nd and 3rd place. The 7th race gives us the path among these contenders (making our directed graph &lt;a href=&quot;http://mathworld.wolfram.com/ConnectedDigraph.html&quot;&gt;strongly connected&lt;/a&gt;).&lt;/p&gt;</content><author><name>Qingyang Chen</name><email>qingyang.chen@gmail.com</email></author><summary type="html">I recently came across a video titled HARD Google Interview Question - The 25 Horses Puzzle. I don’t think Google asks any brain teaser problems so I decided to check it out. Although the problem was formulated like a brain teaser, I found it to actually be a very well-designed technical problem. I could actually apply various technical problem-solving techniques to solve this problem - although it involved no coding. The problem describes a scenario with a “real-world” setting, but it could be modeled nicely with graph theory and topological ordering. The video presented a nice intuitive explanation of the solution, but I want to show how certain techniques can be used to approach this problem step-by-step - techniques that could be applied to problems of all sorts.</summary></entry></feed>