Рассмотрим упрощенную версию понимания вашего списка:
[(a,b,c) | a <- [1..1000], b <- [1..1000], c <- [1..1000]]
Это даст все возможные комбинации a, b и c.Это все равно, что сказать: «Сколько путей могут вынести три тысячи кубиков?»Ответ 1000 *1000* 1000 = 1 000 000 000 различных комбинаций.Если для создания каждой комбинации требуется 0,001 секунды, то для завершения всех комбинаций потребуется 1 000 000 секунд (~ 11,5 дней).(Ладно, 0,001 секунды на самом деле довольно медленно для компьютера, но вы поняли идею)
Когда вы добавляете предикаты к вашему пониманию списка, вычисление все равно занимает столько же времени;на самом деле, это займет больше , поскольку необходимо проверить предикат для каждой из 1 миллиарда вычисляемых комбинаций.
Теперь рассмотрим ваше понимание.Похоже, это должно быть намного быстрее, верно?
[(a,b,c) | c <- [1..1000], b <- [1..c], a <- [1..b], a+b+c=1000, a^2+b^2=c^2]
Есть 1000 вариантов для c.Сколько там б и а?Что ж, средний выбор для c равен 500. Для всех вариантов c, тогда существует в среднем 500 вариантов для b (поскольку b может варьироваться от 1 до c).Аналогичным образом, для всех вариантов c и b существует в среднем 250 вариантов для a.Это очень волнисто, но я уверен, что это точно.Таким образом, 1000 вариантов для c * 1000/2 вариантов для b * 1000/4 вариантов для a = 1 млрд. / 8 ~ = 100 млн.Это в 8 раз быстрее, но если вы обратили внимание, вы заметите, что на самом деле это такая же большая сложность , что и в упрощенной версии выше.Если бы мы сравнили «упрощенные» и «улучшенные» версии той же проблемы, но из [1..100000] вместо [1..1000], «улучшенный» все равно будет только в 8 раз быстрее, чем «упрощенный».
Не поймите меня неправильно, 8x - замечательное ускорение с постоянным коэффициентом.Но если вы не хотите подождать пару часов, чтобы найти решение, вам нужно получить более качественное решение.
Как отметил Нейл, способ уменьшить сложность этой проблемы дляb
и c
, выберите a
, который удовлетворяет a+b+c=1000
.Таким образом, вы не пробуете кучу a
с, которые потерпят неудачу.Это будет отбрасывать сложность большого О;вы будете рассматривать только приблизительно 1000 * 500 * 1 = 500 000 комбинаций вместо ~ 100 000 000.