Task: N-smooth numbers



C#: using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;

namespace NSmooth {
    class Program {
        static readonly List<BigInteger> primes = new List<BigInteger>();
        static readonly List<int> smallPrimes = new List<int>();

        static Program() {
            primes.Add(2);
            smallPrimes.Add(2);

            BigInteger i = 3;
            while (i <= 521) {
                if (IsPrime(i)) {
                    primes.Add(i);
                    if (i <= 29) {
                        smallPrimes.Add((int)i);
                    }
                }
                i += 2;
            }
        }

        static bool IsPrime(BigInteger value) {
            if (value < 2) return false;

            if (value % 2 == 0) return value == 2;
            if (value % 3 == 0) return value == 3;

            if (value % 5 == 0) return value == 5;
            if (value % 7 == 0) return value == 7;

            if (value % 11 == 0) return value == 11;
            if (value % 13 == 0) return value == 13;

            if (value % 17 == 0) return value == 17;
            if (value % 19 == 0) return value == 19;

            if (value % 23 == 0) return value == 23;

            BigInteger t = 29;
            while (t * t < value) {
                if (value % t == 0) return false;
                value += 2;

                if (value % t == 0) return false;
                value += 4;
            }

            return true;
        }

        static List<BigInteger> NSmooth(int n, int size) {
            if (n < 2 || n > 521) {
                throw new ArgumentOutOfRangeException("n");
            }
            if (size < 1) {
                throw new ArgumentOutOfRangeException("size");
            }

            BigInteger bn = n;
            bool ok = false;
            foreach (var prime in primes) {
                if (bn == prime) {
                    ok = true;
                    break;
                }
            }
            if (!ok) {
                throw new ArgumentException("must be a prime number", "n");
            }

            BigInteger[] ns = new BigInteger[size];
            ns[0] = 1;
            for (int i = 1; i < size; i++) {
                ns[i] = 0;
            }

            List<BigInteger> next = new List<BigInteger>();
            foreach (var prime in primes) {
                if (prime > bn) {
                    break;
                }
                next.Add(prime);
            }

            int[] indices = new int[next.Count];
            for (int i = 0; i < indices.Length; i++) {
                indices[i] = 0;
            }
            for (int m = 1; m < size; m++) {
                ns[m] = next.Min();
                for (int i = 0; i < indices.Length; i++) {
                    if (ns[m] == next[i]) {
                        indices[i]++;
                        next[i] = primes[i] * ns[indices[i]];
                    }
                }
            }

            return ns.ToList();
        }

        static void Println<T>(IEnumerable<T> nums) {
            Console.Write('[');

            var it = nums.GetEnumerator();
            if (it.MoveNext()) {
                Console.Write(it.Current);
            }
            while (it.MoveNext()) {
                Console.Write(", ");
                Console.Write(it.Current);
            }

            Console.WriteLine(']');
        }

        static void Main() {
            foreach (var i in smallPrimes) {
                Console.WriteLine("The first {0}-smooth numbers are:", i);
                Println(NSmooth(i, 25));
                Console.WriteLine();
            }
            foreach (var i in smallPrimes.Skip(1)) {
                Console.WriteLine("The 3,000 to 3,202 {0}-smooth numbers are:", i);
                Println(NSmooth(i, 3_002).Skip(2_999));
                Console.WriteLine();
            }
            foreach (var i in new int[] { 503, 509, 521 }) {
                Console.WriteLine("The 30,000 to 3,019 {0}-smooth numbers are:", i);
                Println(NSmooth(i, 30_019).Skip(29_999));
                Console.WriteLine();
            }
        }
    }
}



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;
    }

}