From 84a44c8f38a399361ef364e9e288c3712d82188d Mon Sep 17 00:00:00 2001 From: Junaid82774464 Date: Sun, 23 Oct 2022 02:19:30 +0530 Subject: [PATCH] Challenge2019 Solution for problem 1&2 --- .gitignore | 1 + Problem1/problem1.js | 62 +++++++++++++ Problem2/problem2.js | 90 +++++++++++++++++++ index.js | 9 ++ output1.csv | 4 - output2.csv | 4 - outputs/output1.csv | 5 ++ outputs/output2.csv | 6 ++ package-lock.json | 53 +++++++++++ package.json | 15 ++++ capacities.csv => parsedFiles/capacities.csv | 0 input.csv => parsedFiles/input.csv | 0 parsedFiles/parsedFiles.js | 92 ++++++++++++++++++++ partners.csv => parsedFiles/partners.csv | 34 ++++---- 14 files changed, 350 insertions(+), 25 deletions(-) create mode 100644 .gitignore create mode 100644 Problem1/problem1.js create mode 100644 Problem2/problem2.js create mode 100644 index.js delete mode 100644 output1.csv delete mode 100644 output2.csv create mode 100644 outputs/output1.csv create mode 100644 outputs/output2.csv create mode 100644 package-lock.json create mode 100644 package.json rename capacities.csv => parsedFiles/capacities.csv (100%) rename input.csv => parsedFiles/input.csv (100%) create mode 100644 parsedFiles/parsedFiles.js rename partners.csv => parsedFiles/partners.csv (98%) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..30bc162 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/node_modules \ No newline at end of file diff --git a/Problem1/problem1.js b/Problem1/problem1.js new file mode 100644 index 0000000..ef56ae5 --- /dev/null +++ b/Problem1/problem1.js @@ -0,0 +1,62 @@ +/* Problem statement: +Given a list of content size and Theatre ID, +Find the partner for each delivery where cost of delivery is minimum. +If delivery is not possible, mark that delivery impossible. +*/ +const parsedData = require('../parsedFiles/parsedFiles'); +const fs = require('fs'); + +async function minimumCost() { + + // Erasing the contents of output1.csv file + fs.writeFile('../challenge2019/outputs/output1.csv', '', (error) => { + if (error) throw error; + }); + + const partnersArray = await parsedData.partnersArr(); + const inputArray = await parsedData.inputArr(); + + let partnerId = ''; + let deliveryStatus = false; + let finalCSV = []; + let finalCost = ''; + + // Iterating the input theatres to find the minimun delivery cost + for (let count = 0; count < inputArray.length; count++) { + let currentTheatre = partnersArray.filter((value) => value.theatreId == inputArray[count].theatreId); + + for (let index = 0; index < currentTheatre.length; index++) { + // Checking whether the delievery size falls between the mentioned size slabs + if ((inputArray[count].deliverySize <= currentTheatre[index].maxSlab && inputArray[count].deliverySize >= currentTheatre[index].minSlab)) { + deliveryStatus = true; + let tempCost = (inputArray[count].deliverySize * currentTheatre[index].costPerGb) > (currentTheatre[index].minCost) ? (inputArray[count].deliverySize * currentTheatre[index].costPerGb) : (currentTheatre[index].minCost); + if (finalCost != "") { + if (finalCost > tempCost) { + finalCost = tempCost; + partnerId = currentTheatre[index].partnerId + } + } + else { + finalCost = tempCost; + partnerId = currentTheatre[index].partnerId + } + } + } + // Pushing each object into an array + if (count == 0) { + finalCSV.push(`Challenge 1 Solution \n${inputArray[count].deliveryId},${deliveryStatus},${partnerId},${finalCost}`) + } + else { + finalCSV.push(`\n${inputArray[count].deliveryId},${deliveryStatus},${partnerId != "" ? partnerId : '""'},${finalCost != "" ? finalCost : '""'}`) + } + + // Resetting the variables. + finalCost = ""; + partnerId = ""; + deliveryStatus = false; + } + // Appending the final array to output1.csv file + fs.appendFileSync("../challenge2019/outputs/output1.csv", finalCSV + "\n"); +} + +module.exports = { minimumCost } \ No newline at end of file diff --git a/Problem2/problem2.js b/Problem2/problem2.js new file mode 100644 index 0000000..9a45870 --- /dev/null +++ b/Problem2/problem2.js @@ -0,0 +1,90 @@ +/* +Given a list of content size and Theatre ID, +Assign deliveries to partners in such a way that all deliveries are possible (Higher Priority) +and overall cost of delivery is minimum (i.e. First make sure no delivery is impossible and +then minimise the sum of cost of all the delivery). +If delivery is not possible to a theatre, mark that delivery impossible. +Take partner capacity into consideration as well. +*/ + +const parsedData = require('../parsedFiles/parsedFiles'); +const fs = require('fs'); + +async function minimumCapacity() { + + // Erasing the contents of output2.csv file + fs.writeFile('../challenge2019/outputs/output2.csv', '', (error) => { + if (error) throw error; + }); + + const partnersArray = await parsedData.partnersArr(); + const inputArray = await parsedData.inputArr(); + const capacitiesArray = await parsedData.capacitiesArr(); + + let partnerId = ''; + let deliveryStatus = false; + let csvData = []; + let finalCSV = ''; + let finalCost = ''; + + //Sorting the input file based on the deliverySize + inputArray.sort((a, b) => parseInt(b.deliverySize) - parseInt(a.deliverySize)); + + for (let count = 0; count < inputArray.length; count++) { + let currentTheatre = partnersArray.filter((value) => value.theatreId == inputArray[count].theatreId); + for (let index = 0; index < currentTheatre.length; index++) { + partnerCapacity = capacitiesArray.filter((value) => value.partnerId == currentTheatre[index].partnerId)[0].capacityInGb; + + // Condition to check if the delivery size falls between the slabs and does not exceed the partner capacity + if (inputArray[count].deliverySize <= currentTheatre[index].maxSlab && inputArray[count].deliverySize >= currentTheatre[index].minSlab && partnerCapacity >= inputArray[count].deliverySize) { + deliveryStatus = true; + let tempCost = (inputArray[count].deliverySize * currentTheatre[index].costPerGb) > currentTheatre[index].minCost ? (inputArray[count].deliverySize * currentTheatre[index].costPerGb) : currentTheatre[index].minCost; + + if (finalCost != "") { + if (finalCost > tempCost) { + finalCost = tempCost; + partnerId = currentTheatre[index].partnerId + } + } + else { + finalCost = tempCost; + partnerId = currentTheatre[index].partnerId + } + } + } + + //Checking if delivery is possible and updating the new capacity by subtracting the currently covered capacity + if (deliveryStatus) { + let filteredCapArr = capacitiesArray.filter((value) => value.partnerId == partnerId); + for (let rows = 0; rows < filteredCapArr.length; rows++) { + filteredCapArr[rows].capacityInGb = filteredCapArr[rows].capacityInGb - inputArray[count].deliverySize; + } + } + + // + csvData.push(`${inputArray[count].deliveryId},${deliveryStatus},${partnerId != "" ? partnerId : '""'},${finalCost != "" ? finalCost : '""'}`) + //Resetting the variables + finalCost = ''; + partnerId = ''; + deliveryStatus = false; + + //Sorting the data in the array and storing it in another variable and appending to the output2.csv file. + csvData.sort(); + + //Resetting each time to get a new row + finalCSV = ''; + for (let data = 0; data < csvData.length; data++) { + if (data == 0) { + finalCSV += `Challenge 2 Solution \n${csvData[data]} \n` + } + else { + finalCSV += `${csvData[data]}\n` + } + } + } + // Appending the final array to output2.csv file + fs.appendFileSync("../challenge2019/outputs/output2.csv", finalCSV + "\n"); +} + +module.exports = { minimumCapacity } + diff --git a/index.js b/index.js new file mode 100644 index 0000000..d8d0078 --- /dev/null +++ b/index.js @@ -0,0 +1,9 @@ +const solution1 = require('./Problem1/problem1') +const solution2 = require('./Problem2/problem2') + +async function solution() { + await solution1.minimumCost() + await solution2.minimumCapacity() +}; + +solution(); \ No newline at end of file diff --git a/output1.csv b/output1.csv deleted file mode 100644 index 7c7b275..0000000 --- a/output1.csv +++ /dev/null @@ -1,4 +0,0 @@ -D1,true ,P1,2000 -D2,true ,P1,3250 -D3,true ,P3,15300 -D4,false,"","" diff --git a/output2.csv b/output2.csv deleted file mode 100644 index adcd15b..0000000 --- a/output2.csv +++ /dev/null @@ -1,4 +0,0 @@ -D1,true ,P2,3000 -D2,true ,P1,3250 -D3,true ,P3,15300 -D4,false,"","" diff --git a/outputs/output1.csv b/outputs/output1.csv new file mode 100644 index 0000000..b08f837 --- /dev/null +++ b/outputs/output1.csv @@ -0,0 +1,5 @@ +Challenge 1 Solution +D1,true,P1,2000, +D2,true,P1,3250, +D3,true,P3,15300, +D4,false,"","" diff --git a/outputs/output2.csv b/outputs/output2.csv new file mode 100644 index 0000000..cbb5e23 --- /dev/null +++ b/outputs/output2.csv @@ -0,0 +1,6 @@ +Challenge 2 Solution +D1,true,P2,3000 +D2,true,P1,3250 +D3,true,P3,15300 +D4,false,"","" + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..6a41d93 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,53 @@ +{ + "name": "qube2019", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "qube2019", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "csv-parser": "^3.0.0" + } + }, + "node_modules/csv-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/csv-parser/-/csv-parser-3.0.0.tgz", + "integrity": "sha512-s6OYSXAK3IdKqYO33y09jhypG/bSDHPuyCme/IdEHfWpLf/jKcpitVFyOC6UemgGk8v7Q5u2XE0vvwmanxhGlQ==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "csv-parser": "bin/csv-parser" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/minimist": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + } + }, + "dependencies": { + "csv-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/csv-parser/-/csv-parser-3.0.0.tgz", + "integrity": "sha512-s6OYSXAK3IdKqYO33y09jhypG/bSDHPuyCme/IdEHfWpLf/jKcpitVFyOC6UemgGk8v7Q5u2XE0vvwmanxhGlQ==", + "requires": { + "minimist": "^1.2.0" + } + }, + "minimist": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", + "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8cc2150 --- /dev/null +++ b/package.json @@ -0,0 +1,15 @@ +{ + "name": "qube2019", + "version": "1.0.0", + "description": "This project contains the solutions for 2 problems in the Qube 2019 coding challenge", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "Junaid Althaf", + "license": "ISC", + "dependencies": { + "csv-parser": "^3.0.0" + } +} diff --git a/capacities.csv b/parsedFiles/capacities.csv similarity index 100% rename from capacities.csv rename to parsedFiles/capacities.csv diff --git a/input.csv b/parsedFiles/input.csv similarity index 100% rename from input.csv rename to parsedFiles/input.csv diff --git a/parsedFiles/parsedFiles.js b/parsedFiles/parsedFiles.js new file mode 100644 index 0000000..d692f92 --- /dev/null +++ b/parsedFiles/parsedFiles.js @@ -0,0 +1,92 @@ +const csv = require('csv-parser') +const fs = require('fs') + +let partnersArray = [] +let capacitiesArray = [] +let inputArray = [] + +//Parsing the data from partners.csv +async function partnersArr() { + return new Promise((resolve, reject) => { + fs.createReadStream('./parsedFiles/partners.csv') + .pipe(csv({ headers: false, skipLines: 1 })) + .on('data', (data) => { + try { + const minRange = data['1'].split('-')[0].trim(); + const maxRange = data['1'].split('-')[1].trim(); + partnersArray.push({ + "theatreId": data[0].trim(), + "minSlab": parseInt(minRange), + "maxSlab": parseInt(maxRange), + "minCost": parseInt(data[2].trim()), + "costPerGb": parseInt(data[3].trim()), + "partnerId": data[4].trim(), + }) + } + catch (err) { + console.error("Error parsing csv file : " + err) + reject(err) + } + }) + .on('end', () => { + resolve(partnersArray) + }); + partnersArray = [] + }) +} + +//Parsing the data from capacities.csv +async function capacitiesArr() { + return new Promise((resolve, reject) => { + fs.createReadStream('./parsedFiles/capacities.csv') + .pipe(csv({ headers: false, skipLines: 1 })) + .on('data', (data) => { + try { + capacitiesArray.push({ + "partnerId": data[0].trim(), + "capacityInGb": parseInt(data[1]) + }) + } + catch (err) { + console.error("Error parsing csv file : " + err) + reject(err) + } + }) + .on('end', () => { + resolve(capacitiesArray) + }); + capacitiesArray = [] + }) +} + +//Parsing the data from input.csv +async function inputArr() { + return new Promise((resolve, reject) => { + fs.createReadStream('./parsedFiles/input.csv') + .pipe(csv({ headers: false })) + .on('data', (data) => { + try { + inputArray.push({ + "deliveryId": data[0].trim(), + "deliverySize": parseInt(data[1]), + "theatreId": data[2].trim() + }) + } + catch (err) { + console.error("Error parsing csv file : " + err) + reject(err) + } + }) + .on('end', () => { + resolve(inputArray) + }); + inputArray = [] + }) +} + + +module.exports = { + partnersArr, + capacitiesArr, + inputArr +} \ No newline at end of file diff --git a/partners.csv b/parsedFiles/partners.csv similarity index 98% rename from partners.csv rename to parsedFiles/partners.csv index 3ea8c59..3e09302 100644 --- a/partners.csv +++ b/parsedFiles/partners.csv @@ -1,17 +1,17 @@ -Theatre,Size Slab (in GB),Minimum cost,Cost Per GB,Partner ID -T1 ,0-100 ,1500 ,20 ,P1 -T1 ,100-200 ,2000 ,13 ,P1 -T1 ,200-300 ,2500 ,12 ,P1 -T1 ,300-400 ,3000 ,10 ,P1 -T2 ,0-100 ,1500 ,20 ,P1 -T2 ,100-200 ,2000 ,15 ,P1 -T2 ,200-300 ,2500 ,12 ,P1 -T2 ,300-400 ,3000 ,10 ,P1 -T1 ,0-200 ,1000 ,20 ,P2 -T1 ,200-400 ,2500 ,15 ,P2 -T2 ,0-200 ,2500 ,20 ,P2 -T2 ,200-400 ,3500 ,10 ,P2 -T1 ,100-200 ,800 ,25 ,P3 -T1 ,200-600 ,1200 ,30 ,P3 -T2 ,100-200 ,900 ,15 ,P3 -T2 ,200-400 ,1000 ,12 ,P3 +Theatre,Size Slab (in GB),Minimum cost,Cost Per GB,Partner ID +T1 ,0-100 ,1500 ,20 ,P1 +T1 ,100-200 ,2000 ,13 ,P1 +T1 ,200-300 ,2500 ,12 ,P1 +T1 ,300-400 ,3000 ,10 ,P1 +T2 ,0-100 ,1500 ,20 ,P1 +T2 ,100-200 ,2000 ,15 ,P1 +T2 ,200-300 ,2500 ,12 ,P1 +T2 ,300-400 ,3000 ,10 ,P1 +T1 ,0-200 ,1000 ,20 ,P2 +T1 ,200-400 ,2500 ,15 ,P2 +T2 ,0-200 ,2500 ,20 ,P2 +T2 ,200-400 ,3500 ,10 ,P2 +T1 ,100-200 ,800 ,25 ,P3 +T1 ,200-600 ,1200 ,30 ,P3 +T2 ,100-200 ,900 ,15 ,P3 +T2 ,200-400 ,1000 ,12 ,P3