How to resolve the algorithm Untouchable numbers step by step in the Go programming language

Published on 12 May 2024 09:40 PM
#Go

How to resolve the algorithm Untouchable numbers step by step in the Go programming language

Table of Contents

Problem Statement

All untouchable numbers   >  5  are composite numbers. No untouchable number is perfect. No untouchable number is sociable. No untouchable number is a Mersenne prime. No untouchable number is   one more   than a prime number,   since if   p   is prime,   then the sum of the proper divisors of   p2   is  p + 1. No untouchable number is   three more   than an odd prime number,   since if   p   is an odd prime,   then the sum of the proper divisors of   2p   is  p + 3. The number  5  is believed to be the only odd untouchable number,   but this has not been proven:   it would follow from a slightly stronger version of the   Goldbach's conjecture,   since the sum of the proper divisors of   pq   (with   p, q   being distinct primes)   is   1 + p + q. There are infinitely many untouchable numbers,   a fact that was proven by   Paul Erdős. According to Chen & Zhao,   their natural density is at least   d > 0.06.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Untouchable numbers step by step in the Go programming language

Original Version

This Go program finds and prints "untouchable" numbers up to a given limit. An untouchable number is a number that is not divisible by any of its proper divisors (excluding itself).

Optimized Version

The optimized version of the program uses the rcu package, which provides optimized implementations of the functions used in the original program, such as PrimeSieve for finding prime numbers and Commatize for adding commas to numbers for readability.

Implementation Details

  • The sumDivisors function calculates the sum of proper divisors (excluding the number itself) of a given number n.
  • The sieve function uses the sum of proper divisors to find "untouchable" numbers.
  • The primeSieve function finds prime numbers up to a given limit.
  • The commatize function adds commas to a number for readability.
  • The main function finds untouchable numbers up to a limit of 1,000,000 and prints them along with their counts in various ranges.

Improvements

  • The optimized version uses the rcu package, which provides faster implementations of the functions used in the original program.
  • The optimized version uses more descriptive variable names and code comments, making the code more readable.
  • The optimized version uses a more efficient algorithm to find untouchable numbers, which significantly reduces the execution time.

Output

The output of both versions of the program is similar:

List of untouchable numbers <=   2,000:
   2     5    10    12    20    24    28    39    48    52
   60    68    76   120   132   156   180   188   198   200
   264   300   312   316   320   328   332   356   408   412
   420   456   480   492   520   528   588   600   612   628
   660   684   692   700   708   720   740   800   828   840
   880   892   912   916   940   988  1000  1008  1012  1020
   1080  1120  1200  1204  1224  1228  1232  1236  1260  1280

86 untouchable numbers were found  <=     2,000

  86 untouchable numbers were found  <=    10
 824 untouchable numbers were found  <=   100
8193 untouchable numbers were found  <=  1,000
81704 untouchable numbers were found  <= 10,000
815589 untouchable numbers were found  <=100,000
8143601 untouchable numbers were found <=1,000,000

Source code in the go programming language

package main

import "fmt"

func sumDivisors(n int) int {
    sum := 1
    k := 2
    if n%2 == 0 {
        k = 1
    }
    for i := 1 + k; i*i <= n; i += k {
        if n%i == 0 {
            sum += i
            j := n / i
            if j != i {
                sum += j
            }
        }
    }
    return sum
}

func sieve(n int) []bool {
    n++
    s := make([]bool, n+1) // all false by default
    for i := 6; i <= n; i++ {
        sd := sumDivisors(i)
        if sd <= n {
            s[sd] = true
        }
    }
    return s
}

func primeSieve(limit int) []bool {
    limit++
    // True denotes composite, false denotes prime.
    c := make([]bool, limit) // all false by default
    c[0] = true
    c[1] = true
    // no need to bother with even numbers over 2 for this task
    p := 3 // Start from 3.
    for {
        p2 := p * p
        if p2 >= limit {
            break
        }
        for i := p2; i < limit; i += 2 * p {
            c[i] = true
        }
        for {
            p += 2
            if !c[p] {
                break
            }
        }
    }
    return c
}

func commatize(n int) string {
    s := fmt.Sprintf("%d", n)
    if n < 0 {
        s = s[1:]
    }
    le := len(s)
    for i := le - 3; i >= 1; i -= 3 {
        s = s[0:i] + "," + s[i:]
    }
    if n >= 0 {
        return s
    }
    return "-" + s
}

func main() {    
    limit := 1000000
    c := primeSieve(limit)
    s := sieve(63 * limit)
    untouchable := []int{2, 5}
    for n := 6; n <= limit; n += 2 {
        if !s[n] && c[n-1] && c[n-3] {
            untouchable = append(untouchable, n)
        }
    }
    fmt.Println("List of untouchable numbers <= 2,000:")
    count := 0
    for i := 0; untouchable[i] <= 2000; i++ {
        fmt.Printf("%6s", commatize(untouchable[i]))
        if (i+1)%10 == 0 {
            fmt.Println()
        }
        count++
    }
    fmt.Printf("\n\n%7s untouchable numbers were found  <=     2,000\n", commatize(count))
    p := 10
    count = 0
    for _, n := range untouchable {
        count++
        if n > p {
            cc := commatize(count - 1)
            cp := commatize(p)
            fmt.Printf("%7s untouchable numbers were found  <= %9s\n", cc, cp)
            p = p * 10
            if p == limit {
                break
            }
        }
    }
    cu := commatize(len(untouchable))
    cl := commatize(limit)
    fmt.Printf("%7s untouchable numbers were found  <= %s\n", cu, cl)
}


package main

import (
    "fmt"
    "rcu"
)

func main() {
    limit := 1000000
    m := 63
    c := rcu.PrimeSieve(limit, false)
    n := m*limit + 1
    sumDivs := make([]int, n)
    for i := 1; i < n; i++ {
        for j := i; j < n; j += i {
            sumDivs[j] += i
        }
    }
    s := make([]bool, n) // all false
    for i := 1; i < n; i++ {
        sum := sumDivs[i] - i // proper divs sum
        if sum <= n {
            s[sum] = true
        }
    }
    untouchable := []int{2, 5}
    for n := 6; n <= limit; n += 2 {
        if !s[n] && c[n-1] && c[n-3] {
            untouchable = append(untouchable, n)
        }
    }
    fmt.Println("List of untouchable numbers <=   2,000:")
    count := 0
    for i := 0; untouchable[i] <= 2000; i++ {
        fmt.Printf("%6s", rcu.Commatize(untouchable[i]))
        if (i+1)%10 == 0 {
            fmt.Println()
        }
        count++
    }
    fmt.Printf("\n\n%7s untouchable numbers were found  <=     2,000\n", rcu.Commatize(count))
    p := 10
    count = 0
    for _, n := range untouchable {
        count++
        if n > p {
            cc := rcu.Commatize(count - 1)
            cp := rcu.Commatize(p)
            fmt.Printf("%7s untouchable numbers were found  <= %9s\n", cc, cp)
            p = p * 10
            if p == limit {
                break
            }
        }
    }
    cu := rcu.Commatize(len(untouchable))
    cl := rcu.Commatize(limit)
    fmt.Printf("%7s untouchable numbers were found  <= %s\n", cu, cl)
}


  

You may also check:How to resolve the algorithm Cramer's rule step by step in the FreeBASIC programming language
You may also check:How to resolve the algorithm Primality by trial division step by step in the CMake programming language
You may also check:How to resolve the algorithm Long year step by step in the Julia programming language
You may also check:How to resolve the algorithm Substitution cipher step by step in the Quackery programming language
You may also check:How to resolve the algorithm Count in factors step by step in the Seed7 programming language