June 2018 Update

This commit is contained in:
Ingy döt Net 2018-06-22 20:57:24 +00:00
parent ba8067c3b7
commit 22f33d4004
5278 changed files with 84726 additions and 14379 deletions

View file

@ -24,8 +24,8 @@ being K and subsequent members being the sum of the [[Proper divisors]] of the p
Show all output on this page.
;Cf.
* [[Abundant, deficient and perfect number classifications]]. (Classifications from only the first two members of the whole sequence).
* [[Proper divisors]]
* [[Amicable pairs]]
;Related tasks:
*   [[Abundant, deficient and perfect number classifications]]. (Classifications from only the first two members of the whole sequence).
*   [[Proper divisors]]
*   [[Amicable pairs]]
<br><br>

View file

@ -0,0 +1,106 @@
BEGIN
# aliquot sequence classification #
# maximum sequence length we consider #
INT max sequence length = 16;
# possible classifications #
STRING perfect classification = "perfect ";
STRING amicable classification = "amicable ";
STRING sociable classification = "sociable ";
STRING aspiring classification = "aspiring ";
STRING cyclic classification = "cyclic ";
STRING terminating classification = "terminating ";
STRING non terminating classification = "non terminating";
# structure to hold an aliquot sequence and its classification #
MODE ALIQUOT = STRUCT( STRING classification
, [ 1 : max sequence length ]LONG INT sequence
, INT length
);
# maximum value for sequence elements - if any element is more than this, #
# we assume it is non-teriminating #
LONG INT max element = 140 737 488 355 328;
# returns the sum of the proper divisors of n #
OP DIVISORSUM = ( LONG INT n )LONG INT:
BEGIN
LONG INT abs n = ABS n;
IF abs n < 2 THEN
0 # -1, 0 and 1 have no proper divisors #
ELSE
# have a number with possible divisors #
LONG INT result := 1; # 1 is always a divisor #
# a FOR loop counter can only be an INT, hence the WHILE loop #
LONG INT d := ENTIER long sqrt( abs n );
WHILE d > 1 DO
IF abs n MOD d = 0 THEN
# found another divisor #
result +:= d;
IF d * d /= abs n THEN
# add the other divisor #
result +:= abs n OVER d
FI
FI;
d -:= 1
OD;
result
FI
END # DIVISORSUM # ;
# generates the aliquot sequence of the number k and its classification #
# at most max elements of the sequence are considered #
OP CLASSIFY = ( LONG INT k )ALIQUOT :
BEGIN
ALIQUOT result;
classification OF result := "non-terminating";
INT lb = LWB sequence OF result;
INT ub = UPB sequence OF result;
( sequence OF result )[ lb ] := k; # the first element is always k #
length OF result := 1;
FOR i FROM lb + 1 TO ub DO
( sequence OF result )[ i ] := 0
OD;
BOOL classified := FALSE;
LONG INT prev k := k;
FOR i FROM lb + 1 TO ub WHILE NOT classified DO
length OF result +:= 1;
LONG INT next k := ( sequence OF result )[ i ] := DIVISORSUM prev k;
classified := TRUE;
IF next k = 0 THEN # the sequence terminates #
classification OF result := terminating classification
ELIF next k > max element THEN # the sequence gets too large #
classification OF result := non terminating classification
ELIF next k = k THEN # the sequence that returns to k #
classification OF result
:= IF i = lb + 1 THEN perfect classification
ELIF i = lb + 2 THEN amicable classification
ELSE sociable classification
FI
ELIF next k = prev k THEN # the sequence repeats with non-k #
classification OF result := aspiring classification
ELSE # check for repeating sequence with a period more than 1 #
classified := FALSE;
FOR prev pos FROM lb TO i - 2 WHILE NOT classified DO
IF classified := ( sequence OF result )[ prev pos ] = next k THEN
# found a repeatition #
classification OF result := cyclic classification
FI
OD
FI;
prev k := next k
OD;
result
END # CLASSIFY # ;
# test cases as per the task #
[]LONG INT test cases =
( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
, 11, 12, 28, 496, 220, 1184, 12496, 1264460, 790, 909
, 562, 1064, 1488
, 15355717786080
);
FOR i FROM LWB test cases TO UPB test cases DO
LONG INT k := test cases[ i ];
ALIQUOT seq = CLASSIFY k;
print( ( whole( k, -14 ), ": ", classification OF seq, ":" ) );
FOR e FROM LWB sequence OF seq + 1 TO length OF seq DO
print( ( " ", whole( ( sequence OF seq )[ e ], 0 ) ) )
OD;
print( ( newline ) )
OD
END

View file

@ -0,0 +1,73 @@
/*Abhishek Ghosh, 1st November 2017*/
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
unsigned long long bruteForceProperDivisorSum(unsigned long long n){
unsigned long long i,sum = 0;
for(i=1;i<(n+1)/2;i++)
if(n%i==0 && n!=i)
sum += i;
return sum;
}
void printSeries(unsigned long long* arr,int size,char* type){
int i;
printf("\nInteger : %llu, Type : %s, Series : ",arr[0],type);
for(i=0;i<size-1;i++)
printf("%llu, ",arr[i]);
printf("%llu",arr[i]);
}
void aliquotClassifier(unsigned long long n){
unsigned long long arr[16];
int i,j;
arr[0] = n;
for(i=1;i<16;i++){
arr[i] = bruteForceProperDivisorSum(arr[i-1]);
if(arr[i]==0||arr[i]==n||(arr[i]==arr[i-1] && arr[i]!=n)){
printSeries(arr,i+1,(arr[i]==0)?"Terminating":(arr[i]==n && i==1)?"Perfect":(arr[i]==n && i==2)?"Amicable":(arr[i]==arr[i-1] && arr[i]!=n)?"Aspiring":"Sociable");
return;
}
for(j=1;j<i;j++){
if(arr[j]==arr[i]){
printSeries(arr,i+1,"Cyclic");
return;
}
}
}
printSeries(arr,i+1,"Non-Terminating");
}
void processFile(char* fileName){
FILE* fp = fopen(fileName,"r");
char str[21];
while(fgets(str,21,fp)!=NULL)
aliquotClassifier(strtoull(str,(char**)NULL,10));
fclose(fp);
}
int main(int argC,char* argV[])
{
if(argC!=2)
printf("Usage : %s <positive integer>",argV[0]);
else{
if(strchr(argV[1],'.')!=NULL)
processFile(argV[1]);
else
aliquotClassifier(strtoull(argV[1],(char**)NULL,10));
}
return 0;
}

View file

@ -0,0 +1,103 @@
/*Abhishek Ghosh, 7th November 2017*/
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
unsigned long long raiseTo(unsigned long long base, unsigned long long power){
unsigned long long result = 1,i;
for (i=0; i<power;i++) {
result*=base;
}
return result;
}
unsigned long long properDivisorSum(unsigned long long n){
unsigned long long prod = 1;
unsigned long long temp = n,i,count = 0;
while(n%2 == 0){
count++;
n /= 2;
}
if(count!=0)
prod *= (raiseTo(2,count + 1) - 1);
for(i=3;i*i<=n;i+=2){
count = 0;
while(n%i == 0){
count++;
n /= i;
}
if(count==1)
prod *= (i+1);
else if(count > 1)
prod *= ((raiseTo(i,count + 1) - 1)/(i-1));
}
if(n>2)
prod *= (n+1);
return prod - temp;
}
void printSeries(unsigned long long* arr,int size,char* type){
int i;
printf("\nInteger : %llu, Type : %s, Series : ",arr[0],type);
for(i=0;i<size-1;i++)
printf("%llu, ",arr[i]);
printf("%llu",arr[i]);
}
void aliquotClassifier(unsigned long long n){
unsigned long long arr[16];
int i,j;
arr[0] = n;
for(i=1;i<16;i++){
arr[i] = properDivisorSum(arr[i-1]);
if(arr[i]==0||arr[i]==n||(arr[i]==arr[i-1] && arr[i]!=n)){
printSeries(arr,i+1,(arr[i]==0)?"Terminating":(arr[i]==n && i==1)?"Perfect":(arr[i]==n && i==2)?"Amicable":(arr[i]==arr[i-1] && arr[i]!=n)?"Aspiring":"Sociable");
return;
}
for(j=1;j<i;j++){
if(arr[j]==arr[i]){
printSeries(arr,i+1,"Cyclic");
return;
}
}
}
printSeries(arr,i+1,"Non-Terminating");
}
void processFile(char* fileName){
FILE* fp = fopen(fileName,"r");
char str[21];
while(fgets(str,21,fp)!=NULL)
aliquotClassifier(strtoull(str,(char**)NULL,10));
fclose(fp);
}
int main(int argC,char* argV[])
{
if(argC!=2)
printf("Usage : %s <positive integer>",argV[0]);
else{
if(strchr(argV[1],'.')!=NULL)
processFile(argV[1]);
else
aliquotClassifier(strtoull(argV[1],(char**)NULL,10));
}
return 0;
}

View file

@ -0,0 +1,109 @@
package main
import (
"fmt"
"math"
"strings"
)
const threshold = uint64(1) << 47
func indexOf(s []uint64, search uint64) int {
for i, e := range s {
if e == search {
return i
}
}
return -1
}
func contains(s []uint64, search uint64) bool {
return indexOf(s, search) > -1
}
func maxOf(i1, i2 int) int {
if i1 > i2 {
return i1
}
return i2
}
func sumProperDivisors(n uint64) uint64 {
if n < 2 {
return 0
}
sqrt := uint64(math.Sqrt(float64(n)))
sum := uint64(1)
for i := uint64(2); i <= sqrt; i++ {
if n % i != 0 {
continue
}
sum += i + n / i
}
if sqrt * sqrt == n {
sum -= sqrt
}
return sum
}
func classifySequence(k uint64) ([]uint64, string) {
if k == 0 {
panic("Argument must be positive.")
}
last := k
var seq []uint64
seq = append(seq, k)
for {
last = sumProperDivisors(last)
seq = append(seq, last)
n := len(seq)
aliquot := ""
switch {
case last == 0:
aliquot = "Terminating"
case n == 2 && last == k:
aliquot = "Perfect"
case n == 3 && last == k:
aliquot = "Amicable"
case n >= 4 && last == k:
aliquot = fmt.Sprintf("Sociable[%d]", n - 1)
case last == seq[n - 2]:
aliquot = "Aspiring"
case contains(seq[1 : maxOf(1, n - 2)], last):
aliquot = fmt.Sprintf("Cyclic[%d]", n - 1 - indexOf(seq[:], last))
case n == 16 || last > threshold:
aliquot = "Non-Terminating"
}
if aliquot != "" {
return seq, aliquot
}
}
}
func joinWithCommas(seq []uint64) string {
res := fmt.Sprint(seq)
res = strings.Replace(res, " ", ", ", -1)
return res
}
func main() {
fmt.Println("Aliquot classifications - periods for Sociable/Cyclic in square brackets:\n")
for k := uint64(1); k <= 10; k++ {
seq, aliquot := classifySequence(k)
fmt.Printf("%2d: %-15s %s\n", k, aliquot, joinWithCommas(seq))
}
fmt.Println()
s := []uint64{
11, 12, 28, 496, 220, 1184, 12496, 1264460, 790, 909, 562, 1064, 1488,
}
for _, k := range s {
seq, aliquot := classifySequence(k)
fmt.Printf("%7d: %-15s %s\n", k, aliquot, joinWithCommas(seq))
}
fmt.Println()
k := uint64(15355717786080)
seq, aliquot := classifySequence(k)
fmt.Printf("%d: %-15s %s\n", k, aliquot, joinWithCommas(seq))
}

View file

@ -1,27 +1,37 @@
import: mapping
import: quicksort
import: math
Object method: sum ( coll -- m )
#+ self reduce dup ifNull: [ drop 0 ] ;
Integer method: properDivs
| i l |
ListBuffer new dup add(1) ->l
2 self nsqrt tuck for: i [ self i mod ifFalse: [ l add(i) l add(self i / ) ] ]
sq self == ifTrue: [ l removeLast drop ]
l sort ;
Array new dup 1 over add ->l
2 self nsqrt tuck for: i [ self i mod ifFalse: [ i l add self i / l add ] ]
sq self == ifTrue: [ l pop drop ]
dup sort
;
: aliquot(n) // ( n -- aList ) : Returns aliquot sequence of n
: aliquot( n -- [] ) \ Returns aliquot sequence of n
| end l |
2 47 pow ->end
ListBuffer new dup add(n) dup ->l
while (l size 16 < l last 0 <> and l last end <= and) [ l last properDivs sum l add ] ;
Array new dup n over add ->l
while ( l size 16 < l last 0 <> and l last end <= and ) [ l last properDivs sum l add ]
;
: aliquotClass(n) // ( n -- aList aString ) : Returns aliquot sequence and classification
: aliquotClass( n -- [] s ) \ Returns aliquot sequence and classification
| l i j |
n aliquot dup ->l
l last 0 == ifTrue: [ "terminate" return ]
l second n == ifTrue: [ "perfect" return ]
l third n == ifTrue: [ "amicable" return ]
3 l at n == ifTrue: [ "amicable" return ]
l indexOfFrom(n, 2) ifNotNull: [ "sociable" return ]
l size loop: i [
l indexOfFrom(l at(i), i 1 +) -> j
j i 1 + == ifTrue: [ "aspiring" return ]
l indexOfFrom(l at(i), i 1+ ) -> j
j i 1+ == ifTrue: [ "aspiring" return ]
j ifNotNull: [ "cyclic" return ]
]
"non-terminating" ;
"non-terminating"
;

View file

@ -2,10 +2,10 @@
parse arg low high L /*obtain optional arguments from the CL*/
high=word(high low 10,1); low=word(low 1,1) /*obtain the LOW and HIGH (range). */
if L='' then L=11 12 28 496 220 1184 12496 1264460 790 909 562 1064 1488 15355717786080
numeric digits 20 /*be able to handle the number: BIG */
big=2**47; NTlimit=16+1 /*limits for a non─terminating sequence*/
numeric digits 100 /*be able to compute the number: BIG */
big= 2**47; NTlimit= 16 + 1 /*limits for a non─terminating sequence*/
numeric digits max(9, 1 + length(big) ) /*be able to handle big numbers for // */
#.=.; #.0=0; #.1=0 /*#. are the proper divisor sums. */
#.=.; #.0=0; #.1=0 /*#. are the proper divisor sums. */
say center('numbers from ' low " to " high, 79, "")
do n=low to high; call classify n /*call a subroutine to classify number.*/
end /*n*/ /* [↑] process a range of integers. */
@ -14,13 +14,13 @@ say center('first numbers for each classification', 79, "═")
class.=0 /* [↓] ensure one number of each class*/
do q=1 until class.sociable\==0 /*the only one that has to be counted. */
call classify -q /*minus (-) sign indicates don't tell. */
_=what; upper _; class._=class._+1 /*bump counter for this class sequence.*/
_=what; upper _; class._= class._ +1 /*bump counter for this class sequence.*/
if class._==1 then say right(q, digits()) 'is' center(what, 15) $
end /*q*/ /* [↑] only display the 1st occurrence*/
say /* [↑] process until all classes found*/
say center('classifications for specific numbers', 79, "")
do i=1 for words(L) /*L: is a list of "special numbers".*/
call classify word(L,i) /*call a subroutine to classify number.*/
call classify word(L, i) /*call a subroutine to classify number.*/
end /*i*/ /* [↑] process a list of integers. */
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
@ -28,29 +28,29 @@ classify: parse arg a 1 aa; a=abs(a) /*obtain number that's to be cl
if #.a\==. then s=#.a /*Was this number been summed before?*/
else s=sigma(a) /*No, then classify number the hard way*/
#.a=s; $=s /*define sum of the proper divisors. */
what='terminating' /*assume this kind of classification. */
c.=0; c.s=1 /*clear all cyclic sequences; set 1st.*/
if $==a then what='perfect' /*check for a "perfect" number. */
what= 'terminating' /*assume this kind of classification. */
c.=0; c.s=1 /*clear all cyclic sequences; set 1st.*/
if $==a then what= 'perfect' /*check for a "perfect" number. */
else do t=1 while s\==0 /*loop until sum isn't 0 or > big.*/
m=s /*obtain the last number in sequence. */
if #.m==. then s=sigma(m) /*Not defined? Then sum proper divisors*/
else s=#.m /*use the previously found integer. */
if m==s & m\==0 then do; what='aspiring' ; leave; end
parse var $ . word2 . /* " " 2nd " " " */
if word2==a then do; what='amicable' ; leave; end
if m==s & m\==0 then do; what= 'aspiring' ; leave; end
parse var $ . word2 . /*obtain the 2nd number in sequence. */
if word2==a then do; what= 'amicable' ; leave; end
$=$ s /*append a sum to the integer sequence.*/
if s==a & t>3 then do; what='sociable' ; leave; end
if c.s & m\==0 then do; what='cyclic' ; leave; end
if s==a & t>3 then do; what= 'sociable' ; leave; end
if c.s & m\==0 then do; what= 'cyclic' ; leave; end
c.s=1 /*assign another possible cyclic number*/
/* [↓] Rosetta Code task's limit: >16 */
if t>NTlimit then do; what='non-terminating'; leave; end
if s>big then do; what='NON-TERMINATING'; leave; end
if t>NTlimit then do; what= 'non-terminating'; leave; end
if s>big then do; what= 'NON-TERMINATING'; leave; end
end /*t*/ /* [↑] only permit within reason. */
if aa>0 then say right(a, digits() ) 'is' center(what, 15) $
return /* [↑] only display if A is positive.*/
return /* [↑] only display if AA is positive*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
sigma: procedure expose #.; parse arg x; if x<2 then return 0; odd=x//2
s=1 /* [↓] use only EVEN | ODD ints. ___*/
sigma: procedure expose #. !.; parse arg x; if x<2 then return 0; odd=x//2
s=1 /* [↓] use EVEN or ODD integers. ___*/
do j=2+odd by 1+odd while j*j<x /*divide by all the integers up to √ X */
if x//j==0 then s=s + j + x%j /*add the two divisors to the sum. */
end /*j*/ /* [↓] adjust for square. ___*/

View file

@ -0,0 +1,81 @@
# Project : Aliquot sequence classnifications
# Date : 2017/11/16
# Author : Gal Zsolt (~ CalmoSoft ~)
# Email : <calmosoft@gmail.com>
see "Rosetta Code - aliquot sequence classnifications" + nl
while true
see "enter an integer: "
give k
k=fabs(floor(number(k)))
if k=0
exit
ok
printas(k)
end
see "program complete."
func printas(k)
length=52
aseq = list(length)
n=k
classn=0
priorn = 0
inc = 0
for element=2 to length
aseq[element]=pdtotal(n)
see aseq[element] + " " + nl
if aseq[element]=0
see " terminating" + nl
classn=1
exit
ok
if aseq[element]=k and element=2
see " perfect" + nl
classn=2
exit
ok
if aseq[element]=k and element=3
see " amicable" + nl
classn=3
exit
ok
if aseq[element]=k and element>3
see " sociable" + nl
classn=4
exit
ok
if aseq[element]!=k and aseq[element-1]=aseq[element]
see " aspiring" + nl
classn=5
exit
ok
if aseq[element]!=k and element>2 and aseq[element-2]= aseq[element]
see " cyclic" + nl
classn=6
exit
ok
n=aseq[element]
if n>priorn
priorn=n
inc=inc+1
but n<=priorn
inc=0
priorn=0
ok
if inc=11 or n>30000000
exit
ok
next
if classn=0
see " non-terminating" + nl
ok
func pdtotal(n)
pdtotal = 0
for y=2 to n
if (n % y)=0
pdtotal=pdtotal+(n/y)
ok
next
return pdtotal