Мне нужно написать функцию, которая возвращает список всех пар (x,y), где x, y ∈ N , и:
- x — произведение двух натуральных чисел (x = a • b, где a, b ∈ N) и
- x действительно больше 5, но меньше 500, и
- y — квадратное число (y = c², где c ∈ N), НЕ превышающее 1000, и
- х является делителем у.
Моя попытка:
listPairs :: [(Int, Int)]
listPairs = [(a*b, y) | y <- [0..], a <- [0..], b <- [0..],
(a*b) > 5, (a*b) < 500, (y*y) < 1001,
mod y (a*b) == 0]
Но он ничего не возвращает и компьютер много работает на нем.
Однако, если я выберу меньший диапазон для a
, b
и y
e. грамм. [0..400]
, это занимает до минуты, но возвращает правильный результат.
Итак, как я могу решить проблему с производительностью?
400
слишком низкий. вы должны убедиться, что не пропустили ни одного правильного решения:(a*b)<500, (a*b)>5, a==1, b==499
непротиворечиво. Поэтому используйте[1..499]
(0*x > 5
никогда не бывает истинным). OTOH(y*y) < 1001
==>y < 32
поэтому используйтеy<-[1..31], a<-[1..499]
. Должно сделать это в 32 раза быстрее. Затемa*b < 500
иa*b==b*a
, поэтому используйтеb<-[a..min 499 (div 500 a)]
, что дает нам еще одно значительное уменьшение размера задачи. Теперь это занимает меньше секунды. - person Will Ness   schedule 15.05.2013[(a*b, y*y) | ...
.y
вашего кода соответствует вашему описанию. - person Will Ness   schedule 15.05.2013