Task: Aliquot sequence classifications




Go: 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))
}





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