Can you solve it? The Greplin programming challenge
challenge.greplin.com
challenge.greplin.com
Edit: As others seem to be posting gist/snips etc. so I guess it is OK.
Step 0 - Copied parent string to file: p1.txt
Step 1 - Used python to reverse the entire string and copy to second file: cat p1.txt | python -c "print raw_input()[::-1]" > p2.txt
Step 2 - Formatted the two files, so as to be parsed as FASTA, by adding sequence name headers.
Step 3 - Use bl2seq (blastp) locally or online to align the two "sequences". Final alignment shows only one major chunk of identity, i.e. the answer.
So, in essence, a dynamic programming algo would work.
I would be curious how many people did you lose because of phonecall requirement (before you changed it).
Also CSV for just a list of 22 numbers wasn't really necessary.
If you do web puzzle, the best is to keep everything self-contained, no downloads, no using external channels, just copy and paste.
FYI another Python cheater here (+Wolfram Alpha & Wikipedia, I'm lazy :).
int((1/math.sqrt(5))*(math.pow(((1+math.sqrt(5))/2),fibonacci)-math.pow(((1-math.sqrt(5))/2),fibonacci)))
Reference here: http://mathproofs.blogspot.com/2005/04/nth-term-of-fibonacci...
n
[0 1] = [fib(n) fib(n+1)]
[1 1] [fib(n+1) fib(n+2)]
With repeated squarings, you can efficiently generate any Fibonacci number you want. # memoized fibonacci function
fibtable = {1:1, 0:1}
def fib (n):
global fibtable
if n in fibtable.keys():
return fibtable [n]
val = fib (n-1) + fib (n-2)
fibtable [n] = val
return val last_fib = 0
fib = 1
while fib < 225000 or not is_prime(fib):
last_fib, fib = fib, last_fib + fibMaybe you should have called it the "Greplin Challenge," then, instead of the "Greplin Programming Challenge." It's not a real task, after all; the reward comes from accepting a completely artificial challenge. I'm going to do the challenge before dinner tonight, and before I leave work I could get source code for the solutions from the guy down the hall from me who did the challenge as soon as it was posted -- and you certainly don't want to hire a guy who recodes other people's work for no reason, right?
It was way more fun to do it from scratch :D
Thanks grepplin
p.s. the csv was copied in my [] python list :)
var nums = "3, 4, 9, 14, 15, 19, 28, 37, 47, 50, 54, 56, 59, 61, 70, 73, 78, 81, 92, 95, 97, 99".split(", ");
for(var i = 0;i< nums.length;i++) { nums[i] = parseInt(nums[i],10); }
Instead of just editing the numbers so that it was an array right away. Happens if you code before you think :-)
I quit because this seemed like cheating but now I'm thinking... Maybe it was the point? To see if I would try to find something off-the-shelf to solve the problem quickly. Still not sure it was, because if so the challenge certainly doesn't demonstrate that I have any CS chops. :-\
Spoiler alert: I believe this module will do the trick http://search.cpan.org/~gray/Tree-Suffix-0.21/lib/Tree/Suffi...
I wish I had discovered HN back then.
Hmm... now that I think about it, did you do something like starting at the end of the list, then subtracting numbers as you went until you either found a set that added up to your top number, or found it impossible for that number to be in the set?
It seems like it would take a lot of paper to do that, but it's more efficient than the simple brute force technique I did.
I'm just curious, because I bet there are better ways to do that one and I think the challenge is probably over by now.
I'm pretty sure that cperciva used a similar trick, but in each row you're potentially adding another element of the set, and not potentially adding 1.
This gives you a mapping telling you how many ways there are to get 0, 1, 2, 3, etc as the sum of some subset of the set. Just sum this over the set, and subtract the size of the set. (Every element in the set is the sum of itself, but you don't want to count those.) And there is your answer.
Based on bd's link, I'll just assume that you have super powers. (or I'm approaching the problem the wrong way)
edit: I was starting to think about what to write for #1, but ended finding the answer by looking at it as well.
The problem still stands that one needs to go in the 500,000s for that problem (thus 700s for the square root). That's still a long way to go…
I'm really curious about how cperciva did it. You're supposed to find the first Fibonacci prime over 227,000. The first Fibonacci number over that is obviously not prime (multiple of 3), but the one after that is not obvious even if you have the list of primes obtained with that method.
That 317811 is divisible by 3 is obvious upon adding its digits together.
Once you've verified that 514229 isn't divisible by a handful of small primes, you don't try to prove primality. Instead factor 514230 and stick it in. After dividing by 2, 3, and 5, you've got 17141. It doesn't take that long to run through 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59 and 61. At which point you have an answer you can try plugging in to discover it is correct. Which is a sequence cperciva pretty definitely has memorized. (I do.) Or alternately cperciva may have better factorization techniques memorized.
If you already have a routine around for factoring (I do), then this takes longer than coding it. But I could do it with paper and pencil pretty easily.
To be honest, in the same amount of time, one could also estimate the range where the answer should be and plug it one by one in the form until it validates. (which we'll call a less educated guess :))
while ($string =~ /((\w+)\w?(??{reverse $2}))/g) { print "$1\n"; } text.scan(/(.)(.)(.)(.)(\3)(\2)(\1)/)Oddly enough, it didn't even occur to me to try a regex and I like using them quite a bit.
If it was really meant as a programming challenge, it should feature problems which are worth writing code for.
Ruby solutions to #1 and #2: http://gist.github.com/617676 http://gist.github.com/617678
(not . null) instead of (\x -> length x > 1) is shorter, and works on infinite lists also.
Edit: well, in case you would test for x>0.
Congratulations, you just used an exponential-time algorithm for a polynomial-time problem.
I am not sure if this step of allowing the "shortcuts" was part of the game or not. All that would had to be done is to give 128 elements of the array to exclude at least the most blatant brute-forcing.
But then again... these are all pretty standard computer science problems, nothing that I hadn't in some way done before.
On a side-note: Interestingly I used recursion for each of the three problems. Well... actually for the primes-problem I got stack overflow and rewrote it to not use recursion, but still, at least in principle :=)
Edit: Excellent! Back to hacking.
It looks like the number is a landline in the Bay Area. I wonder if some poor soul at Greplin will be taking calls all day.
For what it's worth - it's just a Twilio app - we thought it would add to the fun.
It seemed eminently likely (to me) that it would be an automated system, but, even if it wasn't, talking to someone isn't that big a deal to me. I certainly wasn't concerned about long-distance charges, but I suppose that might be a problem for some.
I thought it was a nice little twist in the problem set.
A lot of people struggle with the phone. I certainly have, though I'm getting better at it. I've noticed many people become spookily compliant on the phone, endlessly listening to and being polite to even the most annoying callers instead of just hanging up.
Yet also, I'm so tired I couldn't have englished very well in my phone anyway. :-)
I'd write a bit of code to memoize the function before I'd do the Fibonacci numbers, though, and I just don't have time to continue right now, even though it's pretty easy. Are the rest of the tests like that? Do they force you to use more efficient code, rather than simpler brute force tests so that your code has a decent runtime?
Coming back, I see that I really don't need to be very efficient for any of these problems, which I honestly find a little disappointing.
I decided to try a different one on each level, so I used Python, bash (letting GNU coreutils 'factor' do the hard work), and Haskell, respectively.
I can't take credit for the solution I posted though.
I originally wrote a naive O(N^2) complexity solution (which was much shorter and was fine for the length of the input) I had this palindrome code in my 'toolbox' of code I've come across though, I'm afraid I don't know the orig author.
I just tweaked it as this is more in line with the type of example you're looking for.
I've since learned a good deal about Clojure and implemented an idiomatic (but probably less performant) version, for anyone interested in how short this can be:
I should note that I used the existing C code I had because I had no idea where they would intersect and didn't feel like writing Yet Another Arbitrarily Large Integer Handler.
Quick and dirty solutions here: http://gist.github.com/618006
None of my solutions were particularly elegant :-)
And for part 3 I used prolog. About ~6 lines or so.
Four score and seven years ago our faathers brought forth on this containent a new nation conceived inz Liberty and dedicated to the proposition that all men are created equal Now we are engaged in a greaht civil war testing whether that naption or any nartion so conceived and so dedicated can long endure We are qmet on a great battlefiemld of tzhat war
Fun, made my day. Good idea greplin dudes!
int[] nums = {...}
for i = 1 to (2^length(nums) - 1)
int[] possibility = { nums[x] where (2^x bitand i) > 0 }
test possibility and perhaps increment hit counterYou see, all the "ordinary" question involved in job-fitting still have to be asked and answered so sometimes I've done great in ability part only to have really basic "culture" or requirements issue hit later when they could have been caught immediate.
And so, even though I've enjoyed and learned something on these quizzes, the employer who begins a relationship with a quiz seems to be saying they can demand some piece of my time without any investment on their part and this isn't setting a tone reciprocity, something I'd look for in a future employer.
I didn't see the point in doing this in anything but C. I tried it without cheating, and to make it as interesting to myself as possible. Also did it after a week of writing briefs, so that was a nice way to unwind from that! Pretty Fun.
Anyway, if I'm applying for a job (which I wasn't), the last thing I'm going to do is send in a bunch of one-liners.
Also, considering the instructions explicitly say "write code to..." I would say using tools that give you the answers is in fact cheating. It's like math test where you have to show your work.
Of all of the jobs-page challenges, thesixyone's is probably the most practical and I've seen:
Is there a better algorithm? Dynamic programming of some sort? I guess we'd need a longer string to tell the difference.
The confusing bits in the Ruby are actually just the definition of an even and odd palindrome finder, which are the same except for two seed values for where the first comparison is conducted and it's length.
Seriously though, this is awesome. I'd love to know how you guys do in terms of # of applicants and the end-result (any hires?).
about 30 lines of code in the tersest style, 40ish in the readability-obsesssive style I prefer
I guess I could have used a faster primality test, but I didn't feel like writing anything that complex. I know there's a website out there that has a test that works for anything under about 10 billion, if memory serves, by using the probabalistic tests and doing a special check for the only exception. Heck, it even gives you the factors for the largest number in its range...
I would say for code that is executed one time ever, even including the sqrt(n) part is premature optimization (though I did include it)
There's more efficient ways than doing every character, or groups of them... What constitutes a palindrome? What does that mean to simplify what we're doing?
D'oh! My is_palindrome(word) just got a lot shorter, thanks :)
Try this:
for i in range(len(str)):
for j in range(i, len(str)):
if str[i:j] == str[i:j][::-1]:
#...
Choose the start and end indices. Then take a slice to see if it's a palindrome. Nice and speedy! :)def sum_eq(lst,k): total = sum(lst) if total == k or k==0:return 1 elif total < k or len(lst)==1:return 0 else: n1,nr = lst[0],lst[1:] return sum_eq(nr,k-n1) + sum_eq(nr,k)
def sum_all_eq(lst): total = 0 for k in range(1,len(lst)): total += sum_eq(lst[0:k],lst[k]) return total
How terrible is it?
Here is my Part 1 implemented in Ruby. http://gist.github.com/617566
Any improvements welcome!
(warning - contains the answers!)
I think Clojure might've made things a tad easier (given all its sequence functions), but I'm just learning it, so Ruby all the way.
That said, finding the palindromes in Ruby took me about 12 lines of code (less if I didn't structure it using methods).
I got the impression that this particular test was not a good one for finding apt programmers. The questions and the solutions were just so very "off".