자리 올림 세기

대안언어축제 위키에서
입력값(또는 stdin)으로 두 개의 숫자를 받아서 두 숫자의 합에서 발생하는 “자리올림”(carry)의 갯수를 출력(stdout)한다. “0 0″이 입력되면 중단한다.

ex) input : 999  1
    output : 3 carry operations.

ex) input : 123  456
    output : no carry operation.

댓글 보기 옵션

원하시는 댓글 전시 방법을 선택한 다음 "설정 저장"을 누르셔서 적용하십시오.

하스켈 버전

박지인님의 알고리즘을 이용하여 풀었다. 자리 올림이 한 번 발생하면 전체 숫자의 합이 9 줄어든다.

module Main where

import Data.Char (digitToInt)

countCarry x y =  (x' + y' - z) `div` 9  where
    digits = sum . (map digitToInt)
    x' = digits x
    y' = digits y
    z = digits $ show $ read x + read y

main = do
    line <- getLine

    if line == "0 0" then return () else do
        let
            result = countCarry (nums !! 0) (nums !! 1)
                where nums = words line

        putStrLn
            (case result of
                0 -> "No carry operation."

                1 -> "1 carry operation."
                otherwise -> show result ++ " carry operations.")

        main

리스프 버전

하스켈 버전과 비슷한 방식을 사용했다.
차이점은 각 자릿수의 합을 구할 때 0대신 10을 더해서 바로 빼도록 한 것..

(count-carry 1 999)
-> 3

(count-carry 123 456)
-> 0


(defun digit-check (x)
  (let ((modulos (mod x 10)))
    (cond ((= modulos 0) 10)
	  (t modulos))))

(defun count-digit (x)
  (cond ((<= x 9) x)
	((= x 0) 10)
	(t
	 (+
	  (digit-check x)
	  (floor(count-digit (/ x 10)))))))

(defun count-carry (x y)
  (abs (- (+ (count-digit x) (count-digit y)) (count-digit (+ x y)))))