4

私は今このコードに苦労しています。整数が 11 で割り切れるかどうかを調べたいと思います。私が読んだことから、整数は、その桁の合計 (1 回 +、1 回 -) が 11 で割り切れる場合、11 で割り切れます。

例: 8-1+5-6+5 = 11 であるため、56518 は 11 で割り切れ、11 は 11 で割り切れます。

これをHaskellで書き留めるにはどうすればよいですか?前もって感謝します。

4

4 に答える 4

16

で割ったときの余りが0の場合、数値xは割り切れます。したがって、次のことができますyy

divisibleBy11 x = x `rem` 11 == 0
于 2010-10-21T17:17:28.130 に答える
9

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'
于 2010-10-21T17:29:54.933 に答える
2

確かに、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)
于 2010-10-22T14:26:26.183 に答える
0

どうですか...

mod11 n | n < 0 = 11 - mod11 (-n) 
        | n < 11 = n
        | otherwise = mod11 $ (n `mod` 10) - (n `div` 10) 
于 2010-10-22T07:14:26.437 に答える