I have array object in which I compare each string in a array and if one letter is not matching, increment the value. If three characters match with the string then increment the count value, else 0
var obj = ["race", "sack", "grass", "brass", "beat", "pack", "cake"]
fucntion getValue(obj) {
var count = 0
for (var i = 0; i <= obj.length; i++) {
for (var j = 1; j <= obj.length; j++) {
if (obj[i].split("") == obj[j].split("") {
count++;
}
}
}
}
Expected Output
race 1
sack 2 // (pack, cake matches 3 letters with sack so 2)
grass 1
brass 1
beat 0
pack 2
cake 3
function getSameCount(str1, str2) {
let count = 0;
const obj = str2.split("");
for(str of str1){
let idx = obj.findIndex(s => s === str);
if(idx >= 0){
count++;
obj.splice(idx, 1);
}
}
return count;
}
var obj = ["race", "sack", "grass", "brass", "beat", "pack", "cake"]
const res = {}
for (var i = 0; i < obj.length; i++) {
res[obj[i]] = 0
for (var j = 0; j < obj.length; j++) {
if (i != j) {
matchCount = getSameCount(obj[i], obj[j])
if (matchCount === 3) {
res[obj[i]]++
} else {
if (obj[i].length - matchCount == 1) {
res[obj[i]]++
}
}
}
}
}
console.log(res)
You can create an object for output,
parse through each element in the array, replace characters from comparing elements.
check if at least 3 chars got removed if so +1 to respective element.
const arr = ["race", "sack", "grass", "brass", "beat", "pack", "cake"];
const out = Object.fromEntries(arr.map(e => [e, 0]));
for(i in arr) {
for(j in arr) {
if(i == j) continue;
if(arr[i].length !== arr[j].length) continue;
const res = [...arr[i]].reduce((acc, e)=> acc.replace(e, ''), arr[j]);
if(res.length <= arr[j].length - 3) {
out[arr[i]] = out[arr[i]] + 1
}
}
}
console.log(out);
Related
This program is working for a single word but I want to pass an array of strings(more than one word).
let output = getAnagrams("CATCH"); //it is working for this
let output = getAnagrams(["catch", "Priest", "Monkey", "Bruise"]);
I want it to work for this.
function swap(chars, i, j) {
var tmp = chars[i];
chars[i] = chars[j];
chars[j] = tmp;
}
function getAnagrams(input) {
let newInput = input.toString().toLowerCase();
console.log(newInput);
var counter = [],
anagrams = [],
chars = newInput.split(''),
length = chars.length,
i;
for (i = 0; i < length; i++) {
counter[i] = 0;
}
anagrams.push(newInput);
i = 0;
while (i < length) {
if (counter[i] < i) {
swap(chars, i % 2 === 1 ? Counter[i] : 0, i);
counter[i]++;
i = 0;
anagrams.push(chars.join(''));
} else {
counter[i] = 0;
i++;
}
}
// return anagrams;
}
As you already have a method which takes 1 string, why not just call it for each string in your array and then flatten the returning the array using flatMap
function getAnagrams(input) {
let newInput = input.toString().toLowerCase();
var counter = [],
anagrams = [],
chars = newInput.split(''),
length = chars.length,
i;
for (i = 0; i < length; i++) {
counter[i] = 0;
}
anagrams.push(newInput);
i = 0;
while (i < length) {
if (counter[i] < i) {
swap(chars, i % 2 === 1 ? counter[i] : 0, i);
counter[i]++;
i = 0;
anagrams.push(chars.join(''));
} else {
counter[i] = 0;
i++;
}
}
return anagrams;
}
function swap(arr,i,j){
const tmp = arr[i];
arr[i] = arr[j]
arr[j] = tmp
}
const result = ["catch", "Priest", "Monkey", "Bruise"].flatMap(i => getAnagrams(i))
console.log(result)
While taking some online JS tests, I am stuck on why my function for testing if the elements within two arrays are equal is not working. I am using the function to make sure that the new array does not have duplicate values.
The following is my function for testing if the elements of the arrays are equal or not:
const isEqualArr = (a, b) => {
for (let i = 0; i < a.length; i++) {
if (a[i] != b[i]) {
return false;
}
}
return true;
};
I call to the function within a for loop, then I test for undefined, because the first time around, the outputArr is empty
for (let x = 0; x < numsLength; x++) {
if (typeof outputArr[x] != 'undefined') {
if (isEqualArr(tempArr, [outputArr[x]])) {
However, the result shows that there are duplicates:
0: Array [ -1, 0, 1 ]
1: Array [ -1, 2, -1 ]
2: Array []
3: Array [ -1, -1, 2 ]
4: Array []
5: Array [ 0, 1, -1 ]
6: Array [ 0, -1, 1 ]
7: Array [ 1, 0, -1 ]
8: Array [ -1, 0, 1 ]
The other issue is that not only do I have two null arrays (duplicates), but when I test for null before the push, it is not working either:
if(tempArr != null ) {
outputArr.push(tempArr);
}
I have tried tempArr[0] != null, tempArr[0] != '' as well as
if (typeof tempArr[0] != 'undefined')
But it still inserts null arrays into the outputArr.
The following is the premise of the test:
Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.
Notice that the solution set must not contain duplicate triplets. Given nums = [-1,0,1,2,-1,-4]
The following code is my solution, but the duplicate entries, as well as the null entries, makes this an incorrect solution. If you guys can see why my isEqualArr function is at fault, then I would appreciate it.
const threeSum = (nums) => {
let numsLength = nums.length;
let tempArr = [];
let outputArr = [];
if (numsLength > 3) {
for (let i = 0; i < numsLength; i++) {
for (let j = 1; j < numsLength; j++) {
for (let k = 2; k < numsLength; k++) {
if (
i != j &&
i != k &&
j != k &&
nums[i] + nums[j] + nums[k] == 0
) {
tempArr[0] = nums[i];
tempArr[1] = nums[j];
tempArr[2] = nums[k];
for (let x = 0; x < numsLength; x++) {
if (typeof outputArr[x] != 'undefined') {
if (!isEqualArr(tempArr, [outputArr[x]])) {
if (typeof tempArr[0] != 'undefined') {
outputArr.push(tempArr);
console.log(
'temp: ' + tempArr + ' outputArr: ' + outputArr[x]
);
console.log(
'compare: ' + isEqualArr(tempArr, outputArr[x])
);
console.log(outputArr);
tempArr = [];
}
}
}
}
if (i == 0) {
outputArr.push(tempArr);
tempArr = [];
} else {
// do nothing
}
}
}
}
}
}
return outputArr;
};
const isEqualArr = (a, b) => {
for (let i = 0; i < a.length; i++) {
if (a[i] != b[i]) {
return false;
}
}
return true;
};
EDIT: I was able to eliminate the null entries by moving the code that checks if it is the first time to run above the for loop:
if (i == 0) {
outputArr.push(tempArr);
tempArr = [];
} else {
// do nothing
}
for (let x = 0; x < numsLength; x++) {
if (typeof outputArr[x] != 'undefined') {
if (!isEqualArr(tempArr, [outputArr[x]])) {
if (typeof tempArr[0] != 'undefined') {
outputArr.push(tempArr);
console.log(
'temp: ' + tempArr + ' outputArr: ' + outputArr[x]
);
console.log(
'compare: ' + isEqualArr(tempArr, outputArr[x])
);
console.log(outputArr);
tempArr = [];
}
}
}
}
BTW, another thing that is not working if the following logic:
i != j &&
i != k &&
j != k &&
You can see by the outputArr that this logic is being completely ignored.
REFACTORED: even though the online test marked my solution as wrong, you can see with the results, that it is correct. Especially when you factor in the conditionals for making sure that nums[i] != nums[j] and so forth:
const threeSum = (nums) => {
let numsLength = nums.length;
let tempArr = [];
let outputArr = [];
for (let i = 0; i < numsLength; i++) {
for (let j = 0; j < numsLength; j++) {
for (let k = 0; k < numsLength; k++) {
if (
nums[i] != nums[j] &&
nums[i] != nums[k] &&
nums[j] != nums[k] &&
nums[i] + nums[j] + nums[k] == 0
) {
if (typeof outputArr[0] != 'undefined') {
/**********
* if it reaches this conditional
* then outputArr has at least one element
***********/
if (typeof outputArr[k] != 'undefined') {
tempArr[0] = nums[i];
tempArr[1] = nums[j];
tempArr[2] = nums[k];
if (isEqualArr(tempArr, outputArr)) {
// do nothing because there is already an element within the array
} else {
outputArr.push(tempArr);
// empty tempArr after insert
tempArr = [];
}
}
} else {
// push triplet elements into temp array for the first iteration only
tempArr[0] = nums[i];
tempArr[1] = nums[j];
tempArr[2] = nums[k];
// insert tempArr for the first iteration only
outputArr.push(tempArr);
// empty tempArr after insert
tempArr = [];
}
}
}
}
}
return outputArr;
};
const isEqualArr = (a, b) => {
for (elem in b) {
for (let i = 0; i < a.length; i++) {
if (a[i] != elem[i]) {
// do nothing
} else {
return true;
}
}
}
return false;
};
RESULTS:
(3) [Array(3), Array(3), Array(3)]
0: (3) [-1, 0, 1]
1: (3) [1, 0, -1]
2: (3) [-1, 1, 0]
length: 3
Your inner for loop is confusing, if you replace it by a forEach you can see what's going on, you should pass as argument outputArr[x] not [outputArr[x]] and there's more stuff.
const threeSum = (nums) => {
let numsLength = nums.length;
let tempArr = [];
let outputArr = [];
if(numsLength < 3) return;
for (let i = 0; i < numsLength; i++) {
for (let j = 1; j < numsLength; j++) {
for (let k = 2; k < numsLength; k++) {
if (
i != j &&
i != k &&
j != k &&
nums[i] + nums[j] + nums[k] == 0
) {
tempArr.push(nums[i], nums[j], nums[k]); // push three at the same time, it's cleaner and avoid problems
outputArr.forEach((arr, index) => {
if(!isEqualArr(arr, outputArr[index])) outputArr.push(tempArr); // outputs correctly
});
if (i == 0) {
outputArr.push(tempArr);
tempArr = [];
}
}
}
}
}
return outputArr;
};
const isEqualArr = (a, b) => {
for (let i = 0; i < a.length; i++) {
if (a[i] != b[i]) {
return false;
}
}
return true;
};
console.log(threeSum([-1,0,1,2,-1,-4]));
I am currently doing a codewars problem, and I think I almost got it however, I ran across a problem when sorting index values with the same letter. link to problem is here. https://www.codewars.com/kata/5782dd86202c0e43410001f6
function doMath(s) {
let strSplit = s.split(' ');
let clonedArr = strSplit.slice();
for (let i = 0; i < strSplit.length; i++) {
for (let j = 0; j < strSplit[i].length; j++) {
let current = strSplit[i][j];
if (isNaN(current)) {
let letter = current;
strSplit[i] = strSplit[i].replace(letter, '');
strSplit[i] = letter + strSplit[i];
}
}
}
let sortedArr = strSplit.sort();
console.log(sortedArr);
// ["b900", "y369", "z123", "z246", "z89"]
let noLetterArr = sortedArr.map(x => {
return x.slice(1);
});
let numberArr = noLetterArr.map(y => {
return +y;
})
let firstEl = numberArr[0];
for (let i = 1; i < numberArr.length; i++) {
if (numberArr.indexOf(numberArr[i]) % 4 == 1) {
firstEl += numberArr[i];
}
if (numberArr.indexOf(numberArr[i]) % 4 == 2) {
firstEl -= numberArr[i];
}
if (numberArr.indexOf(numberArr[i]) % 4 == 3) {
firstEl *= numberArr[i];
}
}
return firstEl;
}
console.log(doMath('24z6 1z23 y369 89z 900b'));
I would like to sort the sortedArr the ones with the same letter by how they first appeared in string. So since "z246" appeared first in the original string. I would like to have that before "1z23". I had a hard time creating a function for that.
var al = [];
function doMath(s) {
var ar = s.split(" ");
for (let i = 0; i < ar.length; i++) {
for (let char of ar[i]) {
let temp = char.match(/[a-z]/i);
if (temp) {
al[i] = char;
ar[i] = ar[i].replace(char, '');
ar[i] = char + ar[i];
}
}
}
al = al.sort();
//New Sort Logic to pass above test case and others too
var n = [];
for (let i = 0; i < al.length; i++) {
for (let j = 0; j < ar.length; j++) {
if (ar[j].startsWith(al[i]) && !n.includes(ar[j])) {
n.push(ar[j]);
}
}
}
var result = parseInt(n[0].substr(1)),
count = 1;
for (let i = 1; i < n.length; i++) {
if (count == 1) {
result = result + parseInt(n[i].substr(1));
count++;
} else if (count == 2) {
result = result - parseInt(n[i].substr(1));
count++;
} else if (count == 3) {
result = result * parseInt(n[i].substr(1));
count++;
} else if (count == 4) {
result = result / parseInt(n[i].substr(1));
count = 1;
}
}
return Math.round(result);
}
I am trying to insert dash(-) between two even numbers.
Problem is dashes don't locate between two even numbers but at the end of the number.
here is the code
function insertHyphen(str) {
var strArr = str.split('');
var numArr = strArr.map(Number);
for(var i = 0; i < numArr.length; i++) {
if(numArr[i-1]%2===0 && numArr[i]%2===0) {
numArr.push('-');
}
}
return numArr.join('');
}
insertHyphen('112233445566'); // 112233445566---
Using regex:
var p = '112233445566';
var regex = /([02468])([02468])/g
console.log(p.replace(regex, '$1-$2'));
Try it online: https://tio.run/##y0osSyxOLsosKNHNy09J/f#/LLFIoUDBVkHd0NDIyNjYxMTU1MxM3ZqLCyRRlJqeWgGU1NeINjAyMbOI1YQz9NO5uJLz84rzc1L1cvLTNQr0ilILchKTUzXAmnQU1FUMdVWM1DU1rbn#/wcA
Use splice() instead of push(). See here Splice MDN
function insertHyphen(str) {
var strArr = str.split('');
var numArr = strArr.map(Number);
for(var i = 0; i < numArr.length; i++) {
if(numArr[i-1]%2===0 && numArr[i]%2===0) {
numArr.splice(i, 0, '-');
}
}
return numArr.join('');
}
console.log(insertHyphen('112233445566')); // 112-2334-4556-6
replace
numArr.push('-');
with
numArr.splice(i, 0, '-');
function insertHyphen(str) {
var strArr = str.split('');
var numArr = strArr.map(Number);
for(var i = 0; i < numArr.length; i++) {
if(numArr[i-1]%2===0 && numArr[i]%2===0) {
numArr.splice(i, 0, '-');
}
}
return numArr.join('');
}
console.log(insertHyphen('025468 '));
Convert number to String
keep first element of array into separate array i.e. newArray
Run the loop on string length
Check current and the next element is divisible by 2 or not. If yes, push '-' else push the next item.
Finally join the array elements of newArray with ''.
let a = 224578;
let str = a.toString()
var newArray=[arr[0]]
if(arr?.length > 0){
for (let i = 0; i < arr.length; i++) {
if(arr[i] % 2 === 0 && arr[i+1] % 2 === 0){
newArray.push('-', arr[i+1])
} else{
newArray.push(arr[i+1])
}
}
}
console.log('newArray', newArray.join(''))
Push inserts element at the end of the array. You can use splice to enter element at particular position.
arr.splice(index, 0, item);
Here index is the position where you want to insert item element. And 0 represents without deleting 0 elements.
function insertHyphen(str) {
var strArr = str.split('');
var numArr = strArr.map(Number);
for(var i = 0; i < numArr.length; i++) {
if(numArr[i-1]%2===0 && numArr[i]%2===0) {
numArr.splice(i, 0, '-');
}
}
return numArr.join('');
}
console.log(insertHyphen('112233445566'));
A simple way:
function insertHyphen(str) {
var strArr = str.split('');
var numArr = strArr.map(Number);
var result ="";
for(var i = 0; i < numArr.length; i++) {
if((numArr[i+1]!==undefined)&&(numArr[i]%2===0 && numArr[i+1]%2===0)) {
//numArr.push('-');
result = result + numArr[i] + "-";
}else{
result = result + numArr[i];
}
}
return result;
}
console.log(insertHyphen('112233445566'));
You could map the new string by check the value and predecessor.
function insertHyphen(string) {
return Array
.from(string, (v, i) => !i || v % 2 || string[i - 1] % 2 ? v : '-' + v)
.join('');
}
console.log(insertHyphen('22112233445566'));
Using push() method and single loop
let input = '346845';
let result = [input[0]],
len = input.length;
for (var i = 1; i < len; i++) {
if (input[i - 1] % 2 === 0 && input[i] % 2 === 0) {
result.push('-', input[i]);
} else {
result.push(input[i]);
}
}
console.log(result.join(''));
Below I am trying to give string arrays to a function that adds unique words to a words array, and if the word is already in the array to increase the count of the corresponding element in the count array:
var words = [];
var counts = [];
calculate([a, b]);
calculate([a, c]);
function calculate(result) {
for (var i = 0; i < result.length; i++) {
var check = 0;
for (var j = 0; i < tags.length; i++) {
if (result[i] == tags[j]) {
check = 1;
counts[i] = counts[i] + 20;
}
}
if (check == 0) {
tags.push(result[i]);
counts.push(20);
}
check = 0;
}
}
However the output turns out like this:
words = a, b
count = 2, 1
When I expect it to be:
words = a,b,c
count = 2,1,1
Thanks for any help in advance
Breaking the problem down into methods with good names helps you to work out your logic.
Try this:
<script type="text/javascript">
var words = [];
var counts = [];
calculate(["a", "b"]);
calculate(["a", "c"]);
console.log(words);
console.log(counts);
function calculate(result) {
for (var i=0; i<result.length; i++) {
if (array_contains(words, result[i])) {
counts[result[i]]++;
} else {
words.push(result[i]);
counts[result[i]] = 1;
}
}
}
function array_contains(array, value) {
for (var i=0; i<array.length; i++)
if (array[i] == value)
return true;
return false;
}
</script>
Output:
["a", "b", "c"]
[]
a 2
b 1
c 1
Please check this :
you can test it on : http://jsfiddle.net/knqz6ftw/
var words = [];
var counts = [];
calculate(['a', 'b']);
calculate(['a', 'c']);
calculate(['a', 'b', 'c']);
function calculate(inputs) {
for (var i = 0; i < inputs.length; i++) {
var isExist = false;
for (var j = 0; j < words.length; j++) {
if (inputs[i] == words[j]) {
isExist = true
counts[i] = counts[i] + 1;
}
}
if (!isExist) {
words.push(inputs[i]);
counts.push(1);
}
isExist = false;
}
}
console.log(words);
console.log(counts);
Output is :
["a", "b", "c"] (index):46
[3, 2, 2]
A few things were wrong, here's working code:
var words = [];
var counts = [];
calculate(["a", "b"]);
calculate(["a", "c"]);
function calculate(result) {
for (var i = 0; i < result.length; i++) {
var check = 0;
for (var j = 0; j < words.length; j++) {
if (result[i] == words[j]) {
check = 1;
++counts[j];
}
}
if (check == 0) {
words.push(result[i]);
counts.push(1);
}
check = 0;
}
}
Jsbin : http://jsbin.com/hawaco/2/edit?js,console
Things I've changed:
Changed array literal to supply strings instead of variable names: [a,b] to ["a","b"]
Replaced instances of tags (presumably an old name) with words
Changed the 20s to 1s
Made the increment of counts[j] more clear
Fixed use of i/j indices
Things to consider:
Perhaps make this a dictionary rather than a pair of arrays: {"a":1, "b":2}, which would make for simpler code
Pass in the names of the arrays to permit other accumulators, or combine the method and arrays into a single object
Simplified:
var seen = {};
count(["a", "b"], seen);
count(["a", "c"], seen);
function count(words, accumulator) {
for (var i = 0; i < words.length; ++i) {
if(!accumulator.hasOwnProperty(words[i])) {
accumulator[words[i]] = 1;
} else {
++accumulator[words[i]];
}
}
}
Result:
>> seen
[object Object] {
a: 2,
b: 1,
c: 1
}
JSBin: http://jsbin.com/halak/1/edit?js,console
Here's my solution (using an object):
const checkWord = (str) => {
let collection = {};
// split the string into an array
let words = str.split(' ');
words.forEach((word) => {
collection[word] = word;
});
// loop again to check against the array and assign a count
for (let j = 0; j < words.length; j++) {
if (words[j] === collection[words[j]]) {
collection[words[j]] = 0;
}
collection[words[j]]++
}
console.log(collection);
};
You can also use reduce:
const checkWord = (str) => {
let collection = {};
let words = str.split(' ');
words.forEach((word) => {
collection[word] = word;
});
for (var i = 0; i < words.length; i++) {
if (words[i] === collection[words[i]]) {
collection[words[i]] = 0;
}
}
let total = words.reduce((occurrences, word) => {
collection[word]++
return collection;
}, 0);
console.log(total);
};