http://blog.emikek.com/Ghost 0.5Tue, 26 Sep 2017 21:50:27 GMT60I finished watching all the video lectures for MIT 6006. It's a very good course for anyone looking for a refresher on algorithms. In honor of the final unit (Dynamic Programming) I implemented a program to determine the optimal plays for a deck of Blackjack. First feel free to play with it a bit, and then I'll go over some details about how it's implemented.

The optimal plays for the deck are calculated on the fly and it takes just milliseconds. If the memoization (dynamic programming) lines are commented out, the program runs for several minutes.

Step 1: Class taxonomy

Something of a misnomer in a language like Javascript that doesn't have classes (in my opinion, a real strength of the language). Even thought we don't need a classification, we do still at least need to decide how to distribute functionality between the objects and decide how to compose them.

I settled on all these objects:

BlackJack: this class holds the game logic - tests for busts, legal moves, handles the dealer's deterministic logic, deals cards, and asks the player for their move.

Player: this class holds the player's winnings (or losses), the current cards dealt to the player, and has a GetStrategy(...) method to decide the next move.

Deck: a collection of individual cards that can be sorted or dealt.

Solver: a subclass of Blackjack that tries all possible games to determine the best solution.

This taxonomy worked well for the first step of this project, which was to implement a BlackJack "player" to eat through a deck using "by the book" strategy, taking into account the visible dealer card and the player's hand.

Unfortunately, this taxonomy became a liability when it came to implementing the second step, which was the solver. In an ideal world, you could implement a recursive solver taking a single argument which is the state of the game. However, objects are always passed by reference in (as far as I know) all object oriented languages so this destroys state in the lower levels of recursion as the higher levels do their destructive calculations. Properties of the objects that mattered to the solver - for instance the current state of the deck and the hands of the player and dealer - could not be passed as objects and needed to be independent parameters of the solver function in order to retain the information at the lower recursion levels. This experience solidified in my mind the "clash in parity" of object oriented vs functional paradigms. The functional / immutable data paradigm worked great for the solver and the object-oriented / mutable data paradigm worked great for running through a single game, but doing both in a single paradigm was awkward and the number of times I called .slice() is a testament to that.

Step 3: Exponential solution

For any game state provided the current Dealer hand, the current Player hand, and the current deck, calculate recursively the result of hitting vs staying, and return the max.

Step 4: Memoize it

As all possible states are traversed, identical substates will be arrived at so all optimal substates should be memoized for later use. This means the cost of recursion (amoritized) is O(1). This is what allows us to solve an inherently exponential problem in polynomial time.

I made a mistake here in my original implementation because the suffix of the deck is only interesting if not only the position in the deck is identical but also the dealer and player hands are also identical. To put it another way, you can only memoize the result at the beginning of the hand, and also you can only pull out the memoized result at the beginning of the hand. If the deck matches a memoized result but you're in the middle of a hand the value is not useful, where in a lot of other similar dynamic programming problems you don't need to think about that.

Step 5: Check your work

Finally I created a "subclass" of player that provides results to call to GetStrategy(...) in with a pre-computed playbook. This is what is displayed in the browser when you click "play optimal". Composing that player into the BlackJack object with the parent pointers from the dynamic programming solver results in the output you can see.

]]>http://blog.emikek.com/solving-blackjack-in-polynomial-time/f435cc3a-c2b4-4afa-a0c0-1f79c0bc9b7aMon, 10 Aug 2015 17:28:12 GMTIn late March I performed a recital to amuse myself and decided to live-stream it on the internet, also to amuse myself. The solution I came up with is available on Github so you can amuse yourself.

What I learned is that many years already into HTML5 video, the landscape is bleak. Solutions that work are either complex or proprietary. On desktops, flash is still the best solution because of poor support for alternatives. iOS only supports HLS. Android default browsers and chrome have buggy support for DASH so it's not really usable, so WebM is the best for the rest. So for a minimal setup, assuming you want to have users be able to view your broadcast on desktop, iOS and Android, you'll need to support RTMP / flash (desktop), HLS (iOS), and WebM (everyone else).

In terms of open source solutions that support all this, there's not much out there. Red5 streaming server is probably the closest thing to a product that supports this, it has HLS at least available as a plugin. I chose instead to go with as far as I can tell the only other open source option, nginx-rtmp, due to its simplicity. To summarize its capability, it can receive, record, broadcast, or rebroadcast one or more RTMP video streams, and it has built in HLS support. It does not support WebM so I had to use another product called stream-m to host that protocol.

I was expecting up to 100 simultaneous users viewing the stream, which is not that many but enought that I was worried about one server being able to handle all the load. So I achieved a good load-balancing solution with:

1 main media server

2 servers to serve clients using RTMP

2 servers to serve clients using HLS

2 servers to serve clients using WebM

The main server needs to do a lot: receive the incoming video stream and at a minimum run several simultaneous instances of ffmpeg to transcode it to the various bitrates for HLS streaming. It maintains the HLS playlist and also rebroadcasts the RTMP stream 4 times, one to each of the RTMP and WebM servers. I used a giant c3.8xlarge instance for this, unfortunately. I could probably have gotten away with a c3.4xlarge, which is half the size, but during testing I got a dropped stream once or twice and that was unacceptable. Dozens and dozens of ffmpeg threads running in real time just takes a lot of cycles.

Having the clients connect to the dedicated client access servers ensure that there will always be a constant and predictable load on the main media server. This is great, as there will be no chance of a traffic surge interrupting the main encoding process. For RTMP, each client access server is simply configured to rebroadcast the stream to any client that requests it. This means the media server needs only to rebroadcast the stream once for each client server and that allows the client access server to serve as many as it can handle. This allows scaling up by a large constant factor for each stream added from the media server. RTMP streams are extremely cheap with nginx-rtmp. I there was a huge broadcast, the servers could be arranged in a tree, where the media server would rebroadcast to some number of second tier servers, which could rebroadcast to some number of third tier servers which clients could connect to directly. This would allow exponential scaling for each new stream added to the media server, and I can imagine this setup going as large as needed.

HLS scaling is similar. The protocol here is HTTP plain and simple, so each client access server has a plain vanilla installation of nginx with reverse proxy and caching. So the media server servers each HLS file to each of the HLS client access servers once, the client access server caches it and serves to as many clients as it can until the next HLS files are ready. Really simple, and the same tree structure could be applied to these servers to scale to infinity.

stream-m for WebM takes an RTMP stream as input and outputs a WebM stream for clients. The media server serves one RTMP stream to each client access server and allows the client access server to serve as many as it can. All levels in a tree for this protocol would be nginx-rtmp instances passing the rtmp stream along and only the leaves would have stream-m installed.

DNS then takes care of the rest. Each client access server gets an A record pointing to either rtmp.example.com, hls.example.com, or webm.example.com and load is balanced between them that way. This doesn't provide fault tolerance, so to get that in a serious deployment would require either active monitoring that removes bad servers from DNS or an active load balancer that's fine with RTMP, HTTP and WebM. (ELB for the record is fine with RTMP).

Feel free to try out the solution on github. This is an somewhat commoditized extract of the solution I actually used, which has much better security and nicities like automatically setting DNS records but is too tightly tied to my own AWS/on-prem environment to be generally useful. It should be as easy to use as simply creating an AWS keypair and an identity, and then uploading the provided cloudformation template. Let me know your experience if you try it.

]]>http://blog.emikek.com/the-sorry-state-of-live-streamed-video-on-the-web/2c2e9ca8-639b-4a02-902f-e5107c0d04a9Thu, 11 Jun 2015 12:52:15 GMTThe work that Microsoft is doing on the next release of the .NET framework and specifically ASP.NET 5 are very exciting. See here for a good summary. The changes for the most part eliminate all the arguments against using .NET as the platform of choice for a web development project, including:

inability to run on operating systems other than windows

slow development due to constant recompiling

ghettoized community

The work is still in progress but everything is being done publicly on github and the developers are very receptive to working with members of the community as the product takes shape.

I've been using ASP.NET 5 / MVC 6 for a recent project and after a bit of a rocky start dealing with the learning curve (and lack of stable documentation as things are still changing quickly) I've come to be a real fan. Working with C# is about a thousand times better than working with Java, the standard library is second to none, and automatic recompilation as you type is a great productivity boost. Nevermind that PHP gets you that for free without anything nearly as sophisticated as the roslyn compiler, but I digress.

One thing that has been removed in MVC6 is the IMetadataAware interface. This allowed you to create your own subclasses of Attribute that could add data to the ModelMetadata structure to be used in an EditorTemplate or DisplayTemplate view. For instance, you could create a ReadOnlyAttribute:

Since IMetadataAware is removed from MVC6 I had to find another way to inject information into the view from model attributes. MVC6 does provide an IDisplayMetadataProvider, which is just a class you can register that is provided the same ModelMetadata context that IMetadataAware was provided. However, this causes an architectural problem in that any implementation of IDisplayMetadataProvider needs to know all about all the possible Attributes you have and what they mean, which is just bad design. Each attribute should be responsible for its own logic, as far as I'm concerned.

Luckily, it's not hard to recreate the old functionality of IMetadataAware. I first created a new interface, IModelMetadataAware:

Assuming all the Attributes implementing IModelMetadataAware are in a single assembly this should work fine, if not then it can be adjusted accordingly (see AppDomain.CurrentDomain.GetAssemblies()).

]]>http://blog.emikek.com/reinstating-imetadataaware-in-asp-net-5-vnext-mvc-6/9438e4e1-12eb-46c0-badc-d7eb060c3821Wed, 10 Jun 2015 22:35:35 GMTSeveral months ago I set up Mavericks under VMware but need Yosemite now to code up a new iphone app.

I did a clean install of it rather than upgrade Mavericks - which is fraught when running under vmware.

]]>http://blog.emikek.com/hackintosh-yosemite/d90c5ef3-6e85-4e02-a76f-827c7f25bf80Mon, 02 Mar 2015 07:32:25 GMTI'm playing a recital later this month and put together a quick site using the static site generator Jekyll. Aside from the killer performance and easy deployment and backup you get with a static site, the best part of going without a database is security. While escaping variables is always a nagging voice in the back of your head when coding a web app - it's really nice to not even have to think about it.

As usual I scripted out the deployment fully using salt, and added google pagespeed module to nginx to get great performance.

This is part of a hybrid salt-cloud and cloudformation deployment, without going into all the details of it this line will set the DNS (provided it's hosted on route 53 and you have the aws console tools installed and have your site behind an elastic load balancer):

]]>http://blog.emikek.com/jekyll/a8778bc7-5f9f-4575-9e05-0d8f077bef18Mon, 02 Mar 2015 01:37:34 GMTMouse without borders is the best app ever created. It's a tiny little program that lets you share a single mouse and keyboard across multiple workstations over a network.

It also shares clipboards and files across the connected machines.

Now I have it hooked up to my desktop, my laptop, and my Surface. I have visual studio and the browser containing the app on the main 30" screen, documentation and outlook on the laptop, and the New York Times and youtube on the surface :-). And can control them (almost) seamlessly as if they were one - save for moving windows in between them obviously!

A phone has up to four possible letters for each digit. Write a program to print out all possible words (not necessarily dictionary words). Do it recursively and iteratively.

In Python:

]]>http://blog.emikek.com/print-out-all-words-from-a-phone-numbers/d12ac4a7-9164-4545-a446-2793ba00336cTue, 28 Oct 2014 06:24:13 GMTThis presentation at strangeloop has been generating a lot of ink this week:

The presentation was somewhat interesting, the contentious point made was offering an SLA on a system without a good type system was unethical. This generated a lot of strong reactions and counter-reactions.

Yawn.

They may be right, in a vaccuum, or some parallel universe of platonic ideals. But ethics is hardly ever the only consideration. Risk vs return is another one. ROI is another. Is there a point to thinking about correctness at all if we don't even know if anyone wants the product? What's the trade-off of correctness vs all these other considerations?

That's a cold, hard calculation. For many cases, I would venture a guess that the balance leans away from correctness more than Mr. Snively and Ms. Laucher want to admit.

I'm not an advocate for bad software, but I'm definitely an advocate for good enough software. I imagine software quality grows logorithmically. Getting halfway to perfect takes one unit of time. Getting to 75% takes twice that. And so on. At some point - and this point is determined by external factors: the competition, the business area, financial considerations - it's time to stop worrying about type checking and start worrying about your business.

]]>http://blog.emikek.com/gc-finalize-and-dispose/113dcf69-fbc7-4566-81a0-9c913f0773cdFri, 10 Oct 2014 16:52:13 GMTRecusive solution that uses O(n2) memory. A more memory effienct solution would use global state to flag which letters have been used while deeper in the call stack. I opted for a more functional solution without global state.

This solution is not complete, but it solves a useful subset of inputs and does it correctly. Getting a working solution for a subset of posisble inputs is better than an incomplete or flawed solution that tries to cover all possible cases, as long as you can demonstrate to your interviewer that you understand the shortcomings of your solution.

This solution stops searching for a word when the smallest combination of characters in the compound word exists in the list. Therefor it will correctly return "peanut" for { "pea", "nut", "peanut" } but fail on { "pea", "peanut", "peanutbutter" } because it will break up "peanutbutter" after "pea" and not find a match for "nutbutter". A recursive solution that backtracks if it gets to the end of the string could solve this problem.

Find all combinations of 2 nodes which add up to a particular sum. Must have time complexity of O(n).

My solution was O(nlog n), needed a hint to get the idea of using two simultaneous traversals (one in order, one reverse) to find all the combinations in O(n).

]]>http://blog.emikek.com/combinations-of-nodes-adding-up-to-a-sum/d81f9887-74a7-4433-bcf3-5dc8f0d5195dTue, 23 Sep 2014 01:30:28 GMTFrom Cracking the Coding Interview: Implement a program to determine how many hits and pseudo-hits to return from a guess in mastermind.

Turns out a really easy optimization if order doesn't matter much is to treat it like a single dimentional array of length d1 x d2 x d3 ... dn where d1 is the first dimention, etc. These two expressions are exactly equivalent in the way the memory is laid out, for instance: