How do you detect the difference between two similar words?
For example:
word compared to word, gives , as a variable
this compared to .this gives . as a variable
info compared to :info, gives : and , as a variable
In this case we always know which word is the longer one. And the actual word is always the same for the comparison. It's just that the longer one maybe has some extra characters.
I need to do this using javascript only.
You could try checking for difference between the array of characters.
var shortStr = 'info';
var longStr = ':info,';
console.log(Array.from(longStr).filter(function(c) {
return Array.from(shortStr).indexOf(c) === -1;
}));
Also, there's a better way, check if the string is a sub-string, and then remove the sub-string from the main string:
function checkDiff(a, b) {
var big = '', small = '';
if (a.length > b.length) {
big = a;
small = b;
} else {
small = a;
big = b;
}
if (big.indexOf(small) != -1) {
return big.replace(small, "");
} else {
return false;
}
}
alert(checkDiff("word", "word,"));
alert(checkDiff("this", ".this"));
alert(checkDiff("info", ":info,"));
I have added demo for all your cases. It returns the values as a single string, based on the place it has occurred. You can send the output as an array as well, using the .split() method.
function checkDiff(a, b) {
var big = '', small = '';
if (a.length > b.length) {
big = a;
small = b;
} else {
small = a;
big = b;
}
if (big.indexOf(small) != -1) {
console.log(big.replace(small, "").split(""));
return big.replace(small, "").split("");
} else {
return false;
}
}
alert(checkDiff("word", "word,"));
alert(checkDiff("this", ".this"));
alert(checkDiff("info", ":info,"));
Related
So I have this code:
<script>
function add7(n) {
let x = n + 7;
console.log(x);
}
function lastLetter(theString) {
let x = lastIndexOf(theString);
console.log(x);
})
</script>
<script>
function multiply(a, b) {
let ans = a * b;
console.log(ans);
}
</script>
<script>
function capitalize(word) {
if (word = String) {
toLowerCase(word);
charAt(0).toUpperCase(word);
console.log(word);
} else {
console.log("not a string");
}
}
</script>
I write functionName(chosenVariable) in the console and expected to see a clear answer but add7 and lastLetter just returns ReferenceError (function) not defined. and the other 2 get undefined as an answer. I know that I am blind but am I also a bit stupid? I've looked at the code and tried different changes but cant get it to work.
There were a few errors with your code
Extra ) at the end of the first script block
lastIndexOf is not defined anywhere on your script
word = String will just assign the value of the String class to the word variable (and always return true)
Strings are immutable, so you can't edit an existing string you can however create a new string based on another, so using word.toLowerCase() on it's own won't do anything, you need to reassign the value
add7(2);
lastLetter("123123");
multiply(2, 3);
capitalize("asd");
function add7(n) {
let x = n + 7;
console.log(x);
}
function lastLetter(theString) {
let x = theString[theString.length - 1];
console.log(x);
}
function multiply(a, b) {
let ans = a * b;
console.log(ans);
}
function capitalize(word) {
if (typeof word === "string") {
word = word.toLowerCase();
word = word[0].toUpperCase() + word.substring(1);
console.log(word);
} else {
console.log("not a string");
}
}
So I'm working on a simple JavaScript web-based game. The goal is to guess a X digit random number. This means the random number can be 4, 5 digits up to whatever you want. You can actually play the game at www.juegodescifralo.com , (it's in Spanish, sorry about that).
The user inputs a number that is stored as an array. The random number is also generated as an array. Individual numbers in both arrays can be repeated.
There are three types of possible "values/numbers": the "good" ones are the numbers you chose that are in the same position as the ones in the random array. So for example:
Random array is: 1457
User input is: 6851
Number 5 is a "good" number, since it's in the same position. Then there are the second type of "values", which are "regular". This means they are inside the random number but not in the same position. In this example, number 1 would be a "regular" value. And the third type is the "bad" ones, which are not even inside the random array.
The function I've developed is as follows:
function checkNumbers(randomArray, myArray, good, regular, bad) {
for (var x = 0; x < randomArray.length; x++) {
var posRepetido = randomArray.indexOf(myArray[x]); //Is current number inside random array?
if (posRepetido == -1) { //It's not inside
console.log("number " + myArray[x] + "is not inside");
bad++;
} else { //It's inside
regular++;
if (myArray[x] == randomArray[x]) { //If it's the same number...
console.log("number " + myArray[x] + "is in the correct position");
good++;
regular--;
} else { //If it's not the same number
if (randomArray[posRepetido] != myArray[posRepetido]) {
console.log("number " + myArray[x] + "is inside but not in the same position");
} else {
console.log("number " + myArray[x] + "is not inside");
}
}
}
}
var obj = { //Return object for accessing later, to show feedback to the user.
good: good,
regular: regular,
bad: bad
};
return obj;
}
The code is a bit buggy. When there are duplicates in the random array, and one of them is marked as good, then the other one (even if it exists in user input) will be set as bad, not as regular as it should.
The thing becomes even more complicated since you should be able to play against any amount of digits. So I should be able to guess a 20 digit number without "problems".
You can play by yourself at www.juegodescifralo.com
How can I go about this? Any ideas how can I access array data more easily? Thank you very much!
Rather than indexOf comparisons against -1 and checks of myArray[x], it would probably be a lot easier to use includes and array methods such as forEach for better abstraction. All you really need is an if, an else if, and an else. For example:
function checkNumbers(randomArray, userArray, good=0, regular=0, bad=0) {
userArray.forEach((guess, i) => {
if (guess === randomArray[i]) good++;
else if (randomArray.includes(guess)) regular++;
else bad++;
});
return { good, regular, bad };
}
// 4 good
console.log(checkNumbers(
'1234'.split(''),
'1234'.split(''),
));
// 4 good, 2 bad
console.log(checkNumbers(
'1234'.split(''),
'123456'.split(''),
));
// 4 good, 2 regular
console.log(checkNumbers(
'1234'.split(''),
'123412'.split(''),
));
// all regular:
console.log(checkNumbers(
'123456789123456789'.split(''),
'912345678912345678'.split(''),
));
i think it is easier to loop thru it twice like this
function checkNumbers(randomArray, guessArray) {
var clone = randomArray.slice(0);
var good = 0;
var regular = 0;
var bad = 0;
var visited = [];
guessArray.forEach(function(guess, index) {
if (guess === clone[index]) { // the guess is in right position
good++;
clone[index] = "x"; // strike it out so it cannot be used later
visited.push(index);
} else if (clone.indexOf(guess) === -1) {
bad++;
visited.push(index);
}
});
guessArray.forEach(function(guess, index) {
if (!visited.includes(index)) {
var match = clone.indexOf(guess);
if (match !== -1) {
regular++;
clone[match] = "x"; // strike it out so it cannot be used later
}
}
});
return {
good: good,
bad: bad,
regular: regular
}
}
first loop is to check the good and bad. and strikeout the value it is good so it cannot be used again.
second loop to check for the regular and strikeout the value it is used so it cannot be used again.
This should work.
function guessNumber (numUser, numRandom) {
if (typeof numUser == 'number') {
numUser = numUser.toString().split('');
}
if (typeof numRandom == 'number') {
numRandom = numRandom.toString().split('');
}
if (typeof numRandom != 'object' || typeof numUser != 'object') {
return false;
}
if (numRandom == numUser) {
return true;
}
var numRegular = {},
numBuenos = {},
numMalos = {},
numRepeat = {};
for(var i = 0; i < numRandom.length; i++) {
if (!numRepeat[numRandom[i]]) {
numRepeat[numRandom[i]] = 0;
}
numRegular[numRandom[i]] = 0;
numRepeat[numRandom[i]]++;
}
for (var i = 0; i < numUser.length; i++) {
if (numUser[i] == numRandom[i]) {
numBuenos[numUser[i]] = numUser[i];
}else if ($.inArray(numUser[i], numRandom)) {
if (!numRegular[numUser[i]]) {
numRegular[numUser[i]] = 0;
}
if (numRegular[numUser[i]] < numRepeat[numUser[i]]) {
numRegular[numUser[i]]++;
} else {
numMalos[numUser[i]] = numUser[i];
}
} else {
numMalos[numUser[i]] = numUser[i];
}
}
return {
regular: Object.values(numRegular).reduce((a, b) => a + b),
buenos: Object.keys(numBuenos).length,
malos: Object.keys(numMalos).length
};
}
console.log(guessNumber(8365, 8512));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
I'm trying to set up a function that checks if a word or a text is a palindrome. To do that, it splits the text so that every letter is an element of a new array, it takes rid of the white spaces and it makes the reverse array.
Then it checks if every element of the two arrays, at the same positions, are equal. If not it returns false, if yes it returns true.
Here the function:
function palindrome(str) {
var low = str.toLowerCase();
var newArray = low.split("");
var noSpace = newArray.filter(function(val) {
return val !== " ";
});
var reverse = noSpace.reverse();
function check (a, b) {
console.log(`checking '${a}' against '${b}'`);
var partial;
var result = 1;
for (var i = 0; i < a.length; i++) {
console.log(`comparing '${a[i]}' and '${b[i]}'`);
if (a[i] !== b[i]) {
result = 0;
} else {
partial = 1;
result *= partial;
}
}
return result;
}
var result = check(noSpace, reverse);
if (result == 1) {
return true;
} else {
return false;
}
}
palindrome("r y e");
I don't know what's wrong but it seems that the function keeps on returning a true value no matter what word or text I pass to the function. What is wrong with that?
Your issue seems to be because reverse() changes the actual array as well. So doing
var reverse = noSpace.reverse();
Will reverse noSpace and assign a reference to it on the variable reverse. That is, both arrays will be the same (reversed) array.
To bypass that, I've used .slice() to create a copy of the original array, and then called .reverse() on that new array, ridding you of any conflicts.
Here's a working snippet of what it looks like:
function palindrome(str) {
var str_array = str.toLowerCase().split("");
var no_space = str_array.filter(function(val) {
return val !== " ";
});
// By applying '.slice()', we create a new array
// reference which can then be reversed and assigned
// to the 'reverse' variable
var reverse = no_space.slice().reverse();
function check(a, b) {
var partial;
var result = 1;
for(var i=0; i < a.length; i++) {
if(a[i] !== b[i]) {
// We don't need to keep
// comparing the two, it
// already failed
return 0;
} else {
// I've kept this part even though
// I don't really know what it is
// intended for
partial = 1;
result *= partial;
}
}
return result;
}
return check(no_space, reverse) === 1;
}
console.log(palindrome("a b a"));
console.log(palindrome("r y e"));
The way you have coded for palindrome is way too complicated.
But there is one problem with your code: when you do a reverse() it changes the original array as well.
So you will need to make sure that you copy it via slice().
Also you can directly send a boolean result rather than doing a 1 and 0.
At result *= partial;, 1 * 1 will always equal 1
I didn't correct your code, but here is a optimized solution for you.
function palindrom(string) {
var arr = string.split("");
var lengthToCheck = Math.floor(arr.length / 2);
for (var i = 0; i < lengthToCheck; i++) {
if (arr[i] != arr[arr.length - (1 + i)]) {
return false;
}
}
return true;
}
First I split the array after every charater of the passed String. After that I get the half of the length of the array as it's enough to check just one half.
With the for-loop I compare the first half with the second half. As soon as I found two characters that do not match I return false. In case the whole first half matches the second half of the array, the for-loop will be completed and after that true will be returned.
What's actually happening is .reverse() reverses an array in place, it then stores a reference to that array which is not what you're calling in your check() method.
Simple fix would be to change your if statement:
if (a[i] !== b.reverse()[i])
This might not be best practice, but I was wondering if it's possible to break from the arr.find() method.
Here's some code that I was working on that I've since redone with a loop but I was wondering why this is not allowed?
Any help is appreciated!
I understand this isn't the best approach to the problem at hand I'm just curious to why the break doesn't work as intended where am I messed up in my thinking?
//Using the JavaScript language, have the function SimpleSymbols(str) take the str parameterbeing passed and determine if it is an acceptable sequence by either return in the string true or false. The str parameter will be composed of + and = symbols with several letters between them (ie. ++d+===+c++==a) and for the string to be true each letter must be surrounded by a + symbol. So the string to the left would be false. The string will not be empty and will have at least one letter.
//loop through Array
//Determine if letter is surrounded by +
//If yes continue on and return true
//If no break loop and return false
function SimpleSymbols(str){
str = str.split('');
var pass = null;
function finder(char){
if (char.length === 1 && char.match(/[a-z]/i)){
var firstPlus = str.indexOf(char)- 1;
var secondPlus = str.indexOf(char)+ 1;
console.log(str[firstPlus]);
if (str[firstPlus] === '+' && str[secondPlus] === '+'){
pass = 'true';
} else {
pass = 'false'
break;
}
}
}
str.find(finder);
return pass
}
SimpleSymbols('++d+===+c++==a++q++');
This code will break loop in your case after 5 iterations:
SimpleSymbols('++-+d+===*c+3++==a++q-3++');
function SimpleSymbols(str){
str = str.split('');
var pass = null;
str.find(finder);
function finder(char, i){
console.log('Iteration No.' + i);
if (str.indexOf(char) && char.length === 1 && char.match(/[a-z]/i)){
var firstPlus = str.indexOf(char)- 1;
var secondPlus = str.indexOf(char)+ 1;
//console.log(str[firstPlus]);
if (str[firstPlus] === '+' && str[secondPlus] === '+'){
pass = 'true';
return pass;
} else {
pass = 'false';
}
}
}
console.log('FINAL RESULT = ' + pass);
return pass;
}
I am wondering if this code can be modified so that it will render "4,5" and "4.5" (or any number that only has a tenths place) as 4.50 (or 4,50) respectively...rather than as 45.
I think I need to test "source" first to see if it's got the format "x[.,]x" (digit, comma or period, digit) but haven't been able to do that successfully. I've tried using "toFixed" but that messes things up if it's 4.500 or something (which needs to render as 4500, not 4.50!)
Any help would be hugely appreciated. Thank you!
function parse(source) {
var sep = source.charAt(source.length - 3);
switch (sep) {
case '.':
case ',':
var parts = source.split(sep);
var norm = parts[0].replace(/(\.|,|\s)/g, '') + '.' + parts[1];
break;
default:
var norm = source.replace(/(\.|,|\s)/g, '');
}
return Math.round(Number(norm));
}
So I have figured out a regex that identifies the right pattern: /^\d{1}[.,]\d{1}$/ (note there's a slash not showing up right before the period inside the brackets!!)
I have added it into the following little function, which I want to just tack on a zero or leave the variable as is. But for some reason it's now crashing at the part where I'm adding the zero...
function addZeros(number) {
var s = number;
if (s.match(/^\d{1}[\.,]\d{1}$/)) { //should only get here on "X,X" or "X.X" cases
alert(s); //makes it to here, displays only this alert
s = s.toFixed(2); //wtf is wrong with this?!!
alert(s); //does NOT make it to here.
return s;
}
else {
alert('All good in the hood.');
return s;
}
}
If I understand you correctly this should do it
function parse(s) {
var found = false;
['.', ','].forEach(function (el) {
var i = s.indexOf(el);
if (s[i] === s[s.length - 2]) {
s = s + '0';
found = true;
return false;
}
});
if (!found) {
return s.replace(/(\.|,|\s)/g, '');
} else {
return s;
}
}
Run a forEach on each delimiter and figure out how you want it to be formatted.
http://jsfiddle.net/Ek6cJ/
Does this do what you want?
function parse(source) {
var dotIndex = source.lastIndexOf('.');
var commaIndex = source.lastIndexOf(',');
var numDots = source.match(/\./g).length;
if (dotIndex > commaIndex && numDots == 1) {
// Dot-delimited decimal
return Number(source.replace(/,/g, '')).toFixed(2);
} else {
return Number(source.replace(/\./g, '').replace(/,/g, '.')).toFixed(2);
}
}
> parse("1,200,300.20")
"1200300.20"
> parse("1.200.300,20")
"1200300.20"
> parse("1.200.300")
"1200300.00"