Skip to content

problem solution #123

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 1 commit 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
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# Qube Cinemas Challenge 2019
# Qube Cinemas Challenge 2019 - Solution execution steps
To execute the program and generate the output files:
1- Ruby installation required.
2- On 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' will be 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 All @@ -16,7 +21,7 @@ Table 1:

First row allows 0 to 200 GB content to be sent to theatre T1 with the rate 20 paise per GB. However, if total cost comes less than minimum cost, minimum cost (2000 paise) will be charged.

*NOTE*:
*NOTE*:
- Multiple partners can deliver to same theatre


Expand Down Expand Up @@ -69,7 +74,7 @@ D2, 300, T1
```
**OUTPUT**:
```
D1, false, "", ""
D1, false, "", ""
D2, true, P1, 4500
```

Expand Down
4 changes: 4 additions & 0 deletions myoutput1.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
D1,true,P1,2000
D2,true,P1,3250
D3,true,P3,15300
D4,false
4 changes: 4 additions & 0 deletions myoutput2.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
D1,true,P2,3000
D2,true,P1,3250
D3,true,P3,15300
D4,false
73 changes: 73 additions & 0 deletions output.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
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 check_content_size_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 check_partner_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 && check_content_size_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 check_partner_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 for 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 "Output for problem statement 1 titled 'myoutput1.csv'"
#Output for 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 "Output for problem statement 2 titled 'myoutput2.csv'"