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


20

给定两个正整数ab,输出两个正整数cd使得:

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

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

测试用例:

 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 = · · ·…,则我们计算

  • 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)开始。然后,对于每个素数,将其完全除以cd的因式分解:以那个素数最小的那个为准。(在此实现中,如果出现平局,则c失去其指数。)

因此,如果a = 2250 = 2 1 ·3 2 ·5 3b = 360 = 2 3 ·3 2 ·5 1

那么c = 2 0 ·3 0 ·5 3 = 125d = 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

MATL17 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'*ed = d'/e。这使所有属性(因为综合因素保持不变),但因为我删除所有共享的因素d,我做cd互素。

在我的实现中,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

Haskell91 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.