Trova coppie di numeri con un particolare LCM e GCD


9

Stavo lavorando a una domanda di matematica con un mio amico e abbiamo deciso di scrivere una sceneggiatura che trova la risposta. La domanda originale è la seguente:

La differenza tra due numeri naturali è il 2010 e il loro massimo comune denominatore è 2014 volte più piccolo del loro minimo comune moltiplicarsi. Trova tutte le possibili soluzioni.

Abbiamo iniziato a scrivere il programma indipendentemente l'uno dall'altro, e quando ha funzionato abbiamo deciso di giocarci su per ottenere il minor numero di byte che potevamo gestire. Abbiamo finito con questa bellissima riga di codice a 89 byte meravigliosi.

from fractions import*;print[i for i in range(10**6)if i*(i+2010)/gcd(i,i+2010)**2==2014]

Volevamo vedere se qualcuno riesce a scrivere un pezzo di codice più breve, che elenca i primi 1 milione di i. Se sei abbastanza coraggioso da competere, puoi usare qualsiasi linguaggio tu voglia, ma preferiremmo Python 2 per poter confrontare il tuo codice con il nostro.

Si applicano le solite regole, vincono i byte più brevi. Si applicano le scappatoie da golf di codice standard. "Scappatoie" standard che non sono più divertenti

Divertiti!


2
@Rainbolt: Ok, ha permesso qualsiasi lingua. La limitazione di Python era a scopo di confronto. Ma fai quello che vuoi: D
— sammko,

Ci sono risposte diverse da 3 e 5092? Non è stato possibile trovare altro prima di 10.000.000.
— kennytm,

@KennyTM: ho ottenuto 4 e 5092. E sì, non credo che ce ne siano altri.
— Sammko,

Ehi, ho modificato il tuo titolo per riflettere meglio ciò che stai chiedendo. Sentiti libero di cambiarlo se ritieni di aver perso qualcosa.
— FryAmTheEggman,

Rimosso tag python a proposito.
— Timtech,

Risposte:


21

Mathematica, 8 byte

{4,5092}

Prova che 4 e 5092 sono le uniche soluzioni: il problema originale può essere riscritto come

x (x + 2010) = 2014 GCD (x, x + 2010) 2

Scriviamo x come 2 a 2 3 a 3 5 a 5 … e x + 2010 come 2 b 2 3 b 3 5 b 5 … Quindi l'equazione diventa

2 a 2 + b 2 3 a 3 + b 3 5 a 5 + b 5 … = 2014 2 2min (a 2 , b 2 ) 3 2min (a 3 , b 3 ) 5 2min (a 5 , b 5 ) ...

Dal 2014 = 2 × 19 × 53, abbiamo

a p + b p = 2min (a p , b p ) + {1 se p ∈ {2, 19, 53}, 0 altro}

così

a p = b p se p ≠ 2, 19, 53
a p = b p ± 1 altro

così

x + 2010 = 2 ± 1 19 ± 1 53 ± 1 x

Ci sono solo 8 possibili scelte e potremmo facilmente verificare che 4 e 5092 siano le uniche soluzioni intere positive.

Aspetta, sento gente urlare scappatoia standard ...

Mathematica, 45 byte

Select[Range[9^7],2014GCD[#,s=#+2010]^2==s#&]

4

Pyth 27 25

J2010fq+J4/*T+TJ^iTJ2U^T6

Provalo online.

Questo usa il tuo algoritmo in modo abbastanza ingenuo ... Potrei essere in grado di trovare qualcosa di meglio ...

Fondamentalmente filtra i valori che non soddisfano il criterio da range(10**6)

Grazie a @xnor per averlo sottolineato in chat gcd(x,x+2010)==gcd(x,2010)


3

Python 3, 84 byte

FryAmTheEggman ha già suggerito come rendere la tua soluzione di 88 byte, quindi non la posterò. Ma ho pensato di mostrare come è possibile ottenere ancora meno byte in Python 3:

from fractions import*
x=10**6
while x:y=x+2010;x*y-gcd(x,y)**2*2014or print(x);x-=1

(Grazie per FryAmTheEggman per i suggerimenti)

Questo non funziona in Python 2 perché printnon è una funzione.

Non sono sicuro che ci sia permesso, ma se potessimo usare al 9**9posto di 10**6quello sarebbe un altro byte.


Sapevo che c'era un modo per farlo con and/ or... non avrei pensato a Python 3;) Altro sull'argomento: Se l'ordine non ha importanza, penso che l'impostazione x=10**6e l'esecuzione while x:x-=1;...siano più brevi di un byte.
— FryAmTheEggman,

@FryAmTheEggman Dall'aspetto della domanda non sembra che l'ordine sia importante, quindi lo inserirò. Grazie!
— Sp3000,

2

R, 75 caratteri

for(a in 1:1e6){q=1:a;b=a+2010;if(a*b/max(q[!a%%q&!b%%q])^2==2014)print(a)}

Con interruzioni di riga:

for(a in 1:1e6){
    q=1:a
    b=a+2010
    if(a*b/max(q[!a%%q&!b%%q])^2==2014)print(a)
    }

2

GolfScript (41 byte)

La differenza tra due numeri naturali è il 2010 e il loro massimo comune denominatore è 2014 volte più piccolo del loro minimo comune multiplo. Trova tutte le possibili soluzioni.

Chiama i numeri ame bmdove gcd(a, b) = 1e wlog b > a. Quindi la differenza è m(b-a) = 2010, e lcm(am, bm) = abm = 2014mcosì ab=2014.

I fattori del 2014 sono

1 * 2014
2 * 1007
19 * 106
38 * 53

e quelli che hanno differenze che si dividono nel 2010 lo sono

1007 - 2 => m = 2, solution is 4, 2014
53 - 38 => m = 134, solution is 5092, 7102

Dato che sto operando in un linguaggio che non ha GCD o LCM integrato, penso che questa analisi probabilmente accorcia il programma:

44,{).2014{.2$/\@%!}:,~\2$- 2010,***}%0-`

dove 44è floor(sqrt(2014)).

È possibile avvicinarsi abbastanza usando un ciclo ingenuo:

10 6?,1>{.2010+.2${.@\%.}do;.*2014*@@*=},`

Quindi la prova di @ KettyTM che (4,5092) è l'unica soluzione non è corretta?
— Ottimizzatore

@Optimizer, stai leggendo male. Dimostra anche che ci sono due soluzioni e sono le stesse delle mie soluzioni. La sua prova è solo molto più difficile da seguire della mia (IMAO).
— Peter Taylor,

Ah vero. E sì, il tuo ha più senso del suo.
— Ottimizzatore

2

Perl6 61 58 56 54 52

Dà una traduzione abbastanza diretta della tua fonte

for ^10**6 ->\i{i.say if i*(i+2010)/(i gcd(i+2010))**2==2014}

gcd è un'operazione infix in Perl6.

^10**6è l'abbreviazione di 0 ..^ 10**6, dove i ^mezzi escludono questo numero dall'intervallo.


Ovviamente i gcd (i+2010)è lo stesso, i gcd 2010quindi posso salvare 3 personaggi

for ^10**6 ->\i{i.say if i*(i+2010)/(i gcd 2010)**2==2014}

Se uso $_invece di iposso salvare un altro paio di personaggi. ( .sayè l'abbreviazione di $_.say)

for ^10**6 {.say if $_*($_+2010)/($_ gcd 2010)**2==2014}

Posso salvare un altro paio di personaggi usando ... && .sayinvece di .say if ..., perché non ho bisogno di uno spazio su entrambi i lati &&come faccio per if.

for ^10**6 {$_*($_+2010)/($_ gcd 2010)**2==2014&&.say}

Dato che ho fatto entrambe le "ottimizzazioni" precedenti, posso usare il modulo modificatore di istruzione di for, il che significa che posso rimuovere {e }.

$_*($_+2010)/($_ gcd 2010)**2==2014&&.say for ^10**6

Penso che sia il più breve possibile senza usare un algoritmo diverso.


2

J, 26 byte

   I.((*.=+.*4--)2010+])i.1e6
4 5092

Quei dannati verbi a 2 byte ... :)


1

Dyalog APL, 29 personaggi

      a←⍳10        ⍝ the integers up to 10
      a
1 2 3 4 5 6 7 8 9 10
      2010+a       ⍝ corresponding integers at distance 2010
2011 2012 2013 2014 2015 2016 2017 2018 2019 2020
      a∨2010+a     ⍝ GCD-s between elements of a and 2010+a
1 2 3 2 5 6 1 2 3 10
      ⍝ All APL functions (e.g. + and ∨) are prefix-or-infix, right-associative,
      ⍝ and of the same precedence.
      a∧2010+a     ⍝ LCM-s
2011 2012 2013 4028 2015 2016 14119 8072 6057 2020
      ⍝ For which of them is the LCM 2014 times the GCD?
      (a∧2010+a)=2014×a∨2010+a
0 0 0 1 0 0 0 0 0 0
      ⍝ 0 means false, 1 means true
      ⍝ Filter the elements of "a" corresponding to the 1-s
      ((a∧2010+a)=2014×a∨2010+a) / a
4
      ⍝ Let's abstract this as a function by using curlies.
      ⍝ Omega (⍵) stands for the right argument.
      {((⍵∧2010+⍵)=2014×⍵∨2010+⍵) / ⍵} a
4
      ⍝ Up to a million instead of up to ten:
      {((⍵∧2010+⍵)=2014×⍵∨2010+⍵) / ⍵} ⍳1e6
4 5092
      ⍝ Hey, we can save a few characters by making 2010 the left argument, alpha (⍺)
      2010 {((⍵∧⍺+⍵)=2014×⍵∨⍺+⍵) / ⍵} ⍳1e6
4 5092
      ⍝ Remove a pair of parens by using the switch operator ⍨
      ⍝ An "operator" occurs to the right of a function and modifies its behaviour.
      ⍝ In this case A f⍨ B means the same as B f A
      ⍝ Left and right are swapped, hence "switch".
      2010 {⍵ /⍨ (⍵∧⍺+⍵)=2014×⍵∨⍺+⍵)} ⍳1e6
4 5092
      ⍝ That's 32 characters (modulo whitespace).  Not bad, but we can do better.
      ⍝ A "fork" is a sequence of 3 functions in isolation: f g h
      ⍝ It is evaluated as:  ⍺(f g h)⍵  ←→  (⍺ f ⍵)g(⍺ h ⍵)
      ⍝ If the first item is an array instead of a function: A f g  ←→  {A} f g
      ⍝ Forks are right-associative: f g h k l ←→ f g (h k l)
      2010 {⍵ /⍨ (⍺(⊢∧+)⍵)=2014×(⍺(⊢∨+)⍵)} ⍳1e6
4 5092
      ⍝ The "right tack" function (⊢) simply returns its right argument
      ⍝ Let's abuse forks a little further:
      2010 {⍵ /⍨ ⍺((⊢∧+)=(2014×(⊢∨+)))⍵} ⍳1e6
4 5092
      ⍝ ... and more
      2010 {⍺ (⊢(/⍨)((⊢∧+)=(2014×(⊢∨+)))) ⍵} ⍳1e6
4 5092
      ⍝ But {⍺ f ⍵} is equivalent to f
      2010 (⊢(/⍨)((⊢∧+)=(2014×(⊢∨+)))) ⍳1e6
4 5092
      ⍝ Note that now we are not mentioning ⍺ and ⍵ at all.
      ⍝ This is called "point-free style" or "tacit programming".
      ⍝ Removing some unnecessary parens and whitespace:
      2010(⊢(/⍨)(⊢∧+)=2014×⊢∨+)⍳1e6
4 5092
      ⍝ How many characters?
      ⍴'2010(⊢(/⍨)(⊢∧+)=2014×⊢∨+)⍳1e6'
29

1

PARI / GP, 42 byte

[n|n<-[1..8!],2014*gcd(n,t=n+2010)^2==n*t]

Sento che esiste una soluzione estremamente elegante usando il fordivcostrutto di GP ma non potrebbe competere con questa soluzione per pura brevità.


0

Racchetta, 72 caratteri

(filter(λ(i)(=(/(*(+ i 2010)i)(expt(gcd(+ i 2010)i)2))2014))(range 1e6))

1
La racchetta funziona con ISO-8859-7? Altrimenti non penso che λvalga 1 byte.
— kennytm,

0

Haskell, 52 caratteri

show [x|x<-[1..6^8],x*(x+2010)==2014*(gcd x 2010)^2]

Funziona nell'ambiente interattivo Haskell GHCi.

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.