将字母字符串转换为数字并递归求和,使它们低于某个最大值
Convert an alphabetic string into digits and recursively sum them so they're below a certain max
这是一个算术难题给你StackOverflowers。我正在制作一款JS游戏,允许玩家输入自己的名字,并根据他们输入的内容生成另一个名字。有点像这样。基本上,每次有人输入一个特定的字符串时,我都希望通过从列表中获取项来生成相同的其他字符串。
我有一个单词数组,在这个例子中编号为20
"nouns": [
"Nitwit",
"Cretin",
"Village Idiot"
// ..
]
当用户输入他们的名字时,我将每个ASCII字母字符转换为一个数字。我将把所有结果的数字加起来,并使用总数从数组中选择一个单词。
// Convert alpha chars to numerical equivalents
function str2num (mystr) {
mystr = mystr.toUpperCase();
var conv = [],
l = mystr.length,
regex = /^[A-Za-z]+$/;
for (var i = 0; i < l; i++) {
if (regex.test(mystr.charAt(i))) {
conv.push(mystr.charCodeAt(i) - 64);
}
}
var c = conv.length,
sum = 0;
for (var j = 0; j < c; j++) {
sum += conv[j];
}
return sumDigits(sum);
}
由于单词数组中只有20个元素,所以我总是希望总和小于20。如果它等于或大于20,我要把它的数字加起来。这是我目前正在做的。
// Recursively add digits of number together
// till the total is less than length of word list
function sumDigits (number) {
var listLength = adjectives.length;
var sum = number % listLength;
if (number > listLength) {
var remainder = Math.floor(number / 10);
sum += sumDigits(remainder);
}
if (sum > listLength) {
sum = sumDigits(sum);
}
return sum;
}
当我得到的结果低于20时,我将nouns[sum]
的值返回给用户。这段代码非常有效——得到的总和总是低于允许的最大值。但结果并不是很随机——似乎我得到的和在0到20范围的下端不成比例。我不希望用户总是看到列表开头的单词。我是否可以对sumDigits进行任何更改,以确保结果的均匀分布?还是已经正确了?(我做这个JSFiddle是为了演示我所说的内容)
我会让它依赖于名称中字符的字符码:
function getValue(name) {
var letters = name.toLowerCase().split(''),
value = 0,
i = 0;
for(; i < letters.length; i ++) {
value += letters[i].charCodeAt(0);
}
return value % 20;
}
当前实现中的输出和确实是不是均匀分布的。
作为一个例子,考虑所有有一个或两个数字的数字(1 - 99):
1 of them is summed up to 1 ( 1)
2 of them are summed up to 2 ( 2, 20)
3 of them are summed up to 3 ( 3, 30, 21)
4 of them are summed up to 4 ( 4, 40, 31, 22)
5 of them are summed up to 5 ( 5, 50, 41, 32, 23)
6 of them are summed up to 6 ( 6, 60, 51, 42, 33, 24)
7 of them are summed up to 7 ( 7, 70, 61, 52, 43, 34, 25)
8 of them are summed up to 8 ( 8, 80, 71, 62, 53, 44, 35, 26)
9 of them are summed up to 9 ( 9, 90, 81, 72, 63, 54, 45, 36, 27)
9 of them are summed up to 10 (10, 91, 82, 73, 64, 55, 46, 37, 28)
9 of them are summed up to 11 (11, 92, 83, 74, 65, 56, 47, 38, 29)
8 of them are summed up to 12 (12, 93, 84, 75, 66, 57, 48, 39)
7 of them are summed up to 13 (13, 94, 85, 76, 67, 58, 49)
6 of them are summed up to 14 (14, 95, 86, 77, 68, 59)
5 of them are summed up to 15 (15, 96, 87, 78, 69)
4 of them are summed up to 16 (16, 97, 88, 79)
3 of them are summed up to 17 (17, 98, 89)
2 of them are summed up to 18 (18, 99)
1 of them is summed up to 19 (19)
这可能更接近正态分布而不是均匀分布。
为了实现后者,只需返回sum % c
而不是sumDigits(sum)
。
我认为sumDigits
函数返回一个有偏的数。不返回sumDigits(sum)
。您可以返回sum % 20
。
fzzle的回答很好。
或者,您可以使用while进行求和约简:
var reduced = sum;
while(reduced > 20){
reduced -= name.length;
}
这是一个更完整的例子:
var sum = 0;
var name = 'John Smith'.split('');
for(var k in name){
sum += name[k].charCodeAt(0);
}
var key = sum;
while(key > 20){
key -= 'John Smith'.length;
}
如果你测试它,你会看到它产生了不同的结果sumDigits % 20
。请注意,我不知道对于异常长的名称,这个方法将如何表现。让我测试一下。
确认。XD我尝试了John Smith John Smith John Smith John Smithxx
,打破了它。不要认为这是一个答案。(
- 在Javascript数组中查找绝对最大值
- Html5输入属性的默认值,如最小值、最大值、大小等
- 按最大值获取数组索引
- 识别滑块范围的最小值和最大值
- 如何在最大值之前的某个点停止范围滑块
- 访问Highcharts系列的最小/最大值:afterSetExtremes不会激发
- 如何在拖动后获得图表的最小值和最大值放大高图表
- AngularJs:在数字输入字段中设置验证的条件最小值和最大值
- HTML5范围滑块最小值和最大值
- 如何仅在存在最小值和最大值时才显示错误消息
- 在 JavaScript 事件中添加最小值和最大值
- 从 JavaScript 中的数组中获取最大值和最小值
- 获取整数对象属性名称的最小值和最大值
- 高图表 - 在缩放重置中设置最大值和最小值
- Java 脚本 设置日期的最小值和最大值属性
- 使用javascript动态更改select中的最大值
- 如何设置jQuery微调器的最大值和最小值
- 当达到最小值和最大值时,防止在输入中显示额外的文本
- 使用函数从数组中查找最小值和最大值
- 将字母字符串转换为数字并递归求和,使它们低于某个最大值