Зробіть два числа одночасно простими, зберігаючи їх найменше спільне кратне


20

Дано два натуральних числа aі bвиведіть два натуральних числа cта dтаке, що:

Якщо є кілька можливих відповідей, ви можете вивести лише один або всі з них.

Тестові приклади:

 a  b  c  d
12 18  4  9
18 12  9  4
 5  7  5  7
 3  6  1  6 or 3 2
 9  9  9  1 or 1 9
 6 15  2 15 or 6 5
 1  1  1  1

Це . Найкоротша відповідь у байтах виграє.


Що змушує мене повернутися (1, LCM)?
Ніл

1
@Neil Вимога, яка dрозділяєb
Leaky Nun

4
Можливо, вам слід визначити LCM або принаймні не використовувати абревіатуру. Я не знав, про що мене просять трохи.
Пшеничний майстер

Відповіді:


7

Желе , 21 13 байт

ÆEz®0iṂ$¦€ZÆẸ

Спробуйте в Інтернеті!

Якщо a = 2 A · 3 B · 5 C ·… і b = 2 α · 3 β · 5 γ ·… , то обчислюємо

  • c = 2 A> α? A: 0 · 3 B> β? B: 0 · 5 C> γ? C: 0 ·…

  • d = 2 A> α? 0: α · 3 B> β? 0: β · 5 C> γ? 0: γ ·…

Тепер lcm (c, d) = 2 max (A> α? A: 0, A> α? 0: α) ·… = 2 max (A, α) · 3 max (B, β) ·… = lcm ( а, б)

і gcd (c, d) = 2 хв (A> α? A: 0, A> α? 0: α) ·… = 2 0 · 3 0 · 5 0 ·… = 1 .

Іншими словами: почати з (c, d) = (a, b) . Тоді для кожного найвищого простору розділіть цей простір увесь шлях від факторизації c або d : залежно від того, хто має найменший показник для цього простого. (У цій реалізації, у випадку, коли нічия, c втрачає свій показник.)

Отже, якщо a = 2250 = 2 1 · 3 2 · 5 3 і b = 360 = 2 3 · 3 2 · 5 1 ,

тоді c = 2 0 · 3 0 · 5 3 = 125 і d = 2 3 · 3 2 · 5 0 = 72 .

Джонатан Аллан покатався з 8 байтів! Дякую ~


Це мій оригінальний алгоритм ... Алгоритм Perl краще.
Leaky Nun

Дуже хороша. Ось він у 12 байтах
Джонатан Аллан

Ось ще 12 байтÆEZ×Ụ’$€$ZÆẸ
миль

Це тепер дає [1,18]для [15,18]. Початкова версія повертала правильну відповідь ( [5,18]).
Арнольд

1
Ага - так, нам знадобиться заповнювач нуля при транспонеті. ÆEz®0iṂ$¦€ZÆẸповинен зробити трюк на 13.
Джонатан Аллан

4

R, 143 139 123 байт

f=function(a,b,q=1:(a*b))for(i in 1:a)for(j in 1:b)if(!a%%i+b%%j&max(q[!i%%q+j%%q])<2&i*j==min(q[!q%%a+q%%b]))cat(i,j,"\n")

(Дякую @Giuseppe за ті 19 байт!)

З відступами, новими рядками та деякими поясненнями:

f=function(a,b,
           q=1:(a*b)) #Defined as function arguments defaults to avoid having to use curly brackets
    for(i in 1:a)
        for(j in 1:b)
            if(!a%%i + b%%j & #Is a divided by c and b divided by d
               max(q[!i%%q+j%%q])<2 & #Are c and d coprimes
               i*j==min(q[!q%%a+q%%b])) #Is this the same lcm
                   cat(i,j,"\n") #Then print

Тестові приклади:

> f=function(a,b,q=1:(a*b))for(i in 1:a)for(j in 1:b)if(!a%%i+b%%j&max(q[!i%%q+j%%q])<2&i*j==min(q[!q%%a+q%%b]))cat(i,j,"\n")
> f(5,7)
5 7 
> f(12,18)
4 9 
> f(6,15)
2 15 
6 5 
> f(1,1)
1 1 

!має вищий пріоритет перед &та, |але нижчий за +та *; ви повинні мати можливість покататись на кілька байт; тобто !i%%q&j%%qмає бути еквівалентним!i%%q+j%%q
Джузеппе

1
Гаразд добре спостереження: якщо GCD(c,d)==1, значить LCM(c,d)==c*d. Тож ми можемо перевірити, GCD(c,d)==1а потім перевірити, чи не c*d==a*b/GCD(a,b)є останній LCM(a,b)...
Джузеппе

1
Справді! (хоча обчислення a*b/GCD(a,b)не коротше LCM(a,b)).
планнапус

120 байт - анонімна функція + буквальний новий рядок для -3 байт
Джузеппе

4

Лушпиння , 10 байт

→ÖF§-⌋⌉ΠmḊ

Груба сила. Бере і повертає списки, і працює також для більш ніж двох номерів. Спробуйте в Інтернеті!

Пояснення

→ÖF§-⌋⌉ΠmḊ  Implicit input, say [6,15]
        mḊ  Map divisors: [[1,2,3,6],[1,3,5,15]]
       Π    Cartesian product:[[1,1],[2,1],[1,3],[2,3],[3,1],[1,5],[3,3],[6,1],[1,15],[2,5],[3,5],[6,3],[2,15],[6,5],[3,15],[6,15]]
 Ö          Sort by
  F         reduce by
     ⌉      lcm
   -⌋       minus gcd: [[1,1],[3,3],[2,1],[1,3],[3,1],[6,3],[1,5],[2,3],[6,1],[2,5],[3,15],[1,15],[3,5],[6,15],[2,15],[6,5]]
→           Get last element: [6,5]

3

Математика, 82 байти

#&@@Select[Subsets[Flatten@Divisors[{t=#,r=#2}],{2}],GCD@@#==1&&LCM@@#==t~LCM~r&]&

Я не впевнений, але чи не могли ви використовувати індексацію списку Select[...][[1]]замість того, First@Select[...]щоб зберегти байт?
Джонатан Фрех

так, але тоді я міг би використати #&@@замість того, [[1]]щоб зберегти ще одне ;-)
J42161217

3

JavaScript (ES6), 90 84 80 байт

Займає введення в синтаксис currying (a)(b)і повертає масив з 2 цілих чисел.

a=>g=(b,c=1)=>(G=(a,b)=>b?G(b,a%b):a)(c,d=a*b/G(a,b)/c)-1|a%c|b%d?g(b,c+1):[c,d]

Тестові кейси

Як?

a =>                            // a = first input
  g = (                         // g = recursive function that takes:
    b,                          //   b = second input
    c = 1                       //   c = first output divisor, initially set to 1
  ) =>                          //
    (G = (a, b) =>              // G = function that takes a and b
      b ? G(b, a % b) : a       //     and returns the greatest common divisor
    )(                          // we call it with:
      c,                        //   - c
      d = a * b / G(a, b) / c   //   - d = LCM(a, b) / c = a * b / GCD(a, b) / c
    ) - 1 |                     // if the result is not 1 (i.e. c and d are not coprime)
    a % c |                     // or c does not divide a
    b % d ?                     // or d does not divide b:
      g(b, c + 1)               //   do a recursive call with c + 1
    :                           // else:
      [c, d]                    //   return [c, d], a valid factorization of the LCM

3

MATL , 17 16 байт

&YFt&X>2:!=*^!Xp

Спробуйте в Інтернеті!

Той самий метод, що і розчини Jeln's Jelly

Минув час, коли я використовував будь-який MATL (або матлаб з цього питання), тому багато вдосконалень можливо.


3

Haskell ,50 48 47 45 42 байти

(?)=gcd;a!b|c<-div a$a?b=(c*c?b,div b$c?b)

Ідея: я це помітив c*d = a*b/gcd(a,b). Отже алгоритм виконує два етапи:

  1. Почніть з c' = a/gcd(a,b)і d' = b. Це відповідає всім вимогам, крім цього, c'і d'повинно бути співпрацівником.
  2. Щоб зробити їх спільними, я обчислюю, e = gcd(c',d')а потім встановлюю c = c'*eі d = d'/e. Це зберігає всі властивості (оскільки комбіновані фактори залишаються однаковими), але оскільки я видаляю всі спільні фактори d, я створюю cта dберуть участь у роботі.

У моєму здійсненні c'просто називається c.

Спробуйте в Інтернеті!

-3 байти завдяки Лайконі


Використання захисного шаблону для прив’язки cзаощаджує 3 байти: Спробуйте в Інтернеті!
Лайконі

@Laikoni О, я навіть не знав цього фокусу. Спасибі!
Сачан


2

R , 126 байт

function(a,b,g=function(x,y)ifelse(o<-x%%y,g(y,o),y),l=a*b/g(a,b))matrix(c(C<-(1:l)[!l%%1:l],D<-l/C),,2)[g(C,D)<2&!a%%C+b%%D,]

Спробуйте в Інтернеті!

Це вимагає іншого (і , мабуть , менш golfy) підхід до знаходження значень , ніж інший R відповіді .

Пояснення:

function(a,b){
 G <- function(x,y)ifelse(o<-x%%y,G(y,o),y) #gcd function, vectorized for x,y
 l <- a*b/g(a,b)                            #lcm of a,b
 C <- (1:l)[!l%%1:l]                        #divisors of l
 D <- l/C                                   #l/C is the other half of the pair
 rel_prime <- G(C, D) < 2                   #pairs where C,D are relatively prime, lol, GCD
 a_div <- !a%%C                             #divisors of a
 b_div <- !b%%D                             #divisors of b
 C <- C[rel_prime & a_div & b_div]
 D <- D[rel_prime & a_div & b_div]          #filter out the bad pairs
 matrix(c(C,D),,ncol = 2)                   #matrix of pairs, returned
}

за винятком того, що я підбираю всі визначення як аргументи за замовчуванням і роблю всі обчислення в одному рядку для гольф.



2

Haskell , 91 74 байт

a!b=[(x,y)|x<-[1..a],y<-[1..b],rem a x+rem b y+gcd x y<2,lcm a b==lcm x y]

Спробуйте в Інтернеті!

Збережено 17 байт завдяки Лайконі


1
u*v`div`gcd u vзберігає байт.
Лінн

Чи є якась причина не використовувати вбудовану lcmфункцію?
Лайконі

Також rem a x+rem b y+gcd x y<2має працювати.
Лайконі

@Laikoni дуже вагома причина: я навіть не знав, що вбудований lcmіснує. rem a x+rem b y+gcd x y<2працює, і мені цікаво, чи rem a x+rem b y+gcd x y+lcm a b-lcm x y<2 працює. Існує , може бути , а (математична) гарантія того, що lcm a b>=lcm x y.
jferard

1
Дійсно, lcm a b>=lcm x yтому що 1. x=x1*...*xi(просте розкладання) y=y1*...yj, lcm x y=z1*...*zkде z1,...,zkзагальні для x1,...,xiі y1,...,yj. 2. a=u1*...*um*x1*...*xi(первинне розкладання) b=v1*...vn*y1*...yj, lcm a b=t1*...*tlде t1,...,tlзагальні для u1*...*um*x1*...*xiі v1*...vn*y1*...yj. Очевидно, що t1,...,tlмістить z1,...,zk, таким чином lcm a b>=lcm x y. Але це не корисно для написання умови як суми.
jferard


1

Python 3 , 129 байт

lambda a,b:[[c,d]for c in range(1,-~a)for d in range(1,-~b)if((gcd(c,d)<2)*a*b/gcd(a,b)==c*d/gcd(c,d))>a%c+b%d]
from math import*

Спробуйте в Інтернеті! або Спробуйте тестовий набір.

Виводить усі можливі комбінації у вигляді вкладеного списку.


3
Ви і ваш побітовое матеріал ... -~aі -~bможна просто переписати так a+1і b+1для зручності читання: P
Stephen

1
@Stephen Як ви можете бачити, я спеціалізуюся на заплутування
г Xcoder

Не працює для мого нещодавно доданого другого тесту.
Лина монашка

@LeakyNun Відкотився назад. Не встигли перевірити справність гольфу.
Містер Xcoder

1

Желе ,  19 15  14 байт

-4 із вказівником від Leaky Nun (використовуйте вбудований дільник)

Я майже на 100% впевнений, що це не спосіб насправді зробити це, але ось перша спроба.
Давайте подивимося, хто перевершує це на сім-вісім байт!
Так ... дивіться відповідь Лінн з поясненням!

g/־l/
ÆDp/ÇÐṂ

Монадійне посилання, що бере список двох чисел і повертає список списків можливостей.

Спробуйте в Інтернеті!

Як?

g/־l/  - Link: gcd divided by lcm: list [x, y]
g/      - reduce by gcd = gcd(x, y)
   æl/  - reduce by lcm = lcm(x,y)
  ÷     - divide

ÆDp/ÇÐṂ - Main link: list [a, b]    e.g. [160, 90]
ÆD      - divisors (vectorises)          [[1,2,4,5,8,10,16,20,32,40,80,160],[1,2,3,5,6,9,10,15,18,30,45,90]]
  p/    - reduce by Cartesian product    [[1,1],[1,2],...,[1,90],[2,1],[2,2],...,[2,90],....,[160,90]]
     ÐṂ - entries for which this is minimal:
    Ç   -   call the last link (1) as a monad

Давайте подивимося, хто перевершує це на сім-вісім байт! - Не думайте так ...
Містер Xcoder

Ви думаєте, шість? ... ПЕТЬ ?!
Джонатан Аллан

: P Ні ... Я не думаю, що можливе менше ~ 13-15 (звичайно, Денніс не погодиться!)
Містер Xcoder

Вбудований дільник?
Leaky Nun

Так, ÆDале (знизайте плечима) мозок, очевидно, не в снасті ...
Джонатан Аллан

1

Perl 6 , 72 байти

{([X] map {grep $_%%*,1..$_},@^a).grep:{([lcm] @a)==([lcm] $_)==[*] $_}}

Спробуйте в Інтернеті!

Бере список (а, б). Повертає список усіх можливих списків (c, d).

Пояснення:

-> @ab {
    # Generate all pairs (c, d)
    ([X]
         # where c divides a and d divides b.
         map { grep $_%%*, 1..$_ }, @ab)
    # Only keep pairs with lcm(a, b) = lcm(c, d) and lcm(c, d) = c * d.
    # The latter implies gcd(c, d) = 1.
    .grep: { ([lcm] @ab) == ([lcm] $_) == [*] $_ }
}


1

Python 2 + symy , 148 байт

from sympy import*
a,b=input()
c=d=z=1
while(a/c*c+b/d*d<a+b)+gcd(c,d)-1+(lcm(c,d)!=lcm(a,b)):E=c==d==z;Q=c==z;d=+E or Q+d;c=+Q or-~c;z+=E
print c,d

Спробуйте в Інтернеті!

-1 завдяки Джонатану Фреху .

Ця відповідь працює в Python 2 (не Python 3), використовуючи sympy.gcdі sympy.lcmзамість цього, math.gcdі math.lcmякі доступні лише в Python 3. І так, це груба сила :)


Гольф триває ...
Erik the Outgolfer

Ви можете зберегти байт, визначивши Q=c==z;(+7 байт) на початку циклу while та замінивши or(c==z)+dна or Q+d(-4 байти) та c=+(c==z)orна c=+Q or(-4 байти). ( TIO )
Джонатан Фрех

Як питання, чи використовуєте ви +оператор у d=+Eабо c=+(c==z)для перетворення булевого значення в ціле число?
Джонатан Фрех

@JonathanFrech Yes I am, since you can't use True and False instead of 1 and 0 in sympy.
Erik the Outgolfer

Це перший приклад, який я коли-небудь бачив, де ваніль +...має будь-яке вживання.
Джонатан Фрех

1

Желе , 13 байт

Ụ€’×
ÆEz0ÇZÆẸ

Спробуйте в Інтернеті! Моя перша відповідь желе! Правка: ÆEz0µỤ€’×µZÆẸтакож працює на 13 байт. Пояснення:

ÆE              Get prime factor exponents of both values (vectorises)
  z0            Zip but fill the shorter array with 0
    µ           New monadic link
     Ụ€         Grade up each pair (1-indexed)
       ’        Convert to 0-indexing (vectorises)
        ×       Multiply each pair by its grade (vectorises)
         µ      New monadic link
          Z     Zip back into separate lists of prime factor exponents
           ÆẸ   Turn prime exponent lists back into values (vectorises)

1

PARI / GP, 86 байт

Це саме те, що говорить Лін у своїй відповіді:

f(a,b)=forprime(p=2,a*b,v=valuation(a,p);w=valuation(b,p);if(w<v,b/=p^w,a/=p^v));[a,b]

Якщо я не рахую f(a,b)=частини, це 79 байт.


1

05AB1E , 32 26 24 22 20 19 байт

Ó0ζεD`›0sǝ}øεā<ØsmP

Спробуйте в Інтернеті! Я досі не маю уявлення, як писати цією мовою, але принаймні це не жорстокий алгоритм. Пояснення:

Ó                       Get exponents of prime factors (vectorised)
 0ζ                     Zip, filling with 0
   ε      }             For each prime
    D`                  Extract the pair of exponents
      ›0sǝ              Overwrite the smaller with 0
           ø            Zip back into two lists of prime exponents
            ε           For each list (} implied)
             ā<Ø        Get a list of primes
                sm      Raise each prime to the exponent
                  P     Take the product

Що це робить?
Лінн

Same as yours, but by actually factorising and comparing the exponents and recombining the factors.
Neil
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.