Skip to content

Instantly share code, notes, and snippets.

@Proavtor
Last active September 18, 2022 20:12
Show Gist options
  • Save Proavtor/27841633bf2ab247007eb5c620e00463 to your computer and use it in GitHub Desktop.
Save Proavtor/27841633bf2ab247007eb5c620e00463 to your computer and use it in GitHub Desktop.
The code demonstrate an elegance of Ruby with its object oriented approach to solve popular task about finding a celebrity among a group of persons.
# frozen_string_literal: true
class Array
def except(value)
self - [value]
end
end
class Person
attr_reader :name, :known_persons_names
def initialize(name, known_persons_names = [])
@name = name
@known_persons_names = {}
add_known_persons(known_persons_names) unless known_persons_names.empty?
end
def add_known_persons(known_persons_names)
known_persons_names.each do |p|
@known_persons_names[p] = true
end
end
def knows?(person_name)
@known_persons_names[person_name]
end
def doesnt_knows?(person_name)
!knows?(person_name)
end
end
class PersonGroup
attr_reader :persons
def initialize(persons = [])
@persons = []
add(persons) unless persons.empty?
end
def add(persons)
persons.each do |person|
@persons << person
end
end
def find_celebrity_candidate
l = 0
h = @persons.count - 1
while l != h
if @persons[l].knows?(@persons[h].name)
l += 1
else
h -= 1
end
end
@persons[l]
end
def find_celebrity
candidate = find_celebrity_candidate
@persons.except(candidate).each do |other_person|
return nil if candidate.knows?(other_person.name) || other_person.doesnt_knows?(candidate.name)
end
candidate
end
end
my_group = PersonGroup.new(
[
Person.new('Kamil', %w[Ivan Alex Diman Madonna]),
Person.new('Ivan', %w[Kamil Alex Diman Madonna]),
Person.new('Alex', %w[Kamil Ivan Diman Madonna]),
Person.new('Diman', %w[Kamil Ivan Alex Madonna]),
Person.new('Madonna', [])
]
)
puts my_group.find_celebrity.inspect
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment