Given a vector of bits v
, compute the collection of bits that have Hamming distance 1 with v
, then with distance 2, up to an input parameter t
.
So for
011 I should get
~~~
111
001
010
~~~ -> 3 choose 1 in number
101
000
110
~~~ -> 3 choose 2
100
~~~ -> 3 choose 3
How to efficiently compute this? The vector won't be always of dimension 3, e.g. it could be 6. This will run numerous time in my real code, so some efficiency would be welcome as well (even by paying more memory).
My attempt:
#include <iostream>
#include <vector>
void print(const std::vector<char>& v, const int idx, const char new_bit)
{
for(size_t i = 0; i < v.size(); ++i)
if(i != idx)
std::cout << (int)v[i] << " ";
else
std::cout << (int)new_bit << " ";
std::cout << std::endl;
}
void find_near_hamming_dist(const std::vector<char>& v, const int t)
{
// if t == 1
for(size_t i = 0; i < v.size(); ++i)
{
print(v, i, v[i] ^ 1);
}
// I would like to produce t == 2
// only after ALL the t == 1 results are reported
/* how to? */
}
int main()
{
std::vector<char> v = {0, 1, 1};
find_near_hamming_dist(v, 1);
return 0;
}
Output:
MacBook-Pro:hammingDist gsamaras$ g++ -Wall -std=c++0x hammingDist.cpp -o ham
MacBook-Pro:hammingDist gsamaras$ ./ham
1 1 1
0 0 1
0 1 0
#include <stdio.h>
#include <stdint.h>
#include <string.h>
void magic(char* str, int i, int changesLeft) {
if (changesLeft == 0) {
printf("%s\n", str);
return;
}
if (i < 0) return;
// flip current bit
str[i] = str[i] == '0' ? '1' : '0';
magic(str, i-1, changesLeft-1);
// or don't flip it (flip it again to undo)
str[i] = str[i] == '0' ? '1' : '0';
magic(str, i-1, changesLeft);
}
int main(void) {
char str[] = "011";
printf("%s\n", str);
size_t len = strlen(str);
size_t maxDistance = len;
for (size_t i = 1 ; i <= maxDistance ; ++i) {
printf("Computing for distance %d\n", i);
magic(str, len-1, i);
printf("----------------\n");
}
return 0;
}
Output:
MacBook-Pro:hammingDist gsamaras$ nano kastrinis.cpp
MacBook-Pro:hammingDist gsamaras$ g++ -Wall kastrinis.cpp
MacBook-Pro:hammingDist gsamaras$ ./a.out
011
Computing for distance 1
010
001
111
----------------
Computing for distance 2
000
110
101
----------------
Computing for distance 3
100
----------------
First: There is a bijection between hamming dist k bit-vectors and subsets (of n aka v.size()
) of kardinality k (the set of indices with changed bits). Hence, I'd enumerate the subsets of changed indices instead. A quick glance at the SO history shows this reference. You'd have to keep track of the correct cardinalitites of course.
Considering efficiency is probably pointless, since the solution to your problem is exponential anyways.
If Hamming distance h(u, v) = k
, then u^v
has exactly k
bits set. In other words, computing u ^ m
over all masks m
with k
bits set gives all words with the desired Hamming distance. Notice that such set of mask does not depend on u
.
That is, for n
and t
reasonably small, precompute sets of masks with k
bits set, for all k
in 1,t
, and iterate over these sets as required.
If you don't have enough memory, you may generate the k-bit patterns on the fly. See this discussion for details.
In response to Kastrinis' answer, I would like to verify that this can be extended to my basis example, like this:
#include <iostream>
#include <vector>
void print(std::vector<char>&v)
{
for (auto i = v.begin(); i != v.end(); ++i)
std::cout << (int)*i;
std::cout << "\n";
}
void magic(std::vector<char>& str, const int i, const int changesLeft) {
if (changesLeft == 0) {
print(str);
return;
}
if (i < 0) return;
// flip current bit
str[i] ^= 1;
magic(str, i-1, changesLeft-1);
// or don't flip it (flip it again to undo)
str[i] ^= 1;
magic(str, i-1, changesLeft);
}
int main(void) {
std::vector<char> str = {0, 1, 1};
print(str);
size_t len = str.size();
size_t maxDistance = str.size();
for (size_t i = 1 ; i <= maxDistance ; ++i) {
printf("Computing for distance %lu\n", i);
magic(str, len-1, i);
printf("----------------\n");
}
return 0;
}
where the output is identical.
PS - I am also toggling the bit with a different way.
来源:https://stackoverflow.com/questions/40813022/generate-all-sequences-of-bits-within-hamming-distance-t