Как я могу создать кортеж, где каждый член сравнивается выражением? - PullRequest
8 голосов
/ 21 августа 2011

Ну, вот в чем дело:

У меня есть следующий код на Haskell:

[ (a, b, c) | c <- [1..10], b <- [1..10], a <- [1..10], a ^ 2 + b ^ 2 == c ^ 2 ]

Который вернется

[(4,3,5),(3,4,5),(8,6,10),(6,8,10)]

Для тех, кто не знаком с этим, я объясню:

  • Возвращает tuple (a, b, c), где каждое из этих «определений» (a, b, c) получает список (от 1 до 10), а его члены сравниваются с помощью a ^ 2 + b ^ 2 == c ^ 2 ? выражение (каждый член).

Как я могу сделать то же самое (одну строку, если это возможно) в Python / Ruby?

П.С.: они сравниваются в лексикографическом порядке.

Ответы [ 5 ]

12 голосов
/ 21 августа 2011

Это возможно в Python с одной длинной строкой и без импорта.Понимание списка Python может использоваться с несколькими переменными:

>>> [ (a, b, c) for c in range(1, 11) for b in range(1, 11) for a in range(1, 11) if a*a + b*b == c*c ]
[(4, 3, 5), (3, 4, 5), (8, 6, 10), (6, 8, 10)]
11 голосов
/ 21 августа 2011

Рубиновый раствор:

(1..10).to_a.repeated_permutation(3).select { |a, b, c| a*a + b*b == c*c }
# => [[3, 4, 5], [4, 3, 5], [6, 8, 10], [8, 6, 10]] 
9 голосов
/ 21 августа 2011

Python-решение, использующее itertools.product, что эквивалентно вложенным циклам for в выражении генератора:

[(a,b,c) for c,b,a in product(range(1,11), repeat=3) if a*a + b*b == c*c]
5 голосов
/ 21 августа 2011

Альтернатива Ruby без форсирования одинаковых диапазонов:

>> (1..10).to_a.product((1..10).to_a, (1..10).to_a).select { |a, b, c| a*a + b*b == c*c }
#=> [[3, 4, 5], [4, 3, 5], [6, 8, 10], [8, 6, 10]]

Вы можете утверждать, что это не возвращает ожидаемый результат, потому что вы используете c-> b-> a для итерации, но возвращаете (a,До нашей эры).Поэтому я боюсь, что в Ruby, не имея списков, нам нужно сделать что-то вроде этого (map_select = map + compact):

>> (1..10).to_a.product((1..10).to_a, (1..10).to_a).map { |c, b, a| [a, b, c] if a*a + b*b == c*c }.compact
 #=> [[4, 3, 5], [3, 4, 5], [8, 6, 10], [6, 8, 10]]

Не ванильный Ruby, а использование классной библиотеки lazylist Вы можете написать:

>> list { [a, b, c] }.where(:c => (1..10), :b => (1..10), :a => (1..10)) { a*a + b*b == c*c }.to_a
#=> [[4, 3, 5], [3, 4, 5], [8, 6, 10], [6, 8, 10]]
1 голос
/ 21 августа 2011
(for [a (range 1 11)
  b (range 1 11)
  c (range 1 11) :when (=
                        (+ (* a a) (* b b))
                        (* c c))]
  [a b c])

Пример того же.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...