solve 58 in uiua (attempt sieve)
This commit is contained in:
+19
-73
@@ -1,66 +1,12 @@
|
|||||||
# rotate 90 deg
|
# project euler 58
|
||||||
r ← ⍉≡⇌
|
|
||||||
|
|
||||||
# create spiral numbers with n rows and cols
|
p ← =1⧻°/×
|
||||||
# spiral ? n
|
Sieve ← ▽⊸≡p+2⇡
|
||||||
s ← (
|
|
||||||
+1⇡ⁿ2 # create n^2 numbers
|
|
||||||
⊸(
|
|
||||||
⊸(-1×2√/↥) # t*2 - 1, where t = sqrt(max(range(n^2))) = n
|
|
||||||
⌈÷2↙ # create [1 1 2 2 3 ...] until sum is n^2
|
|
||||||
)
|
|
||||||
⊜□˜▽+1°⊏ # successively take 1, 1, 2, 2, 3, ... until all n^2 numbers taken
|
|
||||||
⇌/◇(˜⊂r)⍜⊢⍚¤ # combine all taken with rotating array to form spiral
|
|
||||||
)
|
|
||||||
|
|
||||||
# memoized recursive version of s
|
Primes ← Sieve 37417
|
||||||
σ ← |1 memo(
|
|
||||||
⨬(⊂⊸(++1⇡∩/↥⊃△(⊢⊢)) r σ-1
|
|
||||||
| ⋅(¤[1]) # base-case
|
|
||||||
)⊸=1
|
|
||||||
)
|
|
||||||
|
|
||||||
# generates each diagonal of spiral array
|
|
||||||
Σ ← +1\+ +¤[2 4 6]×8 ⇡⌊÷2
|
|
||||||
|
|
||||||
# get numbers on diagonal
|
|
||||||
d ← ⊜°¤ ↥⊸r⊞=. °⊏
|
|
||||||
|
|
||||||
# is_prime(n) ? n
|
# is_prime(n) ? n
|
||||||
p ← =1⧻°/×
|
# p ← ⨬(=|1)⊸=¯1⊸(⍣⊢¯1▽⤚(=0≡◿) Primes ¤)
|
||||||
|
|
||||||
┌─╴test
|
|
||||||
p ↚ ⊜(⊜⋕⊸≠@\s)⊸≠@\n
|
|
||||||
⍤⤙≍ s 7 p $ 37 36 35 34 33 32 31
|
|
||||||
$ 38 17 16 15 14 13 30
|
|
||||||
$ 39 18 5 4 3 12 29
|
|
||||||
$ 40 19 6 1 2 11 28
|
|
||||||
$ 41 20 7 8 9 10 27
|
|
||||||
$ 42 21 22 23 24 25 26
|
|
||||||
$ 43 44 45 46 47 48 49
|
|
||||||
└─╴
|
|
||||||
|
|
||||||
Sol! ← +1×2⧻⍢(+2⟜(÷⊃⧻/+≡p ^0)|⋅(>0.1)) ⊙1
|
|
||||||
|
|
||||||
# Sol!(d s) 3 # too slow
|
|
||||||
# (σ -1×2) == s
|
|
||||||
# Sol!(d σ -1×2) 3 # too slow (too much memory usage)
|
|
||||||
# Sol!(⊂˜↯1÷2-1⟜(♭ Σ)) 3 # still too slow
|
|
||||||
|
|
||||||
# okay... let's do it mathematically from scratch:
|
|
||||||
|
|
||||||
# primes on diagonals/number of elements on diagonals
|
|
||||||
# Chance ← ÷-1×2⟜(
|
|
||||||
# ⊃((+5+∩×₄⊃×₂ⁿ₂)⇡
|
|
||||||
# | (+3+⊃×₆(×4ⁿ2))⇡
|
|
||||||
# | (+7+⊃×₁₀(×4ⁿ2))⇡
|
|
||||||
# ) ⌊÷2
|
|
||||||
# /+≡p⊂⊂
|
|
||||||
# )
|
|
||||||
#
|
|
||||||
# ⍢(+2|>0.1 Chance) 3
|
|
||||||
|
|
||||||
# that solved it in 4 minutes (with p memoized)... too slow!
|
|
||||||
|
|
||||||
NewP ← (
|
NewP ← (
|
||||||
# get the next three prime candidates (lower right is odd square)
|
# get the next three prime candidates (lower right is odd square)
|
||||||
@@ -71,18 +17,18 @@ NewP ← (
|
|||||||
++∩₃p # count how many are prime (0-3)
|
++∩₃p # count how many are prime (0-3)
|
||||||
)
|
)
|
||||||
|
|
||||||
# initial values are:
|
Sol ← (
|
||||||
# - 5: the amount of numbers so far; 1, 3, 5, 7, 9 (counter for diagonal)
|
# initial values are:
|
||||||
# - NewP.: = 3, since 3, 5, 7 are prime (counter for primes on diagonal)
|
# - 5: the amount of numbers so far; 1, 3, 5, 7, 9 (counter for diagonal)
|
||||||
# - 0: current NewP generation. NewP 0 is 3 (see above)
|
# - NewP.: = 3, since 3, 5, 7 are prime (counter for primes on diagonal)
|
||||||
5 NewP. 0
|
# - 0: current NewP generation. NewP 0 is 3 (see above)
|
||||||
⍢(+4 ⊙+ ⊙⊙(⊸NewP+1) # add 4 for new corners, generate NewP(n+1)
|
5 NewP. 0
|
||||||
| >0.1 ÷ # check prime ratio
|
⍢(+4 ⊙+ ⊙⊙(⊸NewP+1) # add 4 for new corners, generate NewP(n+1)
|
||||||
|
| >0.1 ÷ # check prime ratio
|
||||||
|
)
|
||||||
|
# discard number of primes and diagonal values,
|
||||||
|
# scale generation up to side length
|
||||||
|
# newp gen 0 -> 0*2 + 3 = side length 3
|
||||||
|
# newp gen 1 -> 1*2 + 3 = side length 5, ...
|
||||||
|
⋅⋅(+3×2)
|
||||||
)
|
)
|
||||||
# discard number of primes and diagonal values,
|
|
||||||
# scale generation up to side length
|
|
||||||
# newp gen 0 -> 0*2 + 3 = side length 3
|
|
||||||
# newp gen 1 -> 1*2 + 3 = side length 5, ...
|
|
||||||
⋅⋅(+3×2)
|
|
||||||
|
|
||||||
# that's a 240x speedup, from 4 minutes to 1 second. we can go faster...
|
|
||||||
|
|||||||
Reference in New Issue
Block a user