Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 密码算法求解器分解的效率_C_Algorithm_Solver_Decomposition_Cryptarithmetic Puzzle - Fatal编程技术网

C 密码算法求解器分解的效率

C 密码算法求解器分解的效率,c,algorithm,solver,decomposition,cryptarithmetic-puzzle,C,Algorithm,Solver,Decomposition,Cryptarithmetic Puzzle,问题如下:给定“ABC+DEF=GHI”格式字符串,其中A、B、C等表示唯一数字,请找到给出最大GHI的表达式。例如:输入字符串是AAB+AAB=AAB,则没有解决方案。如果改为AAA+BBB=AAA,则解决方案为999+000=999。另一个示例字符串:ABC+CBA=GGG,结果是=>543+345=888 我很容易就排除了不可能的情况。我心目中的算法是一种蛮力算法,它只是首先尝试最大化rhs。然而,我的问题是做得这么快,而且还要注意唯一的数字。解决这个问题的有效方法是什么 注意:我希望用单

问题如下:给定“ABC+DEF=GHI”格式字符串,其中A、B、C等表示唯一数字,请找到给出最大GHI的表达式。例如:输入字符串是AAB+AAB=AAB,则没有解决方案。如果改为AAA+BBB=AAA,则解决方案为999+000=999。另一个示例字符串:ABC+CBA=GGG,结果是=>543+345=888

我很容易就排除了不可能的情况。我心目中的算法是一种蛮力算法,它只是首先尝试最大化rhs。然而,我的问题是做得这么快,而且还要注意唯一的数字。解决这个问题的有效方法是什么

注意:我希望用单线程方法解决这个问题,我当前的问题是检测“赋值”函数中是否使用了唯一的数字。也许有更好的赋值方法

编辑:根据smci的建议,以下是我最终想要实现的目标:ABRA+CADABRA+ABRA+CADABRA==HOUDINI;7457+1797457+7457+1797457==3609828——这个系统不仅可以处理开头提供的形式I的字符串(3位数字+3位数字=3位数字),还可以处理这些字符串。不过,从简单开始,采用我给出的格式解决方案并没有什么坏处:)

#包括
#包括
#包括
#定义最大表达式大小11+1
#定义MAX_变量9
int variables_read[MAX_variables]={0};
结构变量{
int系数;
int*ptr;
内侧;
int-canhavezero;
无符号值_max;
};
typedef结构变量;
结构方程{
变量*变量[9];//最大值
右上的未签名的非重复字符;
无符号var_计数;
};
类型定义结构方程;
内部动力(内部n,内部k){
int res=1;
对于(int i=0;i变量[E->var_count++]=V;
}
int不可能(字符*表达式){
//如果所有字母相同或结尾字母相同,则没有解决方案
如果(
(表达式[0]==表达式[4]&表达式[0]==表达式[8])||
(!strncmp(表达式,表达式+4,3)和&!strncmp(表达式,表达式+8,3))
)
返回1;
返回0;
}
int赋值(等式*E,int pos,int*值){
如果(!E->变量[pos]->值\u计数){
如果(位置<0)
返回2;
//如果没有可能的值,则重置此值,但从最近的变量中获取一个值计数
E->变量[pos-1]->值_计数--;
E->variables[pos]->value\u count=E->variables[pos]->value\u max;
返回0;
}
int i;
对于(i=9;i>=0&&value[i]=-1;--i)
printf(“将%d分配给%c\n”,E->variables[pos]->value_set[E->variables[pos]->value_count-1],'A'+(E->variables[pos]->ptr-E->variables[0]->ptr));
*(E->变量[pos]->ptr)=值[i];
值[i]=-1;//我们有唯一的数字
返回0;
}
int(方程E){
整数和=0,系数=0;
printf(“正在尝试…\n”);
对于(int i=0;i系数*(*E.变量[i]->ptr);
printf(“%d”,*E.variables[i]->ptr);
if(如变量[i]->侧)
系数*=-1;
总和+=系数;
}
printf(“\nSum为%d\n”,总和);
返回!求和;
}
char*计算(char*表达式){
字符*res;
//首先检查不可能的情况
if(不可能(表达式)){
res=(char*)malloc(sizeof(char)*strlen(“没有解决方案”);
strcpy(res,“没有解决方案!”);
返回res;
}
res=(char*)malloc(sizeof(char)*最大表达式大小);
//现在试着寻找解决方案,首先将给定的字符描述为方程
方程E;
E.var_计数=0;
E.rhs=0上的不同_;
int侧_模式=0,功率计数器=0;
int a=-1,b=-1,c=-1,d=-1,e=-1,f=-1,g=-1,h=-1,i=-1;
int*max_variables[max_variables]={&a、&b、&c、&d、&e、&f、&g、&h、&i};
对于(int j=0;j系数=int_功率(10,2-(功率计数器%3));
V->ptr=max_变量[表达式[j]-'A'];
V->side=side\u模式;
E.distinct_on_rhs+=侧边_模式&!变量_读取[expression[j]-'A'];
如果(!(powcounter%3)){//数字的开头
V->value\u count=9;
V->value_max=9;
V->canhavezero=0;
}
否则{
V->value\u count=10;
V->value_max=10;
V->canhavezero=1;
}
添加变量(&E,V);
变量_read[表达式[j]-'A']=1;
++功率计数器;
}
对于(int j=0;j系数,'A'+(E.variables[j]->ptr-max_variables[0]),E.variables[j]->side);
//我们得到了方程的一个表示形式,现在试着去解它
int=0;
//O(9^N),其中N是不同变量的数量。
//我们可以做的一个优化是,我们首先将可能的最大值分配给rhs编号,然后向下。我们需要最大值。
printf(“Distincts:%d\n”,例如在右上的Distincts\u);
做{
//尝试将值分配给所有变量,并尝试是否解决了该方程
//但首先要尽可能地分配rhs最大值
int值[10]={0,1,2,3,4,5,6,7,8,9};
int temp=E.var\u count-E.distinct\u on\u rhs;
同时(温度=0;--j)
已解决=分配_值(&E,j,值);
if(solved)//不能返回任何解决方案
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_EXPRESSION_SIZE 11 + 1
#define MAX_VARIABLES 9

int variables_read[MAX_VARIABLES] = { 0 };

struct variable {
    int coefficient;
    int* ptr;
    int side;
    int canhavezero;
    unsigned value_max;
};

typedef struct variable Variable;

struct equation {
    Variable* variables[9]; // max
    unsigned distinct_on_rhs;
    unsigned var_count;
};

typedef struct equation Equation;

int int_pow(int n, int k) {
    int res = 1;
    for(int i = 0; i < k; ++i)
        res *= n;
    return res;
}

void AddVariable(Equation* E, Variable* V) {
    E->variables[E->var_count++] = V;
}

int IsImpossible(char* expression) {
    // if all letters are same or end letters are same, no solution
    if(
        (expression[0] == expression[4] && expression[0] == expression[8]) ||
        (!strncmp(expression, expression + 4, 3) && !strncmp(expression, expression + 8, 3))
      )
        return 1;
    return 0;
}

int assign_value(Equation* E, int pos, int* values) {
    if(!E->variables[pos]->value_count) {
        if(pos < 0)
            return 2;
        // if no possible values left, reset this, but take one value count from the closest variable
        E->variables[pos - 1]->value_count--;
        E->variables[pos]->value_count = E->variables[pos]->value_max;
        return 0;
    }
    int i;
    for(i = 9; i >= 0 && values[i] == -1; --i)
    printf("Assigning %d to %c\n", E->variables[pos]->value_set[E->variables[pos]->value_count - 1], 'A' + (E->variables[pos]->ptr - E->variables[0]->ptr));
    *(E->variables[pos]->ptr) = values[i];
    values[i] = -1; // we have unique numbers
    return 0;
}

int isSolved(Equation E) {
    int sum = 0, coeff = 0;
    printf("Trying...\n");
    for(int i = 0; i < E.var_count; ++i) {
        coeff = E.variables[i]->coefficient * (*E.variables[i]->ptr);
        printf("%d ", *E.variables[i]->ptr);
        if(E.variables[i]->side)
            coeff *= -1;
        sum += coeff;
    }
    printf("\nSum was %d\n", sum);
    return !sum;
}

char* evaluate(char* expression) {
    char* res;
    // check for impossible cases first
    if(IsImpossible(expression)) {
        res = (char *) malloc(sizeof(char) * strlen("No Solution!"));
        strcpy(res, "No Solution!");
        return res;
    }
    res = (char *) malloc(sizeof(char) * MAX_EXPRESSION_SIZE);
    // now try to find solutions, first describe the given characters as equations
    Equation E;
    E.var_count = 0;
    E.distinct_on_rhs = 0;
    int side_mode = 0, powcounter = 0;
    int a = -1, b = -1, c = -1, d = -1, e = -1, f = -1, g = -1, h = -1, i = -1;
    int* max_variables[MAX_VARIABLES] = { &a, &b, &c, &d, &e, &f, &g, &h, &i };
    for(int j = 0; j < MAX_EXPRESSION_SIZE - 1; ++j) {
        if(expression[j] == '+')
            continue;
        if(expression[j] == '=') {
            side_mode = 1;
            continue;
        }
        Variable* V = (Variable *) malloc(sizeof(Variable));
        // we know we always get 3 digit numbers but we can easily change if we need to
        V->coefficient = int_pow(10, 2 - (powcounter % 3));
        V->ptr = max_variables[expression[j] - 'A'];
        V->side = side_mode;
        E.distinct_on_rhs += side_mode && !variables_read[expression[j] - 'A'];
        if(!(powcounter % 3)) { // beginning of a number
            V->value_count = 9;
            V->value_max = 9;
            V->canhavezero = 0;
        }
        else {
            V->value_count = 10;
            V->value_max = 10;
            V->canhavezero = 1;
        }
        AddVariable(&E, V);
        variables_read[expression[j] - 'A'] = 1;
        ++powcounter;
    }
    for(int j = 0; j < E.var_count; ++j)
        printf("%d %c %d\n", E.variables[j]->coefficient, 'A' + (E.variables[j]->ptr - max_variables[0]), E.variables[j]->side);
    // we got a representaion of the equation, now try to solve it
    int solved = 0;
    // O(9^N), where N is number of distinct variables.
    // An optimization we can do is, we first assign possible max values to rhs number, then go down. We need max number.
    printf("Distincts: %d\n", E.distinct_on_rhs);
    do {
        // try to assign values to all variables and try if it solves the equation
        // but first try to assign rhs as max as possible
        int values[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        int temp = E.var_count - E.distinct_on_rhs;
        while(temp < E.var_count) {
            solved = assign_value(&E, temp, values);
            ++temp;
        }
        for(int j = E.var_count - 1 - E.distinct_on_rhs; j >= 0; --j)
            solved = assign_value(&E, j, values);
        if(solved) // can return no solution
            break;
        printf("Solving...\n");
        solved = isSolved(E);
        system("PAUSE");
    } while(!solved);
    if(solved == 2) {
        res = (char *) malloc(sizeof(char) * strlen("No Solution!"));
        strcpy(res, "No Solution!");
    }
    else {

    }
    return res;
}

int main() {
    char expression[MAX_EXPRESSION_SIZE] = { 0 };
    do {
        printf("Enter the formula: ");
        scanf("%s", expression);
        char* res = evaluate(expression);
        printf("%s\n", res);
        free(res);
    } while(expression[0] != '-');
    return 0;
}
unsigned long long count = 0;
unsigned long long sol = 0;

void evaluate(int object[]) {
  count++;
  int ABC = object[0] * 100 + object[1] * 10 + object[2];
  int DEF = object[3] * 100 + object[4] * 10 + object[5];
  int GHI = object[6] * 100 + object[7] * 10 + object[8];
  if (ABC + DEF == GHI) {
    printf("%4llu %03d + %03d = %03d\n", ++sol, ABC,DEF,GHI);
  }
}

void form_combos(int pool[], size_t pool_count, int object[],
    size_t object_count, size_t object_count_max) {
  if (object_count >= object_count_max) {
    evaluate(object);
    return;
  }
  assert(pool_count > 0);
  int *pool_end = pool + pool_count - 1;
  for (size_t p = 0; p < pool_count; p++) {
    int sample = pool[p];  // take one out
    pool[p] = *pool_end;   // replace it with the end
    object[object_count] = sample;
    form_combos(pool, pool_count - 1, object, object_count + 1,
        object_count_max);
    pool[p] = sample;      // restore pool item
  }
}

int main() {
  int pool[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  size_t pool_size = sizeof pool / sizeof pool[0];
  #define object_count 9
  int object[object_count];
  form_combos(pool, pool_size, object, 0, object_count);
  printf("Evaluate() iterations %llu\n", count);
}
   1 091 + 762 = 853
   2 091 + 763 = 854
   3 091 + 735 = 826
...
1726 874 + 061 = 935
1727 875 + 046 = 921
1728 876 + 045 = 921
Evaluate() iterations 3628800
ABC*ABC + DEF*DEF == GHI*GHI
  if (ABC*ABC + DEF*DEF == GHI*GHI) {
    printf("%4llu sqr(%03d) + sqr(%03d) = sqr(%03d)\n", ++sol, ABC,DEF,GHI);
  }
   1 sqr(534) + sqr(712) = sqr(890)
   2 sqr(546) + sqr(728) = sqr(910)
   3 sqr(712) + sqr(534) = sqr(890)
   4 sqr(728) + sqr(546) = sqr(910)
Evaluate() iterations 3628800
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_DIGITS 10
#define MAX_VARIABLES 9
#define MAX_EXPRESSION_SIZE 11

int IsImpossible(char* expression) {
    // if all letters are same or end letters are same, no solution
    if(
        (expression[0] == expression[4] && expression[0] == expression[8]) ||
        (!strncmp(expression, expression + 4, 3) && !strncmp(expression, expression + 8, 3))
      )
        return 1;
    return 0;
}

int ArePointersAssigned(int*** pointers) {
    for(int i = 0; i < MAX_VARIABLES; ++i) {
        if(**pointers[i] == -1)
            return 0;
    }
    return 1;
}

int evaluate(int*** pointers) {
    int ABC = *(*pointers[0]) * 100 + *(*pointers[1]) * 10 + *(*pointers[2]);
    int DEF = *(*pointers[3]) * 100 + *(*pointers[4]) * 10 + *(*pointers[5]);
    int GHI = *(*pointers[6]) * 100 + *(*pointers[7]) * 10 + *(*pointers[8]);
    if (ABC + DEF == GHI) { // since we use dfs, if this is a solution simply return it
        //printf("%d + %d = %d\n", ABC, DEF, GHI);
        return 1;
    }
    return 0;
}

// use the solved pointer to escape recursion early
// check_end checks if we reached 6 for the 2nd time, if it's first time we ignore (because it's start state)
void form_combos(int pool[], int pool_count, int object_count, int*** pointers, int* solved) {
    if(object_count == MAX_DIGITS - 1)
        object_count = 0;
    if(*solved) // if a branch solved this, escape recursion
        return;
    if (ArePointersAssigned(pointers)) { // that means we got a full equation set
        *solved = evaluate(pointers);
        if(*solved)
            return;
    }
    int *pool_end = pool + pool_count - 1;
    for (int p = pool_count - 1; p >= 0 && !*solved; p--) {
        int sample = pool[p];  // take one out
        pool[p] = *pool_end;   // replace it with the end
        int temp = **pointers[object_count];
        if(**pointers[object_count] == -1)
            **pointers[object_count] = sample;
        form_combos(pool, pool_count - 1, object_count + 1, pointers, solved);
        pool[p] = sample;      // restore pool item
        if(!*solved)
            **pointers[object_count] = temp;
    }
}

int main() {
    char expression[MAX_EXPRESSION_SIZE] = { 0 };
    printf("Enter the formula: ");
    scanf("%s", expression);
    while(expression[0] != '-') {
        if(IsImpossible(expression))
            printf("No solution!\n");
        else {
            int digits[MAX_DIGITS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            int object[MAX_VARIABLES] = { -1, -1, -1, -1, -1, -1, -1, -1, -1 }; // stack for dfs
            int *A = &object[0], *B = &object[1], *C = &object[2], 
                *D = &object[3], *E = &object[4], *F = &object[5], 
                *G = &object[6], *H = &object[7], *I = &object[8];
            // set same pointers
            int** pointers[MAX_VARIABLES] = { &A, &B, &C, &D, &E, &F, &G, &H, &I };

            // analyze the equation
            int var = 0;
            for(int p = 0; p < MAX_EXPRESSION_SIZE; ++p) {
                if(expression[p] >= 'A' && expression[p] <= 'I') {
                    *pointers[var++] = &object[expression[p] - 'A']; // link same pointers
                }
            }
            int solved = 0, check_end = 0;
            form_combos(digits, MAX_DIGITS, MAX_DIGITS - 4, pointers, &solved);
            if(!solved) // it can be unsolvable still
                printf("No solution!\n");
            else
                printf("%d%d%d + %d%d%d = %d%d%d\n", *A, *B, *C, *D, *E, *F, *G, *H, *I);
        }
        printf("Enter the formula: ");
        scanf("%s", expression);
    }
    return 0;
}