Inverso moltiplicativo modulare


22

Il tuo compito è quello di dare due numeri interi ae bcalcolare l'inverso moltiplicativo modulare di un modulo b, se esiste.

L'inverso modulare di amodulo bè un numero ctale ac ≡ 1 (mod b). Questo numero è univoco modulo bper qualsiasi coppia di ae b. Esiste solo se il più grande divisore comune di aed bè 1.

La pagina Wikipedia per l'inverso moltiplicativo modulare può essere consultata se sono necessarie ulteriori informazioni sull'argomento.

Ingresso e uscita

L'input viene dato come due numeri interi o un elenco di due numeri interi. Il programma dovrebbe generare un singolo numero, l'inverso moltiplicativo modulare che si trova nell'intervallo 0 < c < bo un valore che indica che non vi è alcun inverso. Il valore può essere qualsiasi cosa, tranne un numero nell'intervallo (0,b)e può anche essere un'eccezione. Il valore dovrebbe tuttavia essere lo stesso per i casi in cui non vi è alcun inverso.

0 < a < b può essere assunto

Regole

  • Il programma dovrebbe terminare ad un certo punto e risolvere ogni caso di test in meno di 60 secondi
  • Si applicano scappatoie standard

Casi test

I casi di test di seguito sono riportati nel formato, a, b -> output

1, 2 -> 1
3, 6 -> Does not exist
7, 87 -> 25
25, 87 -> 7
2, 91 -> 46
13, 91 -> Does not exist
19, 1212393831 -> 701912218
31, 73714876143 -> 45180085378
3, 73714876143 -> Does not exist

punteggio

Questo è il codice golf, quindi vince il codice più breve per ogni lingua.

Questa e questa sono domande simili, ma entrambe richiedono situazioni specifiche.


6
Dal piccolo teorema di Fermat segue che l'inverso moltiplicativo di a, se esiste, può essere calcolato in modo efficiente come un ^ (phi (b) -1) mod b, dove phi è la funzione totiaria di Eulero: phi (p0 ^ k0 * p1 ^ k1 * ...) = (p0-1) * p0 ^ (k0-1) * (p1-1) * p1 ^ (k1-1) * ... Non dire che porta a un codice più breve :)
ngn

1
@Jenny_mathy In genere, non è consentito ricevere ulteriori input.
Mr. Xcoder,

3
Conto sei risposte che sembrano essere forzate brutalmente e che difficilmente eseguiranno tutti i casi di test in 60 secondi (alcuni di loro danno uno stack o un errore di memoria prima).
Ørjan Johansen,

1
@ngn: hai combinato il piccolo teorema di Fermat (FLT) con il miglioramento di Eulero. Fermat non era a conoscenza della funzione phi di Euler. Inoltre, il miglioramento di FLT ed Euler si applica solo se gcd (a, b) = 1. Infine, nella forma in cui l'hai scritto, "a ^ (\ phi (b) -1) mod b" è congruente a 1, non a a ^ (- 1). Per ottenere un ^ (- 1), usa una mod ^ (\ phi (b) -2) b.
Eric Towers,

1
@EricTowers Euler è una conseguenza. Riguardo a "gcd (a, b) = 1" - ho detto "se esiste [l'inverso]". Sei sicuro di phi (b) -2?
ngn,

Risposte:


11

Mathematica, 14 byte

Mathematica obbligatoria integrata :

ModularInverse

È una funzione che accetta due argomenti ( ae b) e restituisce l'inverso di una mod b se esiste. In caso contrario, restituisce l'errore ModularInverse: a is not invertible modulo b..


7

JavaScript (ES6), 79 73 62 61 byte

Restituisce falsese l'inverso non esiste.

Utilizza l'algoritmo euclideo esteso e risolve quasi istantaneamente tutti i casi di test.

f=(a,b,c=!(n=b),d=1)=>a?f(b%a,a,d,c-(b-b%a)/a*d):b<2&&(c+n)%n

Casi test


Perché non è possibile scrivere il nome della funzione f, come in f (c, a, b = 0, d = 1, n = a) => c? F (a% c, c, d, b- ( aa% c) / c * d, n): a <2 && (b + n)% n?
RosLuP

@RosLup f(x,y)viene sempre analizzato come una chiamata di funzione, tranne se è esplicitamente preceduto dalla functionparola chiave. Una funzione freccia anonima, d'altra parte, viene dichiarata come (x,y)=>somethinge f=(x,y)=>somethingassegna la funzione alla fvariabile.
Arnauld,

4

Gelatina , 2 byte

æi

Provalo online!

Questo utilizza un built-in per l'inverso modulare e restituisce 0 per nessun inverso modulare.

Gelatina , 7 byte

R×%⁸’¬T

Provalo online!

Emette un set vuoto (rappresentato come stringa vuota) su nessun inverso modulare. A corto di memoria su TIO per i casi di test più grandi, ma dovrebbe funzionare con sufficiente memoria.

Come funziona

R×%⁸’¬T  
R        Generate range of b
 ×       Multiply each by a
  %⁸     Mod each by b
    ’    Decrement (Map 1 to 0 and all else to truthy)
     ¬   Logical NOT
      T  Get the index of the truthy element.

Se vuoi lavorare per casi di test più grandi, prova questa versione (relativamente non rigata), che richiede molto tempo piuttosto che memoria:

Gelatina, 9 byte

×⁴%³’¬ø1#

Provalo online!

Come funziona

×⁴%³’¬ø1#
        #   Get the first
      ø1      one integer
            which meets:
×⁴            When multiplied by a
  %³          And modulo-d by b
    ’         Decrement
     ¬        Is falsy

4

Python 2 , 34 byte

f=lambda a,b:a==1or-~b*f(-b%a,a)/a

Provalo online!

Funzione ricorsiva che dà Trueper print f(1,2), che ritengo accettabile, e gli errori di input non validi.

Stiamo cercando di trovare x in ax1(modb) .

ax1=kbk

Prendere moda1kb(moda)kb1(moda)k

kf(b%a,a)

aab

kax1=kbxkb+1a


3

R + numeri , 15 byte

numbers::modinv

ritorna NAper quelli asenza inversione mod b.

R-Fiddle per provarlo!

R , 33 byte (non concorrenti)

Questo non funzionerà su dimensioni molto grandi bpoiché crea effettivamente un vettore di 32*bbit di dimensioni .

function(a,b)which((1:b*a)%%b==1)

Provalo online!

Restituisce integer(0)(un elenco vuoto) per quelli asenza inversioni mod b.


3

Mathematica, 18 byte

PowerMod[#,-1,#2]&

ingresso

[31, 73714876143]


3

Python 2 , 51 49 54 53 51 49 byte

-1 byte grazie a officialaimm
-1 byte grazie a Shaggy

a,b=input()
i=a<2
while(a*i%b-1)*b%a:i+=1
print+i

Provalo online!

Stampa 0quando non c'è soluzione.


1
Uscite 0per a=1e b=2; dai casi di test, dovrebbe essere generato 1.
Shaggy,

Algo

1
Come ha sottolineato Shaggy, fallisce per2, 1
Mr. Xcoder il

@Shaggy dovrebbe funzionare ora
Rod

Questo non riesce a restituire una risposta in 60 secondi (su TIO) per l'ingresso 31,73714876143.
Ilmari Karonen,

3

Japt , 9 8 byte

Porta gli ingressi in ordine inverso. Uscite -1per nessuna corrispondenza. Salta fuori mentre l'intero più grande diventa più grande.

Ç*V%UÃb1

Provalo

  • Salvato 1 byte grazie all'ETH che indica uno spazio errato e molto ovvio.

L'input del test 73714876143,31sembra produrre un errore di memoria insufficiente su Firefox (e arrestare in modo anomalo Chromium). Non penso che questa sia una risposta valida.
Ilmari Karonen,

@IlmariKaronen: ho chiaramente indicato questo fatto nella mia soluzione. Possiamo assumere memoria infinita ai fini del code golf, quindi i problemi di memoria e gli arresti anomali non invalidano questa soluzione.
Shaggy,

1
Sfortunatamente i problemi di memoria rendono anche impossibile stabilire se il tuo codice risolverà effettivamente i casi di test in 60 secondi, come previsto dalla sfida. Sospetto che non lo farebbe, anche se fosse disponibile memoria sufficiente per non farlo arrestare, ma senza un computer in grado di eseguire il programma per così tanto tempo non c'è modo di dirlo con certezza.
Ilmari Karonen,


2

Python 3 , 49 byte

lambda a,b:[c for c in range(b)if-~c*a%b==1][0]+1

Provalo online!

Python 3 , 50 byte

lambda a,b:[c for c in range(1,b+1)if c*a%b==1][0]

Provalo online!

Ciò genera IndexError: list index out of rangenel caso in cui non vi sia un inverso moltiplicativo modulare, come consentito dalle regole.


Questo non restituisce un risultato per l'ingresso 31,73714876143in 60 secondi (su TIO).
Ilmari Karonen,

@IlmariKaronen sembra finire in 56 secondi sulla mia macchina (Macbook Pro '15)
Mr. Xcoder

2

8 , 6 byte

Codice

invmod

Spiegazione

invmod è un'ottava parola che calcola il valore dell'inverso di a , modulo b. Ritorna nullsu overflow o altri errori.

Utilizzo e casi di test

ok> 1 2 invmod .
1
ok> 3 6 invmod .
null
ok> 7 87 invmod .
25
ok> 25 87 invmod .
7
ok> 2 91 invmod .
46
ok> 13 91 invmod .
null
ok> 19 1212393831 invmod .
701912218
ok> 31 73714876143 invmod .
45180085378
ok> 3 73714876143 invmod .
null


2

J , 28 byte

4 :'(1=x+.y)*x y&|@^<:5 p:y'

Provalo online!

usi il teorema di Eulero . Restituisce 0 se l'inverso non esiste.

Spiegazione

4 :'(1=x+.y)*x y&|@^<:5 p:y'  Input: a (LHS), b (RHS)
4 :'                       '  Define an explicit dyad - this is to use the special
                              form `m&|@^` to perform modular exponentiation
                          y   Get b
                      5 p:    Euler totient
                    <:        Decrement
             x                Get a
                   ^          Exponentiate
               y&|@             Modulo b
       x+.y                   GCD of a and b
     1=                       Equals 1
            *                 Multiply

2

Pyth , 10 byte

3 byte salvati grazie a @Jakube .

xm%*szdQQ1

Provalo qui!

Restituisce -1per nessun inverso moltiplicativo.

Analisi del codice

xm%*szdQQ1      Let Q be the first input.
 m      Q       This maps over [0 ... Q) with a variable d.
   *szd         Now d is multiplied by the evaluated second input.
  %    Q        Now the remained modulo Q is retrieved.
x        1      Then, the first index of 1 is retrieved from that mapping.

Pyth , 15 13 byte

KEhfq1%*QTKSK

Genera un'eccezione nel caso in cui non esista un inverso moltiplicativo.

Provalo qui!

Pyth , 15 byte

Iq1iQKEfq1%*QTK

Ciò aggiunge molti byte per la gestione del caso in cui non esiste un numero simile. Il programma può essere abbreviato in modo significativo se tale caso non dovesse essere gestito:

fq1%*QTK

Provalo qui!


2 byte salvati conKExm%*QdKK1
Jakube il

Oppure 3 byte se si scambia l'ordine degli input:xm%*szdQQ1
Jakube,

@Jakube Grazie mille, modifica!
Mr. Xcoder,

Come funziona?
Kritixi Lithos,

@Cowsquack Ho aggiunto una suddivisione del codice completamente primitiva, ma non ho tempo di includere una spiegazione completa. Spero sia abbastanza chiaro per ora, ma proverò ad aggiungere presto una spiegazione più completa.
Mr. Xcoder,

1

C (gcc) , 115 byte

#define L long long
L g(L a,L b,L c,L d){return a?g(b%a,a,d-b/a*c,c):b-1?0:d;}L f(L a,L b){return(g(a,b,1,0)+b)%b;}

Provalo online!

Algoritmo euclideo esteso, versione ricorsiva

C (gcc) , 119 byte

long long f(a,b,c,d,t,n)long long a,b,c,d,t,n;{for(c=1,d=0,n=b;a;a=t)t=d-b/a*c,d=c,c=t,t=b%a,b=a;return b-1?0:(d+n)%n;}

Provalo online!

Algoritmo euclideo esteso, versione iterativa


1

C (gcc) , 48 110 104 byte

#define f(a,b)g(a,b,!b,1,b)
long g(a,b,c,d,n)long a,b,c,d,n;{a=a?g(b%a,a,d,c-(b-b%a)/a*d):!--b*(c+n)%n;}

Provalo online!

Questo dovrebbe funzionare con tutti gli input (che si adattano in poco tempo) entro 60 secondi.

Modificare. Sto già abusando della nvariabile, quindi potrei anche supporre che gcc inserisca il primo compito %rax.


1
Purtroppo, ciò dà risultati errati anche per input abbastanza piccoli a causa di un overflow di numeri interi all'interno del loop. Ad esempio, f(3,1000001)restituisce 717, che è ovviamente senza senso (la risposta corretta è 333334). Inoltre, anche se questo bug fosse corretto usando un tipo intero più ampio, questo approccio a forza bruta sarebbe sicuramente scaduto per alcuni dei più grandi casi di test forniti nella sfida.
Ilmari Karonen,


0

Assioma, 45 byte

f(x:PI,y:PI):NNI==(gcd(x,y)=1=>invmod(x,y);0)

0 per errore altrimenti restituisci z con x * z Mod y = 1


0

Python 2 , 52 byte

-3 byte grazie a Mr. Xcoder.

f=lambda a,b,i=1:i*a%b==1and i or i<b and f(a,b,i+1)

Provalo online!

I risultati Falsesu nessuna soluzione e gli errori si estendono man mano che baumenta.

TIO incorporato

Sto solo testando iframe in Stack Snippet e funzionano in modo assolutamente fantastico.


Io non sono certo queste opere, non può i*a%bessere 0?
Mago del grano

Errore con "profondità massima di ricorsione superata" per input (31,73714876143).
Ilmari Karonen,

0

JavaScript (ES6), 42 41 39 38 byte

Uscite falseper nessuna corrispondenza. Emetterà un errore di overflow poiché il secondo numero diventa troppo grande.

x=>y=>(g=z=>x*z%y==1?z:z<y&&g(++z))(1)

0

Gelatina , 27 byte

²%³
⁴Ç⁹Сx⁸
ÆṪ’BṚçL$P%³×gỊ¥

Provalo online!

Usa il teorema di Eulero con esponenziazione modulare. Dal momento che Jelly non ha un builtin per eseguire esponentiation modulare, ha dovuto essere implementato e ha impiegato la maggior parte dei byte.


0

Assioma, 99 byte

w(a,b,x,u)==(a=0=>(b*b=1=>b*x;0);w(b rem a,a,u,x-u*(b quo a)));h(a,b)==(b=0=>0;(b+w(a,b,0,1))rem b)

usa la funzione h (); h (a, b) restituisce 0 se l'errore [non esiste inverso] altrimenti restituisce z tale che a * z mod b = 1 Ciò andrebbe bene anche se gli argomenti sono negativi ...

questa sarebbe la funzione generale egcd () che restituisce un elenco di int (quindi possono anche essere negativi)

egcd(aa:INT,bb:INT):List INT==
   x:=u:=-1   -- because the type is INT
   (a,b,x,u):=(aa,bb,0,1)
   repeat
      a=0=>break
      (q,r):=(b quo a, b rem a)
      (b,a,x,u):=(a,r,u,x-u*q)
   [b,x, (b-x*aa)quo bb]

questo è come usarlo

(7) -> h(31,73714876143)
   (7)  45180085378
                                                    Type: PositiveInteger

trovo l'algo di base in internet da https://pastebin.com/A13ybryc

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.