News for hackers. Stuff that matters.
Re:Why it’s hard for programmers to write a program to flatt... by fiedzia on Friday February 24, 2017 @09:52AM (#13724128)
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.
Re:Why it’s hard for programmers to write a program to flatt... by cableshaft on Friday February 24, 2017 @09:59AM (#13724184)
Doesn't stop people from asking these questions of people at all levels. I still get asked these coding questions pretty much every interview I have had, and I have almost a decade of programming experience, and have even been lead programmer on some projects (without the title).

I've been asked a barrage of these questions for senior positions, even.

Especially sucks because I don't usually program terribly fast or well in an interview environment, so I look worse than I actually am, and often get put on the defensive in these interviews, which I absolutely hate.

Re:Why it’s hard for programmers to write a program to flatt... by collyw on Friday February 24, 2017 @01:51PM (#13726466)
Have you ever needed to flatten a list in your career outside exams and interviews?
Re:Why it’s hard for programmers to write a program to flatt... by throwaway2016a on Friday February 24, 2017 @03:08PM (#13727351)
> Have you ever needed to flatten a list in your career outside exams and interviews?

Yes, multiple times in multiple languages. C, C++, Javascript... sometimes "npm install" is not the answer.

Re:Why it’s hard for programmers to write a program to flatt... by mannykannot on Friday February 24, 2017 @02:38PM (#13726965)
I am not an enthusiast of this approach to recruiting, but to be fair, the purpose of the question is not to find someone to flatten lists.

It is reasonable to ask, if a programmer cannot flatten a list, in what sense is that person a programmer? Putting aside the question of whether this is a good approach to recruiting, if this question is being failed with any regularity, it raises some interesting and important questions about the innate difficulty of programming and/or the methods by which it is taught.

Re:Why it’s hard for programmers to write a program to flatt... by brudgers on Friday February 24, 2017 @04:59PM (#13728326)
If the person flattens a list with the:

   Google
   Copy
   Paste
Algorithm, are they a programmer? Are they more or less of a programmer if instead they use racket or clojure's built-in =flatten=?
Re:Why it’s hard for programmers to write a program to flatt... by mannykannot on Friday February 24, 2017 @05:40PM (#13728608)
It is the cases of failure that are interesting and informative, and if the methods you mention are the only ways a person can solve the problem, that counts as a failure - as I mentioned, this is not actually about flattening lists.
Re:Why it’s hard for programmers to write a program to flatt... by cableshaft on Friday February 24, 2017 @02:54PM (#13727163)
I mean, I once wrote a python script called unearthed.py that took all the files in all subfolders and put them into the parent folder, then deleted the subfolders, but I'm pretty sure I just used a simple os.walk for that.

Came in handy when working with rom archives that liked to put everything in its own folder, and a couple of times when I just had a bunch of crap that I didn't want to have to manually dig up anymore.

Other than that? No, not really.

Re:Why it’s hard for programmers to write a program to flatt... by zzzcpan on Friday February 24, 2017 @02:54PM (#13727160)
"Have you ever needed to flatten a list in your career outside exams and interviews?"

I had to write this function to flatten a tree of expressions, so I could sort them by precedence, etc and fold them into a tree. I already had a bunch of higher-order primitives for constructing a parser and that was basically a lazy hack for me to get expressions parsed. I eventually implemented a proper expression parser, that was basically the same thing, but produced a flat list from the beginning.

Re:Why it’s hard for programmers to write a program to flatt... by WkndTriathlete on Monday February 27, 2017 @09:06AM (#13744229)
Flattening a list of lists is a problem that occurs quite frequently in functional programming.

OTOH, in functional programming languages and frameworks, there is no need to actually write a method that does that since it is usually a library function call.

Re:Why it’s hard for programmers to write a program to flatt... by scarface74 on Friday February 24, 2017 @03:32PM (#13727613)
Yes. Something like:

List<List<Blah>> records;

We would send a request off to multiple services, wait for all the responses and then the front end would sometimes need all of the lists and other times need it flatten.

How would I do it?

var allitems = records.SelectMany(b => b).ToList();

Re:Why it’s hard for programmers to write a program to flatt... by fiedzia on Friday February 24, 2017 @03:58PM (#13727835)
Exactly once. But I needed to know recursion, typechecking, and modern language features almost every day.
Re:Why it’s hard for programmers to write a program to flatt... by iguanayou on Friday February 24, 2017 @01:58PM (#13726531)
Yes.
Re:Why it’s hard for programmers to write a program to flatt... by brudgers on Friday February 24, 2017 @11:36AM (#13725134)
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.

Re:Why it’s hard for programmers to write a program to flatt... by fiedzia on Friday February 24, 2017 @12:00PM (#13725397)
> 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.

Re:Why it’s hard for programmers to write a program to flatt... by brudgers on Friday February 24, 2017 @12:42PM (#13725780)
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.

Re:Why it’s hard for programmers to write a program to flatt... by pcmonk on Friday February 24, 2017 @02:08PM (#13726638)
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?
Re:Why it’s hard for programmers to write a program to flatt... by cestith on Friday February 24, 2017 @05:10PM (#13728406)
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?
Re:Why it’s hard for programmers to write a program to flatt... by pcmonk on Friday February 24, 2017 @05:45PM (#13728640)
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).

Re:Why it’s hard for programmers to write a program to flatt... by cestith on Friday February 24, 2017 @09:02PM (#13729544)
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.

Re:Why it’s hard for programmers to write a program to flatt... by dllthomas on Saturday February 25, 2017 @12:35AM (#13730240)
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)
Re:Why it’s hard for programmers to write a program to flatt... by cestith on Saturday February 25, 2017 @05:11AM (#13730913)
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... (which does not handle arbitrary depths)

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

http://search.cpan.org/~rsavage/Set-Array-0.30/lib/Set/Array... (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/ (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/~chocolate/Hash-Fold-0.1.2/lib/Hash/F...

Re:Why it’s hard for programmers to write a program to flatt... by dllthomas on Saturday February 25, 2017 @10:35AM (#13731963)
> 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), 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).

Re:Why it’s hard for programmers to write a program to flatt... by cestith on Sunday February 26, 2017 @02:25PM (#13739198)
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.

Re:Why it’s hard for programmers to write a program to flatt... by dllthomas on Sunday February 26, 2017 @11:12PM (#13741813)
> 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.

Re:Why it’s hard for programmers to write a program to flatt... by brudgers on Friday February 24, 2017 @04:44PM (#13728217)
The example input in the article is:

  [1,[2,3], [4, [5,6]]]
It happens to be representable as a binary tree. Indeterminacy regarding whether or not that is accidental or intentional is due to underspecification of the interview problem. The first time I read a description of Linkedin using logs as the fundamental data structure (for what turns out to be Kafka I later learned) I had an epiphany that there is no such thing as a generic simple data structure living in the wild because data is data because it has semantics, without semantics it is just noise.

To me, it looks like the root node is |1|.

Re:Why it’s hard for programmers to write a program to flatt... by pcmonk on Friday February 24, 2017 @05:50PM (#13728673)
To me, "nested list structure" means list-of-lists, which implies a certain natural tree representation, where all elements in a list are siblings.

But maybe I've just been poisoned by Lisp, which tries to use lists as the elusive generic simple data structure.

(OT: https://en.wikipedia.org/wiki/List_of_lists_of_lists)

Re:Why it’s hard for programmers to write a program to flatt... by collyw on Friday February 24, 2017 @02:09PM (#13726652)
Sorry, are you suggesting that "flatten a list" leads to microservices?
Re:Why it’s hard for programmers to write a program to flatt... by brudgers on Friday February 24, 2017 @04:54PM (#13728289)
If the flattening a list is taken seriously, then it might. Or it might not. Taking the exercise seriously might be a better gauge of a person's long term professional potential than if that person treats the question as frivolous because there is a whole lot of things like testing and error handling and refactoring that might be discarded by a programmer who treats their craft frivolously.
Re:Why it’s hard for programmers to write a program to flatt... by LgWoodenBadger on Friday February 24, 2017 @01:53PM (#13726487)
Idiomatic Java hasn't preferred Arrays since the advent of the Collections API back in 1.2.

Idiomatic Java as of 1.8 now has flatMap on Streams, which all Collection implementations provide.

Re:Why it’s hard for programmers to write a program to flatt... by brudgers on Friday February 24, 2017 @02:04PM (#13726606)
I don't disagree. I was thinking about how Java is typically taught in computer science contexts where Fortran in any language is not uncommon because that context seemed the relevant one to nest inside the context of junior programmers using Java.

One of the difficulties of learning Java is that because it has been around so long, old idioms live on on the internet. For example, the Java examples of flatteing a list (which I recently looked at) do not include flatmapping a stream. It does not surprise me that it is there since I believe Java is an incredible and sophisticated language.

Re:Why it’s hard for programmers to write a program to flatt... by dwc on Friday February 24, 2017 @02:16PM (#13726718)
This wasn't stated as a test for Java programmers. Rather that most programmers chose to implement in Java because they were familiar with it.

And you have to ask, if they were familiar with Java then why didn't they choose one of the idiomatic approaches you suggested? I mean, the "list" part is not an internal requirement so you could easily build a tree/node structure on input...

Re:Why it’s hard for programmers to write a program to flatt... by brudgers on Friday February 24, 2017 @02:22PM (#13726770)
See my answer to the sibling to your comment.