Проверка делимости Интс на 11 - PullRequest
4 голосов
/ 21 октября 2010

Я борюсь с этим кодом прямо сейчас. Я хочу определить, делится ли целое число на 11. Из того, что я прочитал, целое делится на 11, когда сумма (один раз +, один раз -) его цифр делится на 11.

Например: 56518 делится на 11, потому что 8-1 + 5-6 + 5 = 11, а 11 делится на 11.

Как я могу записать это на Хаскеле? Заранее спасибо.

Ответы [ 4 ]

14 голосов
/ 21 октября 2010

Число x делится на y, если его остаток при делении на y равен 0. Так что вы можете просто сделать

divisibleBy11 x = x `rem` 11 == 0
8 голосов
/ 21 октября 2010

ifan Я уверен, что вы знаете, что в реальной жизни вы использовали бы mod или rem для этого простого примера, но алгоритм, о котором вы спрашиваете, интересен.Вот забавный способ сделать это, который подчеркивает функциональную природу Haskell:

digits = map (`mod` 10) . takeWhile (> 0) . iterate (`div` 10)

divisible11 = (== 0) . head . dropWhile (>= 11) . iterate (reduce11 . digits)
  where
    reduce11 []     = 0
    reduce11 (d:ds) = foldl combine d $ zip (cycle [(-), (+)]) ds
    combine d (op, d') = d `op` d'
2 голосов
/ 22 октября 2010

Конечно, div и mod быстрее, но почему бы и нет? Я предполагаю, что проблема заключается в преобразовании числа в список цифр:

toDigits = map (read . (:[])) . show

56518 преобразуется в строку "56518", и каждый символ в строке (каждая цифра) преобразуется в саму строку с map (:[]), на данный момент мы имеем ["5","6","5","1","8"], и мы читаем каждый -значная строка в виде целого числа: [5,6,5,1,8]. Готово.

Теперь мы можем вычислить сумму цифр следующим образом:

sumDigits x = sum (zipWith (*) (cycle [1,-1]) (reverse (toDigits x)))

cycle [1,-1] составляет бесконечный список [1, -1, 1, -1, ...], который мы соединяем с обратным списком цифр (toDigit x) и умножаем элементы каждой пары. Итак, у нас есть [8, -1, 5, -6, 5] и его сумма.

Теперь мы можем сделать это рекурсивно:

isDivisible x
  | x == 11 || x == 0 = True
  | x < 11            = False
  | x > 11            = isDivisible (sumDigits x)
0 голосов
/ 22 октября 2010

Как насчет ...

mod11 n | n < 0 = 11 - mod11 (-n) 
        | n < 11 = n
        | otherwise = mod11 $ (n `mod` 10) - (n `div` 10) 
...