Largest submatrix that is an identity matrix - javascript

I am trying to find the largest submatrix that is an identity matrix. I have no idea how to run through all the possible submatrices. I have however, managed to come up with a function that determines if a matrix is identity:
function isIdentityMatrix(matrix) {
for (var i = 0; i < matrix.length; i++) {
for (var j = 0; j < matrix.length; j++) {
if (matrix[i][j] !== 1 && i === j || matrix[i][j] && i !== j) {
return false;
}
}
}
return true;
}
Any help in looping through all submatrices would be greatly appreciated. Keep in mind that I am a newbie to javascript.

You can try something like this. This program
-Finds a sub-matrix
-Returns true if that martrix is identity or not
Note: This works for nxn matrix only but can be easily tweaked to work with nxm matrix.
let arr=[
[1,1,1,0,0],
[0,1,1,0,0],
[0,0,1,0,0],
[1,0,1,1,0],
[0,0,0,1,1]
];
let finalValue=0;
let n=arr.length;
let N=2;//size of submatrices
function subMatrix(k,n,N,arr)
{
let max_k_x=n-N+1;// per row max value of k
let row=Math.floor(k/max_k_x);
let col=k%max_k_x;
/*
k=6,n=4,N=2
max_k=(4-2+1)*(4-2+1)=9
max_k_x=3
row=2(starting from zero)
col=0
*/
let matrix=new Array();
for(let i=row;i<row+N;i++){
for(let j=col;j<col+N;j++){
matrix.push(arr[i][j]);
}
}
return matrix;
}
function doSomethingWithMatrix(matrix,N){
for(let i=0;i<matrix.length;i++){
if((matrix[i] && (i%(N+1)!==0))||(matrix[i]!==1 && (i%(N+1))===0)){
return false;
}
}
return true;
}
for(let k=0;k<(n-N+1)*(n-N+1);k++){//k can vary from 0 to (((n-N+1)^2)-1)
let matrix=new Array();
matrix=subMatrix(k,n,N,arr);
// console.log(doSomethingWithMatrix(matrix,N));
// console.log(" ");
if(doSomethingWithMatrix(matrix,N)){
finalValue=N;
N++;
k=0;
if(N===n){
N--;
break;
}
}
if(k===(n-N+1)*(n-N+1)-1){
N++;
}
matrix=[];
}
console.log("final N: "+finalValue);
You can change the value N inside the loop to check for NxN sub-matrices.

Related

Sum of Digits works in console but not when returned

So I'm doing a codewars challenge and I have no clue why my code isn't working. I'm a beginner so please don't hate on me.
This is my code:
function digital_root(n) {
let str = n.toString()
let arr = []
let sum = 0
for (let i = 0; i < str.length; i++) {
arr.push(str.charAt(i))
}
for (let i = 0; i < str.length; i++) {
sum += Number(arr[i])
}
let sumStr = sum.toString()
if (sumStr.length > 1) {
digital_root(sum)
} else if (sumStr.length == 1) {
return sum
}
}
It works when I console.log it but not when I return the value. I'm trying to learn recursion. Thanks for the help!
You need to return digital_root(sum) too, if sumStr.length > 1 in order to access recursive returned value.
you have to write return digital_root(sum) instead of just digital_root(sum).
check below:
function digital_root(n) {
let str = n.toString()
let arr = []
let sum = 0
for (let i = 0; i < str.length; i++) {
arr.push(str.charAt(i))
}
for (let i = 0; i < str.length; i++) {
sum += Number(arr[i])
}
let sumStr = sum.toString()
if (sumStr.length > 1) {
return digital_root(sum)
} else if (sumStr.length == 1) {
return sum
}
}
console.log("Digital Root :", digital_root('123456789'));
Ok, it seems you are missing dealing with the return value of digital_root when you call it recursively. See added "return" statement below.
function digital_root(n) {
let str = n.toString()
let arr = []
let sum = 0
for (let i = 0; i < str.length; i++) {
arr.push(str.charAt(i))
}
for (let i = 0; i < str.length; i++) {
sum += Number(arr[i])
}
let sumStr = sum.toString()
if (sumStr.length > 1) {
// ***** You need to deal with the return value of digital_root when you call it.
return digital_root(sum)
} else if (sumStr.length == 1) {
return sum
}
}
However, while JavaScript's functional coding style does support recursive functions, we need to be aware that most JavaScript compilers are not currently optimized to support them safely. Recursion is best applied when you need to call the same function repeatedly with different parameters from within a loop.
Please read this,
https://www.sitepoint.com/recursion-functional-javascript/#:~:text=However%2C%20while%20JavaScript's%20functional%20coding,parameters%20from%20within%20a%20loop.

Having issues trying to solve N Rook problem . Always get n*n solution and not N factorial

I'm trying to get N ways of solves a N rook problem. The issue I am having is currently, I seem to get n*n solutions while it needs to be N! . Below is my code, I have written it in simple loops and functions, so it's quite long. Any help would be greatly appreciated
Note: Please ignore case for n = 2. I get some duplicates which I thought I would handle via JSON.stringify
var createMatrix = function (n) {
var newMatrix = new Array(n);
// build matrix
for (var i = 0; i < n; i++) {
newMatrix[i] = new Array(n);
}
for (var i = 0; i < n; i++) {
for (var j = 0; j < n; j++) {
newMatrix[i][j] = 0;
}
}
return newMatrix;
};
var newMatrix = createMatrix(n);
// based on rook position, greying out function
var collision = function (i, j) {
var col = i;
var row = j;
while (col < n) {
// set the row (i) to all 'a'
col++;
if (col < n) {
if (newMatrix[col][j] !== 1) {
newMatrix[col][j] = 'x';
}
}
}
while (row < n) {
// set columns (j) to all 'a'
row++;
if (row < n) {
if (newMatrix[i][row] !== 1) {
newMatrix[i][row] = 'x';
}
}
}
if (i > 0) {
col = i;
while (col !== 0) {
col--;
if (newMatrix[col][j] !== 1) {
newMatrix[col][j] = 'x';
}
}
}
if (j > 0) {
row = j;
while (row !== 0) {
row--;
if (newMatrix[i][row] !== 1) {
newMatrix[i][row] = 'x';
}
}
}
};
// checks position with 0 and sets it with Rook
var emptyPositionChecker = function (matrix) {
for (var i = 0; i < matrix.length; i++) {
for (var j = 0; j < matrix.length; j++) {
if (matrix[i][j] === 0) {
matrix[i][j] = 1;
collision(i, j);
return true;
}
}
}
return false;
};
// loop for every position on the board
loop1:
for (var i = 0; i < newMatrix.length; i++) {
var row = newMatrix[i];
for (var j = 0; j < newMatrix.length; j++) {
// pick a position for rook
newMatrix[i][j] = 1;
// grey out collison zones due to the above position
collision(i, j);
var hasEmpty = true;
while (hasEmpty) {
//call empty position checker
if (emptyPositionChecker(newMatrix)) {
continue;
} else {
//else we found a complete matrix, break
hasEmpty = false;
solutionCount++;
// reinitiaze new array to start all over
newMatrix = createMatrix(n);
break;
}
}
}
}
There seem to be two underlying problems.
The first is that several copies of the same position are being found.
If we consider the case of N=3 and we visualise the positions by making the first rook placed red, the second placed green and the third to be placed blue, we get these three boards:
They are identical positions but will count as 3 separate ones in the given Javascript.
For a 3x3 board there are also 2 other positions which have duplicates. The gets the count of unique positions to 9 - 2 - 1 -1 = 5. But we are expecting N! = 6 positions.
This brings us to the second problem which is that some positions are missed. In the case of N=3 this occurs once when i===j==1 - ie the mid point of the board.
This position is reached:
This position is not reached:
So now we have the number of positions that should be found as 9 - 2 - 1 - 1 +1;
There appears to be nothing wrong with the actual Javascript in as much as it is implementing the given algorithm. What is wrong is the algorithm which is both finding and counting duplicates and is missing some positions.
A common way of solving the N Rooks problem is to use a recursive method rather than an iterative one, and indeed iteration might very soon get totally out of hand if it's trying to evaluate every single position on a board of any size.
This question is probably best taken up on one of the other stackexchange sites where algorithms are discussed.

How to add a counter to this loop?

I'm a javascript newbie working on a hangman game, I had everything working properly until I realized that my method for comparing my guess to the answer was unable to handle words with multiple letters. I've written a new loop that takes care of this, but that's led to a new problem: I don't know how to work in a counter to keep track of wrong guesses.
This is the loop that I have:
function checkGuess(guess, array) {
for (let i = 0; i < array.length; i++) {
let found = false;
for (let j = 0; j < array.length; j++) {
if (array[i] === guess) {
found = true;
}
}
if (found) {
results += answer[i];
}
}
}
The game will end when the number of wrong guesses reaches a certain count or when results.length = answer.length but I can't figure out how to handle wrong guesses. Any tips would be appreciated.
try this, create a function that return the number of places that the guess exists
function checkGuess(guess, array) {
let found = 0;
for (let i = 0; i < array.length; i++) {
if (array[i] === guess) {
found++;
}
}
return found;
}
then use 2 vars to hold the correct guess and the wrong guess
var correct = 0, wrong = 0
then every time the user is guessing, do the following:
var check = checkGuess(guess, question);
if (check > 0) {
correct += check;
} else {
wrong++;
}
to determine if win or lose
if (wrong >= 3) {
// set it to lose
}
if (correct == question.length) {
// set it to win
}
Is this maybe what you're looking for?
var wrongGuesses = 0;
function checkGuess(guess, array) {
for (let i = 0; i < array.length; i++) {
let found = false;
let go_time = false;
for (let j = 0; j < array.length; j++) {
if (array[i] === guess) {
found = true;
results += answer[i];
}
if(j===(array.length-1)){
go_time = true;
}
}
if (go_time===true&&found!==true) {
wrongGuesses++;
}
}
}

Javascript - Code for finding a list of prime numbers keeps freezing

While working on problem 3 of Project Euler, I'm coming across a problem I can't seem to fix where javascript keeps freezing. Here's my code:
var is_prime = function(n) {
if (n === 1) {
return true;
}
if (n === 2) {
return true;
}
var list1 = []
for (i = 2; i < n; i++) {
list1.push(i);
}
for (i = 2; i < list1.length; i++) {
if (n % i === 0) {
return false;
}
}
return true;
}
var list_of_primes = function(n) {
var list1 = [];
var list2 = [];
for (i = 2; i < n; i++) {
list1.push(i);
}
for (i = 2; i < list1.length; i++) {
if (is_prime(i)) {
list2.push(i);
}
}
return list2;
}
confirm(list_of_primes(1000))
I know my algorithm isn't the most efficient and that I'm just brute forcing the problem, but I'm just wondering what it is I'm doing wrong. I'm pretty sure the problem lies somewhere within this block of code:
for (i = 2; i < list1.length; i++) {
if (is_prime(i)) {
list2.push(i);
}
}
I think a potential problem is that my algorithm is taking too long and that is what is causing javascript to freeze. Is there anyway to get my problem to run long enough to give me the answer?
You could try this.
var is_prime = function(n) {
if (n == 1) {
return true;
}
if (n == 2) {
return true;
}
for (var i = 2; i < n; i++) {
if (n % i == 0) {
return false;
}
}
return true;
}
var list_of_primes = function(n) {
var list2 = [];
for (var i = 2; i < n; i++) {
if (is_prime(i)) {
list2.push(i);
}
}
return list2;
}
confirm(list_of_primes(1000))
Working fine in less than seconds. https://jsfiddle.net/LL85rxv5/
A prime number (or a prime) is a natural number greater than 1 that has no positive divisors other than 1 and itself.
Strictly speaking, 1 is not a prime number so be sure to update that in your code.
Not really sure why your code is timing out, it's just a bit longhand and has an unnecessary array (list1). Anyway, here's a pretty shortened version of the code that comes up with a list of prime numbers from 2 to n.
This isn't too efficient for a large number set because it checks every number individually.
var list_of_primes = function(n) {
var list = [];
for (i = 2; i < n; i++) {
if (is_prime(i)) {
list.push(i);
}
}
return list;
}
function is_prime(i) {
for (var c = 2; c <= Math.sqrt(i); ++c)
if (i % c === 0)
return false;
return true;
}
If you want a bit more efficiency, look into the Sieve of Eratosthenes which can handle much larger sets:
// Credit: http://stackoverflow.com/a/15471749/1265817
var eratosthenes = function(n) {
// Eratosthenes algorithm to find all primes under n
var array = [], upperLimit = Math.sqrt(n), output = [];
// Make an array from 2 to (n - 1)
for (var i = 0; i < n; i++) {
array.push(true);
}
// Remove multiples of primes starting from 2, 3, 5,...
for (var i = 2; i <= upperLimit; i++) {
if (array[i]) {
for (var j = i * i; j < n; j += i) {
array[j] = false;
}
}
}
// All array[i] set to true are primes
for (var i = 2; i < n; i++) {
if(array[i]) {
output.push(i);
}
}
return output;
};
Working examples: https://jsfiddle.net/daCrosby/wfgq28no/
i is a global variable within is_prime function, which interferes with instance used in list_of_primes function. Fix by declaring i as local like this...
var is_prime = function(n) {
var i; // <~~ declare i as local variable here
if (n === 1) {

Variable amount of nested for loops

Edit: I'm sorry, but I forgot to mention that I'll need the values of the counter variables. So making one loop isn't a solution I'm afraid.
I'm not sure if this is possible at all, but I would like to do the following.
To a function, an array of numbers is passed. Each number is the upper limit of a for loop, for example, if the array is [2, 3, 5], the following code should be executed:
for(var a = 0; a < 2; a++) {
for(var b = 0; b < 3; b++) {
for(var c = 0; c < 5; c++) {
doSomething([a, b, c]);
}
}
}
So the amount of nested for loops is equal to the length of the array. Would there be any way to make this work? I was thinking of creating a piece of code which adds each for loop to a string, and then evaluates it through eval. I've read however that eval should not be one's first choice as it can have dangerous results too.
What technique might be appropriate here?
Recursion can solve this problem neatly:
function callManyTimes(maxIndices, func) {
doCallManyTimes(maxIndices, func, [], 0);
}
function doCallManyTimes(maxIndices, func, args, index) {
if (maxIndices.length == 0) {
func(args);
} else {
var rest = maxIndices.slice(1);
for (args[index] = 0; args[index] < maxIndices[0]; ++args[index]) {
doCallManyTimes(rest, func, args, index + 1);
}
}
}
Call it like this:
callManyTimes([2,3,5], doSomething);
Recursion is overkill here. You can use generators:
function* allPossibleCombinations(lengths) {
const n = lengths.length;
let indices = [];
for (let i = n; --i >= 0;) {
if (lengths[i] === 0) { return; }
if (lengths[i] !== (lengths[i] & 0x7fffffff)) { throw new Error(); }
indices[i] = 0;
}
while (true) {
yield indices;
// Increment indices.
++indices[n - 1];
for (let j = n; --j >= 0 && indices[j] === lengths[j];) {
if (j === 0) { return; }
indices[j] = 0;
++indices[j - 1];
}
}
}
for ([a, b, c] of allPossibleCombinations([3, 2, 2])) {
console.log(`${a}, ${b}, ${c}`);
}
The intuition here is that we keep a list of indices that are always less than the corresponding length.
The second loop handles carry. As when incrementing a decimal number 199, we go to (1, 9, 10), and then carry to get (1, 10, 0) and finally (2, 0, 0). If we don't have enough digits to carry into, we're done.
Set up an array of counters with the same length as the limit array. Use a single loop, and increment the last item in each iteration. When it reaches it's limit you restart it and increment the next item.
function loop(limits) {
var cnt = new Array(limits.length);
for (var i = 0; i < cnt.length; i++) cnt[i] = 0;
var pos;
do {
doSomething(cnt);
pos = cnt.length - 1;
cnt[pos]++;
while (pos >= 0 && cnt[pos] >= limits[pos]) {
cnt[pos] = 0;
pos--;
if (pos >= 0) cnt[pos]++;
}
} while (pos >= 0);
}
One solution that works without getting complicated programatically would be to take the integers and multiply them all. Since you're only nesting the ifs, and only the innermost one has functionality, this should work:
var product = 0;
for(var i = 0; i < array.length; i++){
product *= array[i];
}
for(var i = 0; i < product; i++){
doSomething();
}
Alternatively:
for(var i = 0; i < array.length; i++){
for(var j = 0; j < array[i]; j++){
doSomething();
}
}
Instead of thinking in terms of nested for loops, think about recursive function invocations. To do your iteration, you'd make the following decision (pseudo code):
if the list of counters is empty
then "doSomething()"
else
for (counter = 0 to first counter limit in the list)
recurse with the tail of the list
That might look something like this:
function forEachCounter(counters, fn) {
function impl(counters, curCount) {
if (counters.length === 0)
fn(curCount);
else {
var limit = counters[0];
curCount.push(0);
for (var i = 0; i < limit; ++i) {
curCount[curCount.length - 1] = i;
impl(counters.slice(1), curCount);
}
curCount.length--;
}
}
impl(counters, []);
}
You'd call the function with an argument that's your list of count limits, and an argument that's your function to execute for each effective count array (the "doSomething" part). The main function above does all the real work in an inner function. In that inner function, the first argument is the counter limit list, which will be "whittled down" as the function is called recursively. The second argument is used to hold the current set of counter values, so that "doSomething" can know that it's on an iteration corresponding to a particular list of actual counts.
Calling the function would look like this:
forEachCounter([4, 2, 5], function(c) { /* something */ });
This is my attempt at simplifying the non-recursive solution by Mike Samuel. I also add the ability to set a range (not just maximum) for every integer argument.
function everyPermutation(args, fn) {
var indices = args.map(a => a.min);
for (var j = args.length; j >= 0;) {
fn.apply(null, indices);
// go through indices from right to left setting them to 0
for (j = args.length; j--;) {
// until we find the last index not at max which we increment
if (indices[j] < args[j].max) {
++indices[j];
break;
}
indices[j] = args[j].min;
}
}
}
everyPermutation([
{min:4, max:6},
{min:2, max:3},
{min:0, max:1}
], function(a, b, c) {
console.log(a + ',' + b + ',' + c);
});
There's no difference between doing three loops of 2, 3, 5, and one loop of 30 (2*3*5).
function doLots (howMany, what) {
var amount = 0;
// Aggregate amount
for (var i=0; i<howMany.length;i++) {
amount *= howMany[i];
};
// Execute that many times.
while(i--) {
what();
};
}
Use:
doLots([2,3,5], doSomething);
You can use the greedy algorithm to enumerate all elements of the cartesian product 0:2 x 0:3 x 0:5. This algorithm is performed by my function greedy_backward below. I am not an expert in Javascript and maybe this function could be improved.
function greedy_backward(sizes, n) {
for (var G = [1], i = 0; i<sizes.length; i++) G[i+1] = G[i] * sizes[i];
if (n>=_.last(G)) throw new Error("n must be <" + _.last(G));
for (i = 0; i<sizes.length; i++) if (sizes[i]!=parseInt(sizes[i]) || sizes[i]<1){ throw new Error("sizes must be a vector of integers be >1"); };
for (var epsilon=[], i=0; i < sizes.length; i++) epsilon[i]=0;
while(n > 0){
var k = _.findIndex(G, function(x){ return n < x; }) - 1;
var e = (n/G[k])>>0;
epsilon[k] = e;
n = n-e*G[k];
}
return epsilon;
}
It enumerates the elements of the Cartesian product in the anti-lexicographic order (you will see the full enumeration in the doSomething example):
~ var sizes = [2, 3, 5];
~ greedy_backward(sizes,0);
0,0,0
~ greedy_backward(sizes,1);
1,0,0
~ greedy_backward(sizes,2);
0,1,0
~ greedy_backward(sizes,3);
1,1,0
~ greedy_backward(sizes,4);
0,2,0
~ greedy_backward(sizes,5);
1,2,0
This is a generalization of the binary representation (the case when sizes=[2,2,2,...]).
Example:
~ function doSomething(v){
for (var message = v[0], i = 1; i<v.length; i++) message = message + '-' + v[i].toString();
console.log(message);
}
~ doSomething(["a","b","c"])
a-b-c
~ for (var max = [1], i = 0; i<sizes.length; i++) max = max * sizes[i];
30
~ for(i=0; i<max; i++){
doSomething(greedy_backward(sizes,i));
}
0-0-0
1-0-0
0-1-0
1-1-0
0-2-0
1-2-0
0-0-1
1-0-1
0-1-1
1-1-1
0-2-1
1-2-1
0-0-2
1-0-2
0-1-2
1-1-2
0-2-2
1-2-2
0-0-3
1-0-3
0-1-3
1-1-3
0-2-3
1-2-3
0-0-4
1-0-4
0-1-4
1-1-4
0-2-4
1-2-4
If needed, the reverse operation is simple:
function greedy_forward(sizes, epsilon) {
if (sizes.length!=epsilon.length) throw new Error("sizes and epsilon must have the same length");
for (i = 0; i<sizes.length; i++) if (epsilon[i] <0 || epsilon[i] >= sizes[i]){ throw new Error("condition `0 <= epsilon[i] < sizes[i]` not fulfilled for all i"); };
for (var G = [1], i = 0; i<sizes.length-1; i++) G[i+1] = G[i] * sizes[i];
for (var n = 0, i = 0; i<sizes.length; i++) n += G[i] * epsilon[i];
return n;
}
Example :
~ epsilon = greedy_backward(sizes, 29)
1,2,4
~ greedy_forward(sizes, epsilon)
29
One could also use a generator for that:
function loop(...times) {
function* looper(times, prev = []) {
if(!times.length) {
yield prev;
return;
}
const [max, ...rest] = times;
for(let current = 0; current < max; current++) {
yield* looper(rest, [...prev, current]);
}
}
return looper(times);
}
That can then be used as:
for(const [j, k, l, m] of loop(1, 2, 3, 4)) {
//...
}

Categories