7
\$\begingroup\$

Two numbers are considered amicable if the proper divisor sum of the first is the same as the second number, the second number's proper divisor sum is equal to the first number, and the first and second numbers aren't equal.

Let's define S(x) to be the proper divisor sum of x. 220 and 284 are amicable because S(220) = 284 and S(284) = 200.

Your task is, unsurprisingly, to determine whether two inputted numbers are amicable or not. The inputs will be positive integers and you may output two distinct, consistent values for amicable or not.

This is OEIS sequence A259180

This is a so the shortest code wins.

Test cases

input, input => output
220, 284 => 1
52, 100 => 0
10744, 10856 => 1
174292, 2345 => 0
100, 117 => 0
6, 11 => 0
495, 495 => 0
6, 6 => 0
\$\endgroup\$
  • \$\begingroup\$ Related, Related \$\endgroup\$ – caird coinheringaahing Jan 16 '18 at 16:24
  • 6
    \$\begingroup\$ Updating the challenge to invalidate existing solutions ain't cool nor, in my book, is input validation. I suggest either allowing both numbers to be the same or not requiring us to handle those cases. \$\endgroup\$ – Shaggy Jan 16 '18 at 18:38
  • \$\begingroup\$ @Shaggy I agree, but given that half the solutions currently validate the input, and that validating the input is part of the challenge, I can't really change to either of those suggestions, as different solutions would be doing different things. It's an oversight I missed, but revoking it would make the challenge worse overall. \$\endgroup\$ – caird coinheringaahing Jan 16 '18 at 18:44
  • 1
    \$\begingroup\$ @Shaggy in this case, I think an exception might be in order since this is the definition of amicability. \$\endgroup\$ – cole Jan 16 '18 at 18:59
  • \$\begingroup\$ Related Project Euler challenge (#21) \$\endgroup\$ – Kevin Cruijssen Jan 17 '18 at 7:59

24 Answers 24

4
\$\begingroup\$

Jelly, 5 bytes

QfÆṣ⁼

A monadic link taking a list of two integers which returns 1 if they are a pair of amicable numbers and 0 otherwise.

Try it online!

How?

QfÆṣ⁼ - Link: pair of numbers L, [a, b]   e.g. [220,284]  or [6,6]  or [6,11]  or [100,52]
Q     - de-duplicate L                         [220,284]     [6]       [6,11]     [100,52]
  Æṣ  - proper divisor sum of L (vectorises)   [284,220]     [6]       [6,1]      [117,46]
 f    - filter keep left if in right           [220,284]     [6]       [6]        []
    ⁼ - equal to L?                            1             0         0          0
\$\endgroup\$
  • \$\begingroup\$ ;wÆṣỊ and œ¿ÆṣḊ also score 5 bytes. \$\endgroup\$ – Dennis Jan 16 '18 at 18:24
  • \$\begingroup\$ and ÆṣQU⁼ - maybe there is a sneaky 4 somewhere... \$\endgroup\$ – Jonathan Allan Jan 16 '18 at 18:27
3
\$\begingroup\$

Python 2, 71 67 bytes

-4 bytes thanks to xnor

+9 bytes thanks to caird coinheringaahing

lambda c:[sum(i for i in range(1,x)if x%i<1)for x in c]==c[::-1]!=c

partly inspired by [this answer]

\$\endgroup\$
  • 2
    \$\begingroup\$ Welcome to the site! You may not assume that input can be stored in a variable, so you must include the def f(x): return in your bytecount. \$\endgroup\$ – caird coinheringaahing Jan 16 '18 at 19:33
  • \$\begingroup\$ A map with lambda expression is nearly always longer than a list comprehension. \$\endgroup\$ – xnor Jan 16 '18 at 20:41
2
\$\begingroup\$

Python 2, 65 63 66 bytes

-2 bytes thanks to Mr. Xcoder

lambda c:[sum(i*(n%i<1)for i in range(1,n))for n in c]==c[::-1]!=c

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Haskell, 53 bytes

-2 bytes thanks to BMO. -1 byte thanks to Ørjan Johansen.

a!b=a==sum[i|i<-[1..b-1],b`mod`i<1,a/=b]
a#b=a!b&&b!a

Try it online!

Ungolfed with UniHaskell and -XUnicodeSyntax

import UniHaskell

equalsOmega       ∷ Int → Int → Bool
a `equalsOmega` b = a ≡ sum [i | i ← 1 … pred b, i ∣ b, a ≢ b]

areAmicable       ∷ Int → Int → Bool
areAmicable a b   = (a `equalsOmega` b) ∧ (b `equalsOmega` a)
\$\endgroup\$
  • 1
    \$\begingroup\$ Since 0 is not a valid input, you can save a byte by moving a/=b inside the list comprehension. \$\endgroup\$ – Ørjan Johansen Jan 17 '18 at 1:48
2
\$\begingroup\$

J, 51 28 27 24 Bytes

-Lots of bytes thanks to @cole

-1 more byte thanks to @cole

~.-:[:|.(1#.i.*0=i.|])"0

Try it online!

\$\endgroup\$
  • \$\begingroup\$ I think you can use -:[:|.(1#.i.*0=i.|])”0 or something akin to it. The divisor sum (rightmost verb) is taken from mile’s comment on our divisor sum question. Edit: with a different quotation mark since I’m on mobile. \$\endgroup\$ – cole Jan 16 '18 at 17:30
  • \$\begingroup\$ Apparently they need to be not equal so prepend a ~:/*]. \$\endgroup\$ – cole Jan 16 '18 at 18:51
  • \$\begingroup\$ Actually I think you can instead do ~.-:... (match with dedpulicated input), which I stole from the Jelly answer. \$\endgroup\$ – cole Jan 16 '18 at 19:02
  • \$\begingroup\$ I removed an extra -:-match in your code, updated the bytecount, and added a TIO link. Hope that's OK by you. Feel free to roll back if it isn't (but the solution prior had a domain error you'd want to fix). \$\endgroup\$ – cole Jan 17 '18 at 2:30
  • 2
    \$\begingroup\$ 20 bytes with >:@#.~/.~&.q:-:~:*+/ \$\endgroup\$ – miles Jan 17 '18 at 12:16
2
\$\begingroup\$

Brain-Flak, 178 bytes

{(({})(<>))<>({<<>(({})<<>{(({})){({}[()])<>}{}}>)<>([{}](({}[()])))>{[()]((<{}{}>))}{}{}}{}<>)<>}<>(({}<>)<>[({}{}<>)])({<{}({<({}<>[{}])>{()(<{}>)}{}})>(){[()](<{}>)}}<{}{}{}>)

Try it online!

\$\endgroup\$
2
\$\begingroup\$

JavaScript (ES6), 53 bytes

Takes input in currying syntax (a)(b). Returns 0 or 1.

a=>b=>a!=b&a==(g=n=>--a&&a*!(n%a)+g(n))(a=g(a)-b?1:b)

Demo

let f =

a=>b=>a!=b&a==(g=n=>--a&&a*!(n%a)+g(n))(a=g(a)-b?1:b)

console.log(f(220)(284))  // => 1
console.log(f(52)(100))   // => 0
console.log(f(100)(117))  // => 0
console.log(f(6)(6))      // => 0

How?

We use the function g to get the sum of the proper divisors of a given integer.

We first compute g(a) and compare it with b. If g(a) = b, we compute g(b) and compare it with a. Otherwise, we compute g(1), which gives 0 and can't possibly be equal to a.

We additionally check that a is not equal to b.

\$\endgroup\$
2
\$\begingroup\$

Ruby, 64 60 59 58 bytes

->c{c.map{|i|(1...i).sum{|j|i%j<1?j:0}}==c.rotate&&c==c&c}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

R, 67 bytes

function(a,b)sum(which(!a%%1:a))-a==b&sum(which(!b%%1:b))-b==a&b!=a

Try it online!

returns TRUE for amicable, FALSE for not.

\$\endgroup\$
  • 2
    \$\begingroup\$ @BrunoCosta alas, I cannot: it would be 68 bytes \$\endgroup\$ – Giuseppe Jan 16 '18 at 18:22
1
\$\begingroup\$

Perl 6, 53 bytes

{([!=] $_)&&[eqv] .map: {set +$_,sum grep $_%%*,^$_}}

Try it online!

Takes input as a list of two numbers.

\$\endgroup\$
1
\$\begingroup\$

PowerShell, 87 96 bytes

param($a,$b)filter f($n){(1..($n-1)|?{!($n%$_)})-join'+'|iex}(f $a)-eq$b-and(f $b)-eq$a-and$a-$b

Try it online!

Takes input $a,$b. Defines a filter (here equivalent to a function) that takes input $n. Inside we construct a range from 1 to $n-1, pull out those that are divisors, -join them together with + and send that to Invoke-Expression (similar to eval).

Finally, outside the filter, we simply check whether the divisor-sum of one input is equal to the other and vice-versa (and input validation to make sure they're not equal). That Boolean value is left on the pipeline and output is implicit.

\$\endgroup\$
  • \$\begingroup\$ Fails for 6, 6. \$\endgroup\$ – Mr. Xcoder Jan 16 '18 at 18:12
  • \$\begingroup\$ @Mr.Xcoder Boo-urns. Corrected for 9 bytes. :-/ \$\endgroup\$ – AdmBorkBork Jan 16 '18 at 19:12
1
\$\begingroup\$

Pyth, 12 bytes

q{_msf!%dTtU

Takes input as a list.
Try it online

Explanation

q{_msf!%dTtU
   m         Q    For each element d of the (implicit) input...
          tUd     ... get the range [1, ..., d - 1]...
     f!%dT        ... filter those that are factors of d...
    s             ... and take the sum.
 {_               Reverse and deduplicate...
q             Q   ... and check if the end result is the same as the input.
\$\endgroup\$
1
\$\begingroup\$

05AB1E, 8 7 bytes

ÙÑO¥`_`

Try it online!

\$\endgroup\$
  • \$\begingroup\$ Better than üQ_sÑOüQ& for sure lol. \$\endgroup\$ – Magic Octopus Urn Jan 17 '18 at 20:17
1
\$\begingroup\$

Batch, 127 bytes

@if %1==%2 exit/b
@set/as=t=%1+%2
@for /l %%i in (1,1,%s%)do @set/as-=%%i*!(%1%%%%i),t-=%%i*!(%2%%%%i)
@if %s%%t%==00 echo 1

Outputs 1 if the parameters are amicable. Works by subtracting all factors from the sum of the input numbers for each input number, and if both results are zero then the numbers are amicable.

\$\endgroup\$
1
\$\begingroup\$

APL (Dyalog Unicode), 45 38 44 36 35 20 bytes

{(≠/⍵)∧(⌽⍵)≡+/¨¯1↓¨(0=⍵|⍨⍳¨⍵)/¨⍳¨⍵}

Try it online!

Infix Dfn, fixed for the equal inputs case.

Thanks @Uriel for 8 bytes; @cole for 1 byte; @Adám for 15 bytes.

How?

{(≠/⍵)∧(⌽⍵)≡+/¨¯1↓¨(0=⍵|⍨⍳¨⍵)/¨⍳¨⍵} ⍝ Main function, infix. Input is ⍵.
{                               ⍳¨⍵} ⍝ Generate the range [1,n] for each element of ⍵.
                              /¨     ⍝ Replicate into each the resulting vectors of:
                   (  ⍵|⍨⍳¨⍵)        ⍝ ⍵ modulo each element of the ranges;
                    0=               ⍝ Equals 0?
               ¯1↓¨                  ⍝ Drop the last element of each
            +/¨                      ⍝ Sum of each
       (⌽⍵)≡                         ⍝ Check if the results match the inverse of ⍵.
      ∧                              ⍝ Logical AND.
 (≠/⍵)                               ⍝ Inputs are different

@Adám has also helped me with a 22 20 byte tacit function that's equivalent to the Dfn:

≠/∧⌽≡(+/∘∊⍳⊆⍨0=⍳|⊢)¨

Try it online!

How?

≠/∧⌽≡(+/∘∊⍳⊆⍨0=⍳|⊢)¨⍝ Tacit fn, takes one right argument.
     (            )¨ ⍝ For each element e of the argument
               ⍳|⊢   ⍝ e modulo range [1,e]
             0=      ⍝ Equals 0? This generates a boolean vector
            ⍨        ⍝ Swap arguments for the following op/fn
           ⊆         ⍝ Partition. This partitions the right vector argument according to 1-runs from a left boolean vector argument of same size.
          ⍳          ⍝ Range [1,e]
         ∊           ⍝ Enlist; dump all elements into a single vector.
        ∘            ⍝ And then
      +/             ⍝ Sum the elements
   ⌽≡                ⍝ Check if the resulting sums match the inverse of the argument
  ∧                  ⍝ Logical AND
≠/                   ⍝ The elements of the argument are different.
\$\endgroup\$
  • \$\begingroup\$ You can save a few bytes by using eaches rather than duplicating code \$\endgroup\$ – Uriel Jan 16 '18 at 17:30
  • \$\begingroup\$ @Uriel I'm actually working on that. Just thought I should post this so I can edit it later. \$\endgroup\$ – J. Sallé Jan 16 '18 at 17:32
  • \$\begingroup\$ Fails for 6, 6. \$\endgroup\$ – Mr. Xcoder Jan 16 '18 at 18:15
  • \$\begingroup\$ @Mr.Xcoder fixed. I had no idea it was supposed to return falsy for equal inputs. \$\endgroup\$ – J. Sallé Jan 16 '18 at 18:28
  • \$\begingroup\$ Whitespace golf for 36 - {(⍺≠⍵)∧⍵⍺≡+/¨¯1↓¨(0=⍺⍵|⍨⍳¨⍺⍵)/¨⍳¨⍺⍵}. I haven't gone through the logic yet \$\endgroup\$ – Uriel Jan 16 '18 at 19:19
1
\$\begingroup\$

Red, 117 bytes

d: func[n][s: 0 repeat i n / 2[if n // i = 0[s: s + i]]]
a: func[n m][either(m = d n)and(n = d m)and not n = m[1][0]]

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Java (OpenJDK 9), 87 bytes

a->b->a!=b&f(a)==b&f(b)==a
int f(int n){int s=0,d=0;for(;++d<n;)s+=n%d<1?d:0;return s;}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

SNOBOL4 (CSNOBOL4), 153 146 bytes

	DEFINE('D(X)I')
	DEFINE('A(M,N)')
A	A =EQ(D(M),N) EQ(D(N),M) ~EQ(N,M) 1 :(RETURN)
D	I =LT(I,X - 1) I + 1	:F(RETURN)
	D =EQ(REMDR(X,I)) D + I	:(D)

Try it online!

Defines a function A that computes the amicability of two numbers, returning 1 for amicable and the empty string for not. The algorithm is the same as my previous answer so I leave the old explanation below.

	DEFINE('D(X)I')					;*function definition
	M =INPUT					;*read M,N as input
	N =INPUT
	OUTPUT =EQ(D(M),N) EQ(D(N),M) ~EQ(N,M) 1 :(END)	;* if D(M)==N and D(N)==M and N!=M, output 1. goto end.
D	I =LT(I,X - 1) I + 1	:F(RETURN)		;* function body: increment I so long as I+1<X, return if not.
	D =EQ(REMDR(X,I)) D + I	:(D)			;* add I to D if D%%I==0, goto D
END
\$\endgroup\$
1
\$\begingroup\$

Python 3, 84 bytes

d=lambda n:sum(i*(n%i<1)for i in range(1,n))
f=lambda a,b:(d(a)==b)*(d(b)==a)*(a^b)>0

Straightforward solution. d sums up divisors (n%i<1 evaluates to 1 iff i divides n). a^b is nonzero iff a!=b. The LHS of the inequality is thus 0 iff the numbers are not amicable and >0 otherwise.

\$\endgroup\$
1
\$\begingroup\$

Pyth, 13 bytes

&-FQqFms{*MyP

+4 bytes to check if values are distinct, I feel like that shouldn't be part of the challenge...

Can almost certainly be golfed a lot

Try it online!


&-FQqFms{*MyP     Full program, takes input from stdin and outputs to stdout
 -FQ              Q0 - Q1 is true, meaning elements are distinct
&                  and
      m       Q   for each element of the input list, apply
           yPd    take the powerset of the prime factors
        {*M       multiply each list and deduplicate
       s          and sum the list (this represents S(n)+n )
    qF            and fold over equality, returning whether the two elements are equal
\$\endgroup\$
  • \$\begingroup\$ Fixed (filler!) \$\endgroup\$ – Dave Jan 16 '18 at 18:18
1
\$\begingroup\$

APL+WIN, 49 54 41 40 35bytes

Rewritten to reject equal integer inputs

Prompts for screen input of a vector of the two integers.

(≠/n)×2=+/n=⌽+/¨¯1↓¨(0=m|n)×m←⍳¨n←⎕
\$\endgroup\$
  • \$\begingroup\$ Can you please check if this is valid for inputs like 6, 6? \$\endgroup\$ – Mr. Xcoder Jan 16 '18 at 18:13
  • \$\begingroup\$ @Mr. Xcoder It results in 1 for 6,6 which does not agree with the test case above. The divisors of 6 are 1,2,3 which sum to 6 so what am I missing? \$\endgroup\$ – Graham Jan 16 '18 at 18:26
  • \$\begingroup\$ The OP and I had that discussion earlier. \$\endgroup\$ – Mr. Xcoder Jan 16 '18 at 18:27
  • \$\begingroup\$ @Graham OP said they must be different numbers. \$\endgroup\$ – totallyhuman Jan 16 '18 at 18:27
1
\$\begingroup\$

APL NARS, 38 bytes, 18 chars

{≠/⍵∧∧/⍵=⌽-⍵-11π⍵}

11π⍵ find the sum of divisors of ⍵ in 1..⍵; note that the question want (11π⍵)-⍵ and in APLsm

-⍵-11π⍵=-(⍵-11π⍵)=(11π⍵)-⍵

the test

  t←{≠/⍵∧∧/⍵=⌽-⍵-11π⍵}
  t 284 220⋄t 52 100⋄t 10744 10856 ⋄t 174292 2345
1
0
1
0
  t 100 117⋄t 6 11⋄t 495 495⋄t 6 6
0
0
0
0
\$\endgroup\$
1
\$\begingroup\$

Japt, 7 12 10 bytes

Takes input as an array of 2 numbers.

®â¬xÃeUâ w

Try it


  • Added 3 bytes to handle [6,11].
  • Added another 3 bytes after the challenge was updated to require input validation. (Boo-urns on both fronts!)
  • Saved 1 byte thank to Oliver.
\$\endgroup\$
1
\$\begingroup\$

Forth (gforth), 91 86 bytes

: d { n } 0 n 1 do n i mod 0= i * - loop ; 
: f { a b } a b = 1+ a d b = b d a = * * ;

Try it online!

Forth (gforth) No Locals, 94 bytes

A more "Forthy" version that doesn't use local variables

: d 0 over 1 do over i mod 0= i * - loop nip ;
: f 2dup = 1+ -rot 2dup d -rot d = -rot = * * ;

Try it online!

\$\endgroup\$

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.