Eine lineare diophantinische Gleichung in zwei Variablen ist eine Gleichung der Form ax + by = c , wobei a , b und c konstante ganze Zahlen und x und y ganzzahlige Variablen sind.
Für viele natürlich vorkommende diophantinische Gleichungen stehen x und y für Größen, die nicht negativ sein können.
Aufgabe
Schreiben Sie ein Programm oder eine Funktion, die die Koeffizienten a , b und c als Eingabe akzeptiert und ein beliebiges Paar natürlicher Zahlen (0, 1, 2,…) x und y zurückgibt , die die Gleichung ax + by = c verifizieren , falls ein solches Paar vorliegt existiert.
Zusätzliche Regeln
Sie können ein beliebiges Format für die Eingabe und Ausgabe auswählen, das nur die gewünschten Ganzzahlen und optional Array / Liste / Matrix / Tupel / Vektor Ihrer Sprache enthält, sofern Sie keinen Code in die Eingabe einbetten.
Sie können annehmen, dass die Koeffizienten a und b beide ungleich Null sind.
Ihr Code muss für jedes Triplett von ganzen Zahlen zwischen -2 60 und 2 60 funktionieren . Auf meinem Computer (Intel i7-3770, 16 GiB RAM) muss es in weniger als einer Minute fertig sein.
Sie dürfen keine eingebauten Elemente verwenden, die diophantische Gleichungen lösen und diese Aufgabe damit trivialisieren, wie z. B. die von Mathema- tica
FindInstance
oderFrobeniusSolve
.Ihr Code kann sich beliebig verhalten, wenn keine Lösung gefunden werden kann, solange er das Zeitlimit einhält und seine Ausgabe nicht mit einer gültigen Lösung verwechselt werden kann.
Es gelten die Standardregeln für Code-Golf .
Beispiele
Die folgenden Beispiele veranschaulichen gültige E / A für die Gleichung 2x + 3y = 11 , die genau zwei gültige Lösungen enthält ( (x, y) = (4,1) und (x, y) = (1,3) ).
Input: 2 3 11 Output: [4 1] Input: (11 (2,3)) Output: [3],(1)
Die einzig gültige Lösung von 2x + 3y = 2 ist das Paar (x, y) = (1,0) .
Die folgenden Beispiele veranschaulichen gültige E / A für die Gleichung 2x + 3y = 1 , für die keine gültigen Lösungen vorliegen .
Input: (2 3 1) Output: [] Input: 1 2 3 Output: -1 Input: [[2], [3], [1]] Output: (2, -1)
Für (a, b, c) = (1152921504606846883, -576460752303423433, 1) erfüllen alle korrekten Lösungen (x, y) (x, y) = (135637824071393749 - bn, 271275648142787502 + an) für einige nicht negative ganze Zahlen n .
quelle
Antworten:
Pyth, 92 Bytes
Es ist ein ziemliches Monster.
Probieren Sie es online aus: Demonstration . Das Eingabeformat ist
c\n[a,b]
und das Ausgabeformat ist[x,y]
.Für den Fall, dass keine ganzzahlige Lösung existiert, gebe ich nichts aus und für den Fall, dass keine natürliche ganzzahlige Lösung existiert, gebe ich einfach eine zufällige ganzzahlige Lösung aus.
Erklärung (grobe Übersicht)
Zuerst werde ich eine ganzzahlige Lösung für die Gleichung finden,
ax + by = gcd(a,b)
indem ich den erweiterten euklidischen Algorithmus verwende.Dann ändere ich die Lösung (mein Multiplizieren
a
undb
mitc/gcd(a,b)
), um eine ganzzahlige Lösung von zu erhaltenax + by = c
. Dies funktioniert, wennc/gcd(a,b)
es sich um eine Ganzzahl handelt. Sonst gibt es keine Lösung.Alle anderen Ganzzahllösungen haben die Form
a(x+n*b/d) + b(y-n*a/d) = c
mitd = gcd(a,b)
für Ganzzahln
. Mit den beiden Ungleichungenx+n*b/d >= 0
undy-n*a/d >= 0
kann ich 6 mögliche Werte für bestimmenn
. Ich probiere alle 6 aus und drucke die Lösung mit dem höchsten und niedrigsten Koeffizienten.Erklärung (detailliert)
Der erste Schritt besteht darin, eine ganzzahlige Lösung für die Gleichung zu finden
ax' + by' = gcd(a,b)
. Dies kann mithilfe des erweiterten euklidischen Algorithmus erfolgen. Bei Wikipedia können Sie sich ein Bild davon machen, wie es funktioniert . Der einzige Unterschied ist, dassr_i s_i t_i
ich anstelle von 3 Spalten ( ) 6 Spalten (r_i-1 r_i s_i-1 s_i t_i-1 t_i
) verwende. Auf diese Weise muss ich nicht die letzten beiden Zeilen im Speicher behalten, sondern nur die letzte.Jetzt möchte ich eine Lösung finden
ax + by = c
. Dies ist nur möglich, wennc mod gcd(a,b) == 0
. Wenn diese Gleichung erfüllt ist, multipliziere ich einfachx',y'
mitc/gcd(a,b)
.Wir haben eine ganzzahlige Lösung für
ax + by = c
. Beachten Sie , dassx
,y
oder beide negativ sein kann. Unser Ziel ist es daher, diese in nicht negative umzuwandeln.Das Schöne an Diophantine-Gleichungen ist, dass wir alle Lösungen mit nur einer Anfangslösung beschreiben können. Wenn
(x,y)
es sich um eine Lösung handelt, haben alle anderen Lösungen die Form(x-n*b/gcd(a,b),y+n*a/gcd(a,b))
einern
Ganzzahl.Deshalb wollen wir ein
n
, wox-n*b/gcd(a,b) >= 0
undy+n*a/gcd(a,b >= 0
. Nach einer gewissen Transformation kommen wir zu den beiden Ungleichungenn >= -x*gcd(a,b)/b
undn >= y*gcd(a,b)/a
. Beachten Sie, dass das Ungleichungssymbol aufgrund der Division mit einem potenziellen negativena
oder in die andere Richtung zeigen kannb
. Es ist mir egal, ich sage einfach, dass eine Zahl-x*gcd(a,b)/b - 1, -x*gcd(a,b)/b, -x*gcd(a,b)/b + 1
definitiv die Ungleichung 1 und eine Zahly*gcd(a,b)/a - 1, y*gcd(a,b)/a, y*gcd(a,b)/a + 1
die Ungleichung 2 erfüllt. Es gibt einen
, die beide Ungleichungen erfüllt, und eine der 6 Zahlen tut dies auch.Dann berechne ich die neuen Lösungen
(x-n*b/gcd(a,b),y+n*a/gcd(a,b))
für alle 6 möglichen Werte vonn
. Und ich drucke die Lösung mit dem höchsten niedrigsten Wert.Das Sortieren nach ihrer sortierten Reihenfolge funktioniert folgendermaßen. Ich benutze das Beispiel
2x + 3y = 11
Ich sortiere jede der 6 Lösungen (diese werden als Schlüssel bezeichnet) und sortiere die ursprünglichen Lösungen nach ihren Schlüsseln:
Dies sortiert eine vollständige nicht negative Lösung bis zum Ende (falls vorhanden).
quelle
Matlab (660)
Erläuterung:
Der Code verwendet drei Invarianten a, b, c als Eingabe. Diese letzten werden einigen Bedingungen unterworfen, bevor mit der Berechnung fortgefahren wird:
1- wenn (a + b> c) und (a, b, c> 0) keine Lösung!
2- wenn (a + b <c), (a, b, c <0) keine Lösung!
3- wenn (a, b) gemeinsame entgegengesetzte Vorzeichen von c haben: keine Lösung!
4- Wenn GCD (a, b) c nicht teilt, dann keine Lösung mehr! Ansonsten teilen Sie alle Varianten durch GCD.
Danach müssen wir eine andere Bedingung überprüfen, sie sollte den Weg zur gewünschten Lösung erleichtern und verkürzen.
5- Wenn c a oder b dividiert, ist die Lösung s = (x oder y) = (c- [ax, yb]) / [b, a] = C / [b, a] + [ax, yb] / [b a] = S + [ax, yb] / [b, a], wobei S natürlich ist, so dass ax / b oder durch / a fortan nicht negative direkte Lösungen haben würden, die jeweils x = b oder y = a sind. (Beachten Sie, dass Lösungen nur Nullwerte sein können, wenn bei vorherigen beliebigen Lösungen Negative festgestellt werden.)
Wenn das Programm diese Stufe erreicht, wird ein engerer Bereich von Lösungen für x = (c-yb) / a gewobbelt, anstatt, dank der Kongruenz, größere Bereiche von Zahlen zu wobbeln, was durch regelmäßige Zyklen wiederholt wird. Das größte Suchfeld ist [xa, x + a], wobei a der Divisor ist.
VERSUCH ES
quelle
Axiom, 460 Bytes
ungolf und ein test
Bei den anderen möglichen 'Lösungen' gab es einen Fehler, weil versucht wurde, die unendlichen Lösungen in einer Liste zu speichern. Jetzt ist die Grenze von 80 Lösungen max auferlegt
quelle