I wrote a code to generate a random password, but in which way i can check that in the password there is a number, uppercase, lowercase and special characters?
function randomPassword(length) {
var chars = "abcdefghijklmnopqrstuvwxyz!##$%^&*1234567890ABCDEFGHIJKLMNOPQRSTUVWYZ";
var pass = "";
for (var x = 0; x < length; x++) {
var i = Math.floor(Math.random() * chars.length);
pass += chars.charAt(i);
}
return pass;
}
Why not loop over the different sets of characters. Then you don't have to check it at all:
function randomPassword(length) {
var chars = [
"abcdefghijklmnopqrstuvwxyz",
"!##$%^&*",
"1234567890",
"ABCDEFGHIJKLMNOPQRSTUVWYZ"
];
var pass = "";
while (pass.length < length) {
chars.forEach(set => {
if(pass.length < length) {
var i = Math.floor(Math.random() * set.length);
pass += set.charAt(i);
};
});
};
return pass;
};
Every iteration of the while loop will add one character from each of the sets. We check the pass.length the second time to make sure we aren't going over the limit when in the middle of a while loop. You should probably also make sure you return early if the length parameter is less than 4.
Maybe you can leave the password like it is, but to make sure you have the four required characters (number, uppercase, lowercase and special characters), you can later add one of each. These can also be chosen at random.
What you need is RegEx. Here are a few examples:
https://www.thepolyglotdeveloper.com/2015/05/use-regex-to-test-password-strength-in-javascript/
https://gist.github.com/leandromoh/470b0b54208f02a9ba223cdbdd1534bd
https://www.w3schools.com/howto/howto_js_password_validation.asp
You could generate passwords untill you get one that satisfies RegEx which would be the most random way:
function randomPassword(length) {
var chars = "abcdefghijklmnopqrstuvwxyz!##$%^&*1234567890ABCDEFGHIJKLMNOPQRSTUVWYZ";
var pass = "";
for (var x = 0; x < length; x++) {
var i = Math.floor(Math.random() * chars.length);
pass += chars.charAt(i);
}
return pass;
}
function randomStrongPassword(length) {
const strongRegex = new RegExp(`^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!##\$%\^&\*])(?=.{${length},})`)
let pass, valid
do {
pass = randomPassword(length)
valid = strongRegex.test(pass)
} while (valid !== true)
return pass
}
console.log(randomStrongPassword(8))
Or generate it like this and than randomize (I've added a test at end):
function randomPassword(length) {
const lower = 'abcdefghijklmnopqrstuvwxyz'
const upper = lower.toUpperCase()
const special ='!##$%^&*'
const numbers = '1234567890'
const characters = [lower, upper, special, numbers]
let pass = ""
for (var x = 0; x < length; x++) {
characters.forEach(e => {
const i = Math.floor(Math.random() * e.length)
pass += e.charAt(i)
})
}
const splice = Math.max(Math.floor(Math.random() * length) - length, 0)
return [...pass].splice(splice, length).sort(e => Math.random() - 0.5).join('')
}
console.log(randomPassword(10))
// Test password
const minLength = 8
const strongRegex = new RegExp(`^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!##\$%\^&\*])(?=.{${minLength},})`)
console.log(strongRegex.test(randomPassword(6)))
console.log(strongRegex.test(randomPassword(8)))
Related
How can I get the initial letters from a postcode in javascript? I just want the letters before the numbers start, like this:
E.g - 'L159XU' would return 'L'
E.g - 'TW136PZ' would return 'TW'
I was originally doing this:
const letters = postcode.substring(0, 2);
But some only have one letter, while others have two. Is there a way to do this?
I have tested this:
HTML
<p id="test"></p>
JavaScript Regular Expressions
let text = 'TW136PZ';
let pattern = /[a-zA-Z]+|[0-9]+/g;
let result = text.match(pattern);
document.getElementById("test").innerHTML = result[0]; // return "TW"
use a split function with a regex,
let res = "TW136PZ".split(/[0-9]+/)[0] ; // TW
more about regex here
There are different valid implementations
function callX() {
return 'TW136PZ'.slice(0, 'TW136PZ'.search(/[0-9]/))
}
function callY() {
return 'TW136PZ'.split(/[0-9]+/)[0]
}
function callZ() {
return 'TW136PZ'.match( /^[a-zA-Z]+/ )[0]
}
when benchmarking these:
performance.mark("beginX");
for (let i = 0; i < 10000000; ++i) {
callX();
}
performance.mark("endX");
performance.mark("beginY");
for (let i = 0; i < 10000000; ++i) {
callY();
}
performance.mark("endY");
performance.mark("beginZ");
for (let i = 0; i < 10000000; ++i) {
callZ();
}
performance.mark("endZ");
performance.measure("X","beginX","endX");
performance.measure("Y","beginY","endY");
performance.measure("Z","beginZ","endZ");
console.log(performance.getEntriesByType("measure"))
it turns out the first implementation is the fastest, while the second implementation (using split) is the slowest.
I think this is due to not requiring to instantiate another array.
Posting a solution that does not use regular expressions, because I haven't seen one:
function parsePostcode(postcode) {
const charIsADigit = function(ch) {
const code = ch.charCodeAt(0)
return code >= 48 && 58 > code;
};
let prefix = ""
for (let i = 0; i < postcode.length; ++i) {
const ch = postcode[i]
const is_digit = charIsADigit(ch)
if (is_digit) break;
prefix += ch
}
return prefix;
}
console.log(parsePostcode("L159XU"))
console.log(parsePostcode("TW136PZ"))
const postc='TwA1234';
const letters=postc.match( /^[a-zA-Z]+/ )[0];
console.log(letters);
^ – begin of input
a-z – lowercase English Letters included
A-Z – Uppercases included
+ – one or more times it appears!
As you wanted, it returns a string of as many initial latin latters as needed, three in this case.
I'm doing a question that asks: Read 10 numbers and print the biggest number from the list of reading numbers. Make use of Array and Functions.
One Function to read the integer numbers and another function to print the biggest number from the list.
I'm having trouble with getting the biggest number and returning it back to the code so that I can display it. I've messed around with it allot so it might not make as much sense right now (I'm sorry).
I've been stuck on it forever any help would be much appreciated :).
var numbers = [];
var BiggestNumber = 0;
BigestNumber = BiggestSort(numbers);
numbers = ReadNumbers();
Display(BiggestNumber)
function ReadNumbers() {
var ArgNumbers = [];
var ArgInput;
var ctr;
for (ctr = 0; ctr < 3; ctr++) {
ArgInput = parseFloat(prompt("Please enter a number: "));
ArgNumbers.push(ArgInput);
}
return ArgNumbers;
}
function BiggestSort(ArgNumber) {
var ArgNumber = [];
var ArgBiggest = 0;
var ctr;
for (ctr = 0; ctr < 3; ctr++)
if (ArgNumber[ctr] > ArgBiggest) {
ArgBiggest = ArgNumber[ctr];
}
return ArgBiggest;
}
function Display(ArgNumber) {
alert("The biggest number was: " + ArgNumber);
}
I've added a snippet at the end that demonstrates how I might do such a thing from scratch, but let's look at your code first:
From the top:
There's no need to declare numbers and BiggestNumber with initial values and then immediately reassign them. Declare them at assignment time:
// var numbers = [];
// var BiggestNumber = 0;
const BigestNumber = BiggestSort(numbers);
const numbers = ReadNumbers();
There's a typo in BigestNumber (missing second 'g'):
// const BigestNumber = BiggestSort(numbers);
const BiggestNumber = BiggestSort(numbers);
const numbers = ReadNumbers();
You're calling BiggestSort(numbers) before numbers has a meaningful value. Call ReadNumbers() first to initialize numbers, then pass it to BiggestSort:
// const BiggestNumber = BiggestSort(numbers);
// const numbers = ReadNumbers();
const numbers = ReadNumbers();
const BiggestNumber = BiggestSort(numbers);
Again, no need to declare ArgInput and ctr separately. It doesn't really hurt anything, but it's unnecessary:
function ReadNumbers() {
const ArgNumbers = [];
// var ArgInput;
// var ctr;
for (let ctr = 0; ctr < 3; ctr++) {
const ArgInput = parseFloat(prompt("Please enter a number: "));
ArgNumbers.push(ArgInput);
}
return ArgNumbers;
}
You're receiving an ArgNumber parameter, and then declaring another variable with the same name. Use the argument passed in.
Because the ArgNumber parameter is an array, you can use its length property in the loop condition instead of hard-coding 3.
You're missing curly braces around your loop body.
function BiggestSort(ArgNumber) {
// var ArgNumber = [];
let ArgBiggest = 0;
// var ctr;
// for (ctr = 0; ctr < 3; ctr++)
for (let ctr = 0; ctr < ArgNumber.length; ctr++) { // added curly brace
if (ArgNumber[ctr] > ArgBiggest) {
ArgBiggest = ArgNumber[ctr];
}
} // added closing brace
return ArgBiggest;
}
With the changes described above, it works:
const numbers = ReadNumbers();
const BiggestNumber = BiggestSort(numbers);
Display(BiggestNumber);
function ReadNumbers() {
const ArgNumbers = [];
for (let ctr = 0; ctr < 3; ctr++) {
const ArgInput = parseFloat(prompt("Please enter a number: "));
ArgNumbers.push(ArgInput);
}
return ArgNumbers;
}
function BiggestSort(ArgNumber) {
let ArgBiggest = 0;
for (let ctr = 0; ctr < ArgNumber.length; ctr++) {
if (ArgNumber[ctr] > ArgBiggest) {
ArgBiggest = ArgNumber[ctr];
}
}
return ArgBiggest;
}
function Display(ArgNumber) {
alert("The biggest number was: " + ArgNumber);
}
Consider this approach:
// A function to prompt for a series of numbers:
// The 'count' parameter is how many numbers to prompt for.
// The 'previous' parameter is an array of the numbers already entered, initally empty.
function readNumbers (count, previous = []) {
// if count is zero, we're done. return the already entered numbers.
if (count === 0) {
return previous;
}
// prompt for the next number
const number = parseFloat(prompt('Enter a number: '));
// push the new number onto the end of the list
previous.push(number);
// call readNumbers again, subtracting one from 'count'
// and return whatever it returns.
return readNumbers(count - 1, previous);
}
// invoke readNumbers to prompt the user.
const numbers = readNumbers(3);
// use Math.max to find the largest number
const largest = Math.max(...numbers);
// show the result
alert(`The biggest number was ${largest}`);
Correct typos like BigestNumber and BiggestNumber.
do ReadNumbers before BiggestSort method call.
remove\avoid reassigning to parameters\args you pass into method scopes, i.e. ArgNumber in the BiggestSort method.
var numbers = [];
numbers = ReadNumbers(3);
BiggestNumber = BiggestSort(numbers);
Display(BiggestNumber)
function ReadNumbers(numberToRead) {
var ArgNumbers = [];
var ArgInput;
for (var ctr = 0; ctr < numberToRead; ctr++) {
ArgInput = parseFloat(prompt("Please enter a number: "));
ArgNumbers.push(ArgInput);
}
return ArgNumbers;
}
function BiggestSort(ArgNumber) {
var ArgBiggest = 0;
for (var ctr = 0, max = ArgNumber.length; ctr < max; ctr++)
if (ArgNumber[ctr] > ArgBiggest) {
ArgBiggest = ArgNumber[ctr];
}
return ArgBiggest;
}
function Display(ArgNumber) {
alert("The biggest number was: " + ArgNumber);
}
I also passed in the number of loops (numberToRead) and ensure the loop in BiggestSort uses the length of the passed array (ArgNumber).
I am making a javascript function that will input a string, and output a "spongebob mocking text"
basically, you input "Hello, this is a message to the world" and you would get "HeLlO, ThIS iS a MeSsAGe tO tHE wORlD"
basically, randomly decide wheather to capitalize a letter or not. I made a function which i thought would do that, but it didn't work. here is the code that I tested in the js console:
function memify(input) { // function called memify()
var il = input.length; // gets the length of the input
var newinput = input; // creates a new variable that will be changed from input.
for (var i=0;i>il;i++) {
var rng = Math.floor((Math.random()*2)); // random number between 0 and 1. 0 = upper 1 = lower
if (rng === 0) {
newinput.charAt(i).toUpperCase();
}
else {
newinput.charAt(i).toLowerCase();
}
}
return newinput;
}
var text = prompt();
var textmeme = memify(text);
alert(textmeme);
Why is this not working? Do I have an error in my code? Any help will be greatly appreciated.
When you do
newinput.charAt(i).toUpperCase();
you're creating a new uppercase character, but you aren't doing anything with it; it's just an unused expression, so there's no visible change. Primitives (including strings) are immutable - you should explicitly reassign a string to something else (eg newString += newinput.charAt(i).toUpperCase();) to see an effect.
You also need to use
for (var i = 0; i < il; i++) {
// ^
instead of
for (var i = 0; i > il; i++) {
// ^
else, no iterations will run at all.
function memify(input) { // function called memify()
var il = input.length; // gets the length of the input
let changedStr = '';
for (var i = 0; i < il; i++) {
var rng = Math.floor((Math.random() * 2)); // random number between 0 and 1. 0 = upper 1 = lower
if (rng === 0) {
changedStr += input.charAt(i).toUpperCase();
} else {
changedStr += input.charAt(i).toLowerCase();
}
}
return changedStr;
}
var text = prompt();
var textmeme = memify(text);
console.log(textmeme);
Another option, using .map, which looks much cleaner IMO:
const memify = input => [...input]
.map(char => Math.random() < 0.5 ? char.toUpperCase() : char.toLowerCase())
.join('');
console.log(memify(prompt()));
Or more concise, safer and generally better solution :). It does not require for loop, checking length of string and other error prone stuff.
function memify(input) {
var rng = () => Math.random() > 0.5;
var res = input.split('').map( letter =>
rng() ? letter.toUpperCase() : letter.toLowerCase()
).join('');
return res;
}
var textmeme = memify("Hello World");
console.log(textmeme);
Please up-vote if it was helpful :)
I try to create a guessed with javascript and this is the code:
<script>
function makeid(len)
{
var text = "";
//var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var possible = "abc";
for( var i=0; i < len; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
////////////////////////////////////////////
var password = 'abc';
var correctGuess = false
var guess;
do {
document.write(makeid(3) + "<br>");
guess = makeid(3);
if (guess === password) {
correctGuess = true;
}
} while ( ! correctGuess )
document.write("You know the secret password. Welcome.");
</script>
But unfortunately the result is repeated more than once :
The result:
abb baa aac cba cbb aba bbb aac acb cba ccc bab caa bab ccc aac ccb
aba abc bac cbb
This slows down the program,, how disband this problem
Is there a solution?
thank you
Since you want to not check the same password twice, generating random guesses is obviously not the right way to go. As klumme mentioned, storing an array of previous guesses would only increase time and space complexity, so that is also out. What you will have to do is use a brute force method, that is, trying every combination of characters until you get the correct answer. Here's how you can implement it:
NOTE: Keep in mind that brute force algorithms are typically pretty inefficient, and if you use the full alphanumeric string that you have in your original code to brute force passwords of more than 3-4 characters, it will take a significant amount of time (especially in a browser). JavaScript, by nature, is not an extremely powerful number crunching language - so this answer is more for the idea of it, than for use in most real-world environments.
function guesser(len) {
var arr = Array.apply(null, Array(len));
var propIndex = -1;
var indexes = arr.reduce(function(total, curr) {
propIndex++;
total[propIndex] = 0;
return total;
}, {});
var lastGuess = arr.map(function() {
return possible[possible.length - 1];
}).join("");
var guess = "";
var found = false;
while (guess !== lastGuess) {
guess = "";
for (var i = 0; i < propIndex; i++) {
// if on last char, reset to 0 and increment previous index start position
if (indexes[propIndex - i] >= possible.length) {
indexes[propIndex - i - 1]++;
indexes[propIndex - i] = 0;
}
}
for (var i in indexes) {
guess += possible[indexes[i]];
}
document.write(guess + "<br/>");
if (guess === password) {
found = true;
break;
}
// increment last char
indexes[propIndex]++;
}
if (found) {
document.write("You know the secret password. Welcome.");
} else {
document.write("Sorry, you do not know the secret password.");
}
}
var password = 'dcd';
var possible = "abcd";
guesser(password.length);
If I understand you correctly, the problem is that the random password function ("makeid") may return the same password several times. This is no surprise, there's no reason for the function to know which passwords have been tried already. You could keep track of already tried passwords and not try one if it has been tried before (as in Kind user's answer), but in this case it probably wouldn't speed up the program.
A better approach would probably be to iterate through the possible passwords systematically instead of randomly. For example, try "aaa" first, then "aab", "aac" "aba" and so on.
Here is something I came up with -- it's probably not very fast. I use an array of indices into the "possible" string until actually trying the password, because I don't wan't to mess around with indexOf() on the way.
const correctPassword = 'abc';
const possible = 'abc';
const maxIndex = possible.length - 1;
function next(previous) {
var i = previous.length - 1;
while (previous[i] === maxIndex) {
previous[i] = 0;
i--;
// All passwords have been tried.
if (i < 0) {
return [];
}
}
previous[i]++;
return previous;
}
var current = Array(3).fill(0);
var currentPassword;
while (current.length != 0) {
currentPassword = current.map(function (i) {
return possible[i];
}).join('');
document.write(currentPassword + '<br>');
if (currentPassword === correctPassword) {
document.write('You know the secret password. Welcome.');
break;
}
current = next(current);
}
First of all, store the results inside an array. Secondly, add a following condition: if (arr.indexOf(guess) == -1) - if the guessed number is already in the array - skip it.
function makeid(len) {
var text = "";
//var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var possible = "abc";
for (var i = 0; i < len; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
var password = 'abc';
var correctGuess = false;
var guess;
var arr = [];
while (!correctGuess) {
guess = makeid(3);
if (arr.indexOf(guess) == -1) {
arr.push(guess)
if (guess === password) {
correctGuess = true;
}
}
}
console.log(arr);
I got interested in this question and decided to use it as an opportunity to learn more about generators. Note: Uses ES6 syntax, so not necessarily compatible with all platforms.
I wouldn't necessarily recommend this over the other approaches already put in place, but it might be a good future reference.
/**
* Invoke `callback` with every possible combination of `elements` up to length of `length`, until `callback` returns `true`
* #param elements an array of elements to be passed to `callback`
* #param length the maximum number of elements to pass to `callback`
* #param callback a function taking an array of elements, that returns a boolean
* #returns the first combination of elements for which `callback(combination)` returns `true`. Returns undefined if no combination up to the specified `length` returns `true`.
*/
const combineAndCall = (elements = [], length = 0, callback) => {
const it = permuteIterator(elements, length);
for (const el of it) {
if (callback(el)) {
return el;
}
}
};
/**
* Returns a generator that returns permutations, with repeated elements, of an array. The maximum length of each permutation is `len`
* #param arr the array to iterate. The first iteration will always be the empty array.
*
* Example:
* const it = permuteIterator([1,2,3], 2);
* it.next().value; // []
* it.next().value; // [1]
* it.next().value; // [2]
* it.next().value; // [3]
* it.next().value; // [1,1]
* it.next().value; // [1,2]
* it.next().value; // [1,3]
* it.next().value; // [2,1]
* it.next().value; // [2,2]
* ...
* it.next().value; // [3,3]
*
* #len the maximum length of each permutation
* #returns a generator that iterates the array
*/
function *permuteIterator(arr, len) {
let current = [];
function *helper(current, arr, len) {
if (current.length >= len) {
yield current;
} else {
for (const el of arr) {
yield* helper([...current, el], arr, len);
}
}
}
for (let i = 0; i <= len; i++) {
yield* helper([], arr, i);
}
}
/**
* Validates a password
* #param elements an array of strings (usually single characters) to combine into a a single string, and compare against the password
* #returns true if the string resulting from `elements.join("")` exactly equals the real password, false otherwise
*/
const passwordValidator = (elements) => {
const guess = elements.join("");
//console.log("validating:", guess);
return guess === "abc";
};
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
//const alphabet = "abc";
const elements = alphabet.split("");
const guessedPassword = combineAndCall(elements, 3, passwordValidator);
if (guessedPassword) {
console.log(`You know the secret password '${guessedPassword.join("")}'. Welcome.`);
} else {
console.log("You don't know the secret password. Rejected.");
}
I have an array "A" of scrambled, randomly generated ASCII characters... and a message "M". I want to insert the characters of message M into array A such that the order of M's characters are intact... but randomly distributed throughout array A.
Original array: zH$#%#$##$#^^##(%*$#^&#!$^%&
Sample output: zH$#%#^t$##$#^^h##(%*$#^&#i!$^%&s, etc...
var randomChars = [];
for(var i=33;i<127;++i) {
var letter = document.createElement('span');
letter.innerHTML = String.fromCharCode(i);
randomChars.push(letter);
}
var message = "this is a message";
var rand = 0;
for (var i = 0; i < message.split("").length; i++) {
rand = Math.floor((Math.random() * randomChars.length) + rand);
var letters = document.createElement('span');
letters.innerHTML = message.split("")[i];
letters.setAttribute("hidden","");
randomChars.splice(rand, 0, letters);
}
Fiddle: https://jsfiddle.net/0ftm2srz/1/
Use the previous random index as the minimum (non inclusive) of your next randomly generated index. Start at zero.
You could end up with some barely scrambled stuff, though. (!##!$!#$#!##this) But it's random.
EDIT A better way would be to generate a message.length amount of unique random indices, sort them in ascending, and then insert characters from message at those spots in the scrambled array.
http://jsbin.com/kuzepujabo/1/edit?js,console
var o = {
array: "zH$#%#$##$#^^##(%*$#^&#!$^%&".split(''),
msg: "this is a message",
randomMsgIndex: function () { return Math.floor(Math.random() * this.msg.length); },
randomMsgChar: function () { return this.msg[this.randomMsgIndex()]; },
//resultingArray: [],
randomArrayIndex: function () { return Math.floor(Math.random() * this.array.length); }
}
for(var i = 0; i < o.msg.length; i++) {
o.array.splice(o.randomArrayIndex(), 0, o.randomMsgChar());
}
console.log(o.array);
I have come up with this - but I assume it is still not what you want - you probably want something that keeps track of which message chars were already added - so not to add them twice - and make sure the entire message (all its characters) were added to the array.
Version 2 with the feature described above:
var o = {
array: "zH$#%#$##$#^^##(%*$#^&#!$^%&".split(''),
msg: "this is a message",
msgArray: function () { this.msg.split(''); },
randomMsgIndex: function () { return Math.floor(Math.random() * this.msg.length); },
randomMsgChar: function (i) { return this.msg[i]; },
//resultingArray: [],
randomArrayIndex: function () { return Math.floor(Math.random() * this.array.length); },
stripStr: function (indexToSkip, originalStr) {
var result = "";
for (var i = 0; i < originalStr.length; i++)
if (indexToSkip != i)
result += originalStr[i];
return result;
}
}
for(var i = 0; i < o.msg.length; i++) {
var msgRandomIndex = o.randomMsgIndex();
o.array.splice(o.randomArrayIndex(), 0, o.randomMsgChar(msgRandomIndex));
o.msg = o.stripStr(msgRandomIndex, o.msg);
}
console.log(o.array);
I think it it is still not a 100%, but moving towards the "optimized" solution :-)