Сделайте два числа взаимно простыми, сохраняя их наименьшее общее кратное

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 ,

тогда с = 2 0 · 3 0 · 5 3 = 125 и d = 2 3 · 3 2 · 5 0 = 72 .

Джонатан Аллан набрал 8 байтов! Спасибо ~

Линн
источник
Это мой оригинальный алгоритм ... Алгоритм Perl лучше.
Утренняя монахиня
Очень хорошо. Вот оно в 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 
plannapus
источник
!имеет более высокий приоритет, чем &и, |но ниже, чем +и *; таким образом вы сможете уложить в гольф несколько байтов; то есть, !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)).
plannapus
120 байтов - анонимная функция + буквальный
Джузеппе
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]
Zgarb
источник
3

Mathematica, 82 байта

#&@@Select[Subsets[Flatten@Divisors[{t=#,r=#2}],{2}],GCD@@#==1&&LCM@@#==t~LCM~r&]&
J42161217
источник
Я не уверен, но не могли бы вы использовать индексирование списка Select[...][[1]]вместо того, First@Select[...]чтобы сохранить байт?
Джонатан Фрех
да, но тогда я мог бы использовать #&@@вместо того, [[1]]чтобы сохранить еще один ;-)
J42161217
3

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

Принимает ввод в синтаксисе карри (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
Arnauld
источник
3

MATL , 17 16 байт

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

Попробуйте онлайн!

Тот же метод, что и у Линн в желе

Прошло много времени с тех пор, как я использовал любой MATL (или matlab в этом отношении), поэтому возможны многие улучшения.

Б. Мехта
источник
3

Хаскелл ,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 байта благодаря Лайкони

Sacchan
источник
Использование шаблона защиты для связывания cэкономит 3 байта: попробуйте онлайн!
Лайкони
@Laikoni Ооо, я даже не знала этого трюка. Благодарность!
Sacchan
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
}

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

Giuseppe
источник
2

J , 19 байт

(*/:"1)&.|:&.(_&q:)

Попробуйте онлайн!

Основано на решении @ Линн .

объяснение

(*/:"1)&.|:&.(_&q:)  Input: [a, b]
              _&q:   Get exponenets of each prime
         |:&         Transpose
  /:"1 &             Grade each row
 *                   Multiply elementwise
       &.|:          Transpose
           &. _&q:   Convert exponents back to numbers
миль
источник
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 байтов благодаря Laikoni

jferard
источник
1
u*v`div`gcd u vсохраняет байт.
Линн
Есть ли причина не использовать встроенную lcmфункцию?
Лайкони
И rem a x+rem b y+gcd x y<2должно работать.
Лайкони
@ Лайкони - очень веская причина: я даже не знал, что встроенное 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.
Джферард
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*

Попробуйте онлайн!или попробуйте тестовый набор.

Выводит все возможные комбинации в виде вложенного списка.

Мистер Xcoder
источник
3
Вы и ваши побитовые вещи ... -~aи -~bможете просто переписать как a+1и b+1для удобочитаемости: P
Стивен
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
Вы думаете, шесть? ...5?!
Джонатан Аллан
: P Нет ... Я не думаю, что возможно менее ~ 13-15 (Деннис, конечно, не согласится!)
г-н Xcoder
Делитель встроенный?
Утренняя монахиня
Да, Æ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] $_) == [*] $_ }
}
nwellnhof
источник
1

Python 2 + sympy , 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. И да, это грубая сила :)

Эрик 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 Да, так как вы не можете использовать Trueи Falseвместо, 1и 0в симпати.
Эрик 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
Нил
источник
Что это делает?
Линн
То же, что и у вас, но на самом деле факторизация и сравнение показателей и рекомбинация факторов.
Нил