簡體   English   中英

用於提取密碼破解者列表子集的組合算法

[英]Combinatorics algorithm for extracting subsets of lists for a password cracker

我一定很生銹,因為我無法提出解決方案。

假設我們有3個單詞列表:

list1   list2   list3
-----   -----   -----
pizza   red     child
pasta   green   man
apple   blue    adult
pear    yellow  old

我需要從每個列表中選擇子集,例如:

  • 所有選定部分的總和將返回整個列表中的所有可能組合(例如,披薩紅孩子或披薩紅人)
  • 沒有重復項,因此如果選擇的第1部分包含一個組合,則我不希望任何其他組合包含它
  • 選定的部分需要具有一定的最小大小(定義為元素計數1 *計數2 *等)
  • 我需要最少的選定部分

現在,簡單的解決方案當然是了,比如說您必須將此列表分為4個工人4(我在上面稱為“選定部分”),只需將每個披薩開頭的組合發送給工人1,將意大利面發送給2,依此類推。 但是,如果您的工人比最長的列表中的元素多,那是行不通的,事情會變得復雜。

編輯-示例

這樣就給目標列表,找到所有組合。 但是您需要將主要工作拆分為更多機器。

上面說明的簡單解決方案是,最長的列表中有4個元素,只需使用4台機器即可。 在這種情況下,它看起來像這樣:

機器1:

list1   list2   list3
-----   -----   -----
pizza   red     child
        green   man
        blue    adult
        yellow  old

機器2:

list1   list2   list3
-----   -----   -----
        red     child
pasta   green   man
        blue    adult
        yellow  old

機器3:

list1   list2   list3
-----   -----   -----
        red     child
        green   man
apple   blue    adult
        yellow  old

機器4:

list1   list2   list3
-----   -----   -----
        red     child
        green   man
        blue    adult
pear    yellow  old

但是,如果必須將工作分配到比最長列表中的元素數更多的機器上,則此方法將無效。 在這種情況下,假設您需要將工作拆分為8台機器(或每台機器兩輪中的4台機器),則必須看起來像這樣(我使用8台機器是為了簡化示例,但實際數量並非如此)好)。

機器1:

list1   list2   list3
-----   -----   -----
pizza   red     child
        green   man
                adult
                old

機器2:

list1   list2   list3
-----   -----   -----
        red     child
pasta   green   man
                adult
                old

機器3:

list1   list2   list3
-----   -----   -----
        red     child
        green   man
apple           adult
                old

機器4:

list1   list2   list3
-----   -----   -----
        red     child
        green   man
                adult
pear            old

機器5:

list1   list2   list3
-----   -----   -----
pizza           child
                man
        blue    adult
        yellow  old

機器6:

list1   list2   list3
-----   -----   -----
                child
pasta           man
        blue    adult
        yellow  old

機器7:

list1   list2   list3
-----   -----   -----
                child
                man
apple   blue    adult
        yellow  old

機器8:

list1   list2   list3
-----   -----   -----
                child
                man
        blue    adult
pear    yellow  old

如您所見,這是將最大元素為4的原始列表拆分為8台計算機的方法。 問題是,當您無法控制列表中的計算機數量/元素數量時,如何以編程方式執行此操作?

如果有1個工人,則按順序排列:

pizza red child
pizza red man
pizza red adult
pizza red old
pizza green child
pizza green man
pizza green adult
pizza green old
pizza blue child
pizza blue man
pizza blue adult
pizza blue old
pizza yellow child
pizza yellow man
pizza yellow adult
pizza yellow old
pasta red child
pasta red man
pasta red adult
pasta red old
pasta green child
pasta green man
pasta green adult
pasta green old
pasta blue child
pasta blue man
pasta blue adult
pasta blue old
pasta yellow child
pasta yellow man
pasta yellow adult
pasta yellow old
apple red child
apple red man
apple red adult
apple red old
apple green child
apple green man
apple green adult
apple green old
apple blue child
apple blue man
apple blue adult
apple blue old
apple yellow child
apple yellow man
apple yellow adult
apple yellow old
pear red child
pear red man
pear red adult
pear red old
pear green child
pear green man
pear green adult
pear green old
pear blue child
pear blue man
pear blue adult
pear blue old
pear yellow child
pear yellow man
pear yellow adult
pear yellow old

如果您有更多工人,則按范圍划分。 例如,Worker1獲得“披薩紅色孩子”-“披薩藍色孩子”。 工人2獲得“披薩藍人”-“意大利面紅大人”等

#include <vector>
#include <thread>
#include <cstdio>
using namespace std;

vector<vector<string>> lists = {{"apple", "pasta", "pear", "pizza"}, {"red", "green", "blue", "yellow"}, {"child", "man", "adult", "old"}};
const int K = 7;
long long N = 1;

std::vector<long long>  calc_vector(int k){
    long long remain_all = N;
    long long remain_cur = N * k / K;
    std::vector<long long>  ret;
    for(int i=0; i<lists.size(); ++i){
        long long sz = lists[i].size();
        long long i1 = remain_cur * sz / remain_all;
        ret.push_back(i1);
        remain_all /= sz;
        remain_cur -= remain_all * i1;
    }
    return ret;
}


void work(int k){
    auto v1 = calc_vector(k);
    auto v2 = calc_vector(k+1);
    while(v1 != v2){
        printf("%d: %s-%s-%s\n", k, lists[0][v1[0]].c_str(), lists[1][v1[1]].c_str(), lists[2][v1[2]].c_str());
        for(int i=v1.size()-1; i>=0; --i){
            v1[i]++;
            if(v1[i] != lists[i].size() || i==0) break;
            else v1[i] = 0;
        }
    }
}

int main(){
    for(auto &list : lists) N *= list.size();
    vector<thread> threads;
    for(int i=0; i<K; ++i) threads.push_back(thread(work, i));
    for(auto &thread : threads) thread.join();
    return 0;
}

如果我做對了,也許您可​​以嘗試替換在所選部分中選擇的元素。 例如;

披薩-紅色-兒童

然后;

意大利面-紅色-兒童

等等...

因此,您可以嘗試為每種可能的組合操作一個選定的部分,而不是為每種可能的組合創建新的選定部分。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM