Live data from Hacker News

Why it’s hard for programmers to write a program to flatten a list?

shekhargulati.com

121–128 of 128 posts

Re: Why it’s hard for programmers to write a program to flatten a list?

#121

Earlier quoted context omitted.

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 equat…

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…

> 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 flatten a list?

#122
post #56

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.…

Or maybe they want a candidate who asks: what are the functional and non-functional requirements for this task?

If the interviewee guesses whether or not security, speed, memory use, portability, maintainability or anything else are important, maybe they will do the same in production code.

Re: Why it’s hard for programmers to write a program to flatten a list?

#123

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 l…

Gee, that's almost exactly what I got:

  def flatten(nested_list):
      output_list = []
      for elem in nested_list:
          if type(elem) == list:
              output_list.extend(flatten(elem))
          else:
              output_list.append(elem)
      return output_list
I think that's easier to read than the following, and appears to run slightly faster as well?

  import collections

  def flatten(nested_list):
      if isinstance(nested_list, collections.Iterable):
          return [a for i in nested_list for a in flatten(i)]
      else:
          return [nested_list]

Re: Why it’s hard for programmers to write a program to flatten a list?

#124
post #91

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 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…

Type-safe, bonus unit test.

   import org.junit.Test;
   
   import java.util.ArrayList;
   import java.util.Arrays;
   import java.util.List;
   import java.util.stream.Collectors;
   import java.util.stream.Stream;
   
   import static junit.framework.TestCase.assertEquals;
   
   public class FlattenList {
   
       @Test
       public void test() {
           // [1, [2, 3], [4, [5, 6]], [7, [8, [9, 10]]]]
           final FlattenableList list = new FlattenableList();
           list.add(new SingleFlattenable(1));
   
           list.add(new ListOfSingles(Arrays.asList(2, 3)));
   
           list.add(new Flattenable(){{
               add(new SingleFlattenable(4));
               add(new ListOfSingles(Arrays.asList(5, 6)));
           }});
   
           list.add(new Flattenable(){{
               add(new SingleFlattenable(7));
               add(new Flattenable(){{
                   add(new SingleFlattenable(8));
                   add(new ListOfSingles(Arrays.asList(9, 10)));
               }});
           }});
   
           assertEquals(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), list.flatten());
       }
   
       public static class FlattenableList {
   
           final List> list = new ArrayList();
   
           void add(final Flattenable item) {
               list.add(item);
           }
   
           List flatten() {
               return list.stream().flatMap(Flattenable::flatten).collect(Collectors.toList());
           }
   
       }
   
       private static class Flattenable {
   
           final List> contents = new ArrayList();
   
           Stream flatten() {
               return contents.stream().flatMap(Flattenable::flatten);
           }
   
           void add(final Flattenable content) {
               contents.add(content);
           }
   
       }
   
       private static class ListOfSingles extends Flattenable {
   
           final List list;
   
           ListOfSingles(final List list) {
               this.list = list;
           }
   
           @Override
           Stream flatten() {
               return list.stream();
           }
   
       }
   
       private static class SingleFlattenable extends Flattenable {
   
           final T item;
   
           SingleFlattenable(final T item) {
               this.item = item;
           }
   
           @Override
           Stream flatten() {
               return Stream.of(item);
           }
   
       }
   
   }

Re: Why it’s hard for programmers to write a program to flatten a list?

#125
post #35

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…

Non recursive algo with python:

  def flatten(array):
      queue = [array]
      result = []
      while len(queue) > 0:
          item = queue.pop(0)
          if isinstance(item, list):
              for sub_item in item:
                  queue.append(sub_item)
          else:
              result.append(item)
      return result

  a = [1,[2,3], [4, [5,6]]]
  print 'input:', a, '\noutput:', flatten(a)

Re: Why it’s hard for programmers to write a program to flatten a list?

#126

Earlier quoted context omitted.

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…

> 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…

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 flatten a list?

#127

Earlier quoted context omitted.

> 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…

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 pointin…

> 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 flatten a list?

#128
post #34

Earlier quoted context omitted.

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…

Have you ever needed to flatten a list in your career outside exams and interviews?

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.

Post reply on HN