How to optimize memory in an algorithm - javascript

How can I optimize this
if the string can be split without a 4, 422 and 2222 without a remainder, returns true
tests:
input "4" output "true"(4)
input "44" output "true" (4 4)
input "42" output false(4 2!==2222 || 422 || 4)
input "4224224" output true (422 422 4)
input "42222" output true (4 2222)
input "22224"output true (2222 4)
let solution = (password) => {
if (!password) return false
while (password) {
if (password.includes('2222')) {
while (password.includes('2222')) {
password = password.replace('2222', '')
}
}
if (password.includes('422')) {
while (password.includes('422')) {
password = password.replace('422', '')
}
}
if (password.includes('4')) {
while (password.includes('4')) {
password = password.replace('4', '')
}
}
return !!!password
}
}
console.log(solution('4'));
console.log(solution('44'));
console.log(solution('42'));
console.log(solution('4224224'));
console.log(solution('42222'));
console.log(solution('22224'));
this is the same:
let solution = (password) => {
const searchValue = ['2222', '422', '4']
if (!password) return false
for (let elem = 0, i = searchValue[0]; password; elem++) {
if (password.includes(i)) {
while (password.includes(i)) {
password = password.replace(i, '')
}
}
i = searchValue[elem]
if (elem === 3) {
return !!!password
}
}
return !!!password
}
console.log(solution('4'));
console.log(solution('44'));
console.log(solution('42'));
console.log(solution('4224224'));
console.log(solution('42222'));
console.log(solution('22224'));
Memory limitation on startup - 100 MB
must work with -> const bigStr = new Array(9999999).fill(() =>["4", "422", "2222" ][Math.floor(Math.random() * 3)]).map(f => f()).join('')
Sorry, I forgot to mention that regular expressions are not allowed use

1) You can get the desired result with recursion
const matches = ["4", "2222", "422"];
function isMatch(str) {
if (str.trim() === "") return true;
for (let i = 0; i < matches.length; ++i) {
if (str.startsWith(matches[i])) {
if (isMatch(str.replace(matches[i], ""))) return true;
}
}
return false;
}
console.log(isMatch("4"));
console.log(isMatch("44"));
console.log(isMatch("42"));
console.log(isMatch("4224224"));
console.log(isMatch("42222 "));
console.log(isMatch("2222"));
2) You can use regex here \b(4|2222|422)+\b
const regex = /\b(4|2222|422)+\b/;
function isMatch(str) {
return regex.test(str);
}
console.log(isMatch("4"));
console.log(isMatch("44"));
console.log(isMatch("42"));
console.log(isMatch("4224224"));
console.log(isMatch("42222 "));
console.log(isMatch("2222"));

You can just use replaceAll instead of replacing the string each time and check if it is in there another time:
const bigStr = new Array(9999999).fill(() => ["4", "422", "2222"][Math.floor(Math.random() * 3)]).map(f => f()).join('');
const solution = (password) => {
return password !== "" && !password.replaceAll('2222', '').replaceAll('422', '').replaceAll('4', '');
}
console.log(solution("4"));
console.log(solution("44"));
console.log(solution("42"));
console.log(solution("4224224"));
console.log(solution("42222"));
console.log(solution("2222"));
console.log(solution(bigStr))

Related

How to print the object value which is inside a function

I am creating an object inside a function. Now I want to access the value of the object and print it out to the console.
const pattern = /^[a-zA-Z0-9._-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/;
function isEmailAddress(str) {
return str.match(pattern);
}
let signUpFormValidation = (formData) => {
const error = {};
const fields = ['email', 'password', 'name'];
fields.forEach(field => {
if (!formData[`${field}`]) {
error[[field]] = `${field} not present`;
}
})
if (formData.name && (formData.name.length < 3 || formData.name.length > 20)) {
error['name'] = 'Name should be atleast 4 chars and less than 20 chars';
}
if (formData.password && (formData.password.length < 6 || formData.password.length > 30)) {
error['password'] = 'Password should be atleast 6 chars and less than 30 chars';
}
if (formData.email && isEmailAddress(formData.email) === null) {
error['email'] = 'Not a valid email';
}
if (Object.keys(error).length === 0) return null;
return error;
}
I am 'Name should be at least 4 chars and less than 20 chars' in console. How I get it.

Why is my decryption function not working?

I created a function to encrypt and decrypt messages. the encrypting works fine. but when I try to log encrypted Hello World! it just logs H.
const chars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz".split("");
const numbs = "0123456789".split("");
const symbols = "!##$%^&*()_+-=[]{}|;':,./<>?\" ".split("");
function encrypt(message) {
message = message.split("")
var output = []
message.forEach(element => {
if (chars.includes(element)) {
output.push("c" + chars.indexOf(element))
} else if (numbs.includes(element)) {
output.push("n" + numbs.indexOf(element))
} else if (symbols.includes(element)) {
output.push("s" + symbols.indexOf(element))
} else {
console.log(element)
throw new Error(`Unknown character`)
}
});
return output.join("")
}
function decrypt(message) {
message = message.split("");
var output = [];
var prevDeter;
var prevNumbs = [];
message.forEach(element => {
if (element == "c") {
prevDeter = "c"
if (prevNumbs.length > 0) {
output.push(chars[parseInt(prevNumbs.join(""))])
}
} else if (element == "n") {
prevDeter = "n"
if (prevNumbs.length > 0) {
output.push(numbs[parseInt(prevNumbs.join(""))])
}
} else if (element == "s") {
prevDeter = "s"
if (prevNumbs.length > 0) {
output.push(symbols[parseInt(prevNumbs.join(""))])
}
} else {
prevNumbs.push(element)
}
});
return output.join("")
}
//expected to log Hello World! but logs H and when starting the message with a symbol or number it just logs nothing
console.log(decrypt(encrypt("Hello World!")))
Fixed it, i edited the encoding system to place a - between chars and the decoding system to just split the message at - and check if the element starts with c n or s. and then i just used substring to get the number and decrypt it
const chars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz".split("");
const numbs = "0123456789".split("");
const symbols = "!##$%^&*()_+-=[]{}|;':,./<>?\" ".split("");
function encrypt(message) {
message = message.split("");
var output = [];
message.forEach(element => {
if(chars.includes(element)) {
output.push("-c" + chars.indexOf(element));
}else if(numbs.includes(element)) {
output.push("-n" + numbs.indexOf(element));
}else if(symbols.includes(element)) {
output.push("-s" + symbols.indexOf(element));
}else{
console.log(element);
throw new Error(`Unknown character`);
};
});
return output.join("");
};
function decrypt(message) {
message = message.split("-");
console.log(message)
var output = [];
message.forEach(element => {
if(element.startsWith("c")) {
output.push(chars[element.substring(1)]);
}else if(element.startsWith("n")) {
output.push(numbs[element.substring(1)]);
}else if(element.startsWith("s")) {
output.push(symbols[element.substring(1)]);
}else if(element.length < 1){
}else{
throw new Error(`Invalid message`);
}
});
return output.join("");
};
console.log(decrypt(encrypt("Hello World!")));
You need to split the encoded string based on set/index pairs. This is easy enough to do with a look-ahead regular expression and splitting before a c, n or an s. /(?=[cns])/
const chars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz".split("");
const numbs = "0123456789".split("");
const symbols = "!##$%^&*()_+-=[]{}|;':,./<>?\" ".split("");
function encrypt(message) {
message = message.split("")
var output = []
message.forEach(element => {
if (chars.includes(element)) {
output.push("c" + chars.indexOf(element))
} else if (numbs.includes(element)) {
output.push("n" + numbs.indexOf(element))
} else if (symbols.includes(element)) {
output.push("s" + symbols.indexOf(element))
} else {
console.log(element)
throw new Error(`Unknown character`)
}
});
return output.join("")
}
function decrypt(message) {
message = message.split(/(?=[cns])/);
var output = [];
message.forEach(element => {
let set;
switch(element[0]){
case 'c':
set = chars;
break;
case 'n':
set = numbs;
break;
case 's':
set = symbols;
break;
}
const index = parseInt(element.substring(1));
output.push(set[index]);
});
return output.join('');
}
const encrypted = encrypt("Hello World!");
console.log(encrypted);
//expected to log Hello World! but logs H and when starting the message with a symbol or number it just logs nothing
console.log(decrypt(encrypted));

.forEach validates each element but not the whole input? JS

I'm trying to validate a form input with multiple hashtags. I absolutely have to split the input and convert it to lowerCase.
ex) #sun #sea #summer #salt #sand
When I'm typing a hashtag that fails the validation, bubble message pops up and tells me it's wrong.
But if I type the next hashtag correctly, previous bubble message clears and the whole validation fails (form can be sent).
I'm assuming it has something to do with .forEach – possibly there are better solutions I'm not yet aware of.
I'm new to JS and would appreciate your answers very much.
// conditions for validation
const hashtagInput = document.querySelector('.text__hashtags');
const commentInput = document.querySelector('.text__description');
const testStartWith = (hashtag) => {
if (!hashtag.startsWith('#')) {
return 'hashtag should start with #';
}
return undefined;
};
const testShortValueLength = (hashtag) => {
if (hashtag.length === 1) {
return 'hashtag should have something after #';
}
return undefined;
};
const testValidity = (hashtag) => {
const regex = /^[A-Za-z0-9]+$/;
const isValid = regex.test(hashtag.split('#')[1]);
if (!isValid) {
return 'hashtag can't have spaces, symbols like #, #, $, etc, or punctuation marks';
}
return undefined;
};
const testLongValueLength = (hashtag) => {
if (hashtag.length > 20) {
return 'maximum hashtag length is 20 symbols';
}
return undefined;
};
const testUniqueName = (hashtagArray, index) => {
if (hashtagArray[index - 1] === hashtagArray[index]) {
return 'the same hashtag can't be used twice';
}
return undefined;
};
const testHashtagQuantity = (hashtagArray) => {
if (hashtagArray.length > 5) {
return 'only 5 hashtags for each photo';
}
return undefined;
};
const testCommentLength = (commentInput) => {
if (commentInput.value.length >= 140) {
return 'maximum comment length is 140 symbols';
}
return undefined;
};
const highlightErrorBackground = (element) => {
element.style.backgroundColor = '#FFDBDB';
};
const whitenBackground = (element) => {
element.style.backgroundColor = 'white';
};
Here is the validation at work
const testHashtagInput = () => {
const hashtagArray = hashtagInput.value.toLowerCase().split(' ');
hashtagArray.forEach((hashtag, index) => {
let error = testStartWith(hashtag)
|| testShortValueLength(hashtag)
|| testValidity(hashtag)
|| testLongValueLength(hashtag)
|| testUniqueName(hashtagArray, index)
|| testHashtagQuantity(hashtagArray);
if (error) {
highlightErrorBackground(hashtagInput);
hashtagInput.setCustomValidity(error);
} else {
whitenBackground(hashtagInput);
hashtagInput.setCustomValidity('');
}
hashtagInput.reportValidity();
});
if (hashtagInput.value === '') {
whitenBackground(hashtagInput);
hashtagInput.setCustomValidity('');
}
hashtagInput.reportValidity();
};
const testCommentInput = () => {
let error = testCommentLength(commentInput);
if (error) {
highlightErrorBackground(commentInput);
commentInput.setCustomValidity(error);
} else {
whitenBackground(commentInput);
commentInput.setCustomValidity('');
}
commentInput.reportValidity();
};
hashtagInput.addEventListener('input', testHashtagInput);
Yes your forEach reevaluates the entire validity of the input based on the individual items but only the last one actually remains in the end because it's the last one being evaluated.
You could change your evaluation to an array-reducer function; best fit for your intention is the reducer "some" (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some).
It iterates over the list of items and returns whether any one (or more) of the items fullfills the criterion formulated in your callback function.
I didn't get to test it now, but I guess this should do it:
let error = hashtagArray.some((hashtag, index) => {
return (testStartWith(hashtag)
|| testShortValueLength(hashtag)
|| testValidity(hashtag)
|| testLongValueLength(hashtag)
|| testUniqueName(hashtagArray, index)
|| testHashtagQuantity(hashtagArray));
});
if (error) {
highlightErrorBackground(hashtagInput);
hashtagInput.setCustomValidity(error);
} else {
whitenBackground(hashtagInput);
hashtagInput.setCustomValidity('');
}
hashtagInput.reportValidity();
HTH, cheers

How to shorten code or store it in a data file

I am trying to create a feature on my website that prints out values in input boxes after an item from the dropdown menu is selected. Currently, my code works, but it is just too lengthy. Below is the JavaScript code that I would like to shorten or stored in a data file.
function dropdownTip(element){
if(element == "Methane") {
document.getElementById("myText").value="190.6";
document.getElementById("myText1").value="45.99";
document.getElementById("myText2").value="0.012";
}
else if(element == "Ethane") {
document.getElementById("myText").value="305.3";
document.getElementById("myText1").value="48.72";
document.getElementById("myText2").value="0.100";
}
else if(element == "Propane") {
document.getElementById("myText").value="369.8";
document.getElementById("myText1").value="48.48";
document.getElementById("myText2").value="0.152";
}
else if(element == "n-Butane") {
document.getElementById("myText").value="425.1";
document.getElementById("myText1").value="37.96";
document.getElementById("myText2").value="0.200";
}
else if(element == "n-Pentane") {
document.getElementById("myText").value="469.7";
document.getElementById("myText1").value="33.70";
document.getElementById("myText2").value="0.252";
}
else if(element == "n-Hexane") {
document.getElementById("myText").value="507.6";
document.getElementById("myText1").value="30.25";
document.getElementById("myText2").value="0.301";
}
else if(element == "n-Heptane") {
document.getElementById("myText").value="540.2";
document.getElementById("myText1").value="27.40";
document.getElementById("myText2").value="0.350";
}
else if(element == "n-Octane") {
document.getElementById("myText").value="568.7";
document.getElementById("myText1").value="24.90";
document.getElementById("myText2").value="0.400";
}
else if(element == "n-Nonane") {
document.getElementById("myText").value="594.6";
document.getElementById("myText1").value="22.90";
document.getElementById("myText2").value="0.444";
}
else if(element == "n-Decane") {
document.getElementById("myText").value="617.7";
document.getElementById("myText1").value="21.10";
document.getElementById("myText2").value="0.492";
}
The code is actually way longer than this. The else if(element== "x") {} lines actually extend for another 390 lines.
You can add the values in a array of objects and use it something like this obj[element]['text']
var obj = {
"methane" : {"text":"190.6","text1":"45.99","text2":"0.012"},
"eethane" : {"text":"305.3","text1":"48.72","text2":"0.100"}
}
function dropdownTip(element){
if(element) {
console.log(obj[element]['text'],obj[element]['text1'],obj[element]['text2']);
/*document.getElementById("myText").value=obj[element]['text'];
document.getElementById("myText1").value=obj[element]['text1'];
document.getElementById("myText2").value=obj[element]['text2'];*/
}
}
dropdownTip("methane")
I'd use an object indexed by element, whose values are arrays of #myText, #myText1, #myText2 values:
const elementValues = {
Methane: [190.6, 45.99, 0.012],
Ethane: [305.3, 48.72, '0.100'], // you'll need to use strings for trailing zeros
Propane: [369.8, 48.48, 0.152],
'n-Butane': [425.1, 37.96, '0.200'],
// ...
}
function dropdownTip(element){
const possibleArr = elementValues[element];
if (possibleArr) {
['myText', 'myText1', 'myText2'].forEach(
(id, i) => document.getElementById(id).value = possibleArr[i]
);
}
}
You might consider using classes instead of IDs, which would make the code a bit simpler:
const elementValues = {
Methane: [190.6, 45.99, 0.012],
Ethane: [305.3, 48.72, '0.100'], // you'll need to use strings for trailing zeros
Propane: [369.8, 48.48, 0.152],
'n-Butane': [425.1, 37.96, '0.200'],
// ...
}
function dropdownTip(element){
const possibleArr = elementValues[element];
if (possibleArr) {
document.querySelectorAll('.myText').forEach((elm, i) => {
elm.value = possibleArr[i];
});
}
}
const elementValues = {
Methane: [190.6, 45.99, 0.012],
Ethane: [305.3, 48.72, '0.100'], // you'll need to use strings for trailing zeros
Propane: [369.8, 48.48, 0.152],
'n-Butane': [425.1, 37.96, '0.200'],
// ...
}
function dropdownTip(element){
const possibleArr = elementValues[element];
if (possibleArr) {
document.querySelectorAll('.myText').forEach((elm, i) => {
elm.value = possibleArr[i];
});
}
}
<input onchange="dropdownTip(this.value)">
<br>
<input class="myText"></div>
<input class="myText"></div>
<input class="myText"></div>
If you don't like the bracket notation, another option is to write a long multiline string, which you transform into an object afterwards:
const elementValuesStr = `
Methane 190.6 45.99 0.012
Ethane 305.3 48.72, 0.100
Propane 369.8 48.48 0.152
n-Butane 425.1 37.96, 0.200
...
`;
const elementValues = elementValuesStr
.trim()
.split('\n')
.reduce((a, line) => {
const [key, ...vals] = line.match(/\S+/g);
a[key] = vals;
return a;
}, {});
And then you can use the same code as above, using elementValues.
const elementValuesStr = `
Methane 190.6 45.99 0.012
Ethane 305.3 48.72, 0.100
Propane 369.8 48.48 0.152
n-Butane 425.1 37.96, 0.200
`;
const elementValues = elementValuesStr
.trim()
.split('\n')
.reduce((a, line) => {
const [key, ...vals] = line.match(/\S+/g);
a[key] = vals;
return a;
}, {});
console.log(elementValues);

Filter letter by letter on Array Angular

I am trying to filter letter by letter on an array as below
MyJSON
"mainArr":[
{
"data":false,
"myArr":[
{
"myNumber": 12345,
},
{
"myNumber": 8961,
}
]
}
]
And here is code which I am drafting below for search but unable to pick object based on letter keypress or key down or ion-input
if (filterVal && filterVal.trim() !== '') {
this.myArray = this.myArray.filter(function (item) {
const results: any = [];
const obj = item.mainArr[0];
if (_.has(obj, 'myArr')) {
console.log(obj.myArr.indexOf(filterVal));
for (let i = 0; i < obj.myArr.length; i++) {
if (obj.myArr.indexOf(filterVal) !== -1)
return results.push(obj.myArr[i]);
}
}
}
});
}
Refered URL
Tried another way of implementing it, but backspace is not re-binding to original array
let results: any = [];
events.subscribe('filterSearch', (filterVal: string) => {
if (filterVal && filterVal.trim() !== '') {
results = Object.assign(this.allEventsSorted.filter(function (item: any): any {
const fltDty = item.mainArr[0];
if (_.has(fltDty, 'myArr')) {
return _.some(
item.mainArr[0].myArr,
function (tag): any {
return _.startsWith(tag.myNumber, filterVal);
// return _.includes(tag.myNumber, filterVal);
}
);
}
}));
this.allEventsSorted = results;
}
});

Categories