C #, döngü yok
Tamam, bu bağlantılardan birkaçını kaçırdım, ama dürüst olmak gerekirse biraz sıkıcıydılar. Karma tablolar ve ne ile cehennem optimize etmek ilgilenmiyorum. Neden ihtiyacım var? Kahrolasý bir süper bilgisayarýn var!
Cehennem, döngülerle uğraşmak bile istemiyorum! Bu çözüm döngüsüz kuralı izleyecektir .
Yazmak üzere olduğum kodun iyi bir kod veya gerçek hayatta yazacağım kod türü olmadığını lütfen unutmayın (herhangi bir muhtemel işveren bunu okumak için). Bu kod, kısalığı ve bir anlatıda çalışma yeteneğini vurgular ve uygun sözleşmeleri, ritüelleri ve döngüler vb.
Neden bahsettiğimi göstermek için, denklemin işlenenlerini saklamak için genel alanlara sahip şok edici bir sınıfla başlayacağız:
class BealOperands
{
public BigInteger A, B, C, x, y, z;
}
Tamam, muhtemelen en zor olan şeyle başlayacağız. Bu işlenenlerin her birleşimi için izin vermenin bir yolunu bulmamız gerekiyor. Kuşkusuz her permütasyonu kontrol etmekten daha etkili bir şekilde yapmanın yolları var, ama onları anlamaktan rahatsız edilemem. Neden yapayım? Lanet olası bir süper bilgisayarımız var!
İşte bulduğum algoritma. İnanılmaz derecede verimsiz ve aynı işlenenleri tekrar tekrar geçiyor, ama kimin umurunda? Süper bilgisayar!
- Altı işlenene bir taban-2 numarası olarak davranın ve her kombinasyondan geçirin.
- Altı işlenene bir baz-3 numarası olarak davranın ve her kombinasyona izin verin.
- Altı işlenene bir taban-4 numarası olarak davranın ve her kombinasyondan geçirin.
- (...)
Bütün bunlar ilmeksiz nasıl yapılır? Kolay! Sadece IEnumerable
ve IEnumerator
permütasyonları dışarı pompalamak için ilişkili bir uygulamak . Daha sonra sorgulamak için LINQ kullanacağız.
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() { }
}
Şimdi işteyiz! Yapmamız gereken tek şey BealOperandGenerator
Beal's Conjecture'in bir örneğini sıralamak ve bunun bir örneğini bulmak.
Bir sonraki büyük sorunumuz, a'nın BigInteger
gücüne yükseltmek için yerleşik bir yol olmadığıdır BigInteger
. Bir BigInteger.Pow(BigInteger value, int exponent)
, ve başka bir modulo sonsuzun gücüne BigInteger.ModPow(BigInteger value, BigInteger exponent, BigInteger modulus)
yükseltmek için bir yöntem yoktur .BigInteger
BigInteger
Ne parlak bir çivi! Bizim IEnumerable
/ IEnumerator
çekiç ile çözülmesi için yapılmış gibi görünüyor !
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;
}
}
Şimdi Pow
, a üzerinde çağrılabilecek bir uzantı yöntemimiz var BigInteger
veBigInteger
üssü alan ve bir modül almayan .
Tamam, geri dönelim. Belirli bir BealOperands
şeyin Beal Konjonktürünün bir örneği olup olmadığını nasıl anlayabiliriz ? İki şeyin doğru olması gerekir:
- İşlenenler, sayfanın üst kısmında bu formüle takıldığında gerçek bir denklem oluşturmalıdır.
- A, B ve C'nin ortak bir ana faktörü OLMAMALIDIR (yani GCD'si 1'dir).
İlk durumu kontrol etmek için ihtiyacımız olan şey bizde. Ve ikinci koşulu kontrol etmek göründüğünden çok daha kolay çıkıyor. bunu döngüler olmadan uygulamaya çalışmanın tüm kabusu rahatça kaldırmamızı sağlayan BigInteger
güzel bir GreatestCommonDivisor
yöntem sağlar.
Bu yüzden BealOperands
a'nın karşı örnek olup olmadığını kontrol etmek için bir yöntem yazmaya hazırız . İşte gidiyor ...
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;
}
}
Ve son olarak, bu oldukça kaygan Main
yöntemle hepsini bir araya getirebiliriz :
static class Program
{
static void Main()
{
var bealOperandGenerator = new BealOperandGenerator();
if (bealOperandGenerator.Any(o => o.IsBealsConjectureCounterExample()))
{
Console.WriteLine("IN YOUR FACE, BEAL!");
}
}
}