<commit_before>{-
Created       : 2014 May 23 (Fri) 14:32:50 by <NAME>.
Last Modified : 2014 Sep 15 (Mon) 16:07:43 by <NAME>.
-}

module HW01_HC where

import           Data.List       (unfoldr)
import qualified Test.HUnit      as T
import qualified Test.HUnit.Util as U

------------------------------------------------------------------------------
-- Exercise 1

lastDigit :: Integer -> Integer
lastDigit = flip mod 10

dropLastDigit :: Integer -> Integer
dropLastDigit n = truncate ((fromIntegral n / 10)::Double)

e1 :: T.Test
e1 = T.TestList
    [
      U.teq "123last" (lastDigit     123)   3
    , U.teq "0last"   (lastDigit     0)     0
    , U.teq "123drop" (dropLastDigit 123)  12
    , U.teq "5drop"   (dropLastDigit 5)     0
      ---------------------------------------
    , U.teq "397last" (lastDigit     397)   7
    , U.teq "397drop" (dropLastDigit 397)  39
    , U.teq "39last"  (lastDigit     39)    9
    , U.teq "39drop"  (dropLastDigit 39)    3
    , U.teq "3last"   (lastDigit     3)     3
    , U.teq "3drop"   (dropLastDigit 3)     0
    ]

------------------------------------------------------------------------------
-- Exercise 2

toDigits :: Integer -> [Integer]
toDigits = reverse . toDigitsRev

toDigitsRev :: Integer -> [Integer]
toDigitsRev = unfoldr (\n -> if n <= 0 then Nothing else Just (lastDigit n, dropLastDigit n))

e2 :: T.Test
e2 = T.TestList
    [
      U.teq "7" (toDigits    1234) [1,2,3,4]
    , U.teq "9" (toDigitsRev 1234) [4,3,2,1]
    , U.teq "9" (toDigits       0) []
    , U.teq "0" (toDigits   (-17)) []
    ]

------------------------------------------------------------------------------
-- Exercise 3

-- O(n)
-- correct type sig is:
-- doubleEveryOther :: Num a => [a] -> [a]
-- but pinning it at Integer to avoid "defaulting to" messages in test
doubleEveryOther :: [Integer] -> [Integer]
doubleEveryOther xs0 =
    let (_,r)   = deo xs0
        deo xs1 = case xs1 of
            []     -> (False, [])
            (x:xs) -> let (b, xs') = deo xs in (not b, (if b then 2*x else x) : xs')
    in r

-- O(3n)
-- doubleEveryOther3n :: Num a => [a] -> [a]
doubleEveryOther3n :: [Integer] -> [Integer]
doubleEveryOther3n xs0 = reverse $ deo False (reverse xs0)
  where deo b xs1 =
            case xs1 of
                []     -> []
                (x:xs) -> (if b then 2*x else x) : deo (not b) xs

-- http://stackoverflow.com/questions/23842473/what-to-use-instead-of-explicit-recursion-in-haskell
-- doubleEveryOtherLens = over (elements even) (*2) [8,7,6,5]
<commit_msg>Include others solutions in cis194 hw01 (after doing it on my own).<commit_after>{-
Created       : 2014 May 23 (Fri) 14:32:50 by <NAME>.
Last Modified : 2014 Sep 15 (Mon) 16:14:21 by <NAME>.
-}

module HW01_HC where

import           Data.List       (unfoldr)
import qualified Test.HUnit      as T
import qualified Test.HUnit.Util as U

------------------------------------------------------------------------------
-- Exercise 1

lastDigit :: Integer -> Integer
lastDigit = flip mod 10

dropLastDigit :: Integer -> Integer
dropLastDigit n = truncate ((fromIntegral n / 10)::Double)

e1 :: T.Test
e1 = T.TestList
    [
      U.teq "123last" (lastDigit     123)   3
    , U.teq "0last"   (lastDigit     0)     0
    , U.teq "123drop" (dropLastDigit 123)  12
    , U.teq "5drop"   (dropLastDigit 5)     0
      ---------------------------------------
    , U.teq "397last" (lastDigit     397)   7
    , U.teq "397drop" (dropLastDigit 397)  39
    , U.teq "39last"  (lastDigit     39)    9
    , U.teq "39drop"  (dropLastDigit 39)    3
    , U.teq "3last"   (lastDigit     3)     3
    , U.teq "3drop"   (dropLastDigit 3)     0
    ]

------------------------------------------------------------------------------
-- Exercise 2

toDigits :: Integer -> [Integer]
toDigits = reverse . toDigitsRev

toDigitsRev :: Integer -> [Integer]
toDigitsRev = unfoldr (\n -> if n <= 0 then Nothing else Just (lastDigit n, dropLastDigit n))

e2 :: T.Test
e2 = T.TestList
    [
      U.teq "7" (toDigits    1234) [1,2,3,4]
    , U.teq "9" (toDigitsRev 1234) [4,3,2,1]
    , U.teq "9" (toDigits       0) []
    , U.teq "0" (toDigits   (-17)) []
    ]

-- https://github.com/gfixler/cis194/blob/master/hw1/creditCardValidator.hs

charToDigitF :: Char -> Integer
charToDigitF n = head [d | (c,d) <- zip ['0'..'9'] [0..9], c == n]

toDigitsF :: Integer -> [Integer]
toDigitsF n
    | n > 0     = map charToDigitF $ show n
    | otherwise = []

toDigitsRevF :: Integer -> [Integer]
toDigitsRevF = reverse . toDigitsF

------------------------------------------------------------------------------
-- Exercise 3

-- O(n)
-- correct type sig is:
-- doubleEveryOther :: Num a => [a] -> [a]
-- but pinning it at Integer to avoid "defaulting to" messages in test
doubleEveryOther :: [Integer] -> [Integer]
doubleEveryOther xs0 =
    let (_,r)   = deo xs0
        deo xs1 = case xs1 of
            []     -> (False, [])
            (x:xs) -> let (b, xs') = deo xs in (not b, (if b then 2*x else x) : xs')
    in r

-- O(3n)
-- doubleEveryOther3n :: Num a => [a] -> [a]
doubleEveryOther3n :: [Integer] -> [Integer]
doubleEveryOther3n xs0 = reverse $ deo False (reverse xs0)
  where deo b xs1 =
            case xs1 of
                []     -> []
                (x:xs) -> (if b then 2*x else x) : deo (not b) xs

-- http://stackoverflow.com/questions/23842473/what-to-use-instead-of-explicit-recursion-in-haskell
-- doubleEveryOtherLens = over (elements even) (*2) [8,7,6,5]

{'fraction_non_alphanumeric': 0.2322863403944485, 'fraction_numerical': 0.05368882395909423, 'mean_word_length': 1.6691033138401559, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 41, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2223197', 'n_tokens_mistral': 2107, 'n_tokens_neox': 1908, 'n_words': 545}