Task: Brilliant numbers




Go: package main

import (
    "fmt"
    "math"
    "rcu"
    "sort"
)

var primes = rcu.Primes(1e8 - 1)

type res struct {
    bc   interface{}
    next int
}

func getBrilliant(digits, limit int, countOnly bool) res {
    var brilliant []int
    count := 0
    pow := 1
    next := math.MaxInt
    for k := 1; k <= digits; k++ {
        var s []int
        for _, p := range primes {
            if p >= pow*10 {
                break
            }
            if p > pow {
                s = append(s, p)
            }
        }
        for i := 0; i < len(s); i++ {
            for j := i; j < len(s); j++ {
                prod := s[i] * s[j]
                if prod < limit {
                    if countOnly {
                        count++
                    } else {
                        brilliant = append(brilliant, prod)
                    }
                } else {
                    if next > prod {
                        next = prod
                    }
                    break
                }
            }
        }
        pow *= 10
    }
    if countOnly {
        return res{count, next}
    }
    return res{brilliant, next}
}

func main() {
    fmt.Println("First 100 brilliant numbers:")
    brilliant := getBrilliant(2, 10000, false).bc.([]int)
    sort.Ints(brilliant)
    brilliant = brilliant[0:100]
    for i := 0; i < len(brilliant); i++ {
        fmt.Printf("%4d ", brilliant[i])
        if (i+1)%10 == 0 {
            fmt.Println()
        }
    }
    fmt.Println()
    for k := 1; k <= 13; k++ {
        limit := int(math.Pow(10, float64(k)))
        r := getBrilliant(k, limit, true)
        total := r.bc.(int)
        next := r.next
        climit := rcu.Commatize(limit)
        ctotal := rcu.Commatize(total + 1)
        cnext := rcu.Commatize(next)
        fmt.Printf("First >= %18s is %14s in the series: %18s\n", climit, ctotal, cnext)
    }
}


Java: import java.util.*;

public class BrilliantNumbers {
    public static void main(String[] args) {
        var primesByDigits = getPrimesByDigits(100000000);
        System.out.println("First 100 brilliant numbers:");
        List<Integer> brilliantNumbers = new ArrayList<>();
        for (var primes : primesByDigits) {
            int n = primes.size();
            for (int i = 0; i < n; ++i) {
                int prime1 = primes.get(i);
                for (int j = i; j < n; ++j) {
                    int prime2 = primes.get(j);
                    brilliantNumbers.add(prime1 * prime2);
                }
            }
            if (brilliantNumbers.size() >= 100)
                break;
        }
        Collections.sort(brilliantNumbers);
        for (int i = 0; i < 100; ++i) {
            char c = (i + 1) % 10 == 0 ? '\n' : ' ';
            System.out.printf("%,5d%c", brilliantNumbers.get(i), c);
        }
        System.out.println();
        long power = 10;
        long count = 0;
        for (int p = 1; p < 2 * primesByDigits.size(); ++p) {
            var primes = primesByDigits.get(p / 2);
            long position = count + 1;
            long minProduct = 0;
            int n = primes.size();
            for (int i = 0; i < n; ++i) {
                long prime1 = primes.get(i);
                var primes2 = primes.subList(i, n);
                int q = (int)((power + prime1 - 1) / prime1);
                int j = Collections.binarySearch(primes2, q);
                if (j == n)
                    continue;
                if (j < 0)
                    j = -(j + 1);
                long prime2 = primes2.get(j);
                long product = prime1 * prime2;
                if (minProduct == 0 || product < minProduct)
                    minProduct = product;
                position += j;
                if (prime1 >= prime2)
                    break;
            }
            System.out.printf("First brilliant number >= 10^%d is %,d at position %,d\n",
                                p, minProduct, position);
            power *= 10;
            if (p % 2 == 1) {
                long size = primes.size();
                count += size * (size + 1) / 2;
            }
        }
    }

    private static List<List<Integer>> getPrimesByDigits(int limit) {
        PrimeGenerator primeGen = new PrimeGenerator(100000, 100000);
        List<List<Integer>> primesByDigits = new ArrayList<>();
        List<Integer> primes = new ArrayList<>();
        for (int p = 10; p <= limit; ) {
            int prime = primeGen.nextPrime();
            if (prime > p) {
                primesByDigits.add(primes);
                primes = new ArrayList<>();
                p *= 10;
            }
            primes.add(prime);
        }
        return primesByDigits;
    }
}