gpt4 book ai didi

c - 密码算法求解器分解的效率

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:16:39 24 4
gpt4 key购买 nike

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

我已经很容易地排除了不可能的情况。我想到的算法是一种蛮力,它只是先尝试​​最大化 rhs。然而,我的问题是这样做得很快,还要注意独特的数字。解决这个问题的有效方法是什么?

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

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

#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;
}

最佳答案

我将从结果开始。没有那么多不同的情况:

  • AAA
  • AAB, ABA, BAA
  • ABC

所有其他情况都可以通过重命名变量来简化为这些情况。 ABC + CBA = GGG 将变为 DBC + CBD = AAA

那么你有

  • 单变量情况 AAA 的 10 种可能的解决方案
  • 90 (10*9) 对于两个变量情况
  • 三变量情况下为 720 (10*9*8)

假设任何地方都允许零。如果没有,您可以过滤掉那些不允许的。

这会设置等式右侧的变量。每个仅出现在左侧的变量都会添加可能的解决方案。 B 增加了 9 个因子,C 增加了 8 个因子,D 增加了 7 等等。

关于c - 密码算法求解器分解的效率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40294834/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com