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 |
![]() |
Table 2: permalink |
![]() |
Table 3: permalink |
![]() |
Table 4: permalink |
![]() |
Table 5: permalink |
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)
# ==========================================
# 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
DIGIT_MAP = "0123456789ABCDEF": This string acts as a lookup table. If a digit value is15, the code looks at index 15 and retrieves'F'.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.Universal Logic: This version works for any base from 2 to 16 without needing further changes. You simply change
SEARCH_BASE = 16,12, or8at 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