Task: N-smooth numbers




Go: package main

import (
    "fmt"
    "log"
    "math/big"
)

var (
    primes      []*big.Int
    smallPrimes []int
)


func init() {
    two := big.NewInt(2)
    three := big.NewInt(3)
    p521 := big.NewInt(521)
    p29 := big.NewInt(29)
    primes = append(primes, two)
    smallPrimes = append(smallPrimes, 2)
    for i := three; i.Cmp(p521) <= 0; i.Add(i, two) {
        if i.ProbablyPrime(0) {
            primes = append(primes, new(big.Int).Set(i))
            if i.Cmp(p29) <= 0 {
                smallPrimes = append(smallPrimes, int(i.Int64()))
            }
        }
    }
}

func min(bs []*big.Int) *big.Int {
    if len(bs) == 0 {
        log.Fatal("slice must have at least one element")
    }
    res := bs[0]
    for _, i := range bs[1:] {
        if i.Cmp(res) < 0 {
            res = i
        }
    }
    return res
}

func nSmooth(n, size int) []*big.Int {
    if n < 2 || n > 521 {
        log.Fatal("n must be between 2 and 521")
    }
    if size < 1 {
        log.Fatal("size must be at least 1")
    }
    bn := big.NewInt(int64(n))
    ok := false
    for _, prime := range primes {
        if bn.Cmp(prime) == 0 {
            ok = true
            break
        }
    }
    if !ok {
        log.Fatal("n must be a prime number")
    }

    ns := make([]*big.Int, size)
    ns[0] = big.NewInt(1)
    var next []*big.Int
    for i := 0; i < len(primes); i++ {
        if primes[i].Cmp(bn) > 0 {
            break
        }
        next = append(next, new(big.Int).Set(primes[i]))
    }
    indices := make([]int, len(next))
    for m := 1; m < size; m++ {
        ns[m] = new(big.Int).Set(min(next))
        for i := 0; i < len(indices); i++ {
            if ns[m].Cmp(next[i]) == 0 {
                indices[i]++
                next[i].Mul(primes[i], ns[indices[i]])
            }
        }
    }
    return ns
}

func main() {
    for _, i := range smallPrimes {
        fmt.Printf("The first 25 %d-smooth numbers are:\n", i)
        fmt.Println(nSmooth(i, 25), "\n")
    }
    for _, i := range smallPrimes[1:] {
        fmt.Printf("The 3,000th to 3,202nd %d-smooth numbers are:\n", i)
        fmt.Println(nSmooth(i, 3002)[2999:], "\n")
    }
    for _, i := range []int{503, 509, 521} {
        fmt.Printf("The 30,000th to 30,019th %d-smooth numbers are:\n", i)
        fmt.Println(nSmooth(i, 30019)[29999:], "\n")
    }
}


Java: import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

public class NSmoothNumbers {

    public static void main(String[] args) {
        System.out.printf("show the first 25 n-smooth numbers for n = 2 through n = 29%n");
        int max = 25;
        List<BigInteger> primes = new ArrayList<>();
        for ( int n = 2 ; n <= 29 ; n++ ) {
            if ( isPrime(n) ) {
                primes.add(BigInteger.valueOf(n));
                System.out.printf("The first %d %d-smooth numbers:%n", max, n);
                BigInteger[] humble = nSmooth(max, primes.toArray(new BigInteger[0]));
                for ( int i = 0 ; i < max ; i++ ) {
                    System.out.printf("%s ", humble[i]);
                }
                System.out.printf("%n%n");
            }
        }
        
        System.out.printf("show three numbers starting with 3,000 for n-smooth numbers for n = 3 through n = 29%n");
        int count = 3;
        max = 3000 + count - 1;
        primes = new ArrayList<>();
        primes.add(BigInteger.valueOf(2));
        for ( int n = 3 ; n <= 29 ; n++ ) {
            if ( isPrime(n) ) {
                primes.add(BigInteger.valueOf(n));
                System.out.printf("The %d through %d %d-smooth numbers:%n", max-count+1, max, n);
                BigInteger[] nSmooth = nSmooth(max, primes.toArray(new BigInteger[0]));
                for ( int i = max-count ; i < max ; i++ ) {
                    System.out.printf("%s ", nSmooth[i]);
                }
                System.out.printf("%n%n");
            }
        }
        
        System.out.printf("Show twenty numbers starting with 30,000 n-smooth numbers for n=503 through n=521%n");
        count = 20;
        max = 30000 + count - 1;
        primes = new ArrayList<>();
        for ( int n = 2 ; n <= 521 ; n++ ) {
            if ( isPrime(n) ) {
                primes.add(BigInteger.valueOf(n));
                if ( n >= 503 && n <= 521 ) {
                    System.out.printf("The %d through %d %d-smooth numbers:%n", max-count+1, max, n);
                    BigInteger[] nSmooth = nSmooth(max, primes.toArray(new BigInteger[0]));
                    for ( int i = max-count ; i < max ; i++ ) {
                        System.out.printf("%s ", nSmooth[i]);
                    }
                    System.out.printf("%n%n");
                }
            }
        }

    }

    private static final boolean isPrime(long test) {
        if ( test == 2 ) {
            return true;
        }
        if ( test % 2 == 0 ) return false;
        for ( long i = 3 ; i <= Math.sqrt(test) ; i += 2 ) {
            if ( test % i == 0 ) {
                return false;
            }
        }
        return true;
    }

    private static BigInteger[] nSmooth(int n, BigInteger[] primes) {
        int size = primes.length;
        BigInteger[] test = new BigInteger[size];
        for ( int i = 0 ; i < size ; i++ ) {
            test[i] = primes[i];
        }
        BigInteger[] results = new BigInteger[n];
        results[0] = BigInteger.ONE;
        
        int[] indexes = new int[size];
        for ( int i = 0 ; i < size ; i++ ) {
            indexes[i] = 0;
        }
        
        for ( int index = 1 ; index < n ; index++ ) {
            BigInteger min = test[0];
            for ( int i = 1 ; i < size ; i++ ) {
                min = min.min(test[i]);
            }
            results[index] = min;
            
            for ( int i = 0 ; i < size ; i++ ) {
                if ( results[index].compareTo(test[i]) == 0 ) {
                    indexes[i] = indexes[i] + 1;
                    test[i] = primes[i].multiply(results[indexes[i]]);
                }
            }
        }
        return results;
    }

}