Jordan-Pólya numbers

func jordan_pólya_numbers(n, k, F, callback) {

    var factors = F.sort.uniq
    var factors_end = factors.end

    if (k == 0) {
        callback(1)
        return nil
    }

    func (m, k, i=0) {

        if (k == 1) {

            var L = idiv(n,m)

            for j in (i..factors_end) {
                with (factors[j]) {|q|
                    q > L && break
                    callback(m*q)
                }
            }

            return nil
        }

        var L = idiv(n,m).iroot(k)

        for j in (i..factors_end) {
            with (factors[j]) { |q|
                q > L && break
                __FUNC__(m*q, k-1, j)
            }
        }
    }(1, k)

    return nil
}

func inverse_factorial_W(n) {
    var l = (log(n) - log(Num.tau)/2)
    l / lambert_w(l / Num.e) - 1/2
}

var limit = 100e6
var factors = (2..inverse_factorial_W(limit).int -> map { .factorial })
var terms = Set()

for k in (0 .. limit.ilog2) {
    jordan_pólya_numbers(limit, k, factors, {|v| terms << v })
}

terms.sort!

say "The first 50 Jordan-Pólya numbers:"
terms.first(50).each_slice(10, {|*a|
    a.map { '%5s' % _ }.join(' ').say
})

say "\nThere are #{terms.len} Jordan-Pólya numbers <= #{limit.commify}, where largest is #{terms.last}."

Output:

Last updated

Was this helpful?