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 code-golf 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
-
\$\begingroup\$ Related, Related \$\endgroup\$caird coinheringaahing– caird coinheringaahing ♦2018年01月16日 16:24:00 +00:00Commented 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– Shaggy2018年01月16日 18:38:10 +00:00Commented 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\$caird coinheringaahing– caird coinheringaahing ♦2018年01月16日 18:44:03 +00:00Commented 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– cole2018年01月16日 18:59:39 +00:00Commented Jan 16, 2018 at 18:59
-
\$\begingroup\$ Related Project Euler challenge (#21) \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2018年01月17日 07:59:35 +00:00Commented Jan 17, 2018 at 7:59
28 Answers 28
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.
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
-
\$\begingroup\$
;wÆṣỊandœ¿ÆṣḊalso score 5 bytes. \$\endgroup\$Dennis– Dennis2018年01月16日 18:24:56 +00:00Commented Jan 16, 2018 at 18:24 -
\$\begingroup\$ and
ÆṣQU=- maybe there is a sneaky 4 somewhere... \$\endgroup\$Jonathan Allan– Jonathan Allan2018年01月16日 18:27:16 +00:00Commented Jan 16, 2018 at 18:27
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]
-
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): returnin your bytecount. \$\endgroup\$2018年01月16日 19:33:45 +00:00Commented Jan 16, 2018 at 19:33 -
\$\begingroup\$ A
mapwithlambdaexpression is nearly always longer than a list comprehension. \$\endgroup\$xnor– xnor2018年01月16日 20:41:21 +00:00Commented Jan 16, 2018 at 20:41
J, (削除) 51 28 27 (削除ここまで) 24 Bytes
-Lots of bytes thanks to @cole
-1 more byte thanks to @cole
~.-:[:|.(1#.i.*0=i.|])"0
-
\$\begingroup\$ I think you can use
-:[:|.(1#.i.*0=i.|])"0or 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– cole2018年01月16日 17:30:01 +00:00Commented Jan 16, 2018 at 17:30 -
\$\begingroup\$ Apparently they need to be not equal so prepend a
~:/*]. \$\endgroup\$cole– cole2018年01月16日 18:51:46 +00:00Commented 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– cole2018年01月16日 19:02:55 +00:00Commented 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– cole2018年01月17日 02:30:02 +00:00Commented Jan 17, 2018 at 2:30 -
3\$\begingroup\$ 20 bytes with
>:@#.~/.~&.q:-:~:*+/\$\endgroup\$miles– miles2018年01月17日 12:16:38 +00:00Commented Jan 17, 2018 at 12:16
Brain-Flak, 178 bytes
{(({})(<>))<>({<<>(({})<<>{(({})){({}[()])<>}{}}>)<>([{}](({}[()])))>{[()]((<{}{}>))}{}{}}{}<>)<>}<>(({}<>)<>[({}{}<>)])({<{}({<({}<>[{}])>{()(<{}>)}{}})>(){[()](<{}>)}}<{}{}{}>)
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.
Ruby, (削除) 64 60 59 (削除ここまで) 58 bytes
->c{c.map{|i|(1...i).sum{|j|i%j<1?j:0}}==c.rotate&&c==c&c}
Brachylog, 9 bytes
≠.{fk+}m↔
Takes input as a list and outputs through success or failure.
The input
≠ which contains no duplicate values
. is the output variable,
{ }m and its elements'
k proper
f divisor
+ sums
↔ reversed
are also the output variable.
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= * ;
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
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\}
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).
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
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)
-
1\$\begingroup\$ Since 0 is not a valid input, you can save a byte by moving
a/=binside the list comprehension. \$\endgroup\$Ørjan Johansen– Ørjan Johansen2018年01月17日 01:48:33 +00:00Commented Jan 17, 2018 at 1:48
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.
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)
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
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
&-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
-
\$\begingroup\$ Fixed (filler!) \$\endgroup\$Dave– Dave2018年01月16日 18:18:59 +00:00Commented Jan 16, 2018 at 18:18
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←⎕
-
\$\begingroup\$ Can you please check if this is valid for inputs like 6, 6? \$\endgroup\$Mr. Xcoder– Mr. Xcoder2018年01月16日 18:13:37 +00:00Commented 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– Graham2018年01月16日 18:26:19 +00:00Commented Jan 16, 2018 at 18:26
-
\$\begingroup\$ The OP and I had that discussion earlier. \$\endgroup\$Mr. Xcoder– Mr. Xcoder2018年01月16日 18:27:19 +00:00Commented Jan 16, 2018 at 18:27
-
\$\begingroup\$ @Graham OP said they must be different numbers. \$\endgroup\$totallyhuman– totallyhuman2018年01月16日 18:27:20 +00:00Commented Jan 16, 2018 at 18:27
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
Japt, (削除) 7 (削除ここまで) (削除) 12 (削除ここまで) 10 bytes
Takes input as an array of 2 numbers.
®â¬xÃeUâ w
- 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.
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 = * * ;
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 = * * ;
Perl 6, 53 bytes
{([!=] $_)&&[eqv] .map: {set +$_,sum grep $_%%*,^$_}}
Takes input as a list of two numbers.
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
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.
-
\$\begingroup\$ Fails for 6, 6. \$\endgroup\$Mr. Xcoder– Mr. Xcoder2018年01月16日 18:12:39 +00:00Commented Jan 16, 2018 at 18:12
-
\$\begingroup\$ @Mr.Xcoder Boo-urns. Corrected for 9 bytes. :-/ \$\endgroup\$AdmBorkBork– AdmBorkBork2018年01月16日 19:12:43 +00:00Commented Jan 16, 2018 at 19:12
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.
-
\$\begingroup\$ Better than
üQ_sÑOüQ&for sure lol. \$\endgroup\$Magic Octopus Urn– Magic Octopus Urn2018年01月17日 20:17:22 +00:00Commented Jan 17, 2018 at 20:17
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.
APL (Dyalog Unicode), (削除) 45 38 44 36 35 (削除ここまで) 20 bytes
{(≠/⍵)∧(⌽⍵)≡+/ ̈ ̄1↓ ̈(0=⍵|⍨⍳ ̈⍵)/ ̈⍳ ̈⍵}
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=⍳|⊢) ̈
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.
-
\$\begingroup\$ You can save a few bytes by using
eaches rather than duplicating code \$\endgroup\$Uriel– Uriel2018年01月16日 17:30:50 +00:00Commented 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é– J. Sallé2018年01月16日 17:32:39 +00:00Commented Jan 16, 2018 at 17:32
-
\$\begingroup\$ Fails for 6, 6. \$\endgroup\$Mr. Xcoder– Mr. Xcoder2018年01月16日 18:15:19 +00:00Commented 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é– J. Sallé2018年01月16日 18:28:48 +00:00Commented Jan 16, 2018 at 18:28
-
\$\begingroup\$ Whitespace golf for 36 -
{(⍺≠⍵)∧⍵⍺≡+/¨¯1↓¨(0=⍺⍵|⍨⍳¨⍺⍵)/¨⍳¨⍺⍵}. I haven't gone through the logic yet \$\endgroup\$Uriel– Uriel2018年01月16日 19:19:19 +00:00Commented Jan 16, 2018 at 19:19
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]]
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;}
Explore related questions
See similar questions with these tags.