Skip to content

Instantly share code, notes, and snippets.

@challengee
Last active August 29, 2015 14:14
Show Gist options
  • Save challengee/5daa57ec853275aaf6fa to your computer and use it in GitHub Desktop.
Save challengee/5daa57ec853275aaf6fa to your computer and use it in GitHub Desktop.
class Ranking1
attr :origin_object
def initialize(origin_object)
@origin_object = origin_object
end
def top(objects, n)
ranking(objects).take(n)
end
private
def ranking(objects)
# Tier the sort.
tiers = [
->(o) { related?(o) },
:always_shown?.to_proc
]
tiered = tiered_sort(tiers) do |o|
get_score(o)
end
objects.sort(&tiered)
end
def tiered_sort(tiers, &block)
lambda { |x, y| tiered_sort_step(x, y, tiers, &block) }
end
def tiered_sort_step(x, y, tiers, &block)
if tiers.empty?
block.(x) <=> block.(y)
else
first_tier, *rest = tiers
if first_tier.(x) && !first_tier.(y)
-1
elsif !first_tier.(x) && first_tier.(y)
1
else
# Go to next tier.
tiered_sort_step(x, y, rest, &block)
end
end
end
def related?(object)
get_score(object) > 0
end
def get_score(object)
(object.keywords & origin_object.keywords).count
end
end
class Ranking2
attr :origin_object
def initialize(origin_object)
@origin_object = origin_object
end
def top(objects, n)
chosen_objects = []
remaining_count = n
object_tiers = []
object_tiers << get_always_shown_objects(get_related_objects(objects))
object_tiers << get_related_objects(objects)
object_tiers << get_always_shown_objects(objects)
object_tiers << objects
while (remaining_count > 0) && object_tiers.any?
chosen_objects += ranking(object_tiers.shift - chosen_objects).take(remaining_count)
remaining_count = n - chosen_objects.count
end
ranking(chosen_objects)
end
private
def ranking(objects)
objects.sort_by {|object| get_score(object)}.reverse
end
def get_score(object)
(object.keywords & origin_object.keywords).count
end
def get_related_objects(objects)
objects.select {|object| (origin_object.keywords & object.keywords).any? }
end
def get_always_shown_objects(objects)
objects.select {|object| object.always_shown? }
end
end
class Fixnum
def keywords
words = odd? ? ["odd"] : ["even"]
end
def always_shown?
(self % 3) == 0
end
end
objects = (1..15).to_a
origin = objects.shift
puts Ranking1.new(origin).top(objects, 10).inspect # => [15, 3, 9, 5, 11, 7, 13, 12, 6, 10]
puts Ranking2.new(origin).top(objects, 10).inspect # => [15, 9, 3, 5, 13, 11, 7, 12, 6, 14]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment