diff --git a/data/seq_moebius.txt b/data/seq_moebius.txt new file mode 100644 index 0000000..aec9794 --- /dev/null +++ b/data/seq_moebius.txt @@ -0,0 +1,78 @@ +1 +-1 +-1 +0 +-1 +1 +-1 +0 +0 +1 +-1 +0 +-1 +1 +1 +0 +-1 +0 +-1 +0 +1 +1 +-1 +0 +0 +1 +0 +0 +-1 +-1 +-1 +0 +1 +1 +1 +0 +-1 +1 +1 +0 +-1 +-1 +-1 +0 +0 +1 +-1 +0 +0 +0 +1 +0 +-1 +0 +1 +0 +1 +1 +-1 +0 +-1 +1 +0 +0 +1 +-1 +-1 +0 +1 +-1 +-1 +0 +-1 +1 +0 +0 +1 +-1 \ No newline at end of file diff --git a/data/seq_not_primes.txt b/data/seq_not_primes.txt index 17b44a1..b7fde1f 100644 --- a/data/seq_not_primes.txt +++ b/data/seq_not_primes.txt @@ -1,4 +1,5 @@ 0 +1 4 6 8 diff --git a/lib.py b/lib.py index 5b20a7d..eda1d18 100755 --- a/lib.py +++ b/lib.py @@ -7,6 +7,8 @@ import math def is_prime(num): if isinstance(num, str): num = int(num) + if num in [2, 3, 5]: + return True if num & 1 and num % 5 > 0: for i in range(2, math.floor(math.sqrt(num)) + 1): if i & 1 and (num % i) == 0: @@ -24,3 +26,47 @@ def rev(num): # or int(str(num)[::-1]) revs = (revs * 10) + remainder num = num // 10 return revs + + +def power(x, y, p): + res = 1 + x %= p + while (y > 0): + if (y & 1): + res = (res * x) % p + y = y >> 1 + x = (x * x) % p + return res + + +def sqrtNormal(n, p): + n %= p + for x in range(2, p): + if ((x * x) % p == n): + return x + return None + + +# Assumption: p is of the form 3*i + 4 where i >= 1 +def sqrtFast(n, p): + if (p % 4 != 3): + # raise ValueError('Invalid Input') + return sqrtNormal(n, p) + # Try "+(n ^ ((p + 1)/4))" + n = n % p + x = power(n, (p + 1) // 4, p) + if ((x * x) % p == n): + return x + # Try "-(n ^ ((p + 1)/4))" + x = p - x + if ((x * x) % p == n): + return x + return None + + +def elliptic_curve(x, a, b, r): + y2 = (x ** 3 + a * x + b) % r + y = sqrtFast(y2, r) if y2 > 0 else 0 + if y is None: + return None, None + return y, -y % r diff --git a/other/elliptic_curve.py b/other/elliptic_curve.py index 02809f9..cca459a 100755 --- a/other/elliptic_curve.py +++ b/other/elliptic_curve.py @@ -1,79 +1,74 @@ #!/usr/bin/env python3 +import sys +if True: + sys.path.append('..') +import lib as LIB try: from PIL import Image, ImageDraw IMG_OUT = True except ModuleNotFoundError: IMG_OUT = False - -def power(x, y, p): - res = 1 - x %= p - while (y > 0): - if (y & 1): - res = (res * x) % p - y = y >> 1 - x = (x * x) % p - return res +ALL_OF_THEM = [] +OFFSET = 0 +SEPERATORS = [] +PRIMES_RED = False -# Assumption: p is of the form 3*i + 4 where i >= 1 -def sqrtFast(n, p): - if (p % 4 != 3): - raise ValueError('Invalid Input') - # Try "+(n ^ ((p + 1)/4))" - n = n % p - x = power(n, (p + 1) // 4, p) - if ((x * x) % p == n): - return x - # Try "-(n ^ ((p + 1)/4))" - x = p - x - if ((x * x) % p == n): - return x - return None +def write_image(dots, name, h, sz=0, width=None): + if width is None: + width = h + image = Image.new('RGB', (width, h)) + draw = ImageDraw.Draw(image) + draw.rectangle((0, 0, width, h), fill='white') + for x, p1, p2, pr in dots: + z1 = h - 1 - p1 + z2 = h - 1 - p2 + color = 'red' if PRIMES_RED and pr else 'black' + draw.rectangle((x - sz, z1 - sz, x + sz, z1 + sz), fill=color) + draw.rectangle((x - sz, z2 - sz, x + sz, z2 + sz), fill=color) + for x in SEPERATORS: + draw.rectangle((x, 0, x + 1, h), fill='gray') + image.save(name, 'PNG') -def sqrtNormal(n, p): - n %= p - for x in range(2, p): - if ((x * x) % p == n): - return x - return None - - -def elliptic_curve(a, b, r): - print(f'generate curve: a={a}, b={b}, r={r}') - if IMG_OUT: - image1 = Image.new('RGB', (r, r)) - draw1 = ImageDraw.Draw(image1) - draw1.rectangle((0, 0, r, r), fill='white') - image2 = Image.new('RGB', (r, r)) - draw2 = ImageDraw.Draw(image2) - draw2.rectangle((0, 0, r, r), fill='white') - - sqrtFn = sqrtNormal if (r % 4 != 3) else sqrtFast +def draw_curve(a, b, r): + global ALL_OF_THEM, OFFSET, SEPERATORS + # print(f'generate curve: a={a}, b={b}, r={r}') + img_dots = [] txt = '' for x in range(r): - y2 = (x ** 3 + a * x + b) % r - u2 = sqrtFn(y2, r) if y2 > 0 else 0 - if u2 is not None: - z1 = r - 1 - u2 - z2 = r - 1 - (-u2 % r) - print(x, y2, -y2 % r) - txt += f'{x} {y2} {-y2 % r}\n' - if IMG_OUT: - draw1.rectangle((x, z1, x, z1), fill='black') - draw1.rectangle((x, z2, x, z2), fill='black') - draw2.rectangle((x - 2, z1 - 2, x + 2, z1 + 2), fill='black') - draw2.rectangle((x - 2, z2 - 2, x + 2, z2 + 2), fill='black') + p1, p2 = LIB.elliptic_curve(x, a, b, r) + if p1 is not None: + # print(x, p1, p2) + txt += f'{x} {p1} {p2}\n' + # img_dots.append((x + OFFSET, p1, p2, LIB.is_prime(x))) + if LIB.is_prime(x): + img_dots.append((x + OFFSET, p1, p2, True)) - with open(f'ec-a{a}-b{b}-r{r}.txt', 'w') as f: - f.write(txt) - if IMG_OUT: - print('writing image output') - image1.save(f'ec-a{a}-b{b}-r{r}-pp.png', 'PNG') - image2.save(f'ec-a{a}-b{b}-r{r}-lg.png', 'PNG') - print() + # with open(f'ec-a{a}-b{b}-r{r}.txt', 'w') as f: + # f.write(txt) + + ALL_OF_THEM.append(((a, b, r), img_dots)) + OFFSET += len(img_dots) + 10 + SEPERATORS.append(OFFSET - 6) + # if IMG_OUT: + # print(f'writing image output (a={a}, b={b}, r={r})') + # write_image(img_dots, f'ec-a{a}-b{b}-r{r}-pp.png', r) + # write_image(img_dots, f'ec-a{a}-b{b}-r{r}-lg.png', r, sz=2) + # print() -elliptic_curve(a=149, b=263, r=3299) +r = 3299 +t = [2, 3, 5, 7, 13, 23, 43, 79, 149, 263, 463, 829, 1481, 2593] +# t = [2, 3] +for x in t: + ALL_OF_THEM = [] + SEPERATORS = [] + OFFSET = 0 + for y in t: + draw_curve(a=x, b=y, r=r) + + print(f'writing image output ({x}@{t[0]}-{t[-1]} r={r}) {OFFSET}x{r}') + just_all = [z for x, y in ALL_OF_THEM for z in y] + write_image(just_all, f'ec-{x}-r{r}.png', r, sz=3, width=OFFSET) diff --git a/solver.py b/solver.py index 488b791..d75e47a 100755 --- a/solver.py +++ b/solver.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 from RuneSolver import VigenereSolver, SequenceSolver from RuneText import Rune, RuneText +from lib import elliptic_curve import sys @@ -14,6 +15,7 @@ PRIMES_3301 = load_sequence_file('data/seq_primes_3301.txt') NOT_PRIMES = load_sequence_file('data/seq_not_primes.txt') FIBONACCI = load_sequence_file('data/seq_fibonacci.txt') LUCAS = load_sequence_file('data/seq_lucas_numbers.txt') +MOEBIUS = load_sequence_file('data/seq_moebius.txt') def print_all_solved(): @@ -77,17 +79,23 @@ def try_totient_on_unsolved(): slvr = SequenceSolver() slvr.output.QUIET = True slvr.output.BREAK_MODE = '' # disable line breaks - # for uuu in ['54-55']: + # for uuu in ['15-22']: for uuu in ['0-2', '3-7', '8-14', '15-22', '23-26', '27-32', '33-39', '40-53', '54-55']: print() print(uuu) with open(f'pages/p{uuu}.txt', 'r') as f: - slvr.input.load(RuneText(f.read()[:110])) + slvr.input.load(RuneText(f.read()[:15])) # alldata = slvr.input.runes_no_whitespace() + [Rune(i=29)] def b60(x): v = x % 60 return v if v < 29 else 60 - v + + def ec(r, i): + p1, p2 = elliptic_curve(i, 149, 263, 3299) + if p1 is None: + return r.index + return r.index + p1 % 29 # for p in PRIMES[:500]: # print(p) # for z in range(29): @@ -103,7 +111,8 @@ def try_totient_on_unsolved(): # slvr.FN = lambda i, r: Rune(i=b60(r.prime) + z % 29) # slvr.FN = lambda i, r: Rune(i=((r.prime + alldata[i + 1].prime) + z) % 60 // 2) # slvr.FN = lambda i, r: Rune(i=(3301 * r.index + z) % 29) - slvr.FN = lambda i, r: Rune(i=(67 * r.index + z) % 29) + slvr.FN = lambda i, r: Rune(i=(ec(r, i) + z) % 29) + # slvr.FN = lambda i, r: Rune(i=(r.prime - PRIMES[FIBONACCI[i]] + z) % 29) # slvr.FN = lambda i, r: Rune(i=(r.prime ** i + z) % 29) slvr.run()