Skip to content

Instantly share code, notes, and snippets.

@andreyuhai
Last active March 4, 2021 16:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andreyuhai/c6b80a70124d30d9ade62a602e6cdf58 to your computer and use it in GitHub Desktop.
Save andreyuhai/c6b80a70124d30d9ade62a602e6cdf58 to your computer and use it in GitHub Desktop.
Programming task solution that was asked by lunarlogic.io
# 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