Task: Aliquot sequence classifications


C++: #include <cstdint>
#include <iostream>
#include <string>

using integer = uint64_t;


integer divisor_sum(integer n) {
    integer total = 1, power = 2;
    
    for (; n % 2 == 0; power *= 2, n /= 2)
        total += power;
    
    for (integer p = 3; p * p <= n; p += 2) {
        integer sum = 1;
        for (power = p; n % p == 0; power *= p, n /= p)
            sum += power;
        total *= sum;
    }
    
    if (n > 1)
        total *= n + 1;
    return total;
}


void classify_aliquot_sequence(integer n) {
    constexpr int limit = 16;
    integer terms[limit];
    terms[0] = n;
    std::string classification("non-terminating");
    int length = 1;
    for (int i = 1; i < limit; ++i) {
        ++length;
        terms[i] = divisor_sum(terms[i - 1]) - terms[i - 1];
        if (terms[i] == n) {
            classification =
                (i == 1 ? "perfect" : (i == 2 ? "amicable" : "sociable"));
            break;
        }
        int j = 1;
        for (; j < i; ++j) {
            if (terms[i] == terms[i - j])
                break;
        }
        if (j < i) {
            classification = (j == 1 ? "aspiring" : "cyclic");
            break;
        }
        if (terms[i] == 0) {
            classification = "terminating";
            break;
        }
    }
    std::cout << n << ": " << classification << ", sequence: " << terms[0];
    for (int i = 1; i < length && terms[i] != terms[i - 1]; ++i)
        std::cout << ' ' << terms[i];
    std::cout << '\n';
}

int main() {
    for (integer i = 1; i <= 10; ++i)
        classify_aliquot_sequence(i);
    for (integer i : {11, 12, 28, 496, 220, 1184, 12496, 1264460, 790, 909, 562,
                      1064, 1488})
        classify_aliquot_sequence(i);
    classify_aliquot_sequence(15355717786080);
    classify_aliquot_sequence(153557177860800);
    return 0;
}







VB: Option Explicit

Private Type Aliquot
   Sequence() As Double
   Classification As String
End Type

Sub Main()
Dim result As Aliquot, i As Long, j As Double, temp As String

   For j = 1 To 10
      result = Aliq(j)
      temp = vbNullString
      For i = 0 To UBound(result.Sequence)
         temp = temp & result.Sequence(i) & ", "
      Next i
      Debug.Print "Aliquot seq of " & j & " : " & result.Classification & "   " & Left(temp, Len(temp) - 2)
   Next j

Dim a
   
   a = Array(11, 12, 28, 496, 220, 1184, 12496, 1264460, 790, 909, 562, 1064, 1488)
   For j = LBound(a) To UBound(a)
      result = Aliq(CDbl(a(j)))
      temp = vbNullString
      For i = 0 To UBound(result.Sequence)
         temp = temp & result.Sequence(i) & ", "
      Next i
      Debug.Print "Aliquot seq of " & a(j) & " : " & result.Classification & "   " & Left(temp, Len(temp) - 2)
   Next
End Sub

Private Function Aliq(Nb As Double) As Aliquot
Dim s() As Double, i As Long, temp, j As Long, cpt As Long
   temp = Array("non-terminating", "Terminate", "Perfect", "Amicable", "Sociable", "Aspiring", "Cyclic")
   ReDim s(0)
   s(0) = Nb
   For i = 1 To 15
      cpt = cpt + 1
      ReDim Preserve s(cpt)
      s(i) = SumPDiv(s(i - 1))
      If s(i) > 140737488355328# Then Exit For
      If s(i) = 0 Then j = 1
      If s(1) = s(0) Then j = 2
      If s(i) = s(0) And i > 1 And i <> 2 Then j = 4
      If s(i) = s(i - 1) And i > 1 Then j = 5
      If i >= 2 Then
         If s(2) = s(0) Then j = 3
         If s(i) = s(i - 2) And i <> 2 Then j = 6
      End If
      If j > 0 Then Exit For
   Next
   Aliq.Classification = temp(j)
   Aliq.Sequence = s
End Function

Private Function SumPDiv(n As Double) As Double

Dim j As Long, t As Long
    If n > 1 Then
        For j = 1 To n \ 2
            If n Mod j = 0 Then t = t + j
        Next
    End If
    SumPDiv = t
End Function