C #, 루프 없음
좋아, 나는 그 두 개의 링크를 훑어 보았지만 솔직히 말하면 약간 지루했다. 나는 해시 테이블과 그 밖의 것들로 지옥을 최적화하는 데 관심이 없다. 왜해야합니까? 당신은 망할 슈퍼 컴퓨터를 가지고 있습니다!
지옥, 나는 루프로 귀찮게하고 싶지 않습니다! 이 솔루션은 루프없는 규칙을 따릅니다 .
내가 쓰려고하는 코드는 좋은 코드가 아니거나 실생활에서 쓰려는 코드가 아닙니다 (예상 고용주가이 코드를 읽을 경우). 이 코드는 간결성과 내러티브 작업 능력을 강조하며 적절한 관습, 의식 및 고리 등을 강조하지 않습니다.
내가 말하고있는 것을 보여주기 위해, 우리는 방정식의 피연산자를 저장하기 위해 퍼블릭 필드를 가진 충격적인 클래스로 시작할 것입니다.
class BealOperands
{
public BigInteger A, B, C, x, y, z;
}
가장 어려운 과제부터 시작하겠습니다. 이러한 피연산자의 모든 조합을 순회하는 방법을 찾아야합니다. 모든 순열을 확인하는 것보다 더 효율적으로 수행 할 수있는 방법이 있지만, 그것들을 알아낼 수는 없습니다. 왜 내가해야합니까? 망할 슈퍼 컴퓨터가 있습니다!
여기 내가 생각해 낸 알고리즘이 있습니다. 엄청나게 비효율적이며 동일한 피연산자를 반복해서 반복하지만 누가 신경 쓰나요? 슈퍼 컴퓨터!
- 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의 반례를 찾는 것입니다.
우리의 다음 큰 문제는 BigInteger
의 힘 을 높이기위한 기본 제공 방법이없는 것 BigInteger
입니다. 있다 BigInteger.Pow(BigInteger value, int exponent)
, 그리고 BigInteger.ModPow(BigInteger value, BigInteger exponent, BigInteger modulus)
,하지만 방법은 인상하지 않으려면 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
이 Beal의 추측에 대한 반례 인지 어떻게 알 수 있습니까? 두 가지 사실이 필요합니다.
- 페이지 상단에서 해당 수식에 연결하면 피연산자는 실제 방정식을 형성해야합니다.
- A, B 및 C는 공통 소인수를 가져서는 안됩니다 (예 : GCD가 1).
우리는 첫 번째 상태를 확인하기 위해 필요한 것을 얻었습니다. 그리고 두 번째 조건은 소리보다 확인하기가 훨씬 쉽습니다. 루프없이 구현하려고하는 모든 악몽을 편리하게 회피 할 수 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!");
}
}
}