Monday, 15 December 2025

Emirpimes In Bases Greater Than 10

Why stop at bases between 2 and 9? I prompted Gemini again:

Can this program be modified so that it can investigate numbers in bases from 11 to 16? I know this is more difficult because of the necessary use of letters as well as the digits from 0 to 9.  

The program that it came up with works in bases from 2 to 36 which is impressive. I'll include the code and Gemini's explanation of it after the tables that cover bases of 11, 12, 13, 14, 15 and 16.

BASE 11


Table 1: permalink

BASE 12


Table 2: permalink

BASE 13


Table 3: permalink

BASE 14


Table 4: permalink

BASE 15


Table 5: permalink

BASE 16


Here is the code and what Gemini had to say about it. 

Yes, this can definitely be done. The core logic of the mathematics (checking primes and reversing lists of numbers) remains exactly the same. The only complexity is visual: we need to translate the internal numbers (10, 11, 12, etc.) into their representative symbols (A, B, C, etc.) so they are readable in the output.

Here is the upgraded program. It now includes a DIGIT_MAP to handle bases up to 16 (and actually up to 36, if you wanted to go higher).

The Upgraded Python Program (Bases 2–16)

Python
# ==========================================
#  CONFIGURATION (User Inputs)
# ==========================================
SEARCH_BASE = 16          # Supports bases 2 through 16
SEARCH_RANGE = (1, 60000) # Range to search [start, end]

# ==========================================
#  CORE FUNCTIONS
# ==========================================

# Standard mapping for bases > 10
DIGIT_MAP = "0123456789ABCDEF"

def to_base(n, b):
    """Converts an integer n to a list of digit values in base b."""
    if n == 0:
        return [0]
    digits = []
    while n:
        digits.append(int(n % b))
        n //= b
    return digits[::-1]

def from_base(digits, b):
    """Converts a list of digit values in base b back to an integer."""
    n = 0
    for d in digits:
        n = n * b + d
    return n

def get_reversed_val(n, b):
    """Returns the integer value of n with its digits reversed in base b."""
    digits = to_base(n, b)
    # We reverse the list of values (e.g. [1, 15] becomes [15, 1])
    return from_base(digits[::-1], b)

def is_prime(n):
    """Efficient primality test."""
    if n <= 1: return False
    if n <= 3: return True
    if n % 2 == 0 or n % 3 == 0: return False
    i = 5
    while i * i <= n:
        if n % i == 0 or n % (i + 2) == 0:
            return False
        i += 6
    return True

def get_semiprime_factors(n):
    """
    Returns [p, q] if n is a semiprime.
    Returns None otherwise.
    """
    factors = []
    d = 2
    temp = n
    # Optimization: limit search to sqrt(temp)
    while d * d <= temp:
        while temp % d == 0:
            factors.append(d)
            temp //= d
            if len(factors) > 2: 
                return None
        d += 1
    if temp > 1:
        factors.append(temp)
    
    if len(factors) == 2:
        return factors
    return None

def format_in_base(n, b):
    """
    Returns string representation of n in base b using 0-9 and A-F.
    """
    digits = to_base(n, b)
    # Map integer values (e.g., 10) to characters (e.g., 'A')
    return "".join(DIGIT_MAP[d] for d in digits)

# ==========================================
#  MAIN EXECUTION
# ==========================================

print(f"Searching for special Emirpimes in Base {SEARCH_BASE} between {SEARCH_RANGE}...")
print(f"Format: Base 10 | Base {SEARCH_BASE} | Factors (Base {SEARCH_BASE}) | Reversed (Base {SEARCH_BASE}) | Rev Factors (Base {SEARCH_BASE})")
print(f"{'-'*110}")

count = 0
start, end = SEARCH_RANGE

for n in range(start, end + 1):
    # 1. Check if semiprime
    factors = get_semiprime_factors(n)
    if not factors:
        continue
    
    p, q = factors[0], factors[1]
    
    # 2. Get reversed values in the target base
    n_rev_val = get_reversed_val(n, SEARCH_BASE)
    p_rev_val = get_reversed_val(p, SEARCH_BASE)
    q_rev_val = get_reversed_val(q, SEARCH_BASE)
    
    # 3. Check Condition 1: Factors must be 'Emirps' in this base
    # (Reversed factors must be prime)
    if not (is_prime(p_rev_val) and is_prime(q_rev_val)):
        continue
        
    # 4. Check Condition 2: The "Special" Multiplication Property
    # Rev(n) == Rev(p) * Rev(q)
    if n_rev_val == (p_rev_val * q_rev_val):
        
        # Prepare output strings using the Alpha-Numeric formatter
        n_str = format_in_base(n, SEARCH_BASE)
        p_str = format_in_base(p, SEARCH_BASE)
        q_str = format_in_base(q, SEARCH_BASE)
        
        n_rev_str = format_in_base(n_rev_val, SEARCH_BASE)
        p_rev_str = format_in_base(p_rev_val, SEARCH_BASE)
        q_rev_str = format_in_base(q_rev_val, SEARCH_BASE)
        
        factors_str = f"{p_str} x {q_str}"
        rev_factors_str = f"{p_rev_str} x {q_rev_str}"

        # Print formatted columns
        print(f"{n:<10} | {n_str:<10} | {factors_str:<20} | {n_rev_str:<20} | {rev_factors_str:<20}")
        count += 1

print(f"{'-'*110}")
print(f"Found {count} special emirpimes in Base {SEARCH_BASE}.")

Key Improvements

  1. DIGIT_MAP = "0123456789ABCDEF": This string acts as a lookup table. If a digit value is 15, the code looks at index 15 and retrieves 'F'.

  2. format_in_base: This function was rewritten to use the lookup table, ensuring that any number from 10 to 15 is printed as a letter.

  3. Universal Logic: This version works for any base from 2 to 16 without needing further changes. You simply change SEARCH_BASE = 16, 12, or 8 at the top.

Example: What to expect in Base 16 (Hexadecimal)

If you run this with SEARCH_BASE = 16, you might see results involving the digit 'A' (10) or 'C' (12), provided the "no carrying" rule is met.

  • Example: If we had $13 \times 13 = 169$ in Base 10, in Base 16 this is $D \times D = A9$.

  • Since $D$ (13) is a single digit, reversing it changes nothing, so it acts like a palindrome.

  • However, finding multi-digit primes in Base 16 that don't "carry" when multiplied is harder because the "digits" are larger, but the slots fill up differently.

No comments:

Post a Comment