Я пытаюсь решить проблему Проекта Эйлера 58.Debugging неэффективного проект Эйлер 58
По какой-то причине, когда я запускаю следующий код, он делает это через около 3000 звонков до моего зависания компьютера, предположительно, от того, как обременительного код есть. Я бы получил решение с достаточными ресурсами, но в настоящее время я занимаю слишком много времени.
Однако, это так же эффективно, как я могу его получить. Я не знаю, что я мог бы улучшить, чтобы решить эту проблему.
Функция isPrime
просто берет Int и возвращает, если это просто.
Проблема и мои текущие решения приведены ниже.
{-|
- Problem 58
-
- Starting with 1 and spiralling anticlockwise in the following way, a square
- spiral with side length 7 is formed.
-
- 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
-
- It is interesting to note that the odd squares lie along the bottom right
- diagonal, but what is more interesting is that 8 out of the 13 numbers lying
- along both diagonals are prime; that is, a ratio of 8/13 ≈ 62%.
-
- If one complete new layer is wrapped around the spiral above, a square spiral
- with side length 9 will be formed. If this process is continued, what is the
- side length of the square spiral for which the ratio of primes along both
- diagonals first falls below 10%?
-}
import Data.List (genericLength)
import Data.List.Split (splitPlaces)
import EulerFunctions (isPrime)
-- Each ring is another concentric circle in the spiral.
-- The first 3 are [1], [2..9], and [10..25]
type Ring = [Int]
-- Returns an infinite list of rings.
rings :: [Ring]
rings = [1] : splitPlaces [8,16..] [2..]
-- Given a ring, returns the numbers on its corners.
corners :: Ring -> [Int]
corners [1] = [1]
corners ring = let end = last ring
diff = (length ring) `div` 4
in map (\n -> end - n * diff) [0..3]
diagPrimes = scanl1 (+) $ map (genericLength . filter isPrime . corners) rings
diagLengths = [1,5..]
diagPrimeRatios = zipWith (/) diagPrimes diagLengths
p58 = fst . head . filter ((< 0.1) . snd) $ [1,3..] `zip` tail diagPrimeRatios
Возможно, сначала объясните (суть) того, что PE # 58 есть ... –
Это в комментариях! : D –
Я не делал никакого профилирования или тестирования, так что это просто догадки, но: в 'углах' длина кольца становится все более дорогостоящей и, что более важно, даже если' length' были постоянными, 'углы' само по себе становится все более дорогостоящим. Возможно, вы можете использовать некоторую арифметику, чтобы заменить «кольца углов карты» на список с прямым вычислением, содержащий только углы, не тратя так много времени, пропуская не-углы. Я бы также сказал, что 'isPrime' легко подозревается в оптимизации. –