我尝试使用guessed
创建javascript
,这是代码:
<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>
但不幸的是,结果重复了不止一次: 结果:
abb baa
aac
cba cbb aba bbbaac
acb cba ccc bab caa bab cccaac
ccb aba abc bac cbb
这会减慢程序,如何解决这个问题 有解决方案吗? 谢谢
答案 0 :(得分:3)
由于您不想两次检查相同的密码,因此生成随机猜测显然不是正确的方法。正如klumme所提到的,存储一系列先前的猜测只会增加时间和空间的复杂性,因此也是如此。您需要做的是使用强力方法,即尝试每个字符组合,直到您得到正确的答案。以下是如何实现它:
注意:请注意,强力算法通常效率很低,如果您使用原始代码中的完整字母数字字符串来强制使用超过3-4个字符的密码,这将花费大量的时间(特别是在浏览器中)。从本质上讲,JavaScript并不是一种非常强大的数字运算语言 - 所以这个答案更多的是它的概念,而不是在大多数现实环境中使用。
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);
&#13;
答案 1 :(得分:2)
如果我理解正确,问题在于随机密码功能(&#34; makeid&#34;)可能会多次返回相同的密码。这并不奇怪,这个功能没有理由知道已经尝试过哪些密码。您可以跟踪已经尝试过的密码,如果之前已经尝试过,请不要尝试密码(如在用户的答案中),但在这种情况下,它可能不会加快程序的速度。
更好的方法可能是系统地而不是随机地迭代可能的密码。例如,试试&#34; aaa&#34;首先,然后&#34; aab&#34;,&#34; aac&#34; &#34; ABA&#34;等等。
这是我想出来的东西 - 它可能不是很快。我在&#34;可能&#34;中使用了一系列索引。字符串,直到实际尝试密码,因为我不想在路上乱搞indexOf()。
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);
}
答案 2 :(得分:1)
首先,将结果存储在数组中。其次,添加以下条件:if (arr.indexOf(guess) == -1)
- 如果猜测的数字已经在数组中 - 跳过它。
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);
答案 3 :(得分:0)
我对这个问题很感兴趣,并决定用这个机会来了解有关发电机的更多信息。注意:使用ES6语法,因此不一定与所有平台兼容。
我不一定会推荐这个已经实施的其他方法,但它可能是一个很好的未来参考。
/**
* 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.");
}