Solve problem 313
This commit is contained in:
@@ -0,0 +1,99 @@
|
|||||||
|
from lib_prime import primes, is_prime
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from heapq import heappop, heappush
|
||||||
|
from collections import namedtuple
|
||||||
|
from collections import defaultdict
|
||||||
|
from math import sqrt
|
||||||
|
|
||||||
|
P = namedtuple("P", ["x", "y"])
|
||||||
|
|
||||||
|
State = namedtuple("State", ["f", "g", "red", "space"])
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(order=True)
|
||||||
|
class State:
|
||||||
|
g: int
|
||||||
|
red: P
|
||||||
|
space: P
|
||||||
|
|
||||||
|
|
||||||
|
def s(m: int, n: int) -> int:
|
||||||
|
"""What am I doing? It was necessary to find the pattern."""
|
||||||
|
|
||||||
|
def h(s: State) -> int:
|
||||||
|
return abs(m - s.space.x) + abs(n - s.space.y)
|
||||||
|
|
||||||
|
def f(s: State) -> int:
|
||||||
|
return s.g + h(s)
|
||||||
|
|
||||||
|
def done(s: State) -> bool:
|
||||||
|
return s.red.x == m - 1 and s.red.y == n - 1
|
||||||
|
|
||||||
|
# assert m < n, then we could just take result times 2
|
||||||
|
init = State(0, P(0, 0), P(m - 1, n - 1))
|
||||||
|
states = [(0, init)]
|
||||||
|
g_costs = {(init.red, init.space): init.g}
|
||||||
|
|
||||||
|
while states:
|
||||||
|
_, s = heappop(states)
|
||||||
|
if done(s):
|
||||||
|
return s.g
|
||||||
|
|
||||||
|
for dx, dy in [(-1, 0), (0, 1), (1, 0), (0, -1)]:
|
||||||
|
nx, ny = s.space.x + dx, s.space.y + dy
|
||||||
|
if not (0 <= nx < m and 0 <= ny < n):
|
||||||
|
continue
|
||||||
|
nstate = State(s.g + 1, s.red, P(nx, ny))
|
||||||
|
if s.red.x == nx and s.red.y == ny:
|
||||||
|
nstate.red = P(s.space.x, s.space.y)
|
||||||
|
if (
|
||||||
|
not (nstate.red, nstate.space) in g_costs
|
||||||
|
or g_costs[(nstate.red, nstate.space)] > nstate.g
|
||||||
|
):
|
||||||
|
g_costs[nstate.red, nstate.space] = nstate.g
|
||||||
|
heappush(states, (f(nstate), nstate))
|
||||||
|
return -1
|
||||||
|
|
||||||
|
|
||||||
|
def solve_naiv(p_max: int) -> int:
|
||||||
|
t = 0
|
||||||
|
p2_max = p_max * p_max
|
||||||
|
ps = primes(p_max)
|
||||||
|
p2s = set([p * p for p in ps])
|
||||||
|
for m in range(2, p2_max):
|
||||||
|
for n in range(m, p2_max):
|
||||||
|
r = s(m, n)
|
||||||
|
if r in p2s:
|
||||||
|
t += 2
|
||||||
|
if r > p2_max:
|
||||||
|
break
|
||||||
|
return t
|
||||||
|
|
||||||
|
|
||||||
|
def solve(p_max: int) -> int:
|
||||||
|
t = 2
|
||||||
|
r_base = 0
|
||||||
|
delta = 1
|
||||||
|
three = 3
|
||||||
|
for p in range(3, p_max + 1, 2):
|
||||||
|
if is_prime(p):
|
||||||
|
t += r_base * 2
|
||||||
|
r_base += delta
|
||||||
|
three -= 1
|
||||||
|
if three == 0:
|
||||||
|
delta += 1
|
||||||
|
three = 3
|
||||||
|
return t
|
||||||
|
|
||||||
|
|
||||||
|
def euler_313():
|
||||||
|
assert solve_naiv(5) == 4
|
||||||
|
assert solve(20) == 86
|
||||||
|
assert solve(100) == 5482
|
||||||
|
return solve(10**6)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
solution = euler_313()
|
||||||
|
print(f"e313.py: {solution}")
|
||||||
|
# assert solution == 2057774861813004
|
||||||
Reference in New Issue
Block a user