[go: up one dir, main page]

0% found this document useful (1 vote)
5K views24 pages

Problem Solving-3

The document describes an algorithm for finding the optimal assignments of machines to tasks to minimize total cost. It takes as input a string array representing a cost matrix, where each inner string lists the costs of a machine performing each task. It returns the optimal pairings of machines to tasks that minimize total cost. The algorithm converts the string array to a number array, generates all permutations of machine-task assignments, scores each permutation based on total cost, and returns the highest scoring permutation. It provides helper functions to generate permutations, convert the string array, calculate scores, and format the output.

Uploaded by

Mojam Haque
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (1 vote)
5K views24 pages

Problem Solving-3

The document describes an algorithm for finding the optimal assignments of machines to tasks to minimize total cost. It takes as input a string array representing a cost matrix, where each inner string lists the costs of a machine performing each task. It returns the optimal pairings of machines to tasks that minimize total cost. The algorithm converts the string array to a number array, generates all permutations of machine-task assignments, scores each permutation based on total cost, and returns the highest scoring permutation. It provides helper functions to generate permutations, convert the string array, calculate scores, and format the output.

Uploaded by

Mojam Haque
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 24

Optimal Assignments

Have the function OptimalAssignments(strArr) read strArr which will represent an NxN matrix and it will be in the following format: ["(n,n,n...)","(...)",...] where
the n's represent integers. This matrix represents a machine at row i performing task at column j. The cost for this is matrix[i][j]. Your program should determine what
machine should perform what task so as to minimize the whole cost and it should return the pairings of machines to tasks in the following format: (i-j)(...)... Only one
machine can perform one task. For example: if strArr is ["(5,4,2)","(12,4,3)","(3,4,13)"] then your program should return (1-3)(2-2)(3-1) because assigning the
machines to these tasks gives the least cost. The matrix will range from 2x2 to 6x6, there will be no negative costs in the matrix, and there will always be a unique
answer.

Hard challenges are worth 15 points and you are not timed for them.

Examples
Input: ["(1,2,1)","(4,1,5)","(5,2,1)"]
Output: (1-1)(2-2)(3-3)

Input: ["(13,4,7,6)","(1,11,5,4)","(6,7,2,8)","(1,3,5,9)"]
Output: (1-2)(2-4)(3-3)(4-1)

function OptimalAssignments(strArr) {

var len = strArr.length;

//1. get list of permutations


var cmdLines = orderStrings(len);

//2. convert the array of strings to an array of number arrays.


var workArray = convertArray(strArr);

//3. attach to each item in the cmdLine permutation a score


var cmdLinesScores = cmdLines.map(function(val){
return [val, scoreMaker(val)];
})

//4. sort the scores from greatest to least, and return the most efficient
//in string form
cmdLinesScores.sort(function(a, b) {return(b[1] - a[1])});
var rawAnswer = cmdLinesScores.pop()[0];

//5. convert the answer into the required format, and return
return (ansConvert(rawAnswer));

//---------------------helper functions--------------------

function orderStrings(num){
var numArr = [];
for (var i = 0; i < num; i++){
numArr[i] = i + 1;
}
var result = allPerms(numArr).map(function(val) {
return val.join('');
});
return result;
}

function allPerms(inputArray) {
var data = inputArray;
var resultArray = [];
var len = data.length;

if (len === 0) {
return [[]];
}
else {
var first = data.shift();
var words = allPerms(data);
words.forEach(function(word) {
for (var i = 0; i < len; ++i) {
var tmp = word.slice();
tmp.splice(i, 0, first)
resultArray.push(tmp);
}
});
}
return resultArray;
}

function convertArray(arr) {
pattern = /(d+)/g;
newArr = [];

var newArr = arr.map(function(val, ind){


pattern = /(d+)/g;
holdArr = [];
do {
var test = pattern.exec(val);
if (test) {
holdArr.push(parseInt(test[1]));
}
}
while (pattern.lastIndex > 0);
return holdArr;
});
return newArr;
}
function scoreMaker(orderString) {
var orderArr = orderString.split('');
var holdArr = workArray.map(function(val, ind) {
return val[orderArr[ind] - 1];
});
var score = holdArr.reduce(function(first, last){
return first + last;
});
return score;
}
function ansConvert(str) {
var res = '';
for (var i = 0; i < len; i++) {
res = res + '(' + (i+1) + '-' + rawAnswer[i] + ')';
}
return res;
}
}

// keep this function call here


// to see how to enter arguments in JavaScript scroll down
OptimalAssignments(readline());

Transitivity Relations

Have the function TransitivityRelations(strArr) read the strArr parameter being passed which will make up an NxN matrix where the rows are separated by
each pair of parentheses (the matrix will range from 2x2 to 5x5). The matrix represents connections between nodes in a graph where each node corresponds to the
Nth element in the matrix (with 0 being the first node). If a connection exists from one node to another, it will be represented by a  1, if not it will be represented by a 0.
For example: suppose strArr were a 3x3 matrix with input ["(1,1,1)","(1,0,0)","(0,1,0)"], this means that there is a connection from node 0->0, 0->1, and 0->2. For node 1
the connections are 1->0, and for node 2 the connections are 2->1. This can be interpreted as a connection existing from node X to node Y if there is a  1 in the Xth row
and Yth column. Note: a connection from X->Y does not imply a connection from Y->X.

What your program should determine is whether or not the matrix, which represents connections among the nodes, is transitive. A  transitive relation  means that if the
connections 0->1 and 1->2 exist for example, then there must exist the connection 0->2. More generally, if there is a relation xRy and yRz, then xRz should exist within
the matrix. If a matrix is completely transitive, return the string  transitive. If it isn't, your program should return the connections needed, in the following format, in
order for the matrix to be transitive: (N1,N2)-(N3,N4)-(...). So for the example above, your program should return (1,2)-(2,0). You can ignore the reflexive property of
nodes in your answers. Return the connections needed in lexicographical order  [e.g. (0,1)-(0,4)-(1,4)-(2,3)-(4,1)].

Hard challenges are worth 15 points and you are not timed for them.

Examples
Input: ["(1,1,1)","(0,1,1)","(0,1,1)"]
Output: transitive

Input: ["(0,1,0,0)","(0,0,1,0)","(0,0,1,1)","(0,0,0,1)"]
Output: (0,2)-(0,3)-(1,3)

function TransitivityRelations(strArr) {
var len = strArr.length;
var paths = groupings(len, len);
var newArr = prepArr(strArr);
var mark1Arr = endMark(newArr, paths);
var mark2Arr = markUp(newArr, mark1Arr);
mark2Arr = mark2Arr.map(function(val) {
return val + val[0];
});
var tests = mark2Arr.filter(function(val) {
return /-d-/.test(val);
});
var searchResArray = [];
tests.forEach(function(val) {
var test3 = val.match(/d-d-d/g) || [];
console.log('3', test3);
var test4 = val.match(/d-d-d-d/g) || [];
console.log('4', test4);
var test5 = val.match(/d-d-d-d-d/g) || [];
console.log('5', test5);
searchResArray.push(...test3, ...test4, ...test5);
});

var res = [];


searchResArray.forEach(function(val) {
var first = val.slice(0,1);
var second = val.slice(-1);
if (!parseInt(newArr[first][second], 10)) {
res.push('(' + first + ',' + second + ')');
}
});
if (!res.length) return 'transitive';

res = uniq(res).sort();

return res.join('-');

//---------------------Helper Functions---------------------------

function uniq(arr) {
var obj = {};
arr.forEach(function(val) {
obj[val] = true;
});
return Object.keys(obj);
}

//take the original ["(1,1,1,1)"] form and conver to [['1','1','1','1'], etc ] form
function prepArr(arr) {
//convert the string array to an array of four arrays
newInput = arr.map(function(val) {
nums = val.match(/d/g);
return nums;
});
return newInput;
}

//puts an - at the end if the first element is connected to the last


//puts an * at the end if the first element is not connected to the last
function endMark(newArr, paths) {
var arr = paths.map(function(val) {
var begin = val[0];
var end = val[val.length - 1];
if (parseInt(newArr[begin][end], 10)) {
return val.concat('-');
} else {
return val.concat('*');
}
});
return arr;
}

//takes the 1/0 array and uses it to place hyphens between nodes with connections
function markUp(arr, pathArr) {
var len = arr.length;
var copyArr = [];
pathArr.forEach(function(val, ind) {
var str = pathArr[ind][0];
for (var i = 0; i < len - 1; i++) {
var begin = pathArr[ind][i];
console.log('begin', begin);
var end = pathArr[ind][i + 1];
console.log('end', end);
if (parseInt(arr[begin][end])) {
str += ('-' + end);
} else {
str += ('*' + end)
}
}
copyArr.push(str);
});

return copyArr;

/*this function finds all the distinct groupings of strLen objects out
an array n objects long. It works a bit messily, taking the array of
all permutations of all array elements, chopping off the last unwanted
length - n objects, then taking every (length - n)! of that list.
*/
function groupings(arrLen) {
var theArray = [];
for(var i = 0; i < arrLen; i++) {
theArray.push(i.toString());
}

var skipper = 1 //factorial(arrLen - arrLen);


var newArr = permutations(theArray);

newArr = newArr.map(function(val){
return val.slice(0, arrLen);
});
holdArr = [];
newArr.forEach(function(val, ind) {
if(ind % skipper === 0) {
holdArr.push(val);
}
});
return newArr;
// return holdArr;
}
//the permutations function delivers all the possible arrangements of n distinct
letters.
function permutations(arr) {

//create an array of form ['str', [arr]]


var newArr = ['', arr];

return (reduction(rollover(newArr)));
}
/*the rollover function takes an array in the form ['',[a, b, c, . . .]] and
returns a nested array containing all the permutations containing n items, using
each item only once. However, to use, one must use the reduction()function to
get back to a single level array.
*/
function rollover (arr) {
if (arr[1].length === 1) {
arr[0] += arr[1];
return arr[0];
}
else {
var itemArr = arr[1];
var holdArr = [];
var len = itemArr.length;
for (var i = 0; i < len; i++) {
forArr = itemArr.map(function(val) {
return val;
});
forArr.splice(i, 1);
var cons = arr[0] + arr[1][i];
holdArr.push(rollover([cons,forArr]));
};
return holdArr;
}
}
/*
The reduction function takes an array nested several levels and flattens it by
concatenation.
*/
function reduction(arr) {
if (Array.isArray(arr[0])) {
var holdArr = arr.reduce(function(first, last) {
return first.concat(last);
});
return reduction(holdArr);
}
else {
return arr;
}
}

function factorial(num) {
var intNum = parseInt(num, 10);
if (num < 0) return null;
if(num === 0) {
return 1;
}
else if(num === 1) {
return 1;
}
else {
return num * factorial(num - 1);
}
}

// keep this function call here


TransitivityRelations(readline());

Shortest Path

Have the function ShortestPath(strArr) take strArr which will be an array of strings which models a non-looping Graph. The structure of the array will be as
follows: The first element in the array will be the number of nodes N (points) in the array as a string. The next N elements will be the nodes which can be anything (A, B,
C .. Brick Street, Main Street .. etc.). Then after the Nth element, the rest of the elements in the array will be the connections between all of the nodes. They will look
like this: (A-B, B-C .. Brick Street-Main Street .. etc.). Although, there may exist no connections at all.

An example of strArr may be: ["4","A","B","C","D","A-B","B-D","B-C","C-D"]. Your program should return the shortest path from the  first Node to the last Node in the array
separated by dashes. So in the example above the output should be A-B-D. Here is another example with strArr being ["7","A","B","C","D","E","F","G","A-B","A-E","B-C","C-
D","D-F","E-D","F-G"]. The output for this array should be A-E-D-F-G. There will only ever be one shortest path for the array. If no path between the first and last node
exists, return -1. The array will at minimum have two nodes. Also, the connection A-B for example, means that A can get to B and B can get to A.

Hard challenges are worth 15 points and you are not timed for them.

Examples
Input: ["5","A","B","C","D","F","A-B","A-C","B-C","C-D","D-F"]
Output: A-C-D-F
Polynomial Expansion

Have the function PolynomialExpansion(str) take str which will be a string representing a polynomial containing only (+/-) integers, a letter, parenthesis, and the
symbol "^", and return it in expanded form. For example: if str is "(2x^2+4)(6x^3+3)", then the output should be "12x^5+24x^3+6x^2+12". Both the input and output
should contain no spaces. The input will only contain one letter, such as "x", "y", "b", etc. There will only be four parenthesis in the input and your output should contain
no parenthesis. The output should be returned with the highest exponential element first down to the lowest.

More generally, the form of str will be: ([+/-]{num}[{letter}[{^}[+/-]{num}]]...[[+/-]{num}]...)(copy) where "[]" represents optional features, "{}" represents mandatory
features, "num" represents integers and "letter" represents letters such as "x".

Hard challenges are worth 15 points and you are not timed for them.

Examples
Input: "(1x)(2x^-2+1)"
Output: x+2x^-1

Input: "(-1x^3)(3x^3+2)"
Output: -3x^6-2x^3
function PolynomialExpansion(str) {
//first, put the string into an array of polynomial values to be multiplied,
clean
//up, and standardize so values are consistent format (e.g., 5x^1, 4x^0);
var letter = str.match(/[A-Za-z]/)[0];
var modifiedStr = str.replace(/[a-zA-Z]/g, 'x')
.replace(/-/g, '+-')
.replace(/^+-/g, '^-');
var termArray = modifiedStr.split(')');
termArray.pop();

termArray = termArray.map(function(val) {
newVal = val.replace(/(/g, '')
.replace(/d+x(?!^)/g, '$&^1')
.replace(/+-?d+(?!x)/g, '$&x^0')
.replace(/^d+$/, '$&x^0')
.split('+').filter(function(val) {
return val;
});
i
newVal = newVal.map(function(val2) {
var parts = val2.match(/^(-?d+)x^(-?d+)$/);
newObj = { coefficient: parseInt(parts[1], 10),
power: parseInt(parts[2], 10)
}
return newObj;
})
return newVal;
});

//second, iterate over the array using the reduce funtion to send them down to
the
//polyMultiply method
var solution = termArray.reduce(function(val1, val2) {
return polyMultiply(val1, val2);
})

//third, sort by power

solution.sort(function(a, b) {return b.power - a.power});

//fourth, reduce common powers


newSolArray = [];
for (var i = 0; i < solution.length - 1; i++) {
if (solution[i].power !== solution[i + 1].power) {
newSolArray.push(solution[i]);
} else {
solution[i + 1].coefficient = solution[i].coefficient +
solution[i+1].coefficient;
}
}
newSolArray.push(solution.pop());

//fifth, build the new string


var newString = '';

newSolArray.forEach(function(val) {
if (val.power !== 1 && val.power !== 0) {
newString += '+' + val.coefficient.toString() + letter + '^' +
val.power.toString();
} else if (val.power === 1) {
newString += '+' + val.coefficient.toString() + letter;
} else {
newString += '+' + val.coefficient.toString();
}
});

var formattedString = newString.replace(/+-/g, '-')


.replace (/^+/,'')
.replace (/([-+])1([a-zA-Z])/, '$1$2')
.replace (/^1([a-zA-Z])/, '$1')
return(formattedString);
}

//-------------------------------Helper Functions--------------------------------

function polyMultiply(arr1, arr2) {


resultsArray = [];
arr1.forEach(function(val) {
arr2.forEach(function(val2) {
resultsArray.push(termMultiply(val, val2))

})
})
return resultsArray;
}

function termMultiply(obj1, obj2) {


returnObj = {};

returnObj.coefficient = obj1.coefficient * obj2.coefficient;


returnObj.power = obj1.power + obj2.power;

return returnObj;

// keep this function call here


PolynomialExpansion(readline());
 Calculator
Have the function Calculator(str) take the str parameter being passed and evaluate the mathematical expression within in. For example, if  str were "2+(3-1)*3"
the output should be 8. Another example: if str were "(2-0)(6/2)" the output should be 6. There can be parenthesis within the string so you must evaluate it properly
according to the rules of arithmetic. The string will contain the operators: +, -, /, *, (, and ). If you have a string like this: #/#*# or #+#(#)/#, then evaluate from left to
right. So divide then multiply, and for the second one multiply, divide, then add. The evaluations will be such that there will not be any decimal operations, so you do not
need to account for rounding and whatnot.

Hard challenges are worth 15 points and you are not timed for them.

Examples
Input: "6*(4/2)+3*1"
Output: 15

Input: "6/3-1"
Output: 1

function Calculator(str) {
const newStr = str.replace(/([\d)])\(/g, '$1*(')
.replace(/\)([(\d])/g, ')*$1')
.replace(/\*\*/g, '*');
return global.eval(newStr);
}

// keep this function call here


Calculator(readline());

Pattern Chaser

Have the function PatternChaser(str) take str which will be a string and return the longest pattern within the string. A pattern for this challenge will be defined
as: if at least 2 or more adjacent characters within the string repeat at least twice. So for example "aabecaa" contains the pattern aa, on the other hand "abbbaac"
doesn't contain any pattern. Your program should return yes/no pattern/null. So if str were "aabejiabkfabed" the output should be yes abe. If str were "123224" the
output should return no null. The string may either contain all characters (a through z only), integers, or both. But the parameter will always be a string type. The
maximum length for the string being passed in will be 20 characters. If a string for example is "aa2bbbaacbbb" the pattern is "bbb" and not "aa". You must always
return the longest pattern possible.

Hard challenges are worth 15 points and you are not timed for them.

Examples
Input: "da2kr32a2"
Output: yes a2

Input: "sskfssbbb9bbb"
Output: yes bbb
function PatternChaser(str) {
var len = str.length;
var halfLen = Math.floor(str.length / 2);
for (var i = halfLen; i > 1; i--) {
for(var j = 0; j <= len - i; j++) {
var txt = str.substr(j, i);
var regTxt = new RegExp(txt, 'g');
var testMatch = str.match(regTxt);
if (testMatch.length > 1) {
return 'yes ' + txt;
}
}
}
return 'no ' + null;
}

// keep this function call here


// to see how to enter arguments in JavaScript scroll down
PatternChaser(readline());

Weighted Path

Have the function WeightedPath(strArr) take strArr which will be an array of strings which models a non-looping weighted  Graph. The structure of the array will
be as follows: The first element in the array will be the number of nodes N (points) in the array as a string. The next N elements will be the nodes which can be anything
(A, B, C .. Brick Street, Main Street .. etc.). Then after the Nth element, the rest of the elements in the array will be the connections between all of the nodes along with
their weights (integers) separated by the pipe symbol (|). They will look like this: (A|B|3, B|C|12 .. Brick Street|Main Street|14 .. etc.). Although, there may exist no
connections at all.

An example of strArr may be: ["4","A","B","C","D","A|B|1","B|D|9","B|C|3","C|D|4"]. Your program should return the shortest path when the weights are added up from
node to node from the first Node to the last Node in the array separated by dashes. So in the example above the output should be  A-B-C-D. Here is another example
with strArr being ["7","A","B","C","D","E","F","G","A|B|1","A|E|9","B|C|2","C|D|1","D|F|2","E|D|6","F|G|2"]. The output for this array should be  A-B-C-D-F-G. There will only ever
be one shortest path for the array. If no path between the first and last node exists, return  -1. The array will at minimum have two nodes. Also, the connection A-B for
example, means that A can get to B and B can get to A. A path may not go through any Node more than once.

Hard challenges are worth 15 points and you are not timed for them.

Examples
Input: ["4","A","B","C","D", "A|B|2", "C|B|11", "C|D|3", "B|D|2"]
Output: A-B-D

Input: ["4","x","y","z","w","x|y|2","y|z|14", "z|y|31"]
Output: -1
function WeightedPath(strArr) {
//get the number of nodes
var nodeNum = parseInt(strArr.shift());

//create Apple copy of the array argument, rather than a pointer to it.
var newArr = strArr.map(function(val){return val});

//replace the proper names with letters, for simplicity


var modArr = convertArray(newArr);
//=>[ 'A', 'B', 'C', 'D', 'A|B|1', 'B|D|9', 'B|C|3', 'C|D|4' ]
//get an array, containing an object of nodes, and for each an array of
connections
var connections = createObject(modArr);
//=>{ A: [], B: [], C: [], D: [] } [ 'A|B|1', 'B|D|9', 'B|C|3', 'C|D|4' ]

//then convert to an object of key-values (node: [connections])


var connectionsObject = makeObject(connections);
//=>{ A: [ [ 'B', 1 ] ], B: [ [ 'A', 1 ], [ 'D', 9 ], [ 'C', 3 ] ], C: [ [ 'B', 3
], [ 'D', 4 ] ], D: [ [ 'B', 9 ], [ 'C', 4 ] ] }

var fullPaths = paths(connectionsObject);


//=>[ [ 'ABD', 10 ], [ 'ABCD', 8 ] ]

if (fullPaths.length) {
var winner = fullPaths.sort(function(b,a) {return(a[1] - b[1])}).pop();
return finalForm(winner[0]);
}
else {
return -1;
}

//--------------------------------helper functions----------------------------

/*convertArray takes i) the nodeNum and an array of the nodes and paths, and
converts each node name to
a letter character, just to make it easier to work with.
*/
function convertArray (arr) {
arr = arr.map(function(val) {
return val.toLowerCase()
});
for (var i = 0; i < nodeNum; i++) {
var patt = new RegExp(arr[i]);
arr = arr.map(function(val) {
return val.replace(patt, String.fromCharCode(i + 65));
});
}
return arr;
}

function createObject(arr) {
var obj = {};
arr.forEach(function(val) {
if(/^w$/.test(val)) {
obj[val] = [];
}
});
arr.splice(0, nodeNum);
return[obj, arr];
}

function makeObject(arr) {
var connObj = arr[0];
var connArr = arr[1];
for (var char in connObj) {
var patt = new RegExp('(?:(?:' + char + '\|(\w))|(?:(\w)\|' + char +
'))\|(\d+)');
connArr.forEach(function(val) {
var result = patt.exec(val);
if (result) {
resFiltered = result.filter(function(val) {
return val;
})
connObj[char].push([resFiltered[1], parseInt(resFiltered[2])]);
}
});
}
return connObj
}

function paths(obj) {
var endNode = String.fromCharCode(65 + nodeNum - 1);
var resultArr = [['A', 0]];

while(resultArr.some(function(val){return val[0].slice(-1) !== endNode})) {


var hotChar = resultArr[0][0].slice(-1);
if (hotChar === endNode) {
resultArr.push(resultArr.shift());
}
else {
holdArr = obj[hotChar];
holdArr = holdArr.filter(function(val) {
return resultArr[0][0].indexOf(val[0]) === -1;
});
var oldStr = resultArr.splice(0, 1)[0];

holdArr.forEach(function(val) {
resultArr.push([oldStr[0] + val[0], oldStr[1] + val[1]]);
});
}
}
return resultArr;
}

function finalForm(str) {
var truePathArr = str.split('');
truePathArr = truePathArr.map(function(val){
return strArr[val.charCodeAt(0) - 65];
})
return truePathArr.join('-');
}
}

// keep this function call here


// to see how to enter arguments in JavaScript scroll down
WeightedPath(readline());
RREF Matrix

Have the function RREFMatrix(strArr) take strArr which will be an array of integers represented as strings. Within the array there will also be "<>" elements
which represent break points. The array will make up a matrix where the (number of break points + 1) represents the number of rows. Here is an example of
how strArr may look: ["5","7","8","<>","1","1","2"]. There is one "<>", so 1 + 1 = 2. Therefore there will be two rows in the array and the contents will be row1=[5 7 8] and
row2=[1 1 2]. Your program should take the given array of elements, create the proper matrix, and then through the process of Gaussian elimination create a reduced
row echelon form matrix (RREF matrix). For the array above, the resulting RREF matrix would be: row1=[1 0 3], row2=[0 1 -1]. Your program should return that resulting
RREF matrix in string form combining all the integers, like so: "10301-1". The matrix can have any number of rows and columns (max=6x6 matrix and min=1x1 matrix).
The matrix will not necessarily be a square matrix. If the matrix is an nx1 matrix it will not contain the "<>" element. The integers in the array will be such that the
resulting RREF matrix will not contain any fractional numbers.

Hard challenges are worth 15 points and you are not timed for them.

Examples
Input: ["2","4","8","<>","6","12","14"]
Output: 120001

Input: ["2","2","4","<>","1","1","8","<>","7","6","5"]
Output: 100010001
function RREFMatrix(strArr) {
//convert number strings into numbers
strArr = strArr.map(function(val) {
var temp = parseInt(val, 10);
return (temp || temp - 1) ? parseInt(val, 10) : val;
});
//transform input string into an array of rows
var matrixArr = transform(strArr);
var len = matrixArr.length;
//sort by leading zeroes, if any;
orderRows(matrixArr);

for(var i = 0; i < len - 1; i++) {


rows = leadEliminate(matrixArr[i], matrixArr[i + 1]);
if (rows === null) {
orderRows(matrixArr);
console.log(matrixArr);
//i--;
continue;
}
matrixArr[i] = rows[0];
matrixArr[i + 1] = rows[1];
var checker = matrixArr.slice();
orderRows(matrixArr);

if (!checker.every(function(val, ind) {
return val === matrixArr[ind];
})) {
i--;
continue;
}
}
var redPivotArr = [];
matrixArr.forEach(function(row) {
var divisor = row.find(function(val) {
val = parseFloat(val.toFixed(4), 10);
return val !== 0;
});
if (divisor) {
row = row.map(function(item){
return item / divisor
});
redPivotArr.push(row);
} else {
redPivotArr.push(row);
}
});

for (var i = len - 1; i > 0; i--) {


var index = redPivotArr[i].findIndex(function(val) {
posVal = parseFloat(val.toFixed(4), 10);
return posVal !== 0;
});
for (var j = 0; j < i; j++) {
if (redPivotArr[j][index]) {
var ratio = redPivotArr[j][index];
redPivotArr[j] = redPivotArr[j].map(function(item, index) {
return item -= redPivotArr[i][index] * ratio;
})
}
}
}
var resStr = '';
redPivotArr.forEach(function(row) {
row.forEach(function(item) {
resStr += item.toFixed();
});
});

return resStr;
}

//-------------------------helpers----------------------
function transform(arr) {
var resArr = [];
var tempArr = [];
arr.forEach(function(val, ind) {
if (typeof val === 'number') {
tempArr.push(val);
} else {
resArr.push(tempArr.slice());
tempArr = [];
}
});
resArr.push(tempArr);
return resArr
}
function qualified(arr) {

}
function leadEliminate(arr1, arr2) {
var pivotPos = arr1.findIndex(function(val) {
val = parseFloat(val.toFixed(4), 10);
return val !== 0;
});
if (pivotPos === -1) {
return null;
}
if (arr2[pivotPos]) {
var ratio = arr1[pivotPos] / arr2[pivotPos];
var adjustedRow1 = arr1.map(function(val) {
return val / ratio;
});
var adjustedRow2 = arr2.map(function(val, ind) {
return val - adjustedRow1[ind];
})
return [adjustedRow1, adjustedRow2];
} else {
return [arr1, arr2];
}
}

function orderRows(arr) {
arr.sort(function(a, b) {
var aIndex = a.findIndex(function(val) {return val !== 0});
var bIndex = b.findIndex(function(val) {return val !== 0});
aIndex = aIndex === -1 ? Infinity : aIndex;
bIndex = bIndex === -1 ? Infinity : bIndex;
return aIndex - bIndex;
})
return;
// }
}

// keep this function call here


RREFMatrix(readline());

Intersecting Lines

Have the function IntersectingLines(strArr) take strArr which will be an array of 4 coordinates in the form: (x,y). Your program should take these points
where the first 2 form a line and the last 2 form a line, and determine whether the lines intersect, and if they do, at what point. For example: if  strArr is
["(3,0)","(1,4)","(0,-3)","(2,3)"], then the line created by (3,0) and (1,4) and the line created by (0,-3) (2,3) intersect at (9/5,12/5). Your output should therefore be the 2
points in fraction form in the following format: (9/5,12/5). If there is no denominator for the resulting points, then the output should just be the integers like so:  (12,3).
If any of the resulting points is negative, add the negative sign to the numerator like so:  (-491/63,-491/67). If there is no intersection, your output should return the
string "no intersection". The input points and the resulting points can be positive or negative integers.

Hard challenges are worth 15 points and you are not timed for them.
Examples
Input: ["(9,-2)","(-2,9)","(3,4)","(10,11)"]
Output: (3,4)

Input: ["(1,2)","(3,4)","(-5,-6)","(-7,-8)"]
Output: no intersection
function IntersectingLines(strArr) {

var ObjArr = formatCheck(strArr);

var numStringArr = ObjArr.map(function(val) {


return stringIt(val);
});
line1Points = [numStringArr[0], numStringArr[1]];
line2Points = [numStringArr[2], numStringArr[3]];

line1 = fullFormat(line1Points);
line2 = fullFormat(line2Points);

if (line1[4] === line2[4]) {


return line1[5] === line2[5] ? "These are the same line!" : "no
intersection"
}

var bigRes = interPoint([line1, line2]);

bigRes = bigRes.map(function(val){
return mrClean(val);
})

return '(' + bigRes[0] + ',' + bigRes[1] + ')';


}

//---------------------------helper functions--------------------------

/*
formatCheck(): first, it checks to make certain there are four points. Then it
checks
the format of each point. Returns true if all are okay, false if not.
*/

function formatCheck (arr) {

if (arr.length != 4) {
return false;
}
arr = arr.map(function(val) {
val = val.trim();
while (/ss/.test(val)) {
val = val.replace(/ss/, ' ');
}
val = val.replace(/(s+/, '(');
val = val.replace(/,s+/, ',');
return val;
});

patt = /^((?:(-?d*)(?=s|,))?s?(?:(-?d*)/(?=-?d))?(-?d*),(?:(-?d*)(?=s|)))?s?
(?:(-?d*)/(?=-?d))?(-?d*))$/

newArr = arr.map(function(val) {
return patt.exec(val);
});

if (newArr.some(function(val) {return val === null;})) {


return false;
}

else {
newObj = newArr.map(function(val) {
return initFracPrep(val);
});
}
return (newObj);
}

/*
initFracPrep takes a pair of numbers in fraction form (can have an integer part,
separated by a space), and puts out each number as an object, numsObj, with
numer(ator) and denom(inator) parts.
*/
function initFracPrep(arr) {
var num1 = {
I: arr[1] || 0,
N: arr[2] || 0,
D: arr[3] || 1
}
var num2 = {
I: arr[4] || 0,
N: arr[5] || 0,
D: arr[6] || 1
}
var numsObj = {};
numsObj.numer1 = num1.I * num1.D + parseInt(num1.N);
numsObj.denom1 = parseInt(num1.D);
numsObj.numer2 = num2.I * num2.D + parseInt(num2.N);
numsObj.denom2 = parseInt(num2.D);
return numsObj;
}
/*
stringIt takes an object composed of two points in fraction form, and returns them
as an array of strings. ex: { numer1: -12, denom1: 15, numer2: 2, denom2: -6 } =>
['-12/15', '2/-6']
*/

function stringIt(obj) {
var strArr = ([obj.numer1.toString() +'/'+ obj.denom1.toString(),
obj.numer2.toString() + '/' + obj.denom2.toString()]);
var strArr = strArr.map(function(val){
return fractionReduce(val);
})
return strArr;
}

/*
this is the function that takes a fraction string, reduces it, and returns
a fraction string, with all the common factors removed. It requires
dependency function primeFactors() and objectify();
*/
function fractionReduce (str) {
patt = /-?d+/g;
var numArr = str.match(patt);
var numerator = parseInt(numArr[0]);
var denominator = parseInt(numArr[1]);

var numFactorObj = objectify(primeFactors(numerator));


var denFactorObj = objectify(primeFactors(denominator));

for (var x in numFactorObj) {


if (x in denFactorObj) {
var min = Math.min(denFactorObj[x], numFactorObj[x]);
denFactorObj[x] -= min;
numFactorObj[x] -= min;
}
}

var num1 = 1;
for (var x in numFactorObj) {
num1 *= Math.pow(parseInt(x), numFactorObj[x]);
}
var num2 = 1;
for (var x in denFactorObj) {
num2 *= Math.pow(parseInt(x), denFactorObj[x]);
}

return (num1.toString() + '/' + num2.toString());


}

/*
primeFactors takes a number, and return an array, being the list of prime factors
of
the number (closeFunc is just a closure wrapper to get holdArr out of the global
space).
*/

function primeFactors (num) {


var flag = 1;
if (num < 0) {
num = Math.abs(num);
var flag = -1;
}
var factors = closeFunc();
var res = factors(num);
res.push(flag);
return res;
}
function closeFunc() {
var holdArr = [];
function nextFactor(num) {
var pivot = Math.floor(Math.sqrt(num))
var flag = false;
for (var i = 2; i <= pivot; i++) {
if (num % i === 0) {
flag = true;
newNum = num / i;
holdArr.push(i);
return nextFactor(newNum);
}
}
if (!flag) {
holdArr.push(num);
return holdArr
}
}
return nextFactor
}

/*
objectify takes an array of prime factors such as that produced by primeFactors
array produced by closeFunc and converts it into
a counting object.
*/

function objectify(arr) {
var countObj = {};

arr.forEach(function(val) {
vals = val.toString();
if (!countObj[vals]) {
countObj[vals] = 1;
}
else {
countObj[vals] += 1;
}
});
return countObj;
}
/*
fullFormat(): takes the line array and returns an array of the line,
following the format [[x/1, y/1, x/1, y/1, m, b]];
*/
function fullFormat(arr) {
var line1 = arr[0].concat(arr[1]);
var slope1 = slope(line1);
line1.push(slope1);
if (slope1 === undefined) {
yinter1 = undefined;
line1.push(yinter1);
}
else {
var yinter1 = yInter(line1);
line1.push(yinter1);
}
return line1;
}

/*
slope(): takes the line array (i.e., two points) and returns the slope.
Returns undefined for a vertical line.
*/

function slope(arr) {

var rise = stringFracSub(stringFracPrep([arr[1], arr[3]]));


var run = stringFracSub(stringFracPrep([arr[0], arr[2]]));
var stringSlope = stringFracDiv(stringFracPrep([rise, run]));
return parseInt(run) === 0? undefined : fractionReduce(stringSlope);
}

/*
stringFracPrep takes a pair of numbers in fraction form, and puts out each number
as an object, numsObj, with
numer(ator) and denom(inator) parts.
*/
function stringFracPrep(arr) {
var patt = /(-?d+)/(-?d+)/;
var arrSet = patt.exec(arr[0]);
var arr2Set = patt.exec(arr[1]);
var num1 = {
N: arrSet[1],
D: arrSet[2]
}
var num2 = {
N: arr2Set[1],
D: arr2Set[2]
}
var numsObj = {};
numsObj.numer1 = num1.N;
numsObj.denom1 = num1.D;
numsObj.numer2 = num2.N;
numsObj.denom2 = num2.D;
return numsObj;
}

/*
Four functions for taking two numbers in the object form output by
stringFracPrep.
They are stringFracMult; stringFracDiv; stringFracAdd; and stringFracSub.
stringFracMult takes two objects (obtained from stringFracPrep), and multiplies
them,
returning an answer in the same object form.*/

function stringFracMult(nums) {
var resnumer = nums.numer1 * nums.numer2;
var resdenom = nums.denom1 * nums.denom2;
var res = resnumer.toString() + '/' + resdenom.toString();
return fractionReduce(res);
}

function stringFracDiv(nums) {
var resnumer = nums.numer1 * nums.denom2;
var resdenom = nums.numer2 * nums.denom1;
var res = resnumer.toString() + '/' + resdenom.toString();
return fractionReduce(res);
}

function stringFracAdd(nums) {
var resnumer = (nums.numer1 * nums.denom2) + (nums.numer2 * nums.denom1);
var resdenom = nums.denom1 * nums.denom2;
var res = resnumer.toString() + '/' + resdenom.toString();
return fractionReduce(res);

function stringFracSub(nums) {
var resnumer= (nums.numer1 * nums.denom2) - (nums.numer2 * nums.denom1);
var resdenom = nums.denom1 * nums.denom2;
var res = resnumer.toString() + '/' + resdenom.toString();
return fractionReduce(res);

/*
yInter(): takes the line arr (i.e., two points and slope) and returns the
y-intercept.
*/
function yInter(arr) {
var mult = stringFracMult(stringFracPrep([arr[0], arr[4]]));
var res = stringFracSub(stringFracPrep([arr[1], mult]));
return fractionReduce(res);
}

/*
interPoint() takes the fullFormat arrays and returns an array consisting
of the x-value and y-value of the intersecting point. However, this is
all done in decimals, not with fractions.
*/
function interPoint (arr) {
if (arr[0][4] === undefined || arr[1][4] === undefined) {
if (arr[0][4] === undefined) {
var step1 = stringFracMult(stringFracPrep([arr[0][0], arr[1][4]]));
var xVal = arr[0][0];
var yVal = stringFracAdd(stringFracPrep([step1, arr[1][5]]));
return [xVal, yVal];
}

else {
var step1 = stringFracMult(stringFracPrep([arr[1][0], arr[0][4]]));
var xVal= arr[1][0];
var yVal = stringFracAdd(stringFracPrep([step1, arr[0][5]]));
return [xVal, yVal];
}
}
else {
var mTotal = stringFracSub(stringFracPrep([arr[0][4], arr[1][4]]));
var bTotal = stringFracSub(stringFracPrep([arr[1][5], arr[0][5]]));
var xVal = stringFracDiv(stringFracPrep([bTotal, mTotal]));
var yVal1 = stringFracMult(stringFracPrep([xVal, arr[0][4]]));
var yVal = stringFracAdd(stringFracPrep([yVal1, arr[0][5]]));
return[xVal, yVal];
}
}

function mrClean(str) {
var patt = /(-?d+)/(-?d+)/;
var matchArr = patt.exec(str);
var numer = parseInt(matchArr[1]);
var denom = parseInt(matchArr[2]);
var intPart = Math.floor(numer / denom);
var newNumer = numer % denom;
return newNumer === 0 ? intPart.toString() : numer.toString() + '/' +
Math.abs(denom).toString();
}
//return newNumer === 0 ? intPart.toString() : intPart.toString() + ' ' +
newNumer.toString() + '/' + Math.abs(denom).toString()

// keep this function call here


// to see how to enter arguments in JavaScript scroll down
IntersectingLines(readline());

You might also like