Eine Formel für Kongruenzen

10

Der chinesische Restsatz kann in der modularen Arithmetik sehr nützlich sein.

Betrachten Sie beispielsweise die folgenden Kongruenzbeziehungen:

Kongruenzsatz

Für Gruppen von Kongruenzrelationen wie diese, in dem alle Basen ( 3, 5, 7in diesem Beispiel) sind Co-prime miteinander, wird es eine sein und nur ein ganze Zahl nzwischen 1und das Produkt der Basen ( 3*5*7 = 105in diesem Beispiel) , Grenzen eingeschlossen , die erfüllen die Beziehungen .

In diesem Beispiel würde die Zahl 14durch diese Formel generiert werden:

Formel

wo 2, 4, and 0sind aus dem obigen Beispiel angegeben.

70, 21, 15sind die Koeffizienten der Formel und sie sind abhängig von den Basen , 3, 5, 7.

Um die Koeffizienten der Formel ( 70, 21, 15in unserem Beispiel) für eine Reihe von Basen zu berechnen , verwenden wir das folgende Verfahren.

Für jede Zahl ain einer Reihe von Basen:

  1. Finden Sie das Produkt aller anderen Basen, bezeichnet als P.
  2. Finden Sie das erste Vielfache davon P, das einen Rest ergibt, 1wenn durch geteilt a. Dies ist der Koeffizient von a.

Um beispielsweise den Koeffizienten zu berechnen, der der Basis entspricht 3, finden wir das Produkt aller anderen Basen (dh 5*7 = 35) und dann das erste Vielfache dieses Produkts, das einen Rest hinterlässt, 1wenn es durch die Basis geteilt wird.

In diesem Fall 35bleibt ein Rest von 2geteilt durch 3, 35*2 = 70bleibt aber ein Rest von 1geteilt durch 3, so 70ist der entsprechende Koeffizient für 3. In ähnlicher Weise 3*7 = 21bleibt ein Rest von 1geteilt durch 5und 3*5 = 15ein Rest von 1geteilt durch 7.

In einer Nussschale

Für jede Zahl ain einer Reihe von Zahlen:

  1. Finden Sie das Produkt aller anderen Zahlen, bezeichnet als P.
  2. Finden Sie das erste Vielfache davon P, das einen Rest ergibt, 1wenn durch geteilt a. Dies ist der Koeffizient von a.

Die Herausforderung

  • Die Herausforderung besteht darin, für einen Satz von zwei oder mehr Basen den Satz entsprechender Koeffizienten zu finden.
  • Es ist garantiert, dass der Satz von Basen paarweise ko-primiert, und jede Basis ist garantiert größer als 1.
  • Ihre Eingabe ist eine Liste von Ganzzahlen als Eingabe [3,4,5]oder durch Leerzeichen getrennte Zeichenfolge, "3 4 5"oder wie auch immer Ihre Eingaben funktionieren.
  • Ihre Ausgabe sollte entweder eine Liste von Ganzzahlen oder eine durch Leerzeichen getrennte Zeichenfolge sein, die den Satz von Koeffizienten angibt.

Testfälle

input             output
[3,5,7]           [70,21,15]
[2,3,5]           [15,10,6]
[3,4,5]           [40,45,36]
[3,4]             [4,9]
[2,3,5,7]         [105,70,126,120]
[40,27,11]        [9801,7480,6480]
[100,27,31]       [61101,49600,56700]
[16,27,25,49,11]  [363825,2371600,2794176,5583600,529200]

Vielen Dank an Leaky Nun für seine Hilfe beim Schreiben dieser Herausforderung. Wie immer, wenn das Problem unklar ist, lassen Sie es mich bitte wissen. Viel Glück und gutes Golfen!

Sherlock9
quelle
Wird es immer 3 Zahlen in der Eingabe geben?
xnor
@xnor Nein. Testfälle bearbeitet.
Sherlock9

Antworten:

5

Haskell, 61 55 53 Bytes

f x=[[p|p<-[0,product x`div`n..],p`mod`n==1]!!0|n<-x]

Definiert eine Funktion f, die Eingaben akzeptiert und Ausgaben als Liste von Ganzzahlen ausgibt.

f x=[                                          |n<-x]  (1)
              product x                                (2)
                       `div`n                          (3)

Zuerst durchlaufen wir alle ganzen Zahlen in der Eingabe (1). Dann nehmen wir das Produkt aller ganzen Zahlen (2) und dividieren durch n, um nur das Produkt der nicht nganzen Zahlen zu erhalten, nämlich P(3).

           [0,               ..]                       (4)
     [p|p<-                     ,p`mod`n==1]           (5)
                                            !!0        (6)

Dann verwenden wir das Ergebnis ( P) als Schrittwert für einen Bereich, der bei Null beginnt (4). Wir nehmen das Ergebnis [0, P, 2P, 3P, ...]und filtern es nach Werten, für die das Ergebnis einer mod-n-Operation eins ist (5). Schließlich nehmen wir das erste Element, das dank der verzögerten Bewertung funktioniert (6).

Danke an @xnor für 2 Bytes!

Türknauf
quelle
1
Willkommen bei haskell! Ich denke du quotkannst ein sein divund headkann sein !!0.
xnor
4

Gelee , 11 7 Bytes

P:*ÆṪ%P

Probieren Sie es online aus! oder überprüfen Sie alle Testfälle .

Hintergrund

Sei P und a streng positiv, Coprime- Ganzzahlen.

Der zweistufige Prozess in der Frage - Finden eines Vielfachen von P , das einen Rest von 1 ergibt, wenn es durch a geteilt wird - kann durch die folgende Kongruenzgleichung beschrieben werden.

lineare Kongruenzgleichung

Nach dem Euler-Fermat-Theorem haben wir

Euler-Fermat-Theorem

wobei φ die Totientenfunktion von Euler bezeichnet . Aus diesem Ergebnis leiten wir Folgendes ab.

Formel für die lineare Kongruenzgleichung

Da die Herausforderung erfordert, dass wir Px berechnen , beobachten wir dies

Formel für das Endergebnis

wobei Pa als Produkt aller Module berechnet werden kann.

Wie es funktioniert

P:*ÆṪ%P  Main link. Argument: A (list of moduli)

P        Yield the product of all moduli.
 :       Divide the product by each modulus in A.
   ÆṪ    Apply Euler's totient function to each modulus.
  *      Raise each quotient to the totient of its denominator.
     %P  Compute the remainder of the powers and the product of all moduli.
Dennis
quelle
2

J, 13 Bytes

*/|5&p:^~*/%]

Basierend auf der erstaunlichen Antwort von @Dennis .

Verwendungszweck

Einige Testfälle benötigen die Eingabe als erweiterte Ganzzahlen mit einem Suffix x.

   f =: */|5&p:^~*/%]
   f 3 5 7
70 21 15
   f 40x 27 11
9801 7480 6480
   f 16x 27 25 49 11
363825 2371600 2794176 5583600 529200

Erläuterung

*/|5&p:^~*/%]  Input: list B
         */    Reduce B using multiplication to get the product of the values
            ]  Identity function, get B
           %   Divide the product by each value in B, call the result M
   5&p:        Apply the totient function to each value in B, call the result P
       ^~      Raise each value in M to the power of its corresponding value in P
*/             The product of the values in B
  |            Compute each power modulo the product and return

Probieren Sie es hier aus.

Meilen
quelle
2

Mathematica, 27 Bytes

PowerMod[a=LCM@@#/#,-1,#]a&
Alephalpha
quelle
1

Pyth , 14 Bytes

mhfq1%Td*R/*FQ

Testsuite.

Naive Implementierung des Algorithmus.

Undichte Nonne
quelle
1

Gelee, 14 13 Bytes

P:×"Ḷð%"’¬æ.ḷ

Dank @ Dennis ein Byte gespeichert !

Verwendet den in der Challenge-Spezifikation beschriebenen Prozess. Die Eingabe ist eine Liste von Basen und die Ausgabe ist eine Liste von Koeffizienten.

Probieren Sie es online aus oder überprüfen Sie alle Testfälle .

Erläuterung

P:×"Ḷð%"’¬æ.ḷ  Input: a list B
P              Get the product of the list
 :             Divide it by each value in the B, call it M
    Ḷ          Get a range from 0 to k for k in B
  ×"           Vectorized multiply, find the multiples of each M
     ð         Start a new dyadic chain. Input: multiples of M and B
      %"       Vectorized modulo, find the remainders of each multiple by B
        ’      Decrement every value
               If the remainder was 1, decrementing would make it 0
         ¬     Logical NOT, zeros become one and everything else becomes 0
            ḷ  Get the multiples of M
          æ.   Find the dot product between the modified remainders and the multiples
               Return
Meilen
quelle
1

JavaScript (ES6), 80 Byte

a.map(e=>[...Array(e).keys()].find(i=>p*i/e%e==1)*p/e,p=a.reduce((i,j)=>i*j))

Ich habe den erweiterten euklidischen Algorithmus ausprobiert, aber er benötigt 98 Bytes:

a=>a.map(e=>(r(e,p/e)+e)%e*p/e,p=a.reduce((i,j)=>i*j),r=(a,b,o=0,l=1)=>b?r(b,a%b,t,o-l*(a/b|0)):o)

Wenn alle Werte prim sind, kann ES7 dies in 56 Bytes tun:

a=>a.map(e=>(p/e%e)**(e-2)%e*p/e,p=a.reduce((i,j)=>i*j))
Neil
quelle
1

Python + SymPy, 71 Bytes

from sympy import*
lambda x:[(prod(x)/n)**totient(n)%prod(x)for n in x]

Dies verwendet den Algorithmus aus meiner Jelly-Antwort . E / A besteht aus Listen mit SymPy-Nummern.

Dennis
quelle
1

Python 2, 87 84 Bytes

Eine einfache Implementierung des Algorithmus. Golfvorschläge willkommen.

a=input();p=1
for i in a:p*=i
print[p/i*j for i in a for j in range(i)if p/i*j%i==1]
Sherlock9
quelle
Ein vollständiges Programm würde 3 Bytes sparen.
Dennis
1

Cheddar , 64 Bytes

n->n.map(i->(|>i).map(j->(k->k%i>1?0:k)(n.reduce((*))/i*j)).sum)
Undichte Nonne
quelle
Ich sollte ein hinzufügen, .productwas .reduce((*))für Arrays gilt ...
Downgoat
0

GAP , 51 Bytes

GAP hat eine Funktion, mit der das motivierende Beispiel berechnet werden kann ChineseRem([2,5,7],[2,4,0]), die es jedoch nicht so einfach macht, die Koeffizienten zu ermitteln. Wir können den n-ten Koeffizienten erhalten, indem wir die Liste mit einer Eins an der n-ten Position und Nullen an den anderen Positionen als zweites Argument verwenden. Wir müssen also diese Listen erstellen und die Funktion auf alle anwenden:

l->List(Basis(Integers^Size(l)),b->ChineseRem(l,b))
Christian Sievers
quelle
0

Stapel, 148 Bytes

@set p=%*
@set/ap=%p: =*%
@for %%e in (%*)do @for /l %%i in (1,1,%%e)do @call:l %%e %%i
@exit/b
:l
@set/an=p/%1*%2,r=n%%%1
@if %r%==1 echo %n%
Neil
quelle
0

Eigentlich 14 Bytes

Dies verwendet den Algorithmus in Dennis 'Jelly-Antwort . Eine weitere Antwort, die auf meiner Python-Antwort basiert, ist in Vorbereitung. Golfvorschläge willkommen. Probieren Sie es online aus!

;π;)♀\;♂▒@♀ⁿ♀%

Wie es funktioniert

                 Implicit input a.
;                Duplicate a.
 π;)             Take product() of a, duplicate and rotate to bottom.
    ♀\           Integer divide the product by each element of a. Call this list b.
      ;♂▒        Take that list, duplicate, and get the totient of each element.
         @♀ⁿ     Swap and take pow(<item in b>, <corresponding totient>)
            ♀%   Modulo each item by the remaining duplicate product on the stack.
                 Implicit return.

Eine weitere Antwort basiert auf meiner Python-Antwort mit 22 Bytes. Golfvorschläge willkommen. Probieren Sie es online aus!

;π╖`╝╛╜\╛r*"╛@%1="£░`M

Wie es funktioniert

            Implicit input a.
;π╖         Duplicate, take product of a, and save to register 0.
`...`M      Map over a.
  ╝           Save the item, b, in register 1.
  ╛╜\         product(a) // b. Call it P.
  ╛r          Take the range [0...b].
  *           Multiply even item in the range by P. Call this list x.
  "..."£░     Turn a string into a function f.
              Push values of [b] where f returns a truthy value.
    ╛@%         Push b, swap, and push <item in x> % b.
    1=          Does <item> % b == 1?
            Implicit return.
Sherlock9
quelle