Xobni Walks Away From A Microsoft Deal - <AUTHOR> http://www.techcrunch.com/2008/04/30/xobni-walks-away-from-a-microsoft-deal/ <comment><USER2> Why does nobody mention the fact that it would be very unusual for VCs to allow a company to be acquired at a 2x return? I don't know what their pre- money was when they took that 4.25m, but even if they gave away half of the company, that's a post-money of 8.5m. No VC is going to approve a sale for less than 30m in that situation, and even that might be too low.

I don't have any inside knowledge of what went on there, but I can't imagine that selling for 20m was an option for the founders even if they had wanted to.

<comment><USER3> VCs should allow a company to be acquired when they believe its value has peaked, not some preset ratio or return. A smart VC would sell at 80% return if he thought it was only down from there.

<comment><USER2> Well, it's fairly rare a VC invests in a company that early stage and thinks it's peaked a year later. I agree with you, but that doesn't happen.

<comment><USER3> There's certainly a psychological/selection bias aspect to it. If they bought in early they're more likely to have a rosy vision of the future prospects than your average spectator.

</comment></comment></comment></comment><comment><USER4> I admire their guts and their determination. It's awfully hard for 20-something folks to look at 20 million bucks (probably $10mil by the time the investors got their share, but still serious lifestyle-changing money) and walk away from it. Of course, as Matt pointed out, VCs don't like such a small return. 100% in 18 months isn't bad, but it's also not the kind of returns VCs need to see to make their math add up right. They can afford to fail frequently, but they can't afford to succeed modestly on a few investments and fail on the rest of them--they can only afford the failures if the successes are huge. So, it's either fail hard or win huge. It's a weird model, but it seems to work for the investors (the entrepreneurs might not always be getting a great deal out of that math, though).

Anyway, I'm optimistic that the guys have the flexibility to evolve their ideas into a $100mil business. Wider platform support is crucial, of course, but so is solving a "hair on fire" kind of problem. Email is obviously a huge industry, and I know there will be many more huge successes in email-related startups, but they've got some stiff competition.

So, get back to work guys...you've got a long hard road ahead of you.

<comment><USER5> I haven't yet seen an unique usefull idea from xobni so far, except that they group attachements by author....

<comment><USER6> They added Gmail-style conversational threading to Outlook. That's one of the best features of Gmail and something Outlook was really missing. It's not a unique feature, but it's definitely useful. There aren't many companies out there that are trying to improve the basic functionality of email; I'm actually surprised that Xobni has seen so little competition.

<comment><USER7> Once you get used to it, outlook's standard conversation view is more convenient than GMail's, at least for me.

</comment></comment></comment></comment><comment><USER8> I haven't used Xobni, but if Google desktop search can index my Outlook, then Google are most likely but an intern away from eating Xobni's lunch.

Sender, recipients, subject, threading. I wonder if access to Outlook is the real true prize for all that work on Google desktop.

It still seems pretty surprising that the only really viable way to search MS Email is by using Google desktop search.

<comment><USER9> Xobni != Outlook search. At all. And Google Desktop Search is not the only really viable way to search Outlook.

???? Do you even use Windows?

</comment></comment><comment><USER10> I'm honestly surprised by all the fuss over xobni. I have it running on my Outlook at work, where I get a ton of e-mails per day, and I frankly haven't found it to be very useful as of yet. Maybe I haven't fooled with it enough.

<comment><USER11> Search-done-right and the list of attachments sent between myself and a contact have removed a perpetual source of frustration in my workday. Maybe your situation is different.

<comment><USER12> I used to regularly run 5-minute long searches in my inbox to find a particular attachment that I needed. It was hell compared to, say, GMail. I haven't tried Xobni, but the search and attachment features are the right ones to tackle.

<comment><USER7> I heard that Outlook 2007's search is much faster than previous versions. Is that true? Maybe it isn't as fast as Xobni, Lookout, or Google Desktop Search, but people have said that it is fast enough.

</comment></comment></comment></comment><comment><USER13> W.r.t. to simply becoming a feature of Outlook, I can't imagine what else they could possibly have expected. But $20M is a pretty weak offer.

<comment><USER9> With what basis do you have to say $20m is a weak offer? I'm not clear on what numbers you are using to base your view on. I'm not privvy to the internals at Xobni so I couldn't even guess whether $1m is weak let alone $20m.

<comment><USER13> They've taken $5M in funding, which probably means they took it at at least a $10M valuation. Furthermore they're already a mature, established company, probably moreso than any other YC company besides Loopt.

</comment></comment></comment><comment><USER14> I want to reiterate my advice to Xobni, Sell and run! These guys are beasts they will make a copy of Xobni and make you history, remember Netscape.

<comment><USER15> Yea, these beasts can't even compete with their own 5-year old products.

</comment></comment><comment><USER16> I think it's clear that Microsoft want to add these kinds of features to Outlook. I wonder now if they'll attempt to build their own as a direct competitor, or shop around for another business to aquire?

</comment><comment><USER17> I think if you're willing to assume the risk of starting the company in the first place, then you ought to be willing to assume the risk of rejecting an offer and then potentially failing afterwards. It's a risk, but if you enter into it with your eyes open, and the situation makes sense, it's one you shouldn't be afraid of.

I wonder if people wouldn't be having this same conversation about the Google/Yahoo deal that was kicked around in the early days. (I know that deal was different, but it's the same risk - what if your company could become the next Google by turning down this offer?)

On another note, I think this response speaks to the question a lot of people have asked about whether YC companies are being created simply as acquisition targets or whether they're in it to create long term businesses.

<comment><USER18> Just another data point, even AOL tried to acquire yahoo during 95/96 for cheap. Just that price wasnt agreeable I think. Now 12 years later Yahoo acquiring AOL is an option to fend off MS.

</comment></comment><comment><USER19> <http://www.paulgraham.com/googles.html>

"Tip for acquirers: when a startup turns you down, consider raising your offer, because there's a good chance the outrageous price they want will later seem a bargain. [1]

From the evidence I've seen so far, startups that turn down acquisition offers usually end up doing better. Not always, but usually there's a bigger offer coming, or perhaps even an IPO."

<comment><USER20> "Usually" is the key phrase. The first startup I worked for turned down an $50M acquisition offer when we only had 15 employees and no funding. Everyone up to employee 10 would have made at least a million dollars off of the deal. 2 years, $20M of investment and 150 employees later, the company was "sold" for peanuts in a deal where the VCs folded us into another portfolio company and nobody got anything.

<comment><USER21> IIRC, Linuxcare turned down a few offers when it was still 'hot'. I don't think they were very good offers, but it still turned out to be a mistake.

</comment></comment></comment><comment><USER22> I really think that if Xobni sticks to it's guns, they can probably have a nice ISV and make quite a bit more than $20 million a year without breaking a sweat. If they price their product for $100 a license, then they'd only have to sell 200,000 licenses a year to reach $20 million a year.

<comment><USER23> _"If they price their product for $100 a license, then they'd only have to sell 200,000 licenses a year to reach $20 million a year."_

Since the price of MS Office Home Edition is $150, imho they will have a tough time justifying a price higher than $29.99 (with the current feature set of Xobni at least). Don't get me wrong - I like Xobni... I am just saying this from a practical sales standpoint.

Considering this and considering they have to pay income tax instead of capital gains tax, they may have to sell at least a million copies to make $20 million.

Of course they can make it into a product with a ton more features making it worth $100 a piece in the eyes of Joe CubeDweller.

<comment><USER24> "Since the price of MS Office Home Edition is $150..."

I don't think that really has anything to do with it. There are plenty of Office plugins that cost hundreds or even thousands of dollars. It's all about how much value the product offers and how much that value is worth to the users. I don't disagree that $100 a seat seems a bit pricey for Xobni's existing functionality, but I don't doubt it could someday be worth that or even more to a large organization.

<comment><USER25> > There are plenty of Office plugins that cost hundreds or even thousands of > dollars.

Do you remember the names of these plugins? I know there are some dev-tool type plugins that cost a lot.

<comment><USER24> Well, I work in the financial industry, so that's the type of product I'm familiar with... but Bloomberg, FactSet, SNL, Capital IQ, Datastream, Mekko, DealMaven... all of those offer Excel, Outlook and/or PowerPoint plug-ins that carry price tags well above those of the Office apps they depend upon.

<comment><USER23> Thank you for sharing the knowledge. I didn't know that.

Follow-up questions: I look at Xobni as a time (hence money) saving tool for the end user... not a money making tool. Are all the tools/plug-ins that you mentioned money making tools? Can a time saving tool be sold for a price higher than the host app?

<comment><USER24> Well, it's kind of a blurry line that separates the two. The financial industry existed before all of those products did. Building a financial model doesn't _require_ these products -- one could do it by spending hours pouring over government filings, etc. to compile all the information needed -- so they're all "time saving." And since time is money -- faster modeling means more work can be done in the same time, and/or fewer analysts are required to do the same work -- they're all "money making."

I suppose you could distinguish between the "market data/financials products" and "products that save time and thus money in other ways." Mekko, for example, might fall into the latter group -- it's basically just an advanced charting tool. It retails for about $500. DealMaven, which is basically a workflow improvement tool, would probably fall into that category as well, although I'm not sure what it costs.

</comment></comment></comment></comment></comment></comment></comment><comment><USER26> _"... The deal would have been a natural for Microsoft, which was offering to buy the two-year old startup for somewhere in the $20-million range ... Xobni offers a plug-in for Outlook that makes it smarter and easier to use ..."_

The product is a strategic choice. A choke point for desktop users to the Internet. Microsoft desktop users. The low offer could reflect the lack of competition. So the question can Xobni adapt to what people want and bring in a competitor?

Then I read this article ~ [http://www.techcrunch.com/2008/04/28/xobnis- secret-project-m...](http://www.techcrunch.com/2008/04/28/xobnis-secret- project-merge-outlook-with-yahoo-mail/)

</comment><comment><USER27> The poll, as of right now. (heh heh, 1337)

$20 Million?

        * Hell, yes! Are they crazy?
          1600
        * No, they will be worth a lot more a year from now.
          1337

Total Votes: 2937

</comment><comment><USER28> [Shaking my head]

Can't figure out who's behavior is more mystifying...the paymasters at MS, or someone who turns down 20M for a basically useless widget.

<comment><USER29> 50K users find some use in it. I'd like the analytics for GMail. Hell, if they work with gmail, the iGoogle open-social effort might replace facebook for me.

<comment><USER30> 50K downloads is not 50K users.

<comment><USER29> You're right. I just misread the stats.

</comment></comment></comment></comment><comment><USER31> this does not look like an IP buy for MS, it looks like a human capitol buy. It's one thing to have a product, a business and be allowed the freedom to innovate. Its another thing to be brought in and fix someone-else's problem. Its my guess that MS wanted Xobni to re-vitalize outlook rather than advance their product.

</comment><comment><USER32> look they got a 20million dollar offer while still in beta. They're obviously on to something. Turning down the money at this point isn't that risky.</comment>


Write a letter to your future self - <AUTHOR> https://ohlife.com/timecapsule

<comment><USER2> Prediction: service will be shut down way before receiving my letter to self</comment>


Why it's hard for programmers to write a program to flatten a list? - <AUTHOR> https://shekhargulati.com/2017/02/24/why-its-hard-for-programmers-to-write-a-program-to-flatten-a-list/ <comment><USER2> I'm a retired data architect and C developer with 36 years of professional experience. In my opinion, this is not how you find an appropriate candidate. It would be better to ask substantive questions that are related to the thing you are making. What does this person bring to the team? How will the team receive this person? Has this person delivered something of substance in the recent past that would convince you that he/she would succeed on your project? How was this person an asset on their previous job?

<comment><USER3> Those are questions for juniors. Most likely they had no previous job at all. The only thing they can bring is potential, and this question tests it rather well.

<comment><USER4> It does not really test potential because a junior trained in Java has poor tools for flattening a list because idiomatic Java would not represent hierarchical data structure as a nested list. Idiomatic Java would use tree and node objects. Idiomatic Java also prefers arrays over lists for sequential data.

An experienced programmer might look at the problem and choose a better tool: a different language or call a service or rewrite the offending code that produces a nested list or any one of a dozen things that are not bashing away with the hammer of Java.

<comment><USER3> > An experienced programmer might look at the problem and choose a better > tool: a different language

Come on, you are not going to call Haskell or Python to flatten a list in your Java.

> or call a service

I know we have "micro" services now, but really? Sending serialized data to ListFlatteningService to get deserialized FlattenedList?

> or rewrite the offending code

Something may produce it because it makes sense it its context, while it doesn't for you. No offence here.

<comment><USER4> I make no claim to being a good programmer or having high potential (of any sort but the wasted), just the ability to occasionaly mimic those who are. Charged with flattening lists, I'd write my Java in Clojure.

      (flatten [1 [[2] [[3 4] [5 [6]]]]])

as much of it as I could because it would be less work and easier to read and maintain and debug.

Since nested Java lists are isomorphic with trees, there's more than one way to deserialize them: inorder, preorder and postorder. Flattening deserializes in preorder. Expecting different consumers of the nested list to deserialize it in different ways might be a reason that producing a nested list makes sense in a particular context.

Once we start talking about "consumers of the nested list" we are using the language of services. That, for better or worse, is a road that currently tends to lead to micro-services.

<comment><USER5> Aren't list-of-lists more like trees where values are only stored on the leaves? In this case, aren't {pre,in,post}order all the same?

<comment><USER6> For the trivial case in which the nesting always gets deeper at the end like in the OP, perhaps. Take a look at nodes and leaves from my Perl5 example elsewhere in the thread.

        my $nested = [ 1, [ 2, 3 ], [ 4, [ 5, 6, [ 7, [ 8, [ 9, 10 ] ], 11, 12, [ 13, [ 14, [ 15, 16 ], 17 ], 18 ], 19 ], 20 ] ] ];

What the code does when there are leaves and nodes intermixed at arbitrary depths in arbitrary order from left to right determines the final order of your leaves. Are you pre-flattening all the more deeply nested lists and then building your flat list, or are you walking along a certain nesting level and deferring anything that's not a leaf to later flattening?

I gave two examples. One produces a flattened list like this:

        1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

The other products this:

        1 2 3 4 5 6 20 7 11 12 19 8 13 18 9 10 14 17 15 16

Are either of those outside the specification set forth?

<comment><USER5> Generally, "flatten" means the first of those two orders, but I see that the problem as given doesn't disambiguate those. If an interviewer wants to only accept one of those, he should clarify.

Incidentally, the first of those is preorder and postorder traversal of the list-of-lists (inorder only exists for binary trees), while the second is none of those. I would describe that difference as depth-first (first) vs breadth- first (second).

<comment><USER6> I think "flatten" is kind of underdefined.

In many situations, the order of the leaves doesn't matter at all. In others, it matters a great deal. The question should be clear if it does matter.

Depth-first for breadth-first was not specified. Both preorder and postorder are subclasses of depth-first. Neither preorder nor postorder was specified.

Still, it depends on what you consider a node and a leaf and how you build your tree how much the order matters.

Is a deeper nesting level the child node of a value? Are all values leaves and their parent nodes the nesting level? Are nesting levels collapsed into single nodes or are different nested lists at the same level sibling nodes?

         [1,[2,3], [4, [5,6]]]

          []
         / |
        1  [[]].
          / | | \
        2   3 4  [[[]]]
                  |  |
                  5  6

In preorder you're going to get: [], 1, [[]], 2, 3, 4, [[[]]], 5, 6 In postorder: 1, 2, 3, 4, 5, 6, [[[]]], [[]], []

Let me explode that initial root this time and make some values nodes if they are followed by an increased nesting level.:

        [1,[2,3], [4, [5,6]]]

           1
          /  \
        []    []
        |\     |
        2 3    4
               |
              [[]]
              |  |
              5  6

Preorder? 1, [], 2, 3, [], 4, [[]], 5, 6 Postorder? Aah... 2, 3, [], 5, 6, [[]], 4, [], 1

So even after you splice out empty nodes, your values are suddenly out of sort order. It's still depth-first.

Or maybe we just don't build the nesting levels into our tree because we don't care. But we still build the tree according to it. We're flattening, after all, and the spec doesn't say we need to retain a nesting level as some attribute of the objects in the flattened list. But what becomes a node vs. a leaf is left as an exercise.

           1
         / | \
        2  3  4
             / \
            5   6

Preorder? 1, 2, 3, 4, 5, 6 Postorder? 2, 3, 5, 6, 4, 1

So yeah, it matters. The obvious recursive approach is preorder, especially if you want to maintain sorting. That's what I called "flatten" in my code example earlier. "flatten2" is breadth first as mentioned. Consider this depth-first Perl5 subroutine:

        sub flatten3 {
            my $n = shift;
            my $o;
            my @f;

            for ( @$n ) {
                if ( ref $_ eq 'ARRAY' ) {
                    unshift @f, flatten3( $_ );
                } else {
                    push @f, $_;
                }
            }
            return @f;
        }

In each level of recursion it's place the children at the beginning of the array (unshift) and the parent to the end of the array (push) even though it's actually considering them each whenever it reaches them.

Given my expanded example input of:

        my $nested = [ 1, [ 2, 3 ], [ 4, [ 5, 6, [ 7, [ 8, [ 9, 10 ] ], 11, 12, [ 13, [ 14, [ 15, 16 ], 17 ], 18 ], 19 ], 20 ] ] ];

This produces output like this, which is definitely the absolute deepest nesting first in the output.:

        15 16 14 17 13 18 9 10 8 7 11 12 19 5 6 20 4 2 3 1

Then there's a true postorder traversal, with an array holding the parent back until after its immediate children.:

        sub flatten4 {
            my $n = shift;
            my @p;
            my @f;

            for my $node ( @$n ) {
                if ( ref $node ) {
                    push @f, flatten4( $node );
                } else {
                    push @p, $node;
                }
            }

            push @f, @p;
            return @f;
        }

which provides output as such since it's considering the parent node after all its children every time.:

        2 3 9 10 8 15 16 14 17 13 18 7 11 12 19 5 6 20 4 1

Whereas preorder depth-first keeps the numerical order for this input and the breadth-first traversal gives:

       1 2 3 4 5 6 20 7 11 12 19 8 13 18 9 10 14 17 15 16

as previously shown.

So no, preorder and postorder do not necessarily mean the same output just because the input started as a nested list.

A nested list is not simply a list. It is a special representation of a tree. How you consider that tree to be represented by the nested list is important, as is how you traverse it. In fact, in Perl [] is an array reference, which is why this code is testing for references and recursing on them. So it's already traversing an actual tree structure.

<comment><USER7> Don't overthink it. But if we're gonna overthink it, one thing we can notice is that a rose tree is a free monad, and like any free structure is initial in its category - meaning there's a unique monad homomorphism from a rose tree to any other monad. Lists form a monad, so we can ask "what is that homomorphism?" It turns out to be the traditional definition of flatten.

That is to say, only flatten solves these equations for lists and rose trees:

        (flatten . f =<< flatten m) == flatten (f =<< m)
        pure x = flatten (pure x)

<comment><USER6> I believe speaking of monads, monoids, functors, and homomorphism when discussing an interview question for fairly fresh programmers is definitely overthinking it.

I'm not sure what you think is so simple about your solution compared to:

        sub flatten {
            map { ref ? flatten( @$_ ) : $_ } @_;
        }

Goodness, and Perl gets a bad reputation for the amount of punctuation in the code.

Of course if you want flatten in Haskell you have it for Tree and Forest.

        import Data.Tree
        tree = Node "A" [Node "B" [], Node "C" [Node "D" [], Node "E" []], Node "F" []]
        main = do
            print $ flatten tree

If a Perl programmer wanted to pull in a CPAN module, there are many from which to choose. Of course, it was just done in a one-line subroutine...:

[http://search.cpan.org/~obradovic/List- Flatten-0.01/lib/List...](http://search.cpan.org/~obradovic/List- Flatten-0.01/lib/List/Flatten.pm) (which does not handle arbitrary depths)

[http://search.cpan.org/~rthompson/List-Flatten- Recursive-0.1...](http://search.cpan.org/~rthompson/List-Flatten- Recursive-0.103460/lib/List/Flatten/Recursive.pm) (which seems overly complicated)

[http://search.cpan.org/~rsavage/Set- Array-0.30/lib/Set/Array...](http://search.cpan.org/~rsavage/Set- Array-0.30/lib/Set/Array.pm#flatten\(\)) (which tries to flatten hashes as well as lists and seems, well, overly complicated... and pulls in a bunch more methods and functions)

[http://search.cpan.org/~satoh/List- Enumerator-0.10/](http://search.cpan.org/~satoh/List-Enumerator-0.10/) (which seems about right, including stopping the flattening at an arbitrary depth and comes with other _useful_ array tools)

Of course it's possible to apply the concept of flattening to hashes/dictionaries, too, so there goes the concept of keeping the original sort order.

[http://search.cpan.org/~bbc/Hash- Flatten-1.19/lib/Hash/Flatt...](http://search.cpan.org/~bbc/Hash- Flatten-1.19/lib/Hash/Flatten.pm)

[http://search.cpan.org/~chocolate/Hash- Fold-0.1.2/lib/Hash/F...](http://search.cpan.org/~chocolate/Hash- Fold-0.1.2/lib/Hash/Fold.pm)

<comment><USER7> > I believe speaking of monads, monoids, functors, and homomorphism when > discussing an interview question for fairly fresh programmers is definitely > overthinking it.

I agree. I said as much. I just thought it was interesting.

> I'm not sure what you think is so simple about your solution compared to > [...]

Which solution? I didn't present an implementation in this thread. I did elsewhere ([https://news.ycombinator.com/item?id=13726564](https://news.ycombinator.com/item?id=13726564)), but I don't think that's what you're talking about? I was discussing specification, and the code fragment in my comment was a property, not a definition.

> Of course if you want flatten in Haskell you have it for Tree and Forest.

Yes, though Tree is a slightly less natural choice for this than a rose tree (aka `Free []`). Of course, you still have it (in the form of toList).

> If a Perl programmer wanted to pull in a CPAN module, there are many from > which to choose. Of course, it was just done in a one-line subroutine.

... yes?

You seem to be desperately trying to defend perl against an attack you imagine me to have made. I have nothing against perl (at least, nothing beyond a strong desire for static types on large projects, but that applies equally to a great many languages).

<comment><USER6> Oh, I'm not imagining you making an attack on Perl. It happens commonly enough, though. I was commenting that your property had a lot of punctuation and bemoaned that Perl with the same amount often gets criticized for that very thing. Meanwhile many of the same people are fine with Python's invisible punctuation, Lisp's parentheses, or Haskell's syntax which likewise includes a lot of punctuation.

I also was pointing out that Haskell has Tree shipping with it, and Perl's CPAN, which is usually a stellar place to look, has what appear to be some false starts. I'd sort of expect one of the many List:: modules like List::Utils, List::MoreUtils, etc. to have the functionality, but as far as I saw when looking, no. It's easy enough to do in the base language, though. I assumed Haskell from your language and the syntax of your notation.

Your Bash and sed solution appears simple on the surface, but it is using a trick of the data format and bringing together two languages. It's even using a syntax that will confuse some people on first look in that you're putting square brackets within square brackets starting with the right bracket then the left. Many people are going to look at that and at first think it's two empty character classes then do a double take. It's clever, but any simplicity in it is rather baked into some, let's say interesting assumptions. I like it as a snarky response to the problem, but it's not something I'd hire a programmer for proposing as a serious solution.

<comment><USER7> > Oh, I'm not imagining you making an attack on Perl.

'k :-P

> It happens commonly enough, though. I was commenting that your property had > a lot of punctuation and bemoaned that Perl with the same amount often gets > criticized for that very thing. Meanwhile many of the same people are fine > with Python's invisible punctuation, Lisp's parentheses, or Haskell's syntax > which likewise includes a lot of punctuation.

It certainly happens commonly enough, often unfairly. That said, I don't think _Haskellers_ usually complain about Perl's punctuation.

> I also was pointing out [...] of your notation

Ah, I seem to have misread you entirely there.

> Your Bash and sed solution appears simple on the surface, but it is using a > trick of the data format and bringing together two languages.

Well, it's true that we're lucky that a relatively simple transformation of the input format gives us the desired output. But I'm not sure I'd call it a "trick".

> It's even using a syntax that will confuse some people on first look in that > you're putting square brackets within square brackets starting with the > right bracket then the left. Many people are going to look at that and at > first think it's two empty character classes then do a double take.

I mean, you've kinda gotta assume people speak the language...

> I like it as a snarky response to the problem, but it's not something I'd > hire a programmer for proposing as a serious solution.

Well, it was a _snarky_ response, but I think that actually depends on the context. If it was "You have these particular 20 files, that need to be transformed this way just this once", it's a great "serious" solution and I'd totally hire someone who would propose it (or something equivalent in another language) in for that purpose. It's incredibly brittle to some particular changes in the input format (especially if you might find square brackets internal to items) and probably not something that should be built atop.

</comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment></comment><comment><USER8> The first problem I see is that your rubric is a complete shibboleth: The candidate has to guess what you are evaluating. In some interviews, all they want is working code. Others want performance. Others care about testing: Based on the question, I'd not be sure of what you want. There's places where writing the test first will, if anything, be detrimental. Others will love it. You have to be clear on expectations.

The second issue is that a question like that is not even remotely fair across programming languages. What about types? Is a list of lists a sensible, idiomatic practice in that language? It's a trivial question that makes sense in Lisp, and it won't faze a Scala programmer. People are probably going to come up with a good, concise solution in Python or Ruby. In Java, lists of lists are often considered awful things, the generics syntax is torture, and you'll find candidates that will actually think less of you for asking them to write that: If a list of lists happens, it's normally an intermediate step in a computation, and you'd not like to pass, or return, anything with that type signature to anything that isn't a private method.

So compare the very short, boring program that you need in a lisp, with the array of questions a professional Java programmer would have to ask you to make sure that you don't ding them with your list of questions, along with the extra knowledge of how to build generic functions.

Instead, why not ask a simple, yet realistic problem that can be solved in more than one way? A question where you can give someone points for doing good things, instead of subtracting points for not doing exactly what you consider the right solution to be. For extra success, make your rubric public.

I do a lot of interviews as part of my work, and I have noticed that, even for the same problem, little things like rubric clarity and tailoring requirements to the language make big difference in pass percentage on screens. Moreover, they also make a difference when they get to on site interviews if the rubrics all come from the same basic principles (and if they don't, you should change that).

Do yourself and your candidates a favor and abandon this question if you are interviewing people across languages.

<comment><USER9> > The second issue is that a question like that is not even remotely fair > across programming languages. What about types?

I wonder if part of this test _is_ to see if a programmer will choose a language that's appropriate for it. Picking the right tool for the job and whatnot.

</comment></comment><comment><USER10> The word "Java" really should be in the title.

Whatever else you say about it, Java is one of the entry-level languages. It's no wonder there are many entry-level programmers among its users. It's obviously a trade-off, as you get that many more candidates to choose from, compared to for example OCaml, Clojure or Erlang programmers. On the other hand, a percentage of people who _can_ flatten a list is greater in users of the more "advanced" languages.

If you want to have a good signal to noise ratio: avoid languages used in "Programming 101" like a plague and languages which are currently fashionable. This way you'll get candidates who learned the language by themselves, in most cases after learning and mastering their previous language.

Becoming a programmer is a long process. Depending on the person, the time required to learn a single programming language may be shorter than the time needed to really master all the essential programming skills. Which I think explains why there is a correlation between good programmers and people who know more than one programming language.

<comment><USER4> One of the problems is that for Java the task is underspecified: Flatten a list of _what_? Sure this one is integers, is that always the case or should the list take <object>?

Leaving out that information from the question is going to disorient novices who in a high stress situation at the short end of an asymmetrical relationship. I suppose if the interviewer lets them Google, then it is a fair test (and objectively, not Googling before writing code is probably the best criterion for failing miserably).

What the question really measures is how lucky the candidate was in their education. If they were taught in Racket rather than Java:

      (flatten '((1) ((2 3 ((4) (5 6)))))

and if they were taught the JVM rather than Java

      (flatten [[1] [[2 3 [[4] [5 6]]]]]

and with J

      flatten =: [: ; <S:0

I'd bet that the interviewer would not know if it was wrong or right. Which is the same issue of open endedness that the candidate faces.

<comment><USER11> > One of the problems is that for Java the task is underspecified: Flatten a > list of what? Sure this one is integers, is that always the case or should > the list take <object>?

Well, I don't Java much, but I think that even if the result List is just integers, the source list has to be (invalid syntax) List<Integer | List<Integer>>, which is somewhat problematic to type as anything but List<Object> given Java's lack of sum types.

<comment><USER12> More precisely List<Integer | List<Integer | List <Integer | List<Integer | ...> :) That would be trivial in functional languages.

<comment><USER11> It would be trivial in languages with sum types and support for recursive signatures/constructors, which doesn't describe all statically-types functional languages. And there's no reason such a language would have to be functional, though most are.

</comment></comment></comment></comment></comment><comment><USER13> > I am not sure what makes this problem tough for candidates.

Most people aren't programmers, and sad to say, most people employed writing code are not programmers.

I find trivial problems like this are good interview questions. What the person asks, says and does tells me a lot about what they would be like to work with. And it's not like you're using some bizarre datastructure or obscure CS case: this is an ordinary workaday problem. So it's not a "trick" or one-upsmanship, just "do you know your tools?"

</comment><comment><USER3> Some reasons:

* Nobody required this from them before.

* Recursion is rarely used to write business logic, most common thing programmers write and learn. Same for static methods and being generic.

* Type checking is done by compiler for them, so no surprise that they don't know how to do it.

* Relatively few people go beyond minimal, so adoption of is java 8 is low

Overall, it looks like a good question to pick up the best developers - assuming this is what you want.

<comment><USER14> To me, this smells like: * Required before: I only ever code at work. * Recursion: I didn't get any/much theory in school * Type checking: I don't know my language very well. * Going beyond minimal: agreed- try not to hire them.

</comment></comment><comment><USER15> I think a lot of this is based on your experience with languages. If you have exposure to a list/iterator native language like python, you come up with solution in a few seconds, even if you aren't even remotely a programmer. Other languages might not lend themselves to so obvious a solution.

The perl example cited here kind of blows my mind compare to the trivial python approach:

      def flatten(lst):
          rlst=[]
          for x in lst:
              if type(x)==list:
                  for y in(flatten(x)):
                      rlst.append(y)
              else:
                  rlst.append(x)
          return (rlst)

<comment><USER16> You perhaps missed that there were two solutions (+ test infrastructure) in that Perl post. You Python code is the moral equivalent of the three-line "flatten" function in the Perl example. The long "flatten2" function was doing it without recursion.

<comment><USER15> The part that was/is challenging/mind blowing for me to grok was:

       sub flatten {
            my @f;
            push @f, (ref $_ ? flatten( $_ ) : $_ ) for @{ $_[0] };
            return @f;
        }

The implicit $_, and whatever @{ $_[0]} does, is challenging enough that I bet I could find people who had been using perl to do work for years who wouldn't be able to explain what was happening here at first glance, even if they could eventually work it out/write it themselves with a bit of effort.

That's what I meant by native iterative/sequence languages like python lend themselves to easy solutions for this type of question, even for people who _aren 't_ programmers, whereas you really need to be a programmer to come up with something as powerful as the above.

Put another way, doing a complex joined query might be a trivial question for someone who knows even the slightest amount of SQL, but would be beyond most novice python developers (without of course just using a SQL select statement...)

I will admit the (dense) perl solution certainly has its own beauty that the more drawn out python solution is lacking, though I'm guessing it could be written in a pythonic way itself...

<comment><USER17> > I bet I could find people who had been using perl to do work for years who > wouldn't be able to explain what was happening here

Don't jump to conclusions. You will not find such people, because those are very basics. Understanding of $_[0] is necessary to use arguments in Perl functions and understanding of @{...} is necessary to use array references as lists.

<comment><USER15> Challenge accepted.

</comment></comment></comment></comment></comment><comment><USER18> As nobody seems to have posted a Java solution yet:

      import java.util.List;
      import java.util.stream.Collectors;
      import java.util.stream.Stream;
      import static java.util.Arrays.*;

      public class Flatten {

          public static void main(String[] args) {
              List<Object> nested = asList(1, asList(2, 3), asList(4, asList(5,6)));
              List<?> flat = flatten(nested);
              System.out.println(nested);
              System.out.println(flat);
          }

          public static List<?> flatten(List<?> nested) {
              return nested.stream()
                      .flatMap(x -> x instanceof List ? flatten((List<?>) x).stream() : Stream.of(x))
                      .collect(Collectors.toList());
          }
      }

I would say it's a bit of an odd question if you mainly target Java as it's very uncommon to encounter such a construct there, alone because the type system can't handle it properly.

<comment><USER19> Java never fails to astound in its verbosity, even today, even with much better utility functions for things like lists (flatMap/collect are new to me). But, now that I've taken the time to read through it, I see the actual flatten function isn't actually all that different an implementation from the Perl and Python variants other folks have suggested. But, Java sure does make you work for that list data structure.

I know it's verbose because of type definitions, and because there's no bare functions in Java, but it sure does balloon up small programs with a lot of boilerplate, and tends to hide the point of the program behind stuff that doesn't look like the purpose of the program.

</comment></comment><comment><USER20> Couldn't you just do something like:

        def flatten(x):
            if isIterable(x):
                for y in x:
                    yield from flatten(y)
            else:
                yield x

Well, technically this is a generator, but it's easy enough to put its result in a list.

<comment><USER21> I found this on Stack Overflow a while back, and I've been using it in my Python code since then:

        [item for sublist in l for item in sublist]

<comment><USER10> That wouldn't work in this case: it only works with lists where every element is also a list and it only flattens one level deep.

With these constraints, there are quite a few interesting techniques, for example in Scheme you can apply append:

        (apply append list-of-lists)

or in Python you can use reduce with add operator:

        reduce(op.add, list_of_lists) # op == operator module

And anyway, even if it's not the constrained version, the solution is indeed trivial, for example in Erlang:

        flatten(L) -> flatten(L, []).

        flatten([], Acc)            -> Acc;
        flatten([[] | T], Acc)      -> flatten(T, Acc);
        flatten([[_|_]=H | T], Acc) -> flatten(T, Acc ++ H);
        flatten([X | T], Acc)       -> flatten(T, Acc ++ [X]).

(please don't mind the inefficient use of ++, it's a toy example...)

It can get a bit more complex in a statically typed language, especially if you want to have static guarantees (no down-casting from Object), but it's still doable in a couple of minutes...

...is what this post - and discussion - is not about.

It's trivial once you get it, of course. But it's also true that it's almost impossible to figure it out on your own during a stressful interview if you _didn 't get it_ beforehand. It's so easy to forget that. We all once struggled with some concepts, and we all went through many discoveries of facts, techniques, and skills we didn't know existed, much less that we needed them.

What I want to say is that the beginners who fail to answer this question are not bad, they are just beginners. It's ok to reject them right now, but it's not ok to post an article suggesting that "programmers find it hard to solve trivial problems even with my help". It's not programmers, but beginner programmers; it's not trivial problem, just relatively widely known one; and it may well be the help was insufficient.

<comment><USER21> Thank you for the correction!

</comment></comment></comment></comment><comment><USER22> Am I the only one who saw the string representation of the nested array and said "you could just walk it character by character and ignore the brackets and commas?"

<comment><USER23> That is indeed, depending on the context (you know the strings won't contain commas OR that it should be split in the commas), one way to do it in Javascript ( [https://github.com/franciscop/umbrella/blob/master/src/plugi...](https://github.com/franciscop/umbrella/blob/master/src/plugins/args/args.js#L17) ):

        return args.toString().split(/[\s,]+/).filter(/* ... */);

</comment></comment><comment><USER24> When reading this, my immediate instinct was to say: "Easy!"

      import { flattenDeep } from 'lodash';

      const flat = flattenDeep([1,2[3], [4, [5,6]]);

Not sure why employers care about developers being able to write utility functions from scratch, when that is not (typically) the job developers are hired for.

Having said that, I lament the issues that the OP brought up: poor naming, unfamiliarity with their language's data structures, etc. Those are issues that _will_ come up. Especially naming.

<comment><USER25> > _Not sure why employers care about developers being able to write utility > functions from scratch, when that is not (typically) the job developers are > hired for._

Because of the reasons you listed in your next paragraph:

> _poor naming, unfamiliarity with their language 's data structures, etc. > Those are issues that will come up. Especially naming._

No one actually wants a candidate to write "flatten". They want the candidate to demonstrate that they can work through a small problem and write something sane and functional. Utility functions tend to be small and reasonable to put together in about an hour.

With that said, I think this is a mediocre question because no one would create this list of lists-or-ints in Java. If presented well, the problem might be decent. If presented poorly, a lot of junior candidates would likely fail even if they're good candidates.

</comment></comment><comment><USER26> A slight rewrite makes this a reasonable question in Java. A list of lists has a tree structure and asking candidates how to print the items in a tree in depth-first order is reasonable.

The main issue is that you'd never use a list as a tree node in Java. There would be an explicit Node class of some sort.

I do ask a question where one possible solution is to define your own Node class, build a tree, and print it out. But you can also solve it without even realizing you're working with a tree.

</comment><comment><USER6> This is pretty trivial. It doesn't require recursion, although the recursive implementation is much simpler. The spec doesn't specify breadth-first or depth-first. The example input offered comes out the example output offered either way. The spec in the article also doesn't mention making it generic, so I don't see how that's points away for programmers who tackle the input and output given as integers only.

Here's some pretty trivial Perl5 to do recursive or iterative versions.:

        use strict;
        use warnings;
        use Data::Dumper ();
        my $nested = [ 1, [ 2, 3 ], [ 4, [ 5, 6, [ 7, [ 8, [ 9, 10 ] ], 11, 12, [ 13, [ 14, [ 15, 16 ], 17 ], 18 ], 19 ], 20 ] ] ];

        sub flatten {
            my @f;
            push @f, (ref $_ ? flatten( $_ ) : $_ ) for @{ $_[0] };
            return @f;
        }

        sub flatten2 {
            my $n = shift;
            my ( @f, @queue1, @queue2 );
            my $pass = 0;

            for ( @$n ) {
                if ( ref $_ ) {
                    push @queue1, $_;
                } else {
                    push @f, $_;
                }
            }
            until ( $pass > 0 && scalar @queue1 == 0 && scalar @queue2 == 0 ) {
                for ( @queue1 ) {
                    if ( ref $_ ) {
                        push @queue2, @{ $_ };
                    } else {
                        push @f, $_;
                    }
                }
                @queue1 = @queue2;
                @queue2 = ();
                $pass++;
            }

            return @f;
        }

        print STDOUT (join ' ', flatten( $nested )) . "\n";
        my @flat = flatten( $nested );
        print Data::Dumper::Dumper \@flat;

        print STDOUT (join ' ', flatten2( $nested )) . "\n";
        my @flat2 = flatten2( $nested );
        print Data::Dumper::Dumper \@flat2;

<comment><USER17> You can make it nicer and more reliable with Perl:

        sub flatten {
           map { ref $_ eq 'ARRAY' ? flatten(@$_) : $_ } @_
        }

However, this is not something a Java/OO programmer would be comfortable with, especially under the stress of the interview. As it's a bit higher level and closer to a functional way of thinking, than OO.

<comment><USER6> I started to use map, but I've been told time and again anything that does is not a trivial example because you start by explaining what map does.

Anyway, I'm glad the first response to "this is trivial in Perl" is another, simpler Perl response rather than "Perl is dead".

</comment></comment></comment><comment><USER23> I fail to see how some people see this as a _contrieved_ test. It's an issue many programmers have probably found at some point as opposed to fizzbuzz or other artificial tests. Probably other questions related to your business would also be good, but using this as a first and quick filter sounds about right IMO.

In Javascript, depending on your context, it could be as easy as:

         // Only if we're using numbers or other variables without commas on them
         // divide them, remove empty things and make them numbers again
         const flatten = arr => arr.toString().split(/[\s,]+/).filter(e => e).map(n => 0+n);

Or a slightly more complex and "proper" one as:

        // Recursively flatten an array
        const flatten = arr => arr.reduce((all, one) => all.concat(one instanceof Array ? flatten(one) : one), []);

<comment><USER27> The complaint isn't that it's contrived in general. The complaint is that it's a bad question if you're interviewing Java developers (because Java's type system is impoverished, but that's really beside the point).

If you're going to ask this question of a Java developer, you should carefully indicate what form the input takes. Heterogeneous collections are canonical in dynamically typed languages, and also in reasonable typed languages as recursive sum types. But in Java you're stuck between awkward subtyping / dynamic casting, or coding up your own definition of a heterogeneous collections. And in particular, the wording of the question suggests List<Object>, which is terrible style in Java land.

The real take-away is that Java's type system stinks for this sort of thing, and the standard libraries don't offer much help. But if you're interviewing Java developers, you shouldn't start off by asking them to writing terribly non-idiomatic Java code.

</comment></comment><comment><USER7> { echo [; sed s/[][]//g; echo ]; }

<comment><USER28> This is the TYPE of answer I like to see.

</comment></comment><comment><USER29> The fact that "int or list of int" isn't sanely representable in any concise way in the mainstream OO languages is a sign that perhaps this isn't a great example problem for a Java interview.

Obviously you can do this with brute forcing the sum type with some class hierarchy (ugh) or make the algorithm accept some List<object> or Java "List" interface.

Both of those options are pretty terrible.

I think the intents of the question are good - see if the candidates understand the importance of naming, signature, tests.

There has to be a question that does this and doesn't immediately have the subject crying over the type system.

<comment><USER11> > The fact that "int or list of int" isn't sanely representable in any concise > way in the mainstream OO languages is a sign that perhaps this isn't a great > example problem for a Java interview.

OTOH, if you are going to be using Java dealing with real world problems, many of which have aspects that are not neatly representable in Java's type system, some test of how you deal with the mismatch of that type system with a problem statement may be appropriate.

A lot of whether this is appropriate in an interview goes beyond the language used to what the job entails and what you are trying to learn about the candidate from the response.

<comment><USER29> Yes obviously Java is going to be the tool at hand, but to keep focus on the good aspects of this exercise (naming, testing, etc) perhaps it would be best to have a problem that has a good solution in Java.

If the subject does this property with generics that simple sum type alone requires writing several classes just to represent the sum type.

It's not clear from the article what the input _is_. What signature I can use depends on what the input data is. Is it a string rep of the nested list? Can I assume it's any type I want such as my own NestedList?

</comment></comment></comment><comment><USER30> A somewhat more interesting challenge is: write code to _lazily_ flatten a list. It must instantly return, and access the original structure lazily. Each atom is fetched from the original list when the lazy list is accessed. No continuations allowed; at most lexical closures.

My C solution is in this file:

[http://www.kylheku.com/cgit/txr/tree/lib.c](http://www.kylheku.com/cgit/txr/tree/lib.c)

functions lazy_flatten_scan, lazy_flatten_func and lazy_flatten.

</comment><comment><USER31> I don't really write Java, but I fail to see any easy and robust way to assign a type to the flatten function in Java.

Is this the signature you would expect in a solution to this?

        List<Integer> flatten(List<Object>)

Or something like

        List<Integer> flatten(NestedList<Integer>)

with a definition for NestedList?

Is there even a way to define something like NestedList without coercing back and forth from Object? Is there a way you can do this so that you don't have to basically reimplement List?

<comment><USER32> I would either use Object to be quick, or implement a NestedListItem with isNumber(), getNumber(), getList().

The one thing I do like about this problem is it shows when TDD is useful. If you try to write a test case first the representation problem will be the very first thing you run into, and the code will mostly follow from there.

<comment><USER31> Personally, I think this problem shows why sane type systems are useful.

In Haskell

        data NestedList a = Single a | Nested [NestedList a]
        -- Or equivalently, type NestedList = Free []

        flatten :: NestedList a -> [a]
        -- This is pretty much the only reasonable definition of flatten the compiler will accept given this type
        flatten (Single a) = [a]
        flatten (Nested xs) = concatMap flatten xs

        -- or given the Free variation of NestedList
        -- flatten = retract

<comment><USER7> Not necessarily. See my bash solution in another comment :-D

</comment></comment></comment></comment><comment><USER29> This is pretty easy actually: since the question is _horribly_ vague on what the input type actually IS, I'm going to just assume it's a string.

So flatttening the list is just a string split on all delimiters. Done.

My Java is rusty but something like input.split("\\[\\],"). Done.

It's an answer of exactly the same quality as the question...

</comment><comment><USER33> It's trivial, of course, in Common Lisp:

      (defun flatten (x)
        (if (listp x)
            (reduce #'append (mapcar #'flatten x))
          (list x)))

</comment><comment><USER29> > No one thinks about generic program so that solution will work across all > types.

Is this even possible to do generically in Java or C#?

You can do it for objects so that it works for ALL types (i.e "object"), but you can't make it work generically for a type T for any T.

That's why this is such an excellent example of why sum types really are useful.

Writing the flatten interface without generics (Java List or c# IEnumerable) is not generic. If you do that it will accept a heterogeneous list - which we probably don't want.

<comment><USER27> Yes you can code up sum types in the object system of Java or C#.

But are you allowed to do that? The problem write-up makes it sound like you're supposed to be ingesting the interviewer's input. So, how did the interviewer code up sum types? With tons of nasty casting out of List<Object>, or with a slightly less terrible object hierarchy mimicking sum types?

That's what makes the question terrible. It implies you're supposed to be coding against an interface, but in the allowed language (Java) it's totally non-obvious what the interface is.

I'll submit this criteria for coding question: if a big chunk of your candidates can't write down the friggen _type_ of the program you want them to implement -- and if two reasonable people could write down _extremely different types_ for the same question -- then your question is bad and you should throw it out.

<comment><USER29> Agree 100%.

Title of blog post could be "How do I keep failing to convey the basic constraints and requirements of a programming interview question?"

</comment></comment></comment><comment><USER34> This is straight out of my homework for an introductory to CS class. If I can recall, we need an IF statement to detect whether the element IS INT, else length of list. Then just add [Int] or list[:] to the new list.

Ok point being: I didn't believe what I was learning was relevant to industry, in particular linked lists.

</comment><comment><USER35> It took me about 5 minutes to solve this in Swift. My first thought was to use a recursive function that takes an array with a generic type. I'm not sure that would have been my first thought under the stress of an interview. Its very likely I would have frozen and wouldn't have produced anything at all.

<comment><USER36> It took me an embarrassingly long 15 minutes in Python. I had already seen the mention of recursion in the description, so I hope I would have realized that it was needed. (I am guessing I probably would have looked at recursion at the point when I realized that there were multiple levels of nesting, and not just one).

</comment></comment><comment><USER37> After reading the problem, I spent 5 minutes writing a performant, optimized, generic, recursive solution in Java (technically Kotlin). I don't consider that to be one the reasons that I'm a good engineer.

</comment><comment><USER38> I haven't done any interview prep in quite awhile and I feel like even a question like this would leave me dead in the water, given what the post laid out.

</comment><comment><USER39> If you give the option of any language and they choose Java to work on a single instance of an untyped array, they should be disqualified.

</comment><comment><USER40>
      $ node
      > [1, [2, 3], [4, [5, 6]]].toString().split(',').map(n => Number(n))
      [ 1, 2, 3, 4, 5, 6 ]

</comment><comment><USER41> #python code

def flat(x):

      if type(x) == type([]) and len(x)==1:

        return flat(x[0])

      if type(x) == type([]) and len(x)>1:

        return flat(x[0]) + flat(x[1:])

      else:

        return [x]

</comment><comment><USER42> $ irb 2.3.1 :001 > [1,[2,3], [4, [5,6]]].flatten

=> [1, 2, 3, 4, 5, 6]

BOOM!</comment>


Ask HN: please review my tool for rewrite rule testing - <AUTHOR> http://martinmelin.se/rewrite-rule-tester/

<comment><USER2> I tried it with the WordPress rewrites ( <http://codex.wordpress.org/Using_Permalinks> ) and I couldn't get it to work. I think the problem is that I didn't know what to put in REQUEST_FILENAME. I tried the following:

REQUEST_FILENAME: I tried blank, "year/month/day/post-name" and "/year/month/day/post-name".

URL: year/month/day/post-name (to give hostname/year/month/day/post-name).

Rewrite rules copied from the WP link above:

      # BEGIN WordPress
      <IfModule mod_rewrite.c>
      RewriteEngine On
      RewriteBase /
      RewriteCond %{REQUEST_FILENAME} !-f
      RewriteCond %{REQUEST_FILENAME} !-d
      RewriteRule . /index.php [L]
      </IfModule>
      # END WordPress

I got one no match and two rules skipped.

 _EDIT_ : You have an XSS vulnerability in the URL field. Use the first test from this list: <http://ha.ckers.org/xss.html> .

<comment><AUTHOR> Thanks! I've realized I need to come up with a better way to handle the special RewriteCond patterns, such as -f and -d. Right now all variables are handled in the same naive way, i.e. you get to specify their value in text form, but for things like -f/d/l that doesn't work (because for instance -f tests if the input string is a file in the current directory)

</comment></comment><comment><USER3> Very handy - worked well for a couple of simple rules; it'd be good to see more feedback when it can't handle something (e.g. feeding it the rules from [http://stackoverflow.com/questions/992565/why-isnt-this- rewr...](http://stackoverflow.com/questions/992565/why-isnt-this-rewrite-rule- working) just results in a greyed-out URL field).

Trivial nit: backslashes are doubled when rules are restored from the session.

<comment><AUTHOR> Thanks for the feedback, should have a fix up shortly for the backslash problem and will try to improve error handling in the UI some more. That SO thread looks like a great resource for gnarly rulesets to test :)

</comment></comment><comment><USER4> Haven't actually tried it, but anything that helps with mod_rewrite is gonna be useful :)

</comment><comment><USER5> Wow, this is a great idea! One idea, maybe add a small disclaimer or something at the bottom stating that any saved rewrite rules are private - rewrite rules often contain paths to scripts/pages on the filesystem that many people would never wish to reveal to the public. Or, make the storage functionality optional so real privacy freaks can turn it off.

I will definitely use this next time I have to hack 'n slash some rewrite rules though!

</comment><comment><USER6> Very useful indeed, thanks!

I'm missing one important feature though: there is no way to test different host names. I use rewrite rules that check country specific TLDs on the domain name and also rules that check if the domain starts with "m." for mobile specific access by matching against %{HTTP_HOST}. This would also allow one to check if the URL is using an IP address instead of a domain name. This would seem a common need, right?

<comment><USER3> I tried this and an extra field appeared above the URL allowing me to specify a value for HTTP_HOST.

</comment></comment><comment><USER7> Had quick run at it and it seems to work nicely. I spend half my life dealing with rewrites of varying complexity so this might well save me some time!

</comment><comment><USER8> It would be great if you would allow for multiple test URLs, i.e. make the "Enter a URL" input field a textarea that accepts a new URL on every line.

Another suggestion: why not just use localStorage instead of a $_SESSION?

</comment><comment><USER9> Its definitely going to make my life with debugging mod_rewrite rules so much easier. Thanks =D</comment>


2D Terrain generation using midpoint displacement - <AUTHOR> https://bitesofcode.wordpress.com/2016/12/23/landscape-generation-using-midpoint-displacement/ <comment><USER2> This is fantastic for kids or new coders. Its good coding practice, makes apparent the power of a simple, elegant algorithm, and has a big visual/fun payoff. You could spend weeks extending the concept.

And for a 3d example: [https://goo.gl/images/JpSXTW](https://goo.gl/images/JpSXTW)

edit: a friend of mine wrote a game called dragon strike with terrain gen and I can't remember any real interactive 3d being done on a PC before that: [https://extralives.files.wordpress.com/2013/09/dragonstrike_...](https://extralives.files.wordpress.com/2013/09/dragonstrike_1a.jpg)

I'm sure there was prior art in some other pc game, maybe someone remembers...

<comment><USER3> There are tons of early examples of interactive 3D depending on what techniques and technologies you want to consider.

DragonStrike is most like a flight sim, of which the Microsoft Flight Simulator series dates back to 1976-77(for 8080 and Altair!), with FS 3 and 4, from 1988-1989 being most like DragonStrike in terms of tech. Contemporary examples within other genres include: Arctic Fox. M1 Tank Platoon, F-15 Strike Eagle II, Midwinter, Carrier Command, Stunts, and Test Drive III. "Flight sim" style 3D, with wireframes, flat polys and some sprites, was considered the main way to do interactive 3D for a long time, with each renderer having to pick and choose which details to focus on - the most common compromise being to impose heavy distance fog in order to convey detail in screenshots.

In the arcade, flat-shaded, color 3D was done in Atari's I, Robot in 1983! One year later, a simplified raytrace model was used to prerender terrain lighting for Marble Madness - a subtle solution to a problem that otherwise would consume a lot of artist time. Most of the 80's in arcades was dominated by sprite-scaling games with pseudo-3D road engine hardware like Outrun and Space Harrier, though. Wolfenstein 3D and Doom are in many ways more in the pseudo-3D genre than the flight sims, since they exploit a very specific hack with raycasting that gives decent quality and flexibility.

Edit: Wolf3D style raycasting was purportedly used in Alternate Reality: The Dungeon in 1986. You wouldn't know it at a glance, though, since it's a slow- paced RPG where your view is glued to 90-degree angles and snapped to the horizontal center of the grid cells.

<comment><USER2> great recap!

iRobot was awesome, but to be fair it would have never been possible with only a general purpose cpu.

so many of those games showed great skills in optimization and design.

</comment></comment></comment><comment><USER4> Now add missiles! Scorched Earth ftw.

</comment><comment><USER5> If this is new to you, you should also investigate Perlin noise used to generate terrain. There are many examples online. It uses many of the same concepts although it's not quite as intuitive. I suspect it is more efficient, though, although that strongly depends on how good the PRNG you're using is.

</comment><comment><USER6> It seems like the old Moon Patrol (game) mountains, but better.

</comment><comment><USER7> Did he just re-invent fractals? That's roughly how most terrain generators work.

<comment><USER8> Yes, I think you could call it a fractal. The Wikipedia page linked to from the article says that this technique is also called a "random midpoint displacement fractal".

<comment><USER9> Midpoint displacement is mentioned in The Science of Fractal Images (and the Beauty of Fractal Images), and also in Mandelbrot's book Fractal Geometry of Nature.

From a phone, sorry about upside down: [http://m.imgur.com/JGCpnIu](http://m.imgur.com/JGCpnIu)

A snippet from "Science of Fractal Images"

</comment></comment></comment><comment><USER10> The author fails to realize Diamond-Square is called such because a diamond inscribed in a square touch all the midpoints with each corner....very intuitive.

</comment><comment><USER11> Whoever finds that these skylines look "realistic" spends to much time in front of a machine and too little time out in the mountains. This is ridiculous.

<comment><USER12> You put a word in quotes that appears nowhere on the page.

It's a useful technique in the procedural generation toolbox. Hardly ridiculous at all.

<comment><USER13> As one of the more popular terrain generation algorithms, it's a tool that gets used far too often.

Though to be fair, it's not only procedurally generated terrain that's wildly unrealistic in most 3D games. For the vast majority of games (except for, like, Arma), you'd think that the designers had never been outdoors.</comment></comment></comment>


20 blunders I committed in my career which I realised during recession - <AUTHOR> http://www.kapilbhatia.com/2009/01/20/20-blunders-i-committed-in-my-career-which-i-realised-during-recession/ <comment><USER2> I appreciate this guy's honesty. Sometimes we need to open the kimono and be honest with ourselves and others.

But I can't wrap my head around this: "I have masters in software engineering and I couldnt solve pretty simple recursion and data structure problems in one of the interview."

As a clueless hacker that was too arrogant to attend college -- isn't theory pushed like gospel in academia?

<comment><USER3> _isn't theory pushed like gospel in academia?_

No, not really. When I went to school I switched from CS to Math because I felt like the CS program was too job oriented and I wasn't learning anything of lasting theoretical value.

However, recursion and data structure problems are not theory and a master's in software engineering isn't particularly academic.

</comment></comment><comment><USER4> "I was becoming more reluctant to open notepad and try one programming problem." - something is amiss here.</comment>


What Eduardo Saverin owes America. (Hint: Nearly everything.) - <AUTHOR> http://pandodaily.com/2012/05/12/what-eduardo-saverin-owes-america-hint-nearly-everything/ <comment><USER2> What Apple and Google owes to America? Everything...yet that doesn't stop them evading some taxes, much more than Saverin.

<comment><USER3> That corporations in America don't pay their share is not the issue. Its an issue, but not the issue.

<comment><USER2> So we put one individual on the wall, but close our eyes when it comes to corporations which are doing the same thing more or less?

<comment><USER4> You are committing an argumentative fallacy. That other wrongs are being committed does not detract from the wrong being talked about.

</comment></comment></comment></comment><comment><USER5> > he had some pretty terrible ideas for Facebook, including his plan to show > _interstitial ads_ when you went to add a friend

For anyone who doesn't know the what term "interstitial" means (I didn't!):

        interstitials are web pages displayed before or after
        an expected content page, often to display
        advertisements or confirm the user's age (prior
        to showing age-restricted material)

<http://en.wikipedia.org/wiki/Interstitial_webpage>

I wonder if this was something he actually tried to get implemented, or simply threw out there when they were thinking up monetisation strategies - if the latter it seems a bit harsh to pick him up on it!

</comment><comment><USER6> Saverin is paying his taxes.

</comment><comment><USER7> lol. Saverin Sr leaves a country before it gets too dangerous => Applause

Saverin Jr leaves a country before it gets too dangerous => Boo

</comment><comment><USER8> Soap operas on HN heh? As long as he is a law abiding citizen I don't see what business anyone has with what he does or where he lives.

<comment><USER9> The OP isn't making a legal argument, he's making a moral/ethical argument.</comment></comment>


Testing Mincemeat.py MapReduce Scalability using GridCentric - <AUTHOR> http://blog.gridcentriclabs.com/2010/09/gridcentric-testing-mincemeatpy.html

<comment><USER2> Without details on the task he's running and the setup of his cluster, it's hard to know how meaningful these results are. Using a variation of the example, I've seen roughly 80% improvement with each doubling of the cluster size (testing up to 100 workers).

<comment><USER3> How big was the dataset that you saw the 80% improvement? Remember this test was done on a relatively small dataset, 28 MB, so it may have reached a diminishing point a lot faster than with a larger dataset.

<comment><USER2> Ah yes, I missed the part about the size of the dataset. I'm running with a 3GB corpus of text.</comment></comment></comment>


Open source support systems - <AUTHOR>

can anyone recommend any hood open source support systems? need something that will have a front-facing email and an issue trackig backend. already tried out eventum. anything else out there?<p>thanks. <comment><USER2> RT (Best Practical) is a pretty decent system. <http://bestpractical.com/rt/></comment>


Central access management and secure key distribution for OpenSSH based on X.509 - flix- https://keeto.io <comment><AUTHOR> Looks promosing!</comment>


Dear Bootcamps: Raise Your Admissions Bars or Get Out of the Way - <AUTHOR> https://medium.com/@andytiffany/dear-bootcamps-raise-your-admissions-bars-or-get-out-of-the-way-4d04d466b18a <comment><USER2> This essay doesn't consider institutions or classes that would help someone with absolutely zero programming experience try to prepare for the bootcamp admissions process that the author advocates.

While it makes sense to me that the bootcamps should be more cautious about their admissions standards, it still raises the question of what people who have written 0 computer programs are supposed to do when thinking about pursuing a bootcamp. And I guess there are many potential answers to that, but it's a problem quite closely related to this essay's argument.

I remember that at Berkeley there was CS 61A for people who had some prior programming experience (not necessarily directly related to the course content) and CS 3 for people who didn't. Bearing in mind that some people who would be interested could not currently pass the author's proposed screening question (implementing a JavaScript function to return the longest word in a string), it seems someone then ought to create the CS 3 equivalent to prepare those would-be applicants to do so. (And maybe that's ultimately an existing free online class of some kind.)

<comment><USER3> Bootcamps for bootcamps, I suppose.

<comment><USER4> They already exist.

<comment><USER3> It's bootcamps all the way down.

</comment></comment></comment></comment><comment><USER5> I remember back 20-ish years ago when there were all sorts of one year "Multimedia Specialist" programs popping up. Same problem, extremely low bar (ie. have cash? you're in!) and the graduates end up with a bunch of basic skills but no frame of reference on how to apply them to actual problem solving.

Not sure what ever became of those colleges, but they sure pumped out the students.</comment>


Ask HN: What happened to Serendipity, the fare tracker? - <AUTHOR>

A few days ago a neat looking perl script for tracking fares via Kayak made the front page.  I can't seem to find the article and the Google code hosting has 404'd:
http://code.google.com/p/serendipity/
I discovered this when I reloaded the old open tab in my browser.  I'm sorry to see it disappeared.... <comment><USER2> Good question. I was just about to tell a friend about it and this is the only post I can find.

<comment><USER2> Actually, I just remembered that I had left a comment on that thread, so here it is: <http://news.ycombinator.com/item?id=2049698>

He took it down at Kayak's request, because of the load caused by continuous requests on their servers: <http://news.ycombinator.com/item?id=2052920>

Oh well.

</comment></comment><comment><USER3> I had it running and it stopped working. Boo.

</comment><comment><AUTHOR> Edit: I mean, it's 403'd, not 404'd...</comment>