diff --git a/README.md b/README.md index b162885..dcceb9b 100644 --- a/README.md +++ b/README.md @@ -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): @@ -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 @@ -69,7 +74,7 @@ D2, 300, T1 ``` **OUTPUT**: ``` -D1, false, "", "" +D1, false, "", "" D2, true, P1, 4500 ``` diff --git a/myoutput1.csv b/myoutput1.csv new file mode 100644 index 0000000..7116836 --- /dev/null +++ b/myoutput1.csv @@ -0,0 +1,4 @@ +D1,true,P1,2000 +D2,true,P1,3250 +D3,true,P3,15300 +D4,false diff --git a/myoutput2.csv b/myoutput2.csv new file mode 100644 index 0000000..693bd8a --- /dev/null +++ b/myoutput2.csv @@ -0,0 +1,4 @@ +D1,true,P2,3000 +D2,true,P1,3250 +D3,true,P3,15300 +D4,false diff --git a/output.rb b/output.rb new file mode 100644 index 0000000..1b0facf --- /dev/null +++ b/output.rb @@ -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'" \ No newline at end of file