Skip to content

Added solutions for problem statements 1 and 2 #104

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
# Qube Cinemas Challenge 2019
# Qube Cinemas Challenge 2019 - Solution execution steps

To execute the program and generate the output files:
1. Have Ruby installed on your system.
2. Via the terminal, go into the project's directory and run the following command: `ruby output.rb`. This executes the ruby code written in the 'output.rb' file.
3. Once the command is executed successfully, the output files titled 'myoutput1.csv' and 'myoutput2.csv' are generated and can be found in the project's root directory.

# Qube Cinemas Challenge 2019 - Problem Statements

Qube delivers the movie content to theatres all around the world. There are multiple delivery partners to help us deliver the content.

Delivery partners specify the rate of delivery and cost in following manner (All costs are in paise):
Expand Down
88 changes: 88 additions & 0 deletions output.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
require 'csv'

#Fetches 'partners' file and removes all the unnecessary whitespaces.
PARTNERS_TABLE = CSV.parse(File.read("partners.csv"), headers: true, header_converters: lambda {|f| f.strip}, converters: lambda {|f| f ? f.strip : nil})

CAPACITIES_TABLE = CSV.parse(File.read("capacities.csv"), headers: true, header_converters: lambda {|f| f.strip}, converters: lambda {|f| f ? f.strip : nil})

#Fetches 'input' file and sorts it in descending order of content size (required for Problem 2 to ensure least overall cost).
input_table = CSV.parse(File.read("input.csv"), converters: lambda {|f| f ? f.strip : nil})
SORTED_INPUT_TABLE = input_table.sort_by {|row| row[1].to_i}.reverse

def content_size_within_range?(row, delivery_content_size)
row["Size Slab (in GB)"].split('-').first.to_i <= delivery_content_size && delivery_content_size <= row["Size Slab (in GB)"].split('-').last.to_i
end

def calculate_partner_delivery_cost(partner_row, delivery_content_size)
cost_as_per_rate = delivery_content_size*partner_row['Cost Per GB'].to_i
minimum_cost = partner_row['Minimum cost'].to_i
cost = cost_as_per_rate < minimum_cost ? minimum_cost : cost_as_per_rate
end

def partner_has_enough_spare_capacity?(partner_id, delivery_content_size)
partner_total_capacity = CAPACITIES_TABLE.find { |row| row['Partner ID'] == partner_id }['Capacity (in GB)'].to_i
delivery_content_size <= (partner_total_capacity - $partner_allocated_capacities[partner_id])
end

output_1_csv_rows = []
output_2_csv_rows = []
$partner_allocated_capacities = Hash.new(0)
SORTED_INPUT_TABLE.each do |row|
delivery_id = row[0]
delivery_content_size = row[1].to_i
delivery_theatre = row[2]
eligible_delivery_partners = PARTNERS_TABLE.select { |row| row['Theatre'] == delivery_theatre && content_size_within_range?(row, delivery_content_size) }
costs_array = []

if eligible_delivery_partners.any?
eligible_delivery_partners.each do |partner_row|
costs_array << calculate_partner_delivery_cost(partner_row, delivery_content_size)
end
min_cost = costs_array.min
min_index = costs_array.index(min_cost)
cheapest_partner_row = eligible_delivery_partners[min_index]

output_1_csv_rows << [delivery_id, true, cheapest_partner_row['Partner ID'], min_cost]

until partner_has_enough_spare_capacity?(cheapest_partner_row['Partner ID'], delivery_content_size)
#Removes the partner that cannot accomodate the delivery.
costs_array.delete_at(min_index)
eligible_delivery_partners.delete_at(min_index)

break if eligible_delivery_partners.empty?

#Finds the next cheapest delivery partner.
min_cost = costs_array.min
min_index = costs_array.index(min_cost)
cheapest_partner_row = eligible_delivery_partners[min_index]
end

if eligible_delivery_partners.empty?
output_2_csv_rows << [delivery_id, false]
else
output_2_csv_rows << [delivery_id, true, cheapest_partner_row['Partner ID'], min_cost]
$partner_allocated_capacities[cheapest_partner_row['Partner ID']] += min_cost
end
else
output_1_csv_rows << [delivery_id, false]
output_2_csv_rows << [delivery_id, false]
end
end

#Output of problem statement 1.
CSV.open("myoutput1.csv", "w") do |csv|
#Sorts the rows by delivery ID and adds them into the output CSV.
output_1_csv_rows.sort_by {|row| row[0]}.each do |row|
csv << row
end
end
puts "Created CSV file for problem statement 1 titled 'myoutput1.csv'"

#Output of problem statement 2.
CSV.open("myoutput2.csv", "w") do |csv|
#Sorts the rows by delivery ID and adds them into the output CSV.
output_2_csv_rows.sort_by {|row| row[0]}.each do |row|
csv << row
end
end
puts "Created CSV file for problem statement 2 titled 'myoutput2.csv'"