Task: Powerful numbers




Go: package main

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

const adj = 0.0001 

var primes = []uint64{
    2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
} 

func gcd(x, y uint64) uint64 {
    for y != 0 {
        x, y = y, x%y
    }
    return x
}

func isSquareFree(x uint64) bool {
    for _, p := range primes {
        p2 := p * p
        if p2 > x {
            break
        }
        if x%p2 == 0 {
            return false
        }
    }
    return true
}

func iroot(x, p uint64) uint64 {
    return uint64(math.Pow(float64(x), 1.0/float64(p)) + adj)
}

func ipow(x, p uint64) uint64 {
    prod := uint64(1)
    for p > 0 {
        if p&1 != 0 {
            prod *= x
        }
        p >>= 1
        x *= x
    }
    return prod
}

func powerful(n, k uint64) []uint64 {
    set := make(map[uint64]bool)
    var f func(m, r uint64) 
    f = func(m, r uint64) {
        if r < k {
            set[m] = true
            return
        }
        for v := uint64(1); v <= iroot(n/m, r); v++ {
            if r > k {
                if !isSquareFree(v) || gcd(m, v) != 1 {
                    continue
                }
            }
            f(m*ipow(v, r), r-1)
        }
    }
    f(1, (1<<k)-1)
    list := make([]uint64, 0, len(set))
    for key := range set {
        list = append(list, key)
    }
    sort.Slice(list, func(i, j int) bool {
        return list[i] < list[j]
    })
    return list
}

func main() {
    power := uint64(10)
    for k := uint64(2); k <= 10; k++ {
        power *= 10
        a := powerful(power, k)
        le := len(a)
        h, t := a[0:5], a[le-5:]
        fmt.Printf("%d %2d-powerful numbers <= 10^%-2d: %v ... %v\n", le, k, k, h, t)
    }
    fmt.Println()
    for k := uint64(2); k <= 10; k++ {
        power := uint64(1)
        var counts []int
        for j := uint64(0); j < k+10; j++ {
            a := powerful(power, k)
            counts = append(counts, len(a))
            power *= 10
        }
        j := k + 10
        fmt.Printf("Count of %2d-powerful numbers <= 10^j, j in [0, %d): %v\n", k, j, counts)
    }
}


Java: import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class PowerfulNumbers {

    public static void main(String[] args) {
        System.out.printf("Task:  For k = 2..10, generate the set of k-powerful numbers <= 10^k and show the first 5 and the last 5 terms, along with the length of the set%n");
        for ( int k = 2 ; k <= 10 ; k++ ) {
            BigInteger max = BigInteger.valueOf(10).pow(k);
            List<BigInteger> powerfulNumbers = getPowerFulNumbers(max, k);
            System.out.printf("There are %d %d-powerful numbers between 1 and %d.  %nList: %s%n", powerfulNumbers.size(), k, max, getList(powerfulNumbers));
        }
        System.out.printf("%nTask:  For k = 2..10, show the number of k-powerful numbers less than or equal to 10^j, for 0 <= j < k+10%n");
        for ( int k = 2 ; k <= 10 ; k++ ) {
            List<Integer> powCount = new ArrayList<>();
            for ( int j = 0 ; j < k+10 ; j++ ) {
                BigInteger max = BigInteger.valueOf(10).pow(j);
                powCount.add(countPowerFulNumbers(max, k));
            }
            System.out.printf("Count of %2d-powerful numbers <= 10^j, j in [0, %d]: %s%n", k, k+9, powCount);
        }
        
    }
    
    private static String getList(List<BigInteger> list) {
        StringBuilder sb = new StringBuilder();
        sb.append(list.subList(0, 5).toString().replace("]", ""));
        sb.append(" ... ");
        sb.append(list.subList(list.size()-5, list.size()).toString().replace("[", ""));
        return sb.toString();
    }

    private static int countPowerFulNumbers(BigInteger max, int k) {
        return potentialPowerful(max, k).size();
    }

    private static List<BigInteger> getPowerFulNumbers(BigInteger max, int k) {
        List<BigInteger> powerfulNumbers = new ArrayList<>(potentialPowerful(max, k));
        Collections.sort(powerfulNumbers);
        return powerfulNumbers;
    }

    private static Set<BigInteger> potentialPowerful(BigInteger max, int k) {
        
        int[] indexes = new int[k];
        for ( int i = 0 ; i < k ; i++ ) {
            indexes[i] = 1;
        }

        Set<BigInteger> powerful = new HashSet<>();
        boolean foundPower = true;
        while ( foundPower ) {
            
            boolean genPowerful = false;
            for ( int index = 0 ; index < k ; index++ ) {
                BigInteger power = BigInteger.ONE;
                for ( int i = 0 ; i < k ; i++ ) {
                    power = power.multiply(BigInteger.valueOf(indexes[i]).pow(k+i));
                }
                if ( power.compareTo(max) <= 0 ) {
                    powerful.add(power);
                    indexes[0] += 1;
                    genPowerful = true;
                    break;
                }
                else {
                    indexes[index] = 1;
                    if ( index < k-1 ) {
                        indexes[index+1] += 1;
                    }
                }
            }
            if ( ! genPowerful ) {
                foundPower = false;
            }
        }

        return powerful;
    }
    
}