Ответ 1
В статье статьи из комментария Карстена Erdös и Rényi показывают пример того, как проблема может быть сформулирована как поиск наименьшего числа тестовых последовательностей которые вместе могут генерировать уникальный хеш для неизвестной последовательности. Поскольку в их примере показана последовательность, состоящая из пяти цифр, которые были решены четырьмя тестами, я попытался выработать сублинейное число тестов для последовательностей длиной шесть и семь.
Взглянув на пример Эрдеша и Рэнни и вдохновленный упоминанием Иоанни "разделяй и побеждай", я подумал, что, пожалуй, тестовые последовательности делятся, а затем подразделяют последовательность. Потребовалось несколько попыток получить рабочие тесты для длины последовательности семь.
Возможно, один из способов подумать о запрошенном вами алгоритме может быть способом обобщения/автоматизации генерации этих тестовых последовательностей.
В приведенной ниже программе JavaScript сравниваются тестовые последовательности со всеми последовательностями заданной длины, хешируя количество совпадающих цифр. Если две разные последовательности генерируют один и тот же хэш, программа сообщает, что совпадение найдено, что означает, что эта комбинация тестов не будет работать. Если совпадение не найдено, это означает, что хеши уникальны и тесты должны работать.
// http://resnet.uoregon.edu/~gurney_j/jmpc/bitwise.html
function setBits(i)
{
i = i - ((i >> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}
// http://stackoverflow.com/questions/10073699/pad-a-number-with-leading-zeros-in-javascript
function pad(n, width, z) {
z = z || '0';
n = n + '';
return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
}
function numCoincidences(a,b){
var n = 0
for (var i=0; i<a.length; i++){
if (a.charAt(i) == b.charAt(i)){
n ++
}
}
return n
}
var sequenceLength = 6
var tests = [
"111111",
"111000",
"010010",
"011001",
"000100"
]
/***
var sequenceLength = 7
var tests = [
"1111111",
"1111000",
"0100100",
"0110010",
"0110001",
"0001000"
]
***/
var hash = {}
console.log(" " + tests.join(" "))
for (var i=0; i<1<<sequenceLength; i++){
if (setBits(i) < Math.floor(sequenceLength / 2)){
var tmp = pad(i.toString(2),sequenceLength)
var h = ""
for (var j in tests){
h += numCoincidences(tests[j],tmp)
}
console.log(tmp + " " + h.split("").join(" "))
if (hash[h]){
console.log("found match")
} else {
hash[h] = true
}
}
}
console.log("done")
Вывод:
" 111111 111000 010010 011001 000100" <-- test sequences
"000000 0 3 4 3 5"
"000001 1 2 3 4 4" <-- sequences to match, followed by
"000010 1 2 5 2 4" the number of coincidences
"000011 2 1 4 3 3"
"000100 1 2 3 2 6"
"000101 2 1 2 3 5"
"000110 2 1 4 1 5"
"000111 3 0 3 2 4"
"001000 1 4 3 4 4"
"001001 2 3 2 5 3"
"001010 2 3 4 3 3"
"001011 3 2 3 4 2"
"001100 2 3 2 3 5"
"001101 3 2 1 4 4"
"001110 3 2 3 2 4"
"010000 1 4 5 4 4"
"010001 2 3 4 5 3"
"010010 2 3 6 3 3"
"010011 3 2 5 4 2"
"010100 2 3 4 3 5"
"010101 3 2 3 4 4"
"010110 3 2 5 2 4"
"011000 2 5 4 5 3"
"011001 3 4 3 6 2"
"011010 3 4 5 4 2"
"011100 3 4 3 4 4"
"100000 1 4 3 2 4"
"100001 2 3 2 3 3"
"100010 2 3 4 1 3"
"100011 3 2 3 2 2"
"100100 2 3 2 1 5"
"100101 3 2 1 2 4"
"100110 3 2 3 0 4"
"101000 2 5 2 3 3"
"101001 3 4 1 4 2"
"101010 3 4 3 2 2"
"101100 3 4 1 2 4"
"110000 2 5 4 3 3"
"110001 3 4 3 4 2"
"110010 3 4 5 2 2"
"110100 3 4 3 2 4"
"111000 3 6 3 4 2"
"done"