6
\$\begingroup\$

I just started reading about friendly numbers and I think they sound great.

In number theory, friendly numbers are two or more natural numbers with a common abundancy, the ratio between the sum of divisors of a number and the number itself. Two numbers with the same abundancy form a friendly pair; n numbers with the same abundancy form a friendly n-tuple.

So, how small a program can you write to output a list of the first 20 friendly numbers.

Assuming I've understood everything I've read correctly the output of your program should be:

6,28
30,140
80,200
40,224
12,234
84,270
66,308
78,364
102,476
6,496
28,496
114,532
240,600
138,644
120,672
150,700
174,812
135,819
186,868
864,936
222,1036
246,1148

I'd also like to add that the program must calculate the answers and not use any external resources or hard coded answers (thanks Peter).

\$\endgroup\$
9
  • 5
    \$\begingroup\$ can you quote the definition here? We StackExchangers don't like having to visit external sites :-) \$\endgroup\$ Dec 23, 2013 at 17:12
  • 9
    \$\begingroup\$ Two things. Firstly, you ask for the first items but you haven't defined a total ordering on them. Secondly, you make the common beginner's error of not taking requiring the program to do the calculation. I strongly advise you to edit the question to prohibit the use of external resources (or someone will submit a program which downloads the answer) and to require the program to input N and output the first N such pairs (or someone will submit an answer which just uncompresses a precomputed literal string). \$\endgroup\$ Dec 23, 2013 at 18:26
  • \$\begingroup\$ In addition to @PeterTaylor's remarks - in case you consider N being variable you'd have to specify how n-tuples with n>2 should be handled. \$\endgroup\$
    – Howard
    Dec 23, 2013 at 19:26
  • 1
    \$\begingroup\$ +1 to @PeterTaylor. Aside from prohibiting external resources, you also need to forbid hard-coding of the numbers. \$\endgroup\$
    – Iszi
    Dec 23, 2013 at 19:57
  • 2
    \$\begingroup\$ I think you missed 6,496 and 28,496 in your list. \$\endgroup\$
    – marinus
    Dec 23, 2013 at 21:36

9 Answers 9

5
\$\begingroup\$

APL (50)

↑⊃,/{g/⍨{=/{⍵÷⍨+/z/⍨0=⍵|⍨z←⍳⍵}¨⍵}¨g←⍵∘.,⍳⍵-1}¨⍳936

The list is slightly different but oeis.org agrees with me.

Output:

 28   6
140  30
200  80
224  40
234  12
270  84
308  66
364  78
476 102
496   6
496  28
532 114
600 240
644 138
672 120
700 150
812 174
819 135
868 186
936 864
\$\endgroup\$
5
\$\begingroup\$

Ruby, 90 characters

h={}
1.upto(1150){|n|s=0
1.upto(n){|x|s+=x if n%x<1}
r=s/n.to_r
p [h[r],n] if h[r]
h[r]=n}
\$\endgroup\$
1
  • \$\begingroup\$ Nice, although it doesn't include the line [6, 496], here are the results: ideone.com/HrLpbr \$\endgroup\$
    – Felix Eve
    Dec 24, 2013 at 12:26
5
\$\begingroup\$

C (132)

x=1,e;float d(a,b){return b?1.f*(a%b==0)*b/a+d(a,--b):0;}main(){while(x<1148)for(e=x++;--e;)d(x,x)-d(e,e)||(printf("%d,%d\n",e,x));}

Thanks to shiona for the ideas on shorter code. And Felix Eve for the Code(counting down makes more sense if you only search pairs). With the added Pairs even shorter.

Readable Version:

x=1,e;

float d(a,b)
{
    return b?1.f*(a%b==0)*b/a+d(a,--b):0;
}


main()
{
    while(x<1148)
        for(e=x++;--e;)
            d(x,x)-d(e,e)||(printf("%d,%d\n",e,x));
}
\$\endgroup\$
7
  • \$\begingroup\$ There are a lot of improvements to this. I'll make some edits and put them to a pastebin or something and link here. \$\endgroup\$
    – shiona
    Dec 24, 2013 at 2:10
  • \$\begingroup\$ Yes I am Pretty sure, that this can be less than the hard coded Results and I found a few Bytes to optimize out. \$\endgroup\$ Dec 24, 2013 at 2:30
  • 1
    \$\begingroup\$ pastebin.com/AVX6KNau It's by no means perfect, but I hope it'll help you make messier C code :D \$\endgroup\$
    – shiona
    Dec 24, 2013 at 2:42
  • \$\begingroup\$ Yes, I have to try my new C skills at work, I think my code looks too clean :P \$\endgroup\$ Dec 24, 2013 at 3:25
  • \$\begingroup\$ No need to include header file. It will compile without header file(with warnings about impicit declaration of built in functions).You can also just declare main() instead of int main().Perhaps you may try this trick too ;) main(x,e,f){x=1;f=21; \$\endgroup\$
    – Wasi
    Dec 24, 2013 at 5:08
4
\$\begingroup\$

Mathematica 114 112 99 90

Numbers having same abundancy. (90 chars)

This displays integers with a common abundancy. Notice that 6, 28, and 496 have the same abundancy, which means that (6,28), (6,496) and (28, 496) are friendly number pairs. Likewise, 84, 270, 1488, 1638 have the same abundancy.

Because, as Peter Taylor noted, there is no method suggested for total ordering, it is unclear which pairs constitute the "first 20" friendly number pairs.

Grid@Cases[GatherBy[{k, 1~DivisorSigma~k/k}~Table~{k, 2000}, Last], x_ /; Length@x > 1 
:> x[[All, 1]]]

abundancy

\$\endgroup\$
1
  • \$\begingroup\$ I used the term abundancY because otherwise the auto-spelling checker coverts the word to abundance. \$\endgroup\$
    – DavidC
    Dec 24, 2013 at 15:56
4
\$\begingroup\$

Mathematica 62 58 55

Grid@Cases[GatherBy[Range[6!],Tr@Divisors@#/#&],{_,__}]

6   28  496
12  234 
30  140 
40  224 
66  308 
78  364 
80  200 
84  270 
102 476 
114 532 
120 672 
138 644 
150 700 
240 600 

You may go up to 9! without affecting the char count

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

Using awk (303, uncompressed)

 awk 'BEGIN{for (i=1;i<=1150;i++)
             { for (j=1;j<=int(i/2);j++)
                  if (i%j=="0") a[i]+=j
                v=sprintf("%.10f",(a[i]+i)/i)
                #print v,i
               b[v]=b[v] FS i
              }
           for (i in b) {l=split(b[i],x,FS);if (l>1) print b[i]}}' file|sort -n

 6 28 496
 12 234
 30 140
 40 224
 66 308
 78 364
 80 200
 84 270
 102 476
 114 532
 120 672
 135 819
 138 644
 150 700
 174 812
 186 868
 222 1036
 240 600
 246 1148
 864 936
\$\endgroup\$
0
\$\begingroup\$

C - 188

I assume someone will do this with a language that supports literal newlines and requires less boilerplate.

main(){puts("6,28\n30,140\n80,200\n40,224\n12,234\n84,270\n66,308\n78,364\n102,476\n114,532\n240,600\n138,644\n120,672\n150,700\n174,812\n135,819\n186,868\n864,936\n222,1036\n246,1148");}
\$\endgroup\$
0
0
\$\begingroup\$

PHP - 260

$x=1;while($i<20){$d=0;$y=$x;for($y=$x;$y>0;$y--){if($x%$y==0)$d+=$y;}$f=$d/$x.'';$s[$f][]=$x;if(count($s[$f])>1) {$i++;if(count($s[$f])>2){$o[]=$s[$f][0].','.$s[$f][2];$o[]=$s[$f][1].','.$s[$f][2];}else $o[]=implode(',',$s[$f]);}$x++;}echo implode('<br>',$o);

Uncompressed:

$x=1;
$o = array();
while($i<20) {
    $d = 0;
    $y = $x;
    for($y=$x;$y>0;$y--) {
        if($x%$y==0) $d += $y;
    }
    $f = $d / $x.' ';
    $s[$f][] = $x;
    if(count($s[$f])>1) {
        $i++;
        if(count($s[$f])>2) {
            $o[] = $s[$f][0].','.$s[$f][2];
            $o[] = $s[$f][1].','.$s[$f][2];
        } else {
            $o[] = implode(',', $s[$f]);    
        }
    }
    $x++;
}
echo implode('<br>', $o);

This answer is longer than my other answer but works properly (doesn't skip any numbers and only has 2 numbers per row) so I'm more happy with this one.

\$\endgroup\$
0
\$\begingroup\$

C#: 208

public class A{static double D(int n){return 1f*Enumerable.Range(1,n).Where(i=>n%i==0).Sum()/n;}static void Main(){for(int j,i=1;i++<865;)for(j=1;j++<1000;)if(A.D(i)==A.D(j)&&i<j)Console.WriteLine(i+" "+j);}}
\$\endgroup\$

Your Answer

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

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