编写程序以创建匹配输入集到输出集的公式

时间:2014-12-07 02:22:43

标签: function obfuscation theory brute-force

我刚刚在StackOverflow上看到了Obfuscated C解释的解释。我发现比赛非常有趣,因为我每天都要学习新的C,而且每天都有新的编程知识。

一个有趣的是Explain 1-liner party of a US President from IOCCC 2013

如您所见,该程序使用一系列模数函数(即。(整数)%4796%275%4)来散列输入数字以形成两个输出数字之一。这"哈希"功能已被试验并且错误地为一组有限的输入正确工作。

我认为最大限度地减少程序的大小是件好事,这样你就可以将一个结果映射到另一个结果。例如,你可以将{apple,lettuce,carrot,pear,orange,asparagus}转换为数字并通过函数,转换为{1,0,0,1,1,0},这个函数少花了空间比完整的数据库搜索字符串并确定其果实。

所以我的问题是......你如何创建一个程序来强制堆叠的模数函数,这些函数适用于所有给定的输入集和输出集?

继续水果示例,您可以将水果的前两个字母转换为如下数字: apple - > ap - > 0x6170

所以列表变为{0x6170,0x6c65,0x6361,0x7065,0x6f72,0x6173}

所以你想生成一个包含重复模的函数来将{0x6170,0x6c65,0x6361,0x7065,0x6f72,0x6173}映射到{1,0,0,1,1,0}

怎么会这样做?

1 个答案:

答案 0 :(得分:0)

有趣的挑战,但超越了我的数学技能。所以,这是一个简单的C :P

中的暴力实现

我没有数学证明,因此无法证明这将总是找到解决方案,但它适用于您的输入。添加“水果”“克林顿”和“蔬菜”“麦卡因”使其运行时间更长;添加“杏”将发出冲突信号! (已报道,但没有说明在哪里。请注意,类似的项目内的冲突 - fruits 蔬菜 - 实际上应该被允许。我没有写代码为此,但它应该相对简单。)

要查看更长的序列,请添加“banana”。出于某种原因,这需要达到163,13,2。有趣的是,然后添加“金橘”(我的水果已用完)并不需要太长时间,即使使用另一种“椰子”也不会花费太多时间。

实施说明:

您可以将搜索限制为最大输入2字节代码,因为mod函数永远不会对较大的数字执行任何操作。为了保持一致性,这个C代码从测试所有1-mod值开始(尽管我没有找到任何有用的东西)。然后它测试2-mod值,最后测试3-mod值。如果它没有找到值,你可以扩展它以寻找4-mod和5-mod长序列,但搜索时间将以对数方式增加(!)。

应该可以对超过2个值进行分类;这需要非常小的代码重写。我怀疑为所有人寻找一场比赛需要更长的时间。

还应该可以返回除01之外的其他“索引”;正如我写的那样,其余的CPU正在20上努力工作。但是,这似乎需要相当长的时间。

C实施,蛮力:

#include <stdio.h>
#include <stdlib.h>

int main (void)
{
  char *fruits[] = { "apple", "pear", "orange"} ; //, "clinton"  };
  char *veggies[] = { "lettuce", "carrot", "asparagus" }; // , "mccaine" };
  int num_f, num_v, found_match;
  unsigned short *code[2], max_code = 0;

  int i,j, mod_value1, mod_value2, mod_value3;

  num_f = sizeof(fruits)/sizeof(fruits[0]);
  num_v = sizeof(veggies)/sizeof(veggies[0]);

  code[0] = malloc((num_f+num_v)*sizeof(short));
  code[1] = malloc((num_f+num_v)*sizeof(short));

  for (i=0; i<num_f; i++)
  {
    code[0][i] = (fruits[i][0]<<8)+fruits[i][1];
    code[1][i] = 1;
    if (code[0][i] > max_code)
      max_code = code[0][i];
  }
  for (i=0; i<num_v; i++)
  {
    code[0][num_f+i] = (veggies[i][0]<<8)+veggies[i][1];
    code[1][num_f+i] = 0;
    if (code[0][num_f+i] > max_code)
      max_code = code[0][num_f+i];
  }

  for (i=0; i<num_f+num_v; i++)
  {
    for (j=i+1; j<num_f+num_v; j++)
    {
      if (code[0][i] == code[0][j])
      {
        printf ("clash!\n");
        exit(-1);
      }
    }
  }

  printf ("calculating...\n");
  for (mod_value1=1; mod_value1<max_code; mod_value1++)
  {
    found_match = 1;
    for (i=0; i<num_f+num_v; i++)
    {
      if (code[0][i] % mod_value1 != code[1][i])
      {
        found_match = 0;
        break;
      }
    }
    if (found_match)
    {
      printf ("mod %d should work\n", mod_value1);
      break;
    }
  }
  if (found_match)
  {
    for (i=0; i<num_f; i++)
    {
      printf ("%s -> %d\n", fruits[i], code[0][i]  % mod_value2 % mod_value1);
    }
    for (i=0; i<num_v; i++)
    {
      printf ("%s -> %d\n", veggies[i], code[0][num_f+i]  % mod_value2 % mod_value1);
    }
  } else
  {
  for (mod_value1=1; mod_value1<max_code; mod_value1++)
  {
    for (mod_value2=mod_value1+1; mod_value2<max_code; mod_value2++)
    {
      found_match = 1;
      for (i=0; i<num_f+num_v; i++)
      {
        if (code[0][i] % mod_value2 % mod_value1 != code[1][i])
        {
          found_match = 0;
          break;
        }
      }
      if (found_match)
      {
        printf ("mod %d mod %d should work\n", mod_value2, mod_value1);
        break;
      }
    }
    if (found_match)
      break;
  }

  if (found_match)
  {
    for (i=0; i<num_f; i++)
    {
      printf ("%s -> %d\n", fruits[i], code[0][i]  % mod_value2 % mod_value1);
    }
    for (i=0; i<num_v; i++)
    {
      printf ("%s -> %d\n", veggies[i], code[0][num_f+i]  % mod_value2 % mod_value1);
    }
  } else
  {
    for (mod_value1=1; mod_value1<max_code; mod_value1++)
    {
      for (mod_value2=mod_value1+1; mod_value2<max_code; mod_value2++)
      {
        for (mod_value3=mod_value2+1; mod_value3<max_code; mod_value3++)
        {
          found_match = 1;
          for (i=0; i<num_f+num_v; i++)
          {
            if (code[0][i] % mod_value3 % mod_value2 % mod_value1 != code[1][i])
            {
              found_match = 0;
              break;
            }
          }
          if (found_match)
          {
            printf ("mod %d mod %d mod %d should work\n", mod_value3, mod_value2, mod_value1);
            break;
          }
        }
        if (found_match)
          break;
      }
      if (found_match)
        break;
    }

    if (found_match)
    {
      for (i=0; i<num_f; i++)
      {
        printf ("%s -> %d\n", fruits[i], code[0][i] % mod_value3 % mod_value2 % mod_value1);
      }
      for (i=0; i<num_v; i++)
      {
        printf ("%s -> %d\n", veggies[i], code[0][num_f+i] % mod_value3 % mod_value2 % mod_value1);
      }
    }
  }
  }
  return 0;
}

您原来的3个水果,3个素食列表的结果:

mod 25 mod 2 should work
apple -> 1
pear -> 1
orange -> 1
lettuce -> 0
carrot -> 0
asparagus -> 0

晚期结果,适用于20的所需输出:

mod 507 mod 8 mod 3 should work
apple -> 2
pear -> 2
orange -> 2
lettuce -> 0
carrot -> 0
asparagus -> 0

后来的结果是,将“有争议的”“番茄”添加为第2类:

mod 103 mod 7 mod 3 should work
apple -> 1
pear -> 1
orange -> 1
lettuce -> 0
carrot -> 0
asparagus -> 0
tomato -> 2