11
\$\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.

\$s(x)\$ represents the aliquot sum or 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\$
5
  • \$\begingroup\$ Related, Related \$\endgroup\$ Jan 16, 2018 at 16:24
  • 8
    \$\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, 2018 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\$ Jan 16, 2018 at 18:44
  • 3
    \$\begingroup\$ @Shaggy in this case, I think an exception might be in order since this is the definition of amicability. \$\endgroup\$
    – cole
    Jan 16, 2018 at 18:59
  • \$\begingroup\$ Related Project Euler challenge (#21) \$\endgroup\$ Jan 17, 2018 at 7:59

28 Answers 28

5
\$\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\$
2
  • \$\begingroup\$ ;wÆṣỊ and œ¿ÆṣḊ also score 5 bytes. \$\endgroup\$
    – Dennis
    Jan 16, 2018 at 18:24
  • \$\begingroup\$ and ÆṣQU⁼ - maybe there is a sneaky 4 somewhere... \$\endgroup\$ Jan 16, 2018 at 18:27
3
\$\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\$
0
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
  • 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\$ Jan 16, 2018 at 19:33
  • \$\begingroup\$ A map with lambda expression is nearly always longer than a list comprehension. \$\endgroup\$
    – xnor
    Jan 16, 2018 at 20:41
3
\$\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\$
6
  • \$\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, 2018 at 17:30
  • \$\begingroup\$ Apparently they need to be not equal so prepend a ~:/*]. \$\endgroup\$
    – cole
    Jan 16, 2018 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, 2018 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, 2018 at 2:30
  • 3
    \$\begingroup\$ 20 bytes with >:@#.~/.~&.q:-:~:*+/ \$\endgroup\$
    – miles
    Jan 17, 2018 at 12:16
3
\$\begingroup\$

Brain-Flak, 178 bytes

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

Try it online!

\$\endgroup\$
3
\$\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\$
3
\$\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\$
3
\$\begingroup\$

Brachylog, 9 bytes

≠.{fk+}ᵐ↔

Try it online!

Takes input as a list and outputs through success or failure.

             The input
≠            which contains no duplicate values
 .           is the output variable,
  {   }ᵐ     and its elements'
    k        proper
   f         divisor
     +       sums
        ↔    reversed
             are also the output variable.
\$\endgroup\$
3
\$\begingroup\$

Forth (gforth), 80 bytes

Refactored reffu's solution.

: d { n } 0 n 1 do n i mod 0= i * - loop ;
: f 2dup <> -rot 2dup d swap d d= * ;

Try it online!

How it works

: d { n -- divsum } \ Takes a number and gives its divisor sum (excluding self)
                    \ Store n as a local variable
  0 n 1 do          \ Push 0 (sum) and loop through 1 to n-1...
    n i mod 0=      \   If n % i == 0, push -1 (built-in true in Forth); otherwise push 0
    i * -           \   If the value above is -1, add i to the sum
  loop ;            \ End loop and leave sum on the stack

: f ( n1 n2 -- f )  \ Main function f. Takes two numbers and gives if they are amicable
  2dup <>           \ Are they not equal? ( stack: n1 n2 n1<>n2 )
  -rot              \ Move the boolean under n1 n2 ( stack: n1<>n2 n1 n2 )
  2dup d swap d     \ Copy two numbers, apply d to both and swap
                    \ ( stack: n1<>n2 n1 n2 n2.d n1.d )
  d=                \ Compare two 2-cell numbers for equality; n1=n2.d && n2=n1.d
  * ;               \ Return the product of the two booleans
\$\endgroup\$
3
\$\begingroup\$

Desmos, 214 65+102=167 bytes

This is more of a fun answer, not a competitive one:

Expression 1, 65 bytes:

g(N)=\sum_{n=1}^{N-1}\left\{\operatorname{mod}(N,n)=0:n,0\right\}

Expression 2, 102 bytes:

f(M,N)=\left\{\left\{g(N)=M:1,0\right\}+\left\{g(M)=N:1,0\right\}+\left\{M=N:0,1\right\}=3:1,0\right\}

Try It On Desmos!

I feel like this could definitely be golfed a lot. Too bad I can't take out those \left's and \right's, because they are in front of brackets(Desmos won't allow me to for some reason).

\$\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
  • 1
    \$\begingroup\$ Since 0 is not a valid input, you can save a byte by moving a/=b inside the list comprehension. \$\endgroup\$ Jan 17, 2018 at 1:48
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\$
0
2
\$\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\$
2
\$\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\$
1
  • \$\begingroup\$ Fixed (filler!) \$\endgroup\$
    – Dave
    Jan 16, 2018 at 18:18
2
\$\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\$
4
  • \$\begingroup\$ Can you please check if this is valid for inputs like 6, 6? \$\endgroup\$
    – Mr. Xcoder
    Jan 16, 2018 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, 2018 at 18:26
  • \$\begingroup\$ The OP and I had that discussion earlier. \$\endgroup\$
    – Mr. Xcoder
    Jan 16, 2018 at 18:27
  • \$\begingroup\$ @Graham OP said they must be different numbers. \$\endgroup\$ Jan 16, 2018 at 18:27
2
\$\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\$
2
\$\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\$
0
2
\$\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\$
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\$
1
  • 2
    \$\begingroup\$ @BrunoCosta alas, I cannot: it would be 68 bytes \$\endgroup\$
    – Giuseppe
    Jan 16, 2018 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\$
2
  • \$\begingroup\$ Fails for 6, 6. \$\endgroup\$
    – Mr. Xcoder
    Jan 16, 2018 at 18:12
  • \$\begingroup\$ @Mr.Xcoder Boo-urns. Corrected for 9 bytes. :-/ \$\endgroup\$ Jan 16, 2018 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\$
1
  • \$\begingroup\$ Better than üQ_sÑOüQ& for sure lol. \$\endgroup\$ Jan 17, 2018 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\$
8
  • \$\begingroup\$ You can save a few bytes by using eaches rather than duplicating code \$\endgroup\$
    – Uriel
    Jan 16, 2018 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, 2018 at 17:32
  • \$\begingroup\$ Fails for 6, 6. \$\endgroup\$
    – Mr. Xcoder
    Jan 16, 2018 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, 2018 at 18:28
  • \$\begingroup\$ Whitespace golf for 36 - {(⍺≠⍵)∧⍵⍺≡+/¨¯1↓¨(0=⍺⍵|⍨⍳¨⍺⍵)/¨⍳¨⍺⍵}. I haven't gone through the logic yet \$\endgroup\$
    – Uriel
    Jan 16, 2018 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\$
0
\$\begingroup\$

Vyxal, 5 bytes

∆KUṘ⁼

Try it Online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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