Skip to content

Instantly share code, notes, and snippets.

@Sonictherocketman
Created August 28, 2022 23:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Sonictherocketman/49361941c730b31fe5b822d8bbb1d945 to your computer and use it in GitHub Desktop.
Save Sonictherocketman/49361941c730b31fe5b822d8bbb1d945 to your computer and use it in GitHub Desktop.
Multiplicative Persistence Calculations in Python
#! /usr/bin/env pypy3
# Find a number with a multiplicative persistance larger than 11.
from collections import Counter
from functools import reduce
from multiprocessing import Pool
import json
import requests
import time
URL = 'https://api.pushover.net/1/messages.json'
API_KEY = 'xxx'
USER_KEY = 'xxx'
STATE_FILE = 'multiplicative-persistance.json'
CHUNK_SIZE = 5000000
POOL_SIZE = 3
MAX_TASKS = 10
multiply_all = lambda x, y: x*y
def send_push(title, message):
requests.post(URL, data=dict(
token=API_KEY,
user=USER_KEY,
title=title,
message=message,
))
def check_persist(n, count=0):
if n < 10:
return count
next_n = reduce(multiply_all, (int(i) for i in str(n)))
return check_persist(next_n, count+1)
def load():
try:
with open(STATE_FILE) as f:
return json.load(f)
except json.decoder.JSONDecodeError:
print('Invalid state. Restarting counts.')
except FileNotFoundError:
print('Statefile not found. Restarting counts.')
return {}
def save(state):
with open(STATE_FILE, 'w+') as f:
return json.dump(state, f)
def exhaust(values, persistance):
victor = None
for n in values:
n_str = str(n)
if '0' in n_str or '1' in n_str:
# Don't bother. It has zeros. They're useless.
continue
if '1' in n_str:
# Ones just pad the value. A number has the same persistance
# with and without ones.
continue
if '5' in n_str:
# Don't bother. It has zeros later on.
# This is first because it's an automatic skip.
continue
if '2' in n_str and '3' in n_str:
# Don't bother. It resolves to a smaller number.
continue
if '2' in n_str and '4' in n_str:
# Don't bother. It resolves to a smaller number.
continue
sorted_n_str = ''.join(sorted(n_str))
if int(sorted_n_str) < n:
# Don't bother. We've already checked it.
continue
counter = None
if '2' in n_str:
counter = Counter(n_str)
count_2 = counter['2']
if count_2 > 1 and count_2 < 5:
# Don't bother. It resolves to a smaller number.
# e.g. 2*2 = 4 :: 2234 == 434
continue
if '3' in n_str:
if counter is None:
counter = Counter(n_str)
count_3 = counter['3']
if count_3 > 1 and count_3 < 4:
# Don't bother. It resolves to a smaller number.
# e.g. 3*3 = 9 :: 2334 == 294
continue
p = check_persist(n, count=0)
if p and p > persistance:
victor, persistance = n, p
return victor, persistance, n
def main():
state = load()
n = state.get('n', 0)
print(f'Starting from {n}')
largest_persistence = state.get('largest_persistence', 0)
victor = state.get('victor', 0)
with Pool(processes=POOL_SIZE, maxtasksperchild=MAX_TASKS) as pool:
while True:
t = int(time.time())
print(f'Autosaving, Current n={n}, Victor={victor}, Max P={largest_persistence}, T={t}')
save({
**state,
'n': n,
'victor': victor,
'largest_persistence': largest_persistence,
})
time.sleep(0.2)
chunks = []
start = n
end = n + CHUNK_SIZE
for i in range(POOL_SIZE):
chunks.append(range(start, end))
start += CHUNK_SIZE
end += CHUNK_SIZE
results = pool.starmap(exhaust, [
(chunk, largest_persistence)
for chunk in chunks
], chunksize=1)
persistance = max([p for _, p, _ in results])
n = max([n for _, _, n in results])
try:
n_r = min([n_r for n_r, p, _ in results if p == persistance and n_r])
except ValueError:
# Found no new victors
n_r = None
if persistance and persistance > largest_persistence:
print(f'Found New, Current n={n}, Victor={n_r}, Max P={persistance}, T={t}')
victor = n_r
largest_persistence = persistance
save({
**state,
'n': n_r,
'victor': victor,
'largest_persistence': largest_persistence,
})
# Don't alert about small ones.
if persistance > 8:
send_push(
'Found new Persistence!',
f'The largest n so far: {n_r}. '
f'Persistance: {largest_persistence}'
)
n = max([n for _, _, n in results])
if __name__ == '__main__':
main()
#! /usr/bin/env python3
# Find a number with a multiplicative persistance larger than 11.
from collections import Counter
from functools import reduce
import json
import requests
import time
URL = 'https://api.pushover.net/1/messages.json'
API_KEY = 'xxxx'
USER_KEY = 'xxx'
STATE_FILE = 'multiplicative-persistance.json'
PAUSE_AT = 5000000
multiply_all = lambda x, y: x*y
def send_push(title, message):
requests.post(URL, data=dict(
token=API_KEY,
user=USER_KEY,
title=title,
message=message,
))
def check_persist(n, count=0):
if n < 10:
return count
next_n = reduce(multiply_all, (int(i) for i in str(n)))
return check_persist(next_n, count+1)
def load():
try:
with open(STATE_FILE) as f:
return json.load(f)
except json.decoder.JSONDecodeError:
print('Invalid state. Restarting counts.')
except FileNotFoundError:
print('Statefile not found. Restarting counts.')
return {}
def save(state):
with open(STATE_FILE, 'w+') as f:
return json.dump(state, f)
def main():
state = load()
n = state.get('n', 0)
print(f'Starting from {n}')
largest_persistence = state.get('largest_persistence', 0)
victor = state.get('victor', 0)
i = 0
while True:
i += 1
if i % PAUSE_AT == 0:
print(f'Autosaving, Current n={n}, Victor={victor}, Max P={largest_persistence}')
save({
**state,
'n': n,
'victor': victor,
'largest_persistence': largest_persistence,
})
time.sleep(0.1)
n_str = str(n)
if '0' in n_str:
# We don't need to bother. Just replace it and move on.
n_str = n_str.replace('0', '1')
n = int(n_str)
if '1' in n_str:
# Ones just pad the value. A number has the same persistance
# with and without ones.
n_str = n_str.replace('1', '2')
n = int(n_str)
sorted_n_str = ''.join(sorted(n_str))
if int(sorted_n_str) < n:
# Don't bother. We've already checked it.
n += 1
continue
counter = Counter(n_str)
if counter['2'] > 1 and counter['2'] < 5:
# Don't bother. It resolves to a smaller number.
# e.g. 2*2 = 4 :: 2234 == 434
n += 1
continue
if counter['3'] > 1 and counter['3'] < 4:
# Don't bother. It resolves to a smaller number.
# e.g. 3*3 = 9 :: 2334 == 294
n += 1
continue
persistance = check_persist(n, count=0)
if persistance and persistance > largest_persistence:
print(f'Found New, Current n={n}, Victor={n}, Max P={persistance}')
victor = n
largest_persistence = persistance
save({
**state,
'n': n,
'victor': victor,
'largest_persistence': largest_persistence,
})
# Don't alert about small ones.
if persistance > 8:
send_push(
'Found new Persistence!',
f'The largest n so far: {n}. '
f'Persistance: {largest_persistence}'
)
n += 1
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment