Skip to content

Instantly share code, notes, and snippets.

@kjell
Created December 14, 2008 17:12
Show Gist options
  • Save kjell/35726 to your computer and use it in GitHub Desktop.
Save kjell/35726 to your computer and use it in GitHub Desktop.
# http://www.facebook.com/jobs_puzzles/index.php?puzzle_id=7
cap = ARGV[0] ? File.read(ARGV[0]).to_i : 189
=begin
A simplistic, brute force solution:
=end
mod = lambda {|n, m| n%m==0}
word = lambda {|k| return 'Hop' if mod[k,15]; return 'Hophop' if mod[k,5]; return 'Hoppity' if mod[k,3]}
(1..cap).map {|i| s = word[i]; s ? puts(s) : next}
puts "—————————————————"
=begin
Lets try and be a bit more clever.
Exploiting that the modulo operation will repeat itself consistently, we can find the
quotient and remainder of the inputted number (here read into the variable cap). Along
with the sequence of output for the first 15 integers, we solve the problem by printing:
The base output repeated `quotient` times and then
The first n words in the base output, where n is the sum of the
quotients of the remainder when divided by 3 and 5.
=end
words = %w[Hoppity Hophop Hoppity Hoppity Hophop Hoppity Hop]
quo, rem = cap.divmod(15)
puts words*quo + words.first(rem/3+rem/5)
puts "—————————————————"
=begin
But this leads us to a somewhat simpler solution.
With any given input n, the number of printed terms will be n/3+n/5-n/15.
(Please don't make me give a formal proof, but I'm using
the principle of inclusion/exclusion or something like that.)
So we can go from the 1st term up to the (n/3+n/5-n/15)st and consecutively print
the words as they appear in the base case (1..15) output.
=end
(1..(cap/3+cap/5-cap/15)).map {|n| puts words[(n-1)%7]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment