

 This page uses content from Wikipedia. The original article was at Home prime. The list of authors can be seen in the page history. As with Rosetta Code, the text of Wikipedia is available under the GNU FDL. (See links for details on variance)

In number theory, the home prime HP(n) of an integer n greater than 1 is the prime number obtained by repeatedly factoring the increasing concatenation of prime factors including repetitions.

The traditional notation has the prefix "HP" and a postfix count of the number of iterations until the home prime is found (if the count is greater than 0), for instance HP4(2) === HP22(1) === 211 is the same as saying the home prime of 4 needs 2 iterations and is the same as the home prime of 22 which needs 1 iteration, and (both) resolve to 211, a prime.

Prime numbers are their own home prime;

So:

   HP2 = 2
   
   HP7 = 7

If the integer obtained by concatenating increasing prime factors is not prime, iterate until you reach a prime number; the home prime.

   HP4(2) = HP22(1) = 211
   HP4(2) = 2 × 2 => 22; HP22(1) = 2 × 11 => 211; 211 is prime  
   
   HP10(4) = HP25(3) = HP55(2) = HP511(1) = 773
   HP10(4) = 2 × 5 => 25; HP25(3) = 5 × 5 => 55; HP55(2) = 5 × 11 => 511; HP511(1) = 7 × 73 => 773; 773 is prime  



Task
 Find and show here, on this page, the home prime iteration chains for the integers 2 through 20 inclusive.


Stretch goal
 Find and show the iteration chain for 65.


Impossible goal
 Show the the home prime for HP49.


See also
 OEIS:A037274 - Home primes for n >= 2
 OEIS:A056938 - Concatenation chain for HP49


package main
 
import (
    "fmt"
    "math/big"
    "rcu"
    "sort"
)
 
var zero = new(big.Int)
var one = big.NewInt(1)
var two = big.NewInt(2)
var three = big.NewInt(3)
var four = big.NewInt(4)
var five = big.NewInt(5)
var six = big.NewInt(6)
 
// simple wheel based prime factors routine for BigInt
func primeFactorsWheel(m *big.Int) []*big.Int {
    n := new(big.Int).Set(m)
    t := new(big.Int)
    inc := []*big.Int{four, two, four, two, four, six, two, six}
    var factors []*big.Int
    for t.Rem(n, two).Cmp(zero) == 0 {
        factors = append(factors, two)
        n.Quo(n, two)
    }
    for t.Rem(n, three).Cmp(zero) == 0 {
        factors = append(factors, three)
        n.Quo(n, three)
    }
    for t.Rem(n, five).Cmp(zero) == 0 {
        factors = append(factors, five)
        n.Quo(n, five)
    }
    k := big.NewInt(7)
    i := 0
    for t.Mul(k, k).Cmp(n) <= 0 {
        if t.Rem(n, k).Cmp(zero) == 0 {
            factors = append(factors, new(big.Int).Set(k))
            n.Quo(n, k)
        } else {
            k.Add(k, inc[i])
            i = (i + 1) % 8
        }
    }
    if n.Cmp(one) > 0 {
        factors = append(factors, n)
    }
    return factors
}
 
func pollardRho(n *big.Int) *big.Int {
    g := func(x, n *big.Int) *big.Int {
        x2 := new(big.Int)
        x2.Mul(x, x)
        x2.Add(x2, one)
        return x2.Mod(x2, n)
    }
    x, y, d := new(big.Int).Set(two), new(big.Int).Set(two), new(big.Int).Set(one)
    t, z := new(big.Int), new(big.Int).Set(one)
    count := 0
    for {
        x = g(x, n)
        y = g(g(y, n), n)
        t.Sub(x, y)
        t.Abs(t)
        t.Mod(t, n)
        z.Mul(z, t)
        count++
        if count == 100 {
            d.GCD(nil, nil, z, n)
            if d.Cmp(one) != 0 {
                break
            }
            z.Set(one)
            count = 0
        }
    }
    if d.Cmp(n) == 0 {
        return new(big.Int)
    }
    return d
}
 
func primeFactors(m *big.Int) []*big.Int {
    n := new(big.Int).Set(m)
    var factors []*big.Int
    lim := big.NewInt(1e9)
    for n.Cmp(one) > 0 {
        if n.Cmp(lim) > 0 {
            d := pollardRho(n)
            if d.Cmp(zero) != 0 {
                factors = append(factors, primeFactorsWheel(d)...)
                n.Quo(n, d)
                if n.ProbablyPrime(10) {
                    factors = append(factors, n)
                    break
                }
            } else {
                factors = append(factors, primeFactorsWheel(n)...)
                break
            }
        } else {
            factors = append(factors, primeFactorsWheel(n)...)
            break
        }
    }
    sort.Slice(factors, func(i, j int) bool { return factors[i].Cmp(factors[j]) < 0 })
    return factors
}
 
func main() {
    list := make([]int, 20)
    for i := 2; i <= 20; i++ {
        list[i-2] = i
    }
    list[19] = 65
    for _, i := range list {
        if rcu.IsPrime(i) {
            fmt.Printf("HP%d = %d\n", i, i)
            continue
        }
        n := 1
        j := big.NewInt(int64(i))
        h := []*big.Int{j}
        for {
            pf := primeFactors(j)
            k := ""
            for _, f := range pf {
                k += fmt.Sprintf("%d", f)
            }
            j, _ = new(big.Int).SetString(k, 10)
            h = append(h, j)
            if j.ProbablyPrime(10) {
                for l := n; l > 0; l-- {
                    fmt.Printf("HP%d(%d) = ", h[n-l], l)
                }
                fmt.Println(h[n])
                break
            } else {
                n++
            }
        }
    }
}