확률 론적 해결 방법을 찾지 못한 후에 올바른 결과를 이끌어 낼 수있는 무차별 대입 방식을 생각해 냈습니다. 일부 문자열의 경우 전체 상태 공간이 매우 크지 만 결국 알고리즘이 수렴 할 것입니다.
아마도 가장 효율적인 솔루션은 아니지만 트릭을 수행하는 것 같습니다. 아래의 코드는 상당히 최적화 될 수 있지만 예제로 충분해야합니다.
#include <iostream>
#include <set>
#include <functional>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_int_distribution.hpp>
// the input string for the random generator
static const std::string input("hello_world");
// an "empty" character (something not present in the input string)
static const char empty = '?';
// a constant with the input length (the only known fact about the input in the algorithm)
static const unsigned length = input.length();
// randomization algorithm returning triplets
std::string randomTriplet() {
static boost::random::mt19937 gen;
static boost::random::uniform_int_distribution<> dist(0, input.length()-1);
std::set<unsigned> indices;
while(indices.size() < 3)
indices.insert(dist(gen));
std::string result;
for(auto i : indices)
result.push_back(input[i]);
return result;
}
// runs a functor for all possible combinations of input triplet acc to the rules
void allCombinations(const std::string& triplet, const std::function<void(const std::string&)>& functor) {
for(unsigned a=0;a<length-2;++a)
for(unsigned b=a+1;b<length-1;++b)
for(unsigned c=b+1;c<length;++c) {
std::string tmp(length, empty);
tmp[a] = triplet[0];
tmp[b] = triplet[1];
tmp[c] = triplet[2];
functor(tmp);
}
}
// tries to merge two strings, and returns an empty string if it is not possible
std::string putTogether(const std::string& first, const std::string& second) {
std::string result(length, empty);
for(unsigned a=0;a<length;++a)
if((first[a] == empty) || (first[a] == second[a]))
result[a] = second[a];
else if(second[a] == empty)
result[a] = first[a];
else if(first[a] != second[a])
return std::string();
return result;
}
// run a single iteration on a set of input states and a triplet
std::set<std::string> iterate(const std::set<std::string>& states, const std::string& triplet) {
std::set<std::string> result;
// try all combinations on all states
for(auto& s : states) {
allCombinations(triplet, [&](const std::string& val) {
// and if merge is possible, insert it into the result
const std::string together = putTogether(s, val);
if(!together.empty())
result.insert(together);
});
};
return result;
}
int main(int argc, char*argv[]) {
// the current state space (all possible strings given the observations so far)
std::set<std::string> states;
// initialisation - take the first triplet and generate all combinations of this triplet
allCombinations(randomTriplet(), [&](const std::string& val) { states.insert(val); });
// iterate - the number of iterations is rather arbitrary. We cannot stop when the solution
// count is 1, because some input strings (like "hello world", where the double l and o
// are the problem) don't have a unique solution
for(unsigned a=0;a<10000;++a) {
states = iterate(states, randomTriplet());
std::cout << "\r" << "iteration #" << a << ", combinations count = " << states.size() << " " << std::flush;
// however, if we do find a single solution, we don't have to go on
if(states.size() == 1)
break;
}
std::cout << std::endl;
// print them all
for(const auto& i : states)
std::cout << i << std::endl;
return 0;
}
흥미롭게 "인 Hello_World"입력, 출력은 :
iteration #9999, combinations count = 6
hello_world
helol_world
hlelo_world
hleol_world
lhelo_world
lheol_world
트리플 'L'더블 'O'캐릭터 관찰 방법을 통해서만 결정될 수 모호성을 제조 세자를 가진.
Java 또는 C++을 사용하고 있습니까? – APerson
둘 다 할 것이지만 Java를 선호합니다. – Shatazone