

Implore YC: Refactor My Code (uses Ruby and continuations) - mdemare
http://refactormycode.com/codes/83-combinatorial-explosion-with-continuations
This is a real (if sanitized) problem that my start-up has, ready for refactoring (on refactormycode.com which I love and am unaffiliated with). 
======
neilk
I don't know enough Ruby to refactor this, but using continuations to
enumerate possibilities seems like using a sledgehammer to swat a fly.

Am I understanding correctly that your goal is just to arrive at the tail call
of 'contract_sentence' in two parallel ways? In other words, you don't want to
collect the possibilities into an array, and then at the apply
contract_sentence() to each in turn? Is this because you're worried about
violating the form of a proper tail call?

~~~
mdemare
> using continuations to enumerate possibilities seems like using a
> sledgehammer to swat a fly

I just want the fly dead.

> Am I understanding correctly that your goal is just to arrive at the tail
> call of 'contract_sentence' in two parallel ways?

No, not two ways, dozens, and I don't know beforehand where multiple
possibilities will turn up. So, I can't enumerate all possibilities in an
array.

Think of it as finding all paths from the root of a tree to every single leaf,
where the tree is being made up as you walk it.

My current solution involves a lot of administration and makes my code brittle
and hard to extend.

The solution I posted to the toy problem at refactormycode.com works, but
continuations scare me and I don't quite trust their implementation in Ruby.

So I was hoping for a third option, or some advice in general.

~~~
neilk
Ok, your notion of walking a graph is not incorrect, but there's a MUCH
simpler way to look at your problem: combinations.

You basically have a stream of tokens (x), and some of these tokens (C) are
contractible. In other words, they have alternate forms.

So a sentence is something like this:

x1 x2 x3 C1 x4 x5 C2 x6 x7 x8 x9 C3

Now, break it up like so, where the contractible word is at the end of each
segment, and create the alternate forms:

1a) x1 x2 x3 C1 // C1 is "do not" 1b) x1 x2 x3 C1b // C1b is "don't"

2a) x4 x5 C2 // C2 is "he has" 2b) x4 x5 C2b // C2b is "he's"

and so on.

Now just find all the combinations of the above segments. 1a 2a, 1a 2b, 1b 2a,
1b 2b. This may look like a nested-loop thing but it's far easier to do it
recursively.

I have code that does this in Perl, if you want it. I was thinking of
translating it to Ruby as an exercise but it looks like I'm too busy for that
right now.

I suggest you take a look at SICP some day. Writing algorithms like this will
be second nature once you grok those techniques.

------
ced
I'd rather read a clear problem description and come up with my own solution
than infer the problem from the code...

~~~
mdemare
I understand, but the problem is hard to describe succintly.

But if you run the code, you'll understand at once what it does.

