I originally wrote this a few months back, but I have done some work to let the algorithm be easily reproducible, as well as added some features to allow reduced memory (not-so-optimal) variants.