使两个数字互质,同时保留它们的最小公倍数


20

给定两个正整数a和b,输出两个正整数c,d使得:

  • c 分界 a
  • d 分界 b
  • c并且d是互质的
  • 的最小公倍数的c和d等于最小公倍数a和b。

如果可能的答案不只一个,则只能输出其中一个或全部。

测试用例:

 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)?
— 尼尔于2009年

1
@Neil d划分的要求b
— Leaky Nun

4
也许您应该定义LCM或至少不使用首字母缩写词。我不知道有什么要求。
— 小麦巫师

Answers:


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( a,b)

并且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。

乔纳森·艾伦(Jonathan Allan)击倒了8个字节!谢谢〜


这是我的原始算法。Perl算法更好。
— Leaky Nun

非常好。它在12字节中
— Jonathan Allan

这是另一个12英里ÆEZ×Ụ’$€$ZÆẸ
— 英里

现在,这[1,18]为[15,18]。初始版本返回正确的答案([5,18])。
— Arnauld

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
— Giuseppe

1
好的观察:如果GCD(c,d)==1,则LCM(c,d)==c*d。因此,我们可以进行测试GCD(c,d)==1,然后检查c*d==a*b/GCD(a,b)由于后者是LCM(a,b)...
— Giuseppe

1
确实!(尽管计算a*b/GCD(a,b)时间不短于LCM(a,b))。
— plannapus

120个字节 -匿名函数+ -3个字节的文字换行符
— Giuseppe

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

Mathematica,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

在线尝试!

与Lynn Jelly解决方案相同的方法

自从我使用任何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字节感谢Laikoni


使用模式防护绑定可c节省3个字节:在线尝试!
— Laikoni '17

@Laikoni Ooh,我什至不知道那个把戏。谢谢!
— 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,]

在线尝试!

与其他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

J,19个字节

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

在线尝试!

基于@Lynn的解决方案。

说明

(*/:"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]

在线尝试!

Saved 17 bytes thanks to Laikoni


1
u*v`div`gcd u v saves a byte.
— Lynn

Is there any reason not to use the built-in lcm function?
— Laikoni

Also rem a x+rem b y+gcd x y<2 should work.
— Laikoni

@Laikoni a very good reason: I didn't even know the builtin lcm existed. rem a x+rem b y+gcd x y<2 works, and I wonder if rem a x+rem b y+gcd x y+lcm a b-lcm x y<2 works. There is maybe a (mathematical) guarantee that lcm a b>=lcm x y.
— jferard

1
Indeed, lcm a b>=lcm x y because 1. x=x1*...*xi (prime decomposition), y=y1*...yj, lcm x y=z1*...*zk where z1,...,zk are common to x1,...,xi and y1,...,yj. 2. a=u1*...*um*x1*...*xi (prime decomposition), b=v1*...vn*y1*...yj, lcm a b=t1*...*tl where t1,...,tl are common to u1*...*um*x1*...*xi and v1*...vn*y1*...yj. It's obvious that t1,...,tl contains z1,...,zk, thus lcm a b>=lcm x y. But that's not useful for writing the condition as a sum.
— jferard

2

Python 2, 75 bytes

def f(x):n=1;exec'n+=1;j=k=1\nwhile x[j]%k<1:k*=n**j;j^=1\nx[j]/=k/n;'*x[0]

Input is taken as a list, which the function modifies in place.

Try it online!


1

Python 3, 129 bytes

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*

Try it online! or Try the test suite.

Outputs all possible combinations in the form of a nested list.


3
You and your bitwise stuff... -~a and -~b can just be rewritten as a+1 and b+1 for readability :P
— Stephen

1
@Stephen As you can see, I specialize in obfuscation
— Mr. Xcoder

Doesn't work for my newly added second testcase.
— Leaky Nun

@LeakyNun Rolled back. Didn't have time to check the validity of the golf.
— Mr. Xcoder

1

Jelly,  19 15  14 bytes

-4 with pointer from Leaky Nun (use divisor built-in)

I am almost 100% certain this is not the way to actually do this one, but here is a first attempt.
Let's see who outgolfs it with a seven or eight byter!
Yep... see Lynn's answer with explanation!

g/־l/
ÆDp/ÇÐṂ

A monadic link taking a list of the two numbers and returning a list of lists of the possibilities.

Try it online!

How?

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

Let's see who outgolfs it with a seven or eight byter! - Don't think so...
— Mr. Xcoder

You think six? ...FIVE?!
— Jonathan Allan

:P No... I don't think less than ~13-15 is possible (Dennis would disagree, of course!)
— Mr. Xcoder

Divisor built-in?
— Leaky Nun

Yeah ÆD but (shrug) brain obviously not in gear...
— Jonathan Allan

1

Perl 6, 72 bytes

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

Try it online!

Takes a list (a, b). Returns a list of all possible lists (c, d).

Explanation:

-> @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 + sympy, 148 bytes

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

Try it online!

-1 thanks to Jonathan Frech.

This answer works in Python 2 (not Python 3), using sympy.gcd and sympy.lcm instead of math.gcd and math.lcm which are only available in Python 3. And yes, this is brute force :)


Golfing in progress...
— Erik the Outgolfer

You may be able to save a byte by defining Q=c==z; (+7 bytes) at the start of the while loop and replacing or(c==z)+d with or Q+d (-4 bytes) and c=+(c==z)or with c=+Q or (-4 bytes). (TIO)
— Jonathan Frech

Just as a question, are you using the + operator in d=+E or c=+(c==z) to convert a boolean into an integer?
— Jonathan Frech

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

That is the first instance I ever saw where the vanilla +... has any use.
— Jonathan Frech

1

Jelly, 13 bytes

Ụ€’×
ÆEz0ÇZÆẸ

Try it online! My first Jelly answer! Edit: ÆEz0µỤ€’×µZÆẸ also works for 13 bytes. Explanation:

Æ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 bytes

This just does what Lynn says in her answer:

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]

If I do not count the f(a,b)= part, it is 79 bytes.


1

05AB1E, 32 26 24 22 20 19 bytes

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

Try it online! I still have no idea how to write in this language, but at least it's not a brute-force algorithm. Explanation:

Ó                       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

What’s it doing?
— Lynn

Same as yours, but by actually factorising and comparing the exponents and recombining the factors.
— Neil
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.