Suma de cadenas
Definir la función
sumaCadenas :: String -> String -> String
tal que (sumaCadenas xs ys)
es la cadena formada por el número entero que es la suma de los números enteros cuyas cadenas que lo representan son xs
e ys
; además, se supone que la cadena vacía representa al cero. Por ejemplo,
sumaCadenas "2" "6" == "8" sumaCadenas "14" "2" == "16" sumaCadenas "14" "-5" == "9" sumaCadenas "-14" "-5" == "-19" sumaCadenas "5" "-5" == "0" sumaCadenas "" "5" == "5" sumaCadenas "6" "" == "6" sumaCadenas "" "" == "0"
Nota: Escribir las soluciones en Haskell, en Python y en Common Lisp.
Soluciones
A continuación se muestran
- las soluciones en Haskell,
- las soluciones en Python y
- las soluciones en Common Lisp
1. Soluciones en Haskell
import Test.Hspec (Spec, describe, hspec, it, shouldBe) import Test.QuickCheck -- 1ª solución -- =========== sumaCadenas1 :: String -> String -> String sumaCadenas1 xs ys = show (numero xs + numero ys) -- (numero xs) es el número entero representado por la cadena xs -- suponiendo que la cadena vacía representa al cero.. Por ejemplo, -- numero "12" == 12 -- numero "-12" == -12 -- numero "0" == 0 -- numero "" == 0 numero :: String -> Int numero "" = 0 numero xs = read xs -- 2ª solución -- =========== sumaCadenas2 :: String -> String -> String sumaCadenas2 "" "" = "0" sumaCadenas2 "" ys = ys sumaCadenas2 xs "" = xs sumaCadenas2 xs ys = show (read xs + read ys) -- 3ª solución -- =========== sumaCadenas3 :: String -> String -> String sumaCadenas3 xs ys = show (sum (map read (filter (not . null) [xs, ys]))) -- 4ª solución -- =========== sumaCadenas4 :: String -> String -> String sumaCadenas4 = ((show . sum . map read . filter (not . null)) .) . (. return) . (:) -- Verificación -- ============ verifica :: IO () verifica = hspec spec specG :: (String -> String -> String) -> Spec specG sumaCadenas = do it "e1" $ sumaCadenas "2" "6" `shouldBe` "8" it "e2" $ sumaCadenas "14" "2" `shouldBe` "16" it "e3" $ sumaCadenas "14" "-5" `shouldBe` "9" it "e4" $ sumaCadenas "-14" "-5" `shouldBe` "-19" it "e5" $ sumaCadenas "5" "-5" `shouldBe` "0" it "e6" $ sumaCadenas "" "5" `shouldBe` "5" it "e7" $ sumaCadenas "6" "" `shouldBe` "6" it "e8" $ sumaCadenas "" "" `shouldBe` "0" spec :: Spec spec = do describe "def. 1" $ specG sumaCadenas1 describe "def. 2" $ specG sumaCadenas2 describe "def. 3" $ specG sumaCadenas3 describe "def. 4" $ specG sumaCadenas4 -- La verificación es -- λ> verifica -- -- 32 examples, 0 failures -- Equivalencia de las definiciones -- ================================ -- La propiedad es prop_sumaCadenas :: Int -> Int -> Bool prop_sumaCadenas x y = all (== sumaCadenas1 xs ys) [sumaCadenas2 xs ys, sumaCadenas3 xs ys, sumaCadenas4 xs ys] where xs = show x ys = show y -- La comparación es -- λ> quickCheck prop_sumaCadenas -- +++ OK, passed 100 tests. -- Comparación de eficiencia -- ========================= -- La comparación es -- λ> sumaCadenas1 (show (10^10000)) ('-' : show (10^10000)) -- "0" -- (0.03 secs, 7,814,456 bytes) -- λ> sumaCadenas2 (show (10^10000)) ('-' : show (10^10000)) -- "0" -- (0.03 secs, 7,814,360 bytes) -- λ> sumaCadenas3 (show (10^10000)) ('-' : show (10^10000)) -- "0" -- (0.03 secs, 7,814,936 bytes) -- λ> sumaCadenas4 (show (10^10000)) ('-' : show (10^10000)) -- "0" -- (0.03 secs, 7,814,872 bytes)
2. Soluciones en Python
# 1ª solución # =========== # numero(xs) es el número entero representado por la cadena xs # suponiendo que la cadena vacía representa al cero.. Por ejemplo, # numero "12" == 12 # numero "-12" == -12 # numero "0" == 0 # numero "" == 0 def numero(s: str) -> int: if not s: return 0 return int(s) def sumaCadenas1(xs: str, ys: str) -> str: return str(numero(xs) + numero(ys)) # 2ª solución # =========== def sumaCadenas2(xs: str, ys: str) -> str: if xs == "" and ys == "": return "0" if xs == "": return ys if ys == "": return xs return str(int(xs) + int(ys)) # 3ª solución # =========== def sumaCadenas3(xs: str, ys: str) -> str: x = int(xs or "0") y = int(ys or "0") return str(x + y) # 4ª solución # =========== def sumaCadenas4(xs: str, ys: str) -> str: return str(sum(map(int, filter(lambda x: x != '', [xs, ys])))) # Verificación # ============ def test_sumaCadenas() -> None: for sumaCadenas in [sumaCadenas1, sumaCadenas2, sumaCadenas3, sumaCadenas4]: assert sumaCadenas("2", "6") == "8" assert sumaCadenas("14", "2") == "16" assert sumaCadenas("14", "-5") == "9" assert sumaCadenas("-14", "-5") == "-19" assert sumaCadenas("5", "-5") == "0" assert sumaCadenas("", "5") == "5" assert sumaCadenas("6", "") == "6" assert sumaCadenas("", "") == "0" print("Verificado") # La verificación es # >>> test_sumaCadenas() # Verificado
3. Soluciones en Common Lisp
(ql:quickload "fiveam" :silent t) (defpackage :suma-de-cadenas (:use :cl :fiveam)) (in-package :suma-de-cadenas) ;;; 1ª solución ;;; =========== ;;; (numero xs) es el número entero representado por la cadena xs ;;; suponiendo que la cadena vacía representa al cero.. Por ejemplo, ;;; (numero "12") == 12 ;;; (numero "-12") == -12 ;;; (numero "0") == 0 ;;; (numero "") == 0 (defun numero (s) (if (string= s "") 0 (parse-integer s))) (defun suma-cadenas1 (xs ys) (write-to-string (+ (numero xs) (numero ys)))) ;;; 2ª solución ;;; =========== (defun suma-cadenas2 (xs ys) (cond ((and (string= xs "") (string= ys "")) "0") ((string= xs "") ys) ((string= ys "") xs) (t (write-to-string (+ (parse-integer xs) (parse-integer ys)))))) ;;; 3ª solución ;;; =========== (defun suma-cadenas3 (xs ys) (write-to-string (reduce #'+ (mapcar #'parse-integer (remove-if (lambda (zs) (string= zs "")) (list xs ys))) :initial-value 0))) ;;; Verificación ;;; ============ (test suma-cadenas (mapc (lambda (suma-cadenas) (is (equal (funcall suma-cadenas "2" "6") "8")) (is (equal (funcall suma-cadenas "14" "2") "16")) (is (equal (funcall suma-cadenas "14" "-5") "9")) (is (equal (funcall suma-cadenas "-14" "-5") "-19")) (is (equal (funcall suma-cadenas "5" "-5") "0")) (is (equal (funcall suma-cadenas "" "5") "5")) (is (equal (funcall suma-cadenas "6" "") "6")) (is (equal (funcall suma-cadenas "" "") "0")) ) '(suma-cadenas1 suma-cadenas2 suma-cadenas3))) (defun verifica () (run! 'suma-cadenas)) ;;; La verificación es ;;; (verifica) ;;; ;;; Running test SUMA-CADENAS ........ ;;; Equivalencia de las definiciones ;;; ================================ ;;; La propiedad es (test suma-cadenas-equiv (for-all ((x (gen-integer)) (y (gen-integer))) (let ((xs (write-to-string x)) (ys (write-to-string y))) (is (string= (suma-cadenas1 xs ys) (suma-cadenas2 xs ys))) (is (string= (suma-cadenas1 xs ys) (suma-cadenas2 xs ys)))))) (defun comprueba () (run 'suma-cadenas-equiv)) ;;; La comprobación es ;;; > (comprueba) ;;; ;;; Running test SUMA-CADENAS-EQUIV ... ;;; Comparación de eficiencia ;;; ========================= ;;; La comparación es ;;; > (defvar c1 (write-to-string (expt 10 10000))) ;;; > (defvar c2 (write-to-string (- (expt 10 10000)))) ;;; > (time (suma-cadenas1 c1 c2)) ;;; 0.050 seconds of real time ;;; > (time (suma-cadenas2 c1 c2)) ;;; 0.051 seconds of real time ;;; > (time (suma-cadenas3 c1 c2)) ;;; 0.036 seconds of real time