Tell me more ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Two numbers are said to be 'amicable' or 'friends' if the sum of the divisors of the first is equal to the second, and viceversa. For example, the divisors of 220 are: 1, 2, 4, 5, 10, 11, 20, 22, 44, 55, 110 which sums up 284. 284 divisors are 1, 2, 4, 71 and 142, which sums 220, thus 220 and 284 are friends. Write a function which returns either true of false if a number is a friend of other number.

Examples:

friend(220) ==> true

friend(7) ==> false

friend(284) ==> true

Function with least number of chars wins.

NOTE: I just found out that there is a similar question, but I believe this one is simpler and perhaps more general.

share|improve this question
You are missing some divisors, namely: N is a divisor of N. – Thomas Eding Jul 19 '11 at 20:06
that is true. I need to indicate that N is not included in its divisors.. – leonardo Jul 19 '11 at 21:01

9 Answers

Haskell, 47

o m=sum[x|x<-[1..m-1],m`mod`x<1]
f m=(o.o)m==m

Call the f function (for "friend").
Didn't provide a main because nobody else is doing so.

share|improve this answer
1  
(m-1) -> m-1 – Thomas Eding Jul 19 '11 at 20:04
@trinithis: thanks – marinus Jul 20 '11 at 12:02
Haskell was made for problems like this. – eternalmatt Jul 21 '11 at 1:14

Python, 67

a=lambda x:sum(i for i in range(1,x)if x%i<1)
b=lambda x:x==a(a(x))
share|improve this answer
2  
Suggestion xrange(1,x) => range(x) and not x%i to x%i<1 – Charles Beattie Jul 9 '11 at 14:41
just xrange to range %0 causes an error – Charles Beattie Jul 9 '11 at 15:10
good tips Charles! – leonardo Jul 11 '11 at 18:18

eTeX, 177 (yes, that language is too verbose)

\let~\ifnum\let\c\newcount\c\X\c\D\c\R\def\!{\advance\D1 ~\D<\X~\X=\numexpr\D*\numexpr
\X/\D\advance\R\D\fi\!\fi}\def\a#1{\X#1 \!\X\R\D0\R0 \!\message{~#1=\R YES\else NO\fi}\end}

Used as etex filename.tex "\a{220}".

share|improve this answer
nice. i did not know that language exists... – leonardo Jul 11 '11 at 18:18
It is an extension of {TeX, written by D. E. Knuth}, written by many people, including P. Breitenlohner. (EDIT: added braces to help parse the sentence) – Bruno Le Floch Jul 11 '11 at 22:06
I think you can trim it down some more by doing something like \let\n\numexpr and \let\v\advance. Also, it seems like everyone else is just implementing a function that returns a boolean; you might be able to save some more characters by converting it to setting a \newif instead of printing a \message. – ESultanik Jul 20 '11 at 13:30
@ESultanik: when a primitive is used only twice, it is typically not worth doing \let\x\primitive: this uses 10 chars (\let\x and twice \x) plus the length of the primitive instead of twice the length of the primitive. Both \advance and \numexpr take 8 characters, so it's better here to stick with those. – Bruno Le Floch Jul 25 '11 at 10:38
@Bruno: Oops! For some reason I thought it would save a character or two; I must have messed up the arithmetic in my head. Sorry about that. – ESultanik Jul 25 '11 at 12:22

Scala, 67

def d(n:Int)=(1 to n-1).filter(n%_==0).sum
def f(n:Int)=d(d(n))==n
share|improve this answer

Ruby, 95

l=lambda{|n|(1..n-1).select{|e|n.modulo(e)==0}.reduce(:+)}
m=lambda{|n|(l.call(l.call(n))==n)}
share|improve this answer

Ruby 1.9, 57 characters

s=->n{eval (1...n).select{|a|n%a<1}*?+}
f=->n{s[s[n]]==n}

Pretty similar to all the other solutions here.

share|improve this answer

J, 24 characters

The pure answer is this:

=(+/&(((0:=|~)#])i.))^:2

It's a monad that takes a scalar and returns 0 or 1 if it's a friend or not. Unfortunately J precedence rules make it impossible to use with no separator from its argument. I'm keeping the character count as such because of the way the question is worded. Anyway, here's a demonstration of three possible ways to use it:

   NB. using a named verb
   f =: =(+/&(((0:=|~)#])i.))^:2
   f 220
1
   NB. using parentheses
   (=(+/&(((0:=|~)#])i.))^:2) 7
0
   NB. using verb "Same"
   =(+/&(((0:=|~)#])i.))^:2 [ 284
1

Obligatory J unscrambling:

  • i. 220 returns the list of naturals below 220 (0, 1, 2 to 219)
  • (|~i.) 220 divides them all by 220 and returns the remainder
  • ((0:=|~)i.) 220 compares to 0 (returns boolean as 0 or 1)
  • (((0:=|~)#])i.) 220 returns the natural where the 1s were. In effect: returns the full divisor list.
  • (+/&(((0:=|~)#])i.)) 220 sums them.
  • ((+/&(((0:=|~)#])i.))^:2) 220 performs the operation twice.
  • (=(+/&(((0:=|~)#])i.))^:2) 220 checks we fall back on the initial argument.
share|improve this answer

Q, 42 33

{x={0+/a(&)0=x mod a:(!)6h$(1+x%2)}/[2;x]}

shorter by not limiting the check for divisors to enumerations up to n/2 but obviously slower as a result:

{x={0+/a(&)0=x mod a:(!)x}/[2;x]}

timing

q)\t {x={0+/a(&)0=x mod a:(!)x}/[2;x]} 2200000
289
q)\t {x={0+/a(&)0=x mod a:(!)6h$(1+x%2)}/[2;x]} 2200000
124
share|improve this answer

GolfScript (25 chars)

{.{:a,(\{.a\%!*+}/}2*=}:f

a can, of course, be replaced by the name of any other variable whose contents you don't care about.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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