Вот альтернативный порядок того же списка (по предложению Хаммара):
-- the integer points along the diagonals of slope -1 on the cartesian plane,
-- organized by x-intercept
-- diagonals = [ (0,0), (1,0), (0,1), (2,0), (1,1), (0,2), ...
diagonals = [ (n-i, i) | n <- [0..], i <- [0..n] ]
-- the multiples of three paired with the squares
paar = [ (3*x, y^2) | (x,y) <- diagonals ]
и в действии:
ghci> take 10 diagonals
[(0,0),(1,0),(0,1),(2,0),(1,1),(0,2),(3,0),(2,1),(1,2),(0,3)]
ghci> take 10 paar
[(0,0),(3,0),(0,1),(6,0),(3,1),(0,4),(9,0),(6,1),(3,4),(0,9)]
ghci> elem (9, 9801) paar
True
Используя диагональный путь, чтобы пройти через все возможныезначения, мы гарантируем, что мы достигаем каждой конечной точки за конечное время (хотя некоторые точки все еще находятся за пределами памяти).
Как указывает Хаммар в своем комментарии, этого недостаточно, так каквсе еще потребуется бесконечное количество времени, чтобы получить False
ответ.
Однако у нас есть порядок элементов paar, а именно (3*a,b^2)
предшествует (3*c,d^2)
при a + b < c + d
.Таким образом, чтобы определить, находится ли данная пара (x,y)
в paar
, нам нужно только проверить пары (p,q)
, в то время как p/3 + sqrt q <= x/3 + sqrt y
.
Чтобы избежать использования Floating
чисел, мы можем использовать немного более свободныйусловие, что p <= x || q <= y
.Конечно, p > x && q > y
подразумевает p/3 + sqrt q > x/3 + sqrt y
, так что это будет включать любые возможные решения, и оно гарантированно прекратит работу.
Так что мы можем встроить эту проверку в
-- check only a finite number of elements so we can get a False result as well
isElem (p, q) = elem (p,q) $ takeWhile (\(a,b) -> a <= p || b <= q) paar
И использовать ее:
ghci> isElem (9,9801)
True
ghci> isElem (9,9802)
False
ghci> isElem (10,9801)
False