Live data from Hacker News

The Programming Interview from Hell

pythonforengineers.com

111–120 of 147 posts

Re: The Programming Interview from Hell

#111
post #9

OK - but here's a genuine problem that came up the other day in my work (reconciling two datasets - we have various many-to-one mappings of ids that we then want to reconcile against each other). I think it's quite a neat computer science/algorithm challenge, so here goes: Write a function which takes as input a list of sets, many of which are not disjoint, but will output a list of sets where all of the non-disjoint…

Great exercise! Here's my solution in Java, seems be about O(n):

    class Ptr {
        public Ptr next;
    }
    
     List> mergeIntersecting(List> lists) {
        Map lookup = new HashMap();
        Map> output = new HashMap();
        for (List list : lists) {
            Ptr ptr = new Ptr();
            if (list.isEmpty()) {
                output.put(ptr, new ArrayList());
            }
            for (T value : list) {
                Ptr prev = lookup.get(value);
                lookup.put(value, ptr);
                while (prev != null && prev != ptr) {
                    Ptr tmp = prev.next;
                    prev.next = ptr;
                    prev = tmp;
                }
            }
        }
        for (Map.Entry entry : lookup.entrySet()) {
            Ptr ptr = entry.getValue();
            while (ptr.next != null) {
                ptr = ptr.next;
            }
            if (!output.containsKey(ptr)) {
                output.put(ptr, new ArrayList());
            }
            output.get(ptr).add(entry.getKey());
        }
        return new ArrayList(output.values());
    }
If I give it random lists of integers, it takes around 1 microsecond per element of input. Really curious if there's any way to speed it up a lot.

Re: The Programming Interview from Hell

#112
post #40

i recently had an interview which was plain smart what i need to get my work done questions i loved it ( i took that offer ). but then there were few where they did ask me a question on solution implementation and when i solve it they said there is a better way to do this and then I would be like ok then let's discuss but then they were quiet on the other side and waiting to hear me answer the best possible way to so…

You should definitely contact a reddit user called CommaHorror. This is his writing style, which I believe would complement yours quite nicely: https://www.reddit.com/user/commahorror

i completely agree. I wrote that comment from my mobile and it is not my friend.

P.S : this is replied from desktop. hope this works for you

Re: The Programming Interview from Hell

#113
post #61

Earlier quoted context omitted.

It certainly did! I just didn't understand at the time not to hire employees who simply say "I'd Google it" over and over :D.

Ah, so was the candidate poor because they had a bad attitude and refused to try to solve the problem at first, or was it because their technical skills were lacking?

More the former. Technically they seemed quite proficient, but they proved difficult to work with and didn't end up gelling with the team very well.

Re: The Programming Interview from Hell

#114
I had the exact same interview when applying to be a barista at philz coffee.

The technical questions were my fault because I told the interviewer I was a researcher in number theory and enjoyed working with embedded systems.. to which they said, 'oh, can you talk a bit about that?'

Each comma denotes an email response explaining I was chosen to move on and to please fulfill the next request: Send resume with cover letter, fill out online application, make 90s video about why you should serve coffee, first video chat interview, come in to meet recruiter, come in to meet store manager.

I only made it through the first of the three interviews. Ultimately I think we both dodged a bullet there.

Honestly!

Ask an employee next time you get a coffee there what kind of interview process they had to go through.

PS- should have made a 90s '90s video about why I should serve coffee.. definitely would have gotten their minimum wage offering then.

Re: The Programming Interview from Hell

#115
post #9

OK - but here's a genuine problem that came up the other day in my work (reconciling two datasets - we have various many-to-one mappings of ids that we then want to reconcile against each other). I think it's quite a neat computer science/algorithm challenge, so here goes: Write a function which takes as input a list of sets, many of which are not disjoint, but will output a list of sets where all of the non-disjoint…

Robert Sedgewick's course [1] and associated book/booksite [2] have a good overview of Union-Find problem and various algorithms to solve it. [1] https://www.coursera.org/learn/algorithms-part1 [2] http://algs4.cs.princeton.edu/15uf/

Indeed, Union-Find is the first subject the course covers, because it uses it as an example of an elementary algorithm.

Re: The Programming Interview from Hell

#116
post #22

Earlier quoted context omitted.

linked list is not complex for christ sake.

I think the original intent of the linked list question was to see if the candidate knew pointers. Implementing in a non pointer language would be trivial and definitely not complex.

Are linked lists even a difficult example of pointer use? You don't exactly have to do fancy pointer arithmetic with them. You just have to be a little bit careful when inserting or deleting nodes.

Re: The Programming Interview from Hell

#117

Earlier quoted context omitted.

Python. Ruby. Javascript. Lisp. Haskel (IIRC). They all use them internally, but don't tend to make them available to the programmer (usually because they aren't needed).

They have references (at least python, lisp that I know of, likely the others as well), which is enough to implement linked lists.

The ability to implement linked lists != pointers and references

Behind the scene, yes, every Python variable is a reference to an object. It's not addressable, however, and in the case of immutable objects (like strings), you can't modify the underlying object and keep all references pointed at that updated object.

Re: The Programming Interview from Hell

#118
post #9

OK - but here's a genuine problem that came up the other day in my work (reconciling two datasets - we have various many-to-one mappings of ids that we then want to reconcile against each other). I think it's quite a neat computer science/algorithm challenge, so here goes: Write a function which takes as input a list of sets, many of which are not disjoint, but will output a list of sets where all of the non-disjoint…

Assuming everything fits in memory, the following seems reasonable. The basic idea is to essentially think of each set as a region in some abstract space. If two sets have an element in common, then they are directly connected in that space. Build a map of these direct connections, and then you can use a flood fill to find connected regions. Each connected region corresponds to an output set.

Here's a test implementation, assuming input is one line per input set with space separated values on each line. Output format is the same.

    #!/usr/bin/env perl
    use strict;

    my @in;
    my @out;
    my %sawin;
    my %merge;
    my %merged;

    while ()
    {
        chomp;
        s/^\s+//;
        push @in, [split /\s+/];
    }

    for (my $i = 0; $i $b} keys %out];
    }

    foreach (@out) {
        print join(" ", @$_), "\n";
    }

    sub expand_merge
    {
        my($base) = @_;
        my @todo = keys %{$merge{$base}};
        my %done = ($base => 1);
        while (@todo) {
            my $next = shift @todo;
            next if $done{$next};
            $done{$next} = 1;
            push @todo, keys %{$merge{$next}};
        }
        return keys %done;
    }
Everything should be linear in the total number of elements except for expand_merge (the flood fill-like part). I think worst case for expand_merge could be quadratic in the number of elements, which would occur if each set overlapped a large fraction of the other sets.

If things won't fit in memory, I don't know how to do it in the general case. I suppose the first thing I'd do is look at the source of the sets to see if there are any limits on that. For instance, if we are dealing with a very large number of sets without a lot of members per set, and the range of numbers in each set is not very large, then it should be possible to partition the input into two sets of sets, A and B, such that it is easy to show that no sets in A contain any overlap with any sets in B, so we've reduced the problem to two smaller problems that can be solved independently and their outputs concatenated. Repeat.

For the general case, I'd start out by sorting the elements of each set, and by sorting the set of sets. While Googling for a refresher on external sorting and then coding up that part, I'd be hoping for some flash of brilliance to deal with what to do after that.

If no flash of brilliance arrived, I'd probably try something like this (assuming that I can at least fit several of the sets into memory at once). Let's assume that each set is stored in a file, named after its order in the sorted list of sets.

Read the first set into memory. Then scan through the remaining sets, in sorted order, checking each for overlap with the first. For any that overlap, merge them in memory with the first. When all the sets have been processed, or a point is reached where the first element of the current set is larger than the last element of the merged first set and so you can infer that no more merging will happen on this pass, write the merged first set out, replacing the original first set, and delete the files for all the sets that merged with the first.

Repeat this until no new sets merge with the first. At this point, you can mark the first as done, and it becomes the first output set.

Repeat with the first remaining set as your new first set, and so on.

As long as the biggest single output set and the biggest single input set will both fit in memory at the same time, I think that the above approach works.

I have a feeling that there is some clever way to do this that is much more efficient and is much more obvious (in the mathematical sense...in other words, after you look at it for a very long time and think about it really really hard it was clearly obvious).

My guess is that the clever solution will heavily involve sorting...not that I'm really going out on a limb with that guess, because almost everything is sorting when you look at it right. For example, here's a shell script that given a list of x, y coordinates on STDIN (one coordinate pair per line, x and y separated by space) outputs the result of doing one generation of Conway's Life with the input being the initial cell configuration:

    > alive.$$
    while read cells
    do
        echo $cells >> alive.$$
        set x $cells
        x=$2
        y=$3
        echo $x $((y-1))
        echo $x $((y+1))
        echo $((x-1)) $((y-1))
        echo $((x-1)) $y
        echo $((x-1)) $((y+1))
        echo $((x+1)) $((y-1))
        echo $((x+1)) $y
        echo $((x+1)) $((y+1))
    done | sort | uniq -c > neighbors.$$
    grep '^ *3'  has2.$$
    sort alive.$$ -o alive.$$
    comm -12 has2.$$ alive.$$
    rm has2.$$ neighbors.$$ alive.$$

Note that the key operation is "sort". This runs in O(n log n) where n is the number of live cells (assuming your Unix uses an n log n sort...).

Re: The Programming Interview from Hell

#119
post #37

The hiring manager of a small software company gave me a quick brief before handing me off to his technical heavy. "He's hard to get along with, but he's really smart. Oh, and he has two PhDs. He'll tell you that." I was ushered in. The Guy with Two PhDs (he showed me his business card first, and there were indeed two PhDs on it) asked me: "What is the simplest way to synchronize two threads?" I rattled off some sync…

"Raise interrupt priority" is not a way to synchronize threads, let alone the simplest. I know what I'm talking about; I worked on multithreading for Linux before the rewrite to NPTL and I invented the PTHREAD_MUTEX_ADAPTIVE_NP type that you still find in Glibc. On a project several years ago, I did use interrupt priority in conjunction with threads as a complete hack. The issue was this: the interrupt service routines for an IDE-based compact flash were running CPU intensive polling loops, taking away app CPU time. I created a priority scheme where certain interrupt priority levels overlapped with thread priority levels. That is, it was possible to suppress the interrupts for this IDE device while certain important threads were dispatched. As in, automatically: when the kernel dispatched a thread in that priority range, interrupts below that value would be blocked (not by disabling CPU interrupts, but the actual interrupt controller's detailed mask of interrupts, where we pick the specific ones that get masked). When the thread lost the CPU, they would be unblocked. This solution/workaround worked well enough to deal with the issue it was intended for.

Re: The Programming Interview from Hell

#120
post #48

Earlier quoted context omitted.

Of course, you acted like a smartass for no apparent reason. You will never be asked to reimplement a library function on your job, these questions are used to see how you approach a problem, your reasoning, etc...

That is how I approach a problem. I've seen too many inexperienced developers reinvent the wheel - badly - instead of taking a step back and wondering, "is this a solved problem"? Is this part of our core competency or can we outsource it, find an existing package, etc.

Even good, senior developers do this. A lot of people just jump into a problem because it's fun, but don't stop to say "hey, someone must have solved this already. Let me see if there's an open-source solution out there."
Post reply on HN