考虑以下问题http://potw.quinnftw.com/problem/2015/1/
Will最近感到非常孤独。为了帮助自己,他创建了一个约会网站。作为一名计算机科学家,他提出了一种有趣的方法来计算一个人与另一个人的匹配程度。
根据输入的信息,Will将创建一个32位无符号整数,作为人员数据的掩码。为了计算一对夫妇之间的兼容性,Will会检查他们有多少相似的比特。匹配越多,匹配越好。人们也必须记住,对立面吸引人。
您的目标是设计一种算法,以显示具有最高兼容级别和最低兼容级别的对。
总结中的问题是键入一些整数N
,然后输入N
量names
的相应32位无符号整数。
目标是设计一种算法,显示具有最高兼容级别和最低兼容级别的对。
您可以在链接中查看详细信息。这不是一个太多的阅读。
考虑样本输入
5
Danniel 116077289
Bowman 2316887705
Cleveland 2186347654
Marinda 2662238983
Viviana 3393681530
输出
Bowman Cleveland
Marinda Viviana
我很难理解这个问题。是否告诉我根据数字的出现进行匹配?基本上我跟踪一个int中有多少个整数在另一个名称int中是相同的?输出是通过将这对名称与最常见的数字一起使用来实现的吗?然后第二对具有最少的常见数字?
任何洞察我如何理解这个问题都会很好。到目前为止,我对它的印象是简单地匹配两个具有最多出现次数的名称。然而,32位部分令我感到困惑,我不确定这部分是什么意思。
我想用javascript或java来做这件事,但是一旦我完全明白问题是什么,我就不会认为编码太过分了。
谢谢!
考虑其中一个解决方案http://potw.quinnftw.com/solution/17/
我无法理解的部分是for for循环
public static int getScore(long x, long y) {
int score = 0;
for (long i = x ^ y; i > 0; i = i >> 1)
if (i-1 == (i & (i-1)))
score++;
return 32 - score;
}
我很困惑为什么我在这里使用xOR并且每次迭代循环时潜水2次。
答案 0 :(得分:3)
如果你仔细阅读了这个问题,这是一个关于"两个32位数有多少相同位的问题。您必须以二进制形式检查数字(您可以查看每个位)并比较代表每个人特征的数字之间的位。
因此,一个人的号码可能会被表示为
01001101110011010011010100101111
和另一个
01111100010011010011010100010111
要查看它们的匹配程度,您必须查看在相同对应位置的位同时为0
或1
的位中,有多少位具有相同的值。为具有相同值的每个位添加一个匹配分数。
由于这是某种学习练习,我不会只是提供代码,但会指向reference on manipulating bits in Javascript。
事实证明,这个问题有多个阶段:
我的解决方案的输出(尚未链接,因此OP可以自行解决问题):
Visually in Binary
00000110111010110011001011101001 Danniel
10001010000110001110011010011001 Bowman
10000010010100010000010010000110 Cleveland
10011110101011101000101100000111 Marinda
11001010010001110111100001111010 Viviana
All Comparisons (sorted)
Bowman,Cleveland:19
Danniel,Viviana:17
Danniel,Bowman:16
Cleveland,Viviana:16
Danniel,Cleveland:15
Danniel,Marinda:15
Bowman,Marinda:15
Bowman,Viviana:15
Cleveland,Marinda:14
Marinda,Viviana:12
Best Matches
Bowman,Cleveland: 19
Danniel,Viviana: 17
这里有一个提示,用于比较两个数字中给定的位是否相同:
var bitmask = 1; // start with lowest bit
var num1 = 116077289;
var num2 = 2316887705;
if ((num1 & bitmask) === (num2 & bitmask)) {
// the bit represented by bitmask is the same in both numbers
}
下一个提示:如果位掩码为2
,那么您将比较第二位。如果位掩码为4
,则您将第三位8
再与第四位16
,第五位进行比较,依此类推至第32位。添加计数器,您可以计算匹配的位数。
这是一个有效的解决方案:
// function used to make display prettier
function zeroPadLeft(str, len) {
while (str.length < len) {
str = "0" + str;
}
return str;
}
function compareBits(num1, num2) {
// score is the number of matching bits
var score = 0;
// start with first bit
var mask = 1;
// create rotating mask to individually compare each of the lowest 32 bits
for (var i = 0; i < 32; i++) {
// if this bit has the same value, increase the score
if ((num1 & mask) === (num2 & mask)) {
++score;
}
// advance mask to next bit with shift left operator
mask = mask << 1;
}
return score;
}
// input data
var data = [
{name:"Danniel", value:116077289},
{name:"Bowman", value:2316887705},
{name:"Cleveland", value:2186347654},
{name:"Marinda", value:2662238982},
{name:"Viviana", value:3393681530}
];
// show the starting data in binary so we can see a visual representation of the actual bits
log("<b>Visually in Binary</b>");
data.forEach(function (item) {
log(zeroPadLeft(item.value.toString(2), 32) + " " + item.name);
});
// record the score of all possible combinations in the scores array of objects
log("<hr>");
log("<b>All Comparisons</b>");
var scores = [];
for (var j = 0; j < data.length; j++) {
for (var k = j + 1; k < data.length; k++) {
var score = compareBits(data[j].value, data[k].value);
// record the score and two names as an object inserted into an array
scores.push({
name1: data[j].name,
name2: data[k].name,
score: score
})
}
}
// sort by best score to make it easier to find the highest score
scores.sort(function (a, b) {
return b.score - a.score;
});
// output sorted scores so we can see them visually
scores.forEach(function (item) {
log(item.name1 + "," + item.name2 + ":" + item.score);
});
// now find the top scores with no person repeated
log("<hr>");
log("<b>Best Matches</b>");
// namesUsed keeps track of which names have already found a high score so we don't use them again
var namesUsed = {};
while (scores.length > 0) {
var bestItem = scores.shift();
// if either of these names has already been used, then skip this score
if (namesUsed[bestItem.name1] || namesUsed[bestItem.name2]) {
continue;
}
log(bestItem.name1 + "," + bestItem.name2 + ": " + bestItem.score);
namesUsed[bestItem.name1] = true;
namesUsed[bestItem.name2] = true;
}
&#13;
body {font-family: "Courier New";}
&#13;
<script src="http://files.the-friend-family.com/log.js"></script>
&#13;
比较位的说明
关键部分是计算两个数字相同的位:
function compareBits(num1, num2) {
// score is the number of matching bits
var score = 0;
// start with first bit
var mask = 1;
// create rotating mask to individually compare each of the lowest 32 bits
for (var i = 0; i < 32; i++) {
// if this bit has the same value, increase the score
if ((num1 & mask) === (num2 & mask)) {
++score;
}
// advance mask to next bit with shift left operator
mask = mask << 1;
}
return score;
}
这是我认为最简单的理解实现(不是最快的)。基本上它的作用是定义一个初始值为1
的掩码号。当我们使用每个值逻辑和掩码编号时,我们在每个数字中隔离一个位。然后我们可以比较剩余的单个位以查看它们是否相等。如果是这样,请提高分数。然后,将掩模向左移动一个位置,以便我们可以查看下一个位。重复32次,我们比较了32位中的每一位,计算了多少具有相同的值。
如果你想看看钝操作是如何得到的,这里有一个非常快速的算法Hamming weight implementation:
function countSimilarBitsHamming(num1, num2) {
// xor sets a bit to 0 if both are the same and 1 if different
// so if we xor and then negate, we get bits that are the same
var sameBits = ((~(num1 ^ num2)) & 0xFFFFFFFF) >>> 0;
sameBits = sameBits - ((sameBits >> 1) & 0x55555555);
sameBits = (sameBits & 0x33333333) + ((sameBits >> 2) & 0x33333333);
return (((sameBits + (sameBits >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}
这是一个更慢的实现,但位计数部分是一个简单的字符串计数:
function countBitsString(num1, num2) {
// xor sets a bit to 0 if both are the same and 1 if different
// so if we xor and then negate, we get bits that are the same
var sameBits = ((~(num1 ^ num2)) & 0xFFFFFFFF) >>> 0;
var str = sameBits.toString(2).replace(/0/g, "");
return str.length;
}
步骤:
0
的结果,如果它们的值不同,则生成1
。~
运算符来否定它。现在,只要两个数字具有相同的位,我们就有1
。0
移位值为>>> 0
,这将清除签署位。1
s,所以只需查看字符串的长度以及字符串中1
的位置。答案 1 :(得分:1)
&#34;位&#34;是&#34;二进制数字&#34;的缩写。因此,32位整数是一个整数,可以使用32位二进制数字表示。一个&#34;未签名&#34;整数不能为负数,因此使用普通二进制存储而不是使用two's complement。
在二进制文件中,输入可能更有意义。
Danniel 00000110111010110011001011101001
Bowman 10001010000110001110011010011001
Cleveland 10000010010100010000010010000110
Marinda 10011110101011101000101100000111
Viviana 11001010010001110111100001111010
根据问题,兼容性通过相同位数来衡量。因此,您可以使用按位运算符&
。按位AND通过逐位比较来组合两个数字。如果两个位都相同,则会在结果中放置1
。如果两个位都不同,则会在结果中放置0
。
例如,&
将Danniel与Bowman进行比较。
Danniel 00000110111010110011001011101001
Bowman 10001010000110001110011010011001
Result: 01110011000011000010101110001111
要找到最兼容的情侣,请找到&
导致最多 1
的情侣。
要找到最少兼容的情侣,请找到&
导致最少 1
的情侣。
答案 2 :(得分:0)
在打我的头5小时之后
function compareBit(num1,num2)
{
var mask = 1;
var count = 0;
for(var i = 0; i<32;i++)
{
if((num1&mask) === (num2&mask))
{
++count;
}
mask = mask << 1;
}
return count;
}
var obj = [];
var number = prompt("Enter how many names and id's you will put");
for(var i = 0 ; i<number ; i++)
{
query = prompt("Enter name then id, you must put one space in between");
query_result = query.split(" ");
obj.push({name:query_result[0],value:query_result[1]});
}
var scores = [];
for (var a = 0 ; a<obj.length ; a++){
for(var b = a+1 ; b<obj.length ; b++){
var score = compareBit(obj[a].value,obj[b].value);
scores.push({name1:obj[a].name,name2:obj[b].name,score:score})
}
}
var max = scores.reduce(function(prev,current){
return (prev.score > current.score) ? prev : current;
});
var min = scores.reduce(function(prev,current){
return (prev.score < current.score) ? prev : current;
});
console.log(max.name1+ " " + max.name2);
console.log(min.name1+ " " + min.name2);