【问题标题】:Find/simplify overlapping modulo查找/简化重叠模数
【发布时间】:2018-05-27 10:47:21
【问题描述】:

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

我目前有很多硬编码的模条件,有什么简单的方法可以减少条件的数量吗?

一般来说,如果您已经检查过x % 2 == 0,则可以跳过检查x % 4 == 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...

【问题讨论】:

  • 究竟是什么问题,检查数字是否可整除?
  • 你可以在通过x % 2 == 0时跳过x % 4 == 0
  • @Sefe 我相信 OP 的意思是,如果你测试 x % 2 == 0 并返回,那么之后就不需要测试 x % 4 == 0,因为任何能被 4 整除的东西也能被 2 整除。跨度>
  • @juharr 但这就是他已经在做的事情。删除第二个测试(实际上不在提供的实际代码中)将改变代码的语义。这显然是他不想要的。
  • @juharr,确切地说,这只是一个例子,因为当涉及到“+”时我不明白该怎么做。问题是是否有任何多余的检查,如果有如何找到它们?

标签: c# modulo simplify integer-division


【解决方案1】:

我假设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。一个例子:假设一个整数delaydelay % lcm == 1924。然后我们有delay % 6 等于(delay % lcm) % 61924 % 64。同样,只要delay % lcm 是硬编码残基列表中的值i,我们测试它以匹配您ifs 中的所有各种条件,那么我们知道delay 也匹配它们,因为——对于任何 m 特定的 if 正在测试的对象——我们以我们已经知道 i % m 匹配条件的方式生成了我们的列表,现在我们有了 (delay % m) == (delay % lcm) % m) == i % m

注意:这种方法之所以可行,是因为您的一组条件排除了许多只有小模量的残基。例如,如果有一个异常条件与一个大素数进行比较,则残差列表很容易变得太大而无法处理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-31
    • 2020-11-05
    • 2016-06-09
    • 2014-09-15
    相关资源
    最近更新 更多