私は今このコードに苦労しています。整数が 11 で割り切れるかどうかを調べたいと思います。私が読んだことから、整数は、その桁の合計 (1 回 +、1 回 -) が 11 で割り切れる場合、11 で割り切れます。
例: 8-1+5-6+5 = 11 であるため、56518 は 11 で割り切れ、11 は 11 で割り切れます。
これをHaskellで書き留めるにはどうすればよいですか?前もって感謝します。
で割ったときの余りが0の場合、数値x
は割り切れます。したがって、次のことができますy
y
divisibleBy11 x = x `rem` 11 == 0
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'
確かに、div
そしてmod
より速いですが、なぜですか?問題は、数値を数字のリストに変換することだと思います。
toDigits = map (read . (:[])) . show
56518
は文字列に変換され、"56518"
文字列内の各記号(すべての桁)は、を使用して文字列自体に変換されますmap (:[])
。この時点で、があり["5","6","5","1","8"]
、すべての1桁の文字列を整数値として読み取ります[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)
どうですか...
mod11 n | n < 0 = 11 - mod11 (-n)
| n < 11 = n
| otherwise = mod11 $ (n `mod` 10) - (n `div` 10)