C#、ループなし
わかりました、私はそれらのリンクのいくつかをスキムしました、しかし正直に言うと、それらは少し退屈でした。ハッシュテーブルなどで地獄を最適化することに興味はありません。なぜ必要なのですか?あなたはひどいスーパーコンピューターを持っています!
地獄、私はループに煩わされたくさえありません!このソリューションは、ループなしのルールに従います。
私がこれから書くコードは、良いコードでも、実際の生活で書くような種類のコードでもありません(将来の雇用主がこれを読んだ場合に備えて)。このコードは、簡潔さと物語で働く能力を強調し、適切な慣習と儀式、ループなどを強調しません。
私が話していることを示すために、方程式のオペランドを格納するパブリックフィールドを持つ衝撃的なクラスから始めます。
class BealOperands
{
public BigInteger A, B, C, x, y, z;
}
OK、おそらく最も難しい課題から始めましょう。これらのオペランドのすべての組み合わせを変更する方法を見つけ出す必要があります。すべての順列をチェックするよりも効率的に行う方法は間違いなくありますが、それらを理解するのは面倒です。そして、なぜ私はする必要がありますか?私たちはひどいスーパーコンピューターを持っています!
これが私が思いついたアルゴリズムです。それは信じられないほど非効率的で、同じオペランドを何度も繰り返しますが、誰が気にしますか?スーパーコンピューター!
- 6つのオペランドを基数2の数として扱い、すべての組み合わせを順列します。
- 6つのオペランドを基数3の数として扱い、すべての組み合わせを順列します。
- 6つのオペランドを基数4として扱い、すべての組み合わせを順列します。
- (...)
ループなしでこれをすべて行う方法は?簡単!を実装して、順列をポンプアウトするためにIEnumerable
関連付けIEnumerator
ます。後で、LINQを使用してクエリします。
class BealOperandGenerator : IEnumerable<BealOperands>
{
// Implementation of IEnumerable<> and IEnumerable -- basically boilerplate to get to BealOperandGeneratorEnumerator.
public IEnumerator<BealOperands> GetEnumerator() { return new BealOperandGeneratorEnumerator(); }
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
class BealOperandGeneratorEnumerator : IEnumerator<BealOperands>
{
public BealOperandGeneratorEnumerator() { Reset(); }
private BealOperands operands;
private BigInteger @base;
public void Reset()
{
// A is set to 0, which is "before" its minimum value, because IEnumerators are supposed to
// point to their first element *after* the first call to MoveNext().
// All other operands are set to their minimum values.
operands = new BealOperands { A = 0, B = 1, C = 1, x = 3, y = 3, z = 3 };
@base = 2;
}
public BealOperands Current
{
get
{
// We need to return a copy, since we'll be manipulating our internal one.
return new BealOperands {
A = operands.A, B = operands.B, C = operands.C,
x = operands.x, y = operands.y, z = operands.z };
}
}
public bool MoveNext()
{
// Increment the lowest "digit" and "carry" as necessary.
operands.A++;
if (operands.A - 1 >= @base)
{
operands.A = 1; operands.B++;
if (operands.B - 1 >= @base)
{
operands.B = 1; operands.C++;
if (operands.C - 1 >= @base)
{
operands.C = 1; operands.x++;
if (operands.x - 3 >= @base)
{
operands.x = 3; operands.y++;
if (operands.y - 3 >= @base)
{
operands.y = 3; operands.z++;
if (operands.z - 3 >= @base)
{
operands.z = 3; @base++;
}
}
}
}
}
}
// There will always be more elements in this sequence.
return true;
}
// More boilerplate
object System.Collections.IEnumerator.Current { get { return Current; } }
public void Dispose() { }
}
今、私たちは仕事をしています!する必要があるのは、インスタンスを列挙し、BealOperandGenerator
Beal's Conjectureの反例を見つけることだけです。
私たちの次の大きな問題は、a BigInteger
をa のべき乗する組み込みの方法がないように見えることですBigInteger
。BigInteger.Pow(BigInteger value, int exponent)
、およびがありますが、BigInteger.ModPow(BigInteger value, BigInteger exponent, BigInteger modulus)
a BigInteger
を別の累乗BigInteger
無限大で累乗する方法はありません。
問題のなんて光沢のある爪!IEnumerable
/ IEnumerator
ハンマーで解決するように作られたようです!
class BigIntegerPowerEnumerable : IEnumerable<Tuple<BigInteger, BigInteger>>
{
public BigIntegerPowerEnumerable(BigInteger @base, BigInteger exponent) { this.@base = @base; this.exponent = exponent; }
BigInteger @base, exponent;
public IEnumerator<Tuple<BigInteger, BigInteger>> GetEnumerator() { return new BigIntegerPowerEnumerator(@base, exponent); }
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
class BigIntegerPowerEnumerator : IEnumerator<Tuple<BigInteger, BigInteger>>
{
public BigIntegerPowerEnumerator(BigInteger @base, BigInteger exponent)
{
originalBase = @base;
originalExponent = exponent;
Reset();
}
BigInteger originalBase, currentBase, originalExponent, currentExponent;
bool finished;
public void Reset()
{
// IEnumerable.Reset() is a silly method. You're required to implement it when you implement IEnumerable,
// but it isn't used by foreach or LINQ or anything. If you want to re-enumerate the enumerable, just get
// a brand new enumerator.
// In this case it gets in the way. The only reason I'm storing the original values is so I can implement
// this useless method properly. I supposed I could just throw a NotImplementedException or something,
// but it's done now.
currentBase = originalBase;
currentExponent = originalExponent;
finished = false;
}
public bool MoveNext()
{
if (finished) return false;
if (currentExponent <= Int32.MaxValue)
{
currentBase = BigInteger.Pow(currentBase, (Int32)currentExponent);
currentExponent = 1;
finished = true;
}
else
{
currentBase = BigInteger.Pow(currentBase, Int32.MaxValue);
currentExponent -= Int32.MaxValue;
}
return true;
}
public Tuple<BigInteger, BigInteger> Current
{
get { return new Tuple<BigInteger, BigInteger>(currentBase, currentExponent); }
}
object System.Collections.IEnumerator.Current { get { return Current; } }
public void Dispose() { }
}
static class BigIntegerPowExtension
{
public static BigInteger Pow(this BigInteger @base, BigInteger exponent)
{
return new BigIntegerPowerEnumerable(@base, exponent).Last().Item1;
}
}
今、私たちは、拡張メソッド持っPow
Aで呼び出すことができ、BigInteger
でがあり、BigInteger
指数を受け取り、モジュラスは受け取りません。
さて、一歩下がろう。特定のものBealOperands
がビールの予想の反例であるかどうかはどうすればわかりますか?さて、次の2つが真実である必要があります。
- オペランドは、ページの上部でその数式にプラグインされると、真の方程式を形成する必要があります。
- A、B、およびCに共通の素因数があってはなりません(つまり、GCDは1です)。
最初の条件を確認するために必要なものが揃っています。そして、2番目の条件は、音よりも確認がはるかに簡単であることがわかります。BigInteger
素敵なGreatestCommonDivisor
メソッドを提供します。これにより、ループなしで実装しようとする悪夢全体を便利に回避できます。
したがって、a BealOperands
が反例かどうかをチェックするメソッドを作成する準備ができました。ここに行く...
static class BealOperandsExtensions
{
public static bool IsBealsConjectureCounterExample(this BealOperands o)
{
// If the equation isn't even true, we don't have a counter example unfortunately
if (o.A.Pow(o.x) + o.B.Pow(o.y) != o.C.Pow(o.z))
{
return false;
}
// We have a counterexample if A, B and C are coprime
return BigInteger.GreatestCommonDivisor(o.A, o.B) == 1 &&
BigInteger.GreatestCommonDivisor(o.A, o.C) == 1 &&
BigInteger.GreatestCommonDivisor(o.B, o.C) == 1;
}
}
そして最後に、このかなり滑らかなMain
方法ですべてをまとめることができます。
static class Program
{
static void Main()
{
var bealOperandGenerator = new BealOperandGenerator();
if (bealOperandGenerator.Any(o => o.IsBealsConjectureCounterExample()))
{
Console.WriteLine("IN YOUR FACE, BEAL!");
}
}
}