Live data from Hacker News

The Programming Interview from Hell

pythonforengineers.com

121–130 of 147 posts

Re: The Programming Interview from Hell

#121

Earlier quoted context omitted.

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.

If have references you can pretty much always implement lists. First all you do not need mutability, you can implement linked lists form immutable cons cells, second python has mutable references so implementing linked lists is trivial (the fact that some objects are in fact immutable is immaterial).

Re: The Programming Interview from Hell

#122

Earlier quoted context omitted.

Knowing of data structures is more important IMO. The hoops I've seen people jump through in code because they don't know about sets.

And when you see that do you wish they'd never been hired due to this insurmountable hole in their knowledge of data structures or do you take 30 seconds to tell them about sets?

At what point do we just take someone out of high school and teach them to program?

Re: The Programming Interview from Hell

#123
I'm taking an introductory course to CS, and a week before the midterm they introduced linked lists -- which to me at first just seemed to be lists within lists with extra rules. What applications do they have in the real world?

Re: The Programming Interview from Hell

#126
post #22

Earlier quoted context omitted.

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.

You do need to understand the difference between an object and a refrence to it. Seems trivial bit surprising many programmers seem not to understand it.

Re: The Programming Interview from Hell

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

My guess would be that simplest way to sync two threads is exit them both. ;)

Re: The Programming Interview from Hell

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

Here's a shell script for the case where the sets are too big to fit in memory, assuming that you are on a Unix system and it has a sort program that can sort a file that won't fit in memory.

Input: one file per set, with names of the form set.X. Format of the file is one value per line. E.g., the set (1, 2, 3) might be in file set.0 with contents

  1
  2
  3
Output: each run of the script will merge overlapping set.X files, deleting files that are made redundant. It will tell you how many sets were merged.

Run the script repeatedly until it says "merged 0".

    #!/bin/bash
    for i in set.*
    do
        sed -e "s/$/ $i/"  m.$$
    last_val=-1
    last_set=
    merged=0
    while read in
    do
        set x $in
        if [ $2 -eq $last_val ]
        then
            if [ -f $3 ]
            then
                cat $last_set $3 | sort -n | uniq > t
                mv t $last_set
                rm $3
                merged=$((merged + 1))
            fi
        else
            last_val=$2
            last_set=$3
        fi
    done 
The above does more passes over the complete set of elements than is necessary, in order to minimize memory use. At the cost of a little more memory, it could write the commands done in the while loop (cat|sort|uniq;mv;rm) out to a file, and then edit that file to adjust it to take into account the affect of the rm's, and then do one pass of merging.

That would look something like this. First, you'd run this script once:

    #!/bin/bash
    for i in set.*; do sed -e "s/$/ $i/"  m
    last_val=-1
    last_set=
    line=2
    > s
    while read in
    do
        set x $in
        if [ $2 -eq $last_val ]
        then
            #echo "if [ -f $3 ]; then cat $last_set $3 | sort -n | uniq > t; mv t $last_set; rm $3; fi"
            echo "cat $last_set $3 | sort -n | uniq > t; mv t $last_set; rm $3"
            echo "$line,\$s/$3/$last_set/g" >> s
            line=$((line + 1))
        else
            last_val=$2
            last_set=$3
        fi
    done  c
That gives an output command file, c, that looks like this:

  cat set.4 set.7 | sort -n | uniq > t; mv t set.4; rm set.7
  cat set.0 set.5 | sort -n | uniq > t; mv t set.0; rm set.5
  cat set.1 set.5 | sort -n | uniq > t; mv t set.1; rm set.5
  cat set.5 set.7 | sort -n | uniq > t; mv t set.5; rm set.7
  cat set.2 set.6 | sort -n | uniq > t; mv t set.2; rm set.6
  cat set.3 set.6 | sort -n | uniq > t; mv t set.3; rm set.6
Note the problem with this. Line #1 removes set.7 after merging it with set.4. But line #4 refers to set.7. Since 7 was merged into 4, it needs to refer to set.4 at that point, not set.7.

The script that made c also outputs a file, s, with sed commands to do the above fix. For the above example, it looks like this:

  2,$s/set.7/set.4/g
  3,$s/set.5/set.0/g
  4,$s/set.5/set.1/g
  5,$s/set.7/set.5/g
  6,$s/set.6/set.2/g
  7,$s/set.6/set.3/g
There is still a problem, because note that s suffers from the same problem that c does! Line #4 of s also refers to set.7, but at that point it should be set.4.

So, before using s to fix s, we have to use s to fix s: "sed -f s s2", giving this for s2:

  2,$s/set.7/set.4/g
  3,$s/set.5/set.0/g
  4,$s/set.0/set.1/g
  5,$s/set.4/set.0/g
  6,$s/set.6/set.2/g
  7,$s/set.2/set.3/g
In this case, that is sufficient. We could now "sed -f s2 c2" and then "bash c2", and we'd be left with set.1 and set.3, with the other sets properly merged in.

However, in more complicated cases one application of s to itself is not always enough. What we really should do is keep applying it to itself until we hit a fixed point, so "sed -f s2 s3" giving:

  2,$s/set.7/set.4/g
  3,$s/set.5/set.0/g
  4,$s/set.0/set.1/g
  5,$s/set.4/set.1/g
  6,$s/set.6/set.2/g
  7,$s/set.2/set.3/g
and if you them apply s3 to itself, you will see that there is no change, so s3 is our fixed point. We could then "sed -f s3 c3". Turns out that c3 is identical to c2, so we get the same results as earlier.
Post reply on HN