查找/简化重叠模数

时间:2017-12-13 13:59:55

标签: c# modulo simplify integer-division

我今天有一些代码解决了“代码第2部分的问世”。 https://adventofcode.com/

我目前有许多硬编码的模数条件,有没有简单的方法来减少条件数?

一般情况下,如果您已经选中x % 4 == 0,则可以跳过检查x % 2 == 0。但是我很难搞清楚如何在涉及添加时进行简化。我可以查询任何建议或资源吗?

if (delay % 6 == 0)
{
    return false;
}

if ((delay +1) % 2 == 0)
{
    return false;
}

if ((delay +2) % 4 == 0)
{
    return false;
}

if ((delay + 4) % 6 == 0)
{
    return false;
}

if ((delay + 6) % 14 == 0)
{
    return false;
}

if ((delay + 8) % 8 == 0)
{
    return false;
}

if ((delay + 10) % 14 == 0)
{
    return false;
}
if ((delay + 12) % 10 == 0)
{
    return false;
}
if ((delay + 14) % 10 == 0)
{
    return false;
}
if ((delay + 16) % 14 == 0)
{
    return false;
}
if ((delay + 18) % 10 == 0)
{
    return false;
}
if ((delay + 20) % 10 == 0)
{
    return false;
}
if ((delay + 22) % 22 == 0)
{
    return false;
}
if ((delay + 24) % 22 == 0)
{
    return false;
}

if ((delay + 26) % 18 == 0)
{
    return false;
} 

if ((delay + 28) % 14 == 0)
{
    return false;
}

if ((delay + 32) % 14 == 0)
{
    return false;
}

if ((delay + 36) % 16 == 0)
{
    return false;
}

if ((delay + 40) % 14 == 0)
{
    return false;
}

if ((delay + 44) % 32 == 0)
{
    return false;
}

if ((delay + 50) % 18 == 0)
{
    return false;
}

if ((delay + 56) % 26 == 0)
{
    return false;
}
if ((delay + 58) % 26 == 0)
{
    return false;
}
if ((delay + 60) % 26 == 0)
{
    return false;
}

if ((delay + 62) % 22 == 0)
{
    return false;
}

if ((delay + 64) % 26 == 0)
{
    return false;
}

if ((delay + 66) % 26 == 0)
{
    return false;
}

if ((delay + 68) % 26 == 0)
{
    return false;
}

if ((delay + 70) % 26 == 0)
{
    return false;
}

if ((delay + 74) % 26 == 0)
{
    return false;
}
if ((delay + 76) % 26 == 0)
{
    return false;
}
if ((delay + 80) % 26 == 0)
{
    return false;
}

if ((delay + 88) % 26 == 0)
{
    return false;
}

doSomeComputation...

1 个答案:

答案 0 :(得分:0)

我假设delay始终是非负的。如果您的输入无法保证这一点,您可以将模数调用替换为修复它的版本,如this answer中所示。也就是说,您发布的逻辑可以用以下方式复制:

const int lcm = 1441440;
int[] residues = new int[]
{
    1924,
    92644,
    132964,
    223684,
    354724,
    395044,
    616804,
    657124,
    788164,
    878884,
    1009924,
    1050244,
    1181284,
    1272004,
    1312324,
    1403044
};
if (!residues.Contains(delay % lcm)) return false;

如何生成它的说明:lcm是您要修改的数字的least common multiple。您可以通过询问WolframAlpha或其他任何方式来获得该信息。通过简单地遍历所有残差mod lcm并检查哪些残差通过逻辑已经可以获得常数残差。以下代码是我用来打印它们的代码,其中函数myPass只是您在上面提供的逻辑。

for (int i = 0; i < 1441440; ++i)
   if (myPass(i))
       Console.WriteLine("i = {0}", i);

解释它的工作原理:如果delay是一个整数而m是一个正整数而n是一个可被m整除的正整数,那么delay % m的值等于(delay % n) % m。例如:假设整数delay具有delay % lcm == 1924。然后我们delay % 6等于(delay % lcm) % 61924 % 64。同样,只要delay % lcm是我们测试的残差硬编码列表中的值i,以匹配您if中的所有各种条件,那么我们就知道{ {1}}也匹配它们,因为 - 对于特定delay正在测试的m - 我们生成了我们的列表,我们已经知道if匹配条件,现在我们有i % m

注意:这种方法是可行的,因为您的条件集排除了许多只有小模量的残留物。例如,如果存在一个与大质数相比的偏离条件,那么残留物列表很容易变得太大而无法处理。