Last active
March 4, 2021 16:41
-
-
Save andreyuhai/c6b80a70124d30d9ade62a602e6cdf58 to your computer and use it in GitHub Desktop.
Programming task solution that was asked by lunarlogic.io
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# LUNARLOGIC.IO PROGRAMMING TASK | |
# Imagine we are organizing a Lunar dinner. | |
# 30 people have confirmed that they will come. | |
# We will all be seating at five 6-person tables (A, B, C, D, E, respectively). | |
# There will be 3 courses. After each course we'll change our seats. | |
# We'd like every person to sit with as many different people as possible throughout the dinner. | |
# As a bonus you may think of future similar occasions where different number of people and tables may be available. | |
# Write a program that would assign 30 people to their seats (A1, A2, A3, etc., up to E6) during each course with that goal in mind. | |
# As a bonus you may think of future similar occasions where different number of people and tables may be available. | |
require 'set' | |
class Person | |
attr_accessor :id, :acquaintances | |
@@id = 1 | |
def initialize | |
@id = @@id | |
@@id += 1 | |
@acquaintances = Set.new | |
end | |
def meet(object) | |
case object | |
when Person | |
@acquaintances << object | |
when Table | |
object.compact.each do |person| | |
@acquaintances << person | |
end | |
end | |
end | |
# Return number of people that a person already has met at a given table. | |
# The lower the acquaintance_score is the better. | |
# Which means the person has not met most of the people at a given table yet. | |
def acquaintance_score(table) | |
score = 0 | |
table.each do |person| | |
score += 1 if @acquaintances.include? person | |
end | |
score | |
end | |
end | |
class Table < Array | |
attr_accessor :id, :history | |
@@id = 1 | |
def initialize(num_seats) | |
@id = @@id | |
@@id += 1 | |
@num_seats = num_seats | |
@index = 0 | |
@history = [] | |
super() | |
end | |
# Seat a person at the table. | |
# The person sitting at a table meets all the people that | |
# are already sitting at the table at that time. | |
def seat(new_person) | |
new_person.meet(self) | |
self.each do |person| | |
person.meet(new_person) | |
end | |
self[@index] = new_person | |
@index += 1 | |
end | |
# Return whether the table is full | |
def full? | |
self.size.eql? @num_seats | |
end | |
# Clear table for new seating plan for the next course | |
def clear | |
@history << self.clone | |
@index = 0 | |
super | |
end | |
end | |
def seating_plan(num_people, num_tables, num_seats, num_courses) | |
people = num_people.times.map { Person.new } | |
tables = num_tables.times.map { Table.new(num_seats) } | |
num_courses.times do |course| | |
# If it's the first course | |
# we can seat people however we want | |
if course.eql? 0 | |
people_dupp = people.clone | |
tables.cycle(num_seats) do |table| | |
table.seat people_dupp.shift | |
end | |
# Otherwise seat people depending on their acquaintance score | |
else | |
people.each do |person| | |
free_tables = tables.select{ |t| not t.full? } | |
scores = free_tables.map { |table| person.acquaintance_score(table) } | |
best_table = scores.index(scores.min) | |
free_tables[best_table].seat(person) | |
end | |
end | |
tables.map(&:clear) | |
end | |
# Print seating plan | |
num_courses.times do |course| | |
puts "Course ##{course + 1} sitting plan" | |
tables.each do |table| | |
puts "\tTable ##{table.id} #{table.history[course].map { |person| person.id }}" | |
end | |
end | |
# Calculate how many people each person will meet with | |
acquaintance_map = {} | |
people.each do |person| | |
num_acquaintances = person.acquaintances.size | |
acquaintance_map[num_acquaintances.to_s] ||= [] | |
acquaintance_map[num_acquaintances.to_s] << person.id | |
end | |
# Sort acquaintance_map in decreasing order | |
acquaintance_map = acquaintance_map.sort_by { |k, v| k.to_i }.reverse.to_h | |
# Print num of acquaintances to the screen | |
puts "\n\nAcquaintances" | |
acquaintance_map.each do |k, v| | |
puts "\tThese people will meet #{k} people: #{v}" | |
end | |
end | |
num_people = 30 | |
num_tables = 5 | |
num_courses = 3 | |
num_seats = 6 | |
seating_plan(num_people, num_tables, num_seats, num_courses) | |
# EXAMPLE OUTPUT of seating_plan | |
# | |
# Course #1 sitting plan | |
# Table #1 [1, 6, 11, 16, 21, 26] | |
# Table #2 [2, 7, 12, 17, 22, 27] | |
# Table #3 [3, 8, 13, 18, 23, 28] | |
# Table #4 [4, 9, 14, 19, 24, 29] | |
# Table #5 [5, 10, 15, 20, 25, 30] | |
# Course #2 sitting plan | |
# Table #1 [1, 2, 3, 4, 5, 26] | |
# Table #2 [6, 7, 8, 9, 10, 27] | |
# Table #3 [11, 12, 13, 14, 15, 28] | |
# Table #4 [16, 17, 18, 19, 20, 29] | |
# Table #5 [21, 22, 23, 24, 25, 30] | |
# Course #3 sitting plan | |
# Table #1 [1, 7, 10, 13, 19, 22] | |
# Table #2 [2, 6, 14, 15, 18, 23] | |
# Table #3 [3, 9, 11, 17, 20, 24] | |
# Table #4 [4, 8, 12, 16, 25, 26] | |
# Table #5 [5, 21, 27, 28, 29, 30] | |
# Acquaintances | |
# These people will meet 15 people: [2, 3, 6, 8, 11, 12] | |
# These people will meet 14 people: [1, 4, 5, 9, 10, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 28, 29] | |
# These people will meet 12 people: [7, 26, 30] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment