diff --git a/wk3/elm.json b/wk3/elm.json new file mode 100644 index 0000000..ce2a08d --- /dev/null +++ b/wk3/elm.json @@ -0,0 +1,24 @@ +{ + "type": "application", + "source-directories": [ + "src" + ], + "elm-version": "0.19.1", + "dependencies": { + "direct": { + "elm/browser": "1.0.2", + "elm/core": "1.0.5", + "elm/html": "1.0.0" + }, + "indirect": { + "elm/json": "1.1.3", + "elm/time": "1.0.0", + "elm/url": "1.0.0", + "elm/virtual-dom": "1.0.3" + } + }, + "test-dependencies": { + "direct": {}, + "indirect": {} + } +} diff --git a/wk3/src/Caesar2.elm b/wk3/src/Caesar2.elm new file mode 100644 index 0000000..f6f8eb6 --- /dev/null +++ b/wk3/src/Caesar2.elm @@ -0,0 +1,113 @@ +module Caesar2 exposing (..) + +{- + Caesar cipher (Part 2) + Dimitar Byalkov and Kaloyan Stoykov +-} + +encode: Int -> Char -> Char +encode offset character = + -- Char.isUpper replaces the check for the ASCII code range of uppercase letters + if Char.isUpper character then + shiftChar (Char.toCode 'A') offset character + -- Char.isLower replaces the check for the ASCII code range of lowercase letters + else if Char.isLower character then + shiftChar (Char.toCode 'a') offset character + else ' ' + +-- shiftChar takes the common arithmetic actions from the if-statement in 'encode' +shiftChar: Int -> Int -> Char -> Char +shiftChar baseCode offset character = + Char.fromCode(baseCode + modBy 26 ((Char.toCode character) - baseCode + offset - 26)) + +decode: Int -> Char -> Char +decode offset character = + encode (0 - offset) character + + +{- Return a list with a filter function that keeps only uppercase and lowercase ascii chars. -} +normalize: String -> String +normalize input = + String.fromList (List.filter Char.isAlpha (String.toList input)) + + +encrypt: Int -> String -> String +encrypt offset input = + case String.uncons input of + -- Check for empty string + Nothing -> + "" + -- When string is split into form of "a", "bc" for example, encode the head and call recursively with the same offset -> encoded char :: encrypt offset tail + Just (head, tail) -> + String.cons (encode offset head) (encrypt offset tail) + +{- Mirrored version of encrypt with decode and decrypt used instead -} +decrypt: Int -> String -> String +decrypt offset input = + case String.uncons input of + Nothing -> + "" + Just (head, tail) -> + String.cons (decode offset head) (decrypt offset tail) + + + + +testEncodeUpperSmallOffsetA: Bool +testEncodeUpperSmallOffsetA = (encode 5 'A' == 'F') + +testEncodeUpperBigOffsetF: Bool +testEncodeUpperBigOffsetF = (encode 348 'F' == 'P') + +testEncodeLowerSmallOffsetQ: Bool +testEncodeLowerSmallOffsetQ = (encode 9 'q' == 'z') + +testEncodeLowerBigOffsetG: Bool +testEncodeLowerBigOffsetG = (encode 215 'g' == 'n') + +testDecodeUpperSmallOffsetA: Bool +testDecodeUpperSmallOffsetA = (decode 5 'F' == 'A') + +testDecodeUpperBigOffsetF: Bool +testDecodeUpperBigOffsetF = (decode 348 'P' == 'F') + +testDecodeLowerSmallOffsetQ: Bool +testDecodeLowerSmallOffsetQ = (decode 9 'z' == 'q') + +testDecodeLowerBigOffsetG: Bool +testDecodeLowerBigOffsetG = (decode 215 'n' == 'g') + + +testShiftChar: Bool +testShiftChar = (shiftChar 97 3 'a' == 'd') + + +testNormalize: Bool +testNormalize = (normalize "Hello, Fontys!" == "HelloFontys") + + +testNormalizeB: Bool +testNormalizeB = (normalize "Hello#@#!#@" == "Hello") + + +testEncrypt: Bool +testEncrypt = (encrypt 7 "HelloFontys" == "OlssvMvuafz") + + +testEncryptB: Bool +testEncryptB = (encrypt 6 "RandomText" == "XgtjusZkdz") + + +testDecrypt: Bool +testDecrypt = (decrypt 6 "Hsdsakw" == "Bmxmueq") + + +testDecryptB: Bool +testDecryptB = (decrypt 9 "HSAhsh" == "YJRyjy") + + +allCaesar2Tests = [testEncodeUpperSmallOffsetA, testEncodeUpperBigOffsetF, testEncodeLowerSmallOffsetQ, testEncodeLowerBigOffsetG, testDecodeUpperSmallOffsetA, testDecodeUpperBigOffsetF, testDecodeLowerSmallOffsetQ, testDecodeLowerBigOffsetG, testShiftChar, testNormalize, testNormalizeB, testEncrypt, testEncryptB, testDecrypt, testDecryptB] + + + + diff --git a/wk3/src/Caesar3.elm b/wk3/src/Caesar3.elm new file mode 100644 index 0000000..98a8dc5 --- /dev/null +++ b/wk3/src/Caesar3.elm @@ -0,0 +1,44 @@ +module Caesar3 exposing (..) + +-- importing Caesar cipher (part 2) +import Caesar2 exposing (..) + +{- + Caesar cipher (Part 3) + Dimitar Byalkov and Kaloyan Stoykov +-} + +candidates: List String -> String -> List (Int, String) +candidates canaries encryptedText = + case canaries of + [] -> + [] + x :: xs -> + filterList x (bruteGenerator encryptedText 0) ++ candidates (List.drop 1 canaries) encryptedText + +bruteGenerator: String -> Int -> List (Int, String) +bruteGenerator encryptedText accumulator = + if accumulator < 25 then + (accumulator, (decrypt accumulator encryptedText)) :: bruteGenerator encryptedText (accumulator + 1) + else + List.singleton (accumulator, (decrypt accumulator encryptedText)) + +filterList: String -> List (Int, String) -> List (Int, String) +filterList canary candidateTexts = + case candidateTexts of + [] -> + [] + (x, y) :: xs -> + if containsText canary y then + (x, y) :: filterList canary xs + else + filterList canary xs + +containsText: String -> String -> Bool +containsText canary text = + if String.left (String.length canary) text == canary then + True + else if String.length text == 0 then + False + else + containsText canary (String.dropLeft 1 text) \ No newline at end of file diff --git a/wk3/src/CreditCard.elm b/wk3/src/CreditCard.elm new file mode 100644 index 0000000..2277a20 --- /dev/null +++ b/wk3/src/CreditCard.elm @@ -0,0 +1,222 @@ +module CreditCard exposing (..) +import Html exposing (Html) + +------------------------------------------------------------------------------------------------------------------------------ +-- Validating Credit Card Numbers +------------------------------------------------------------------------------------------------------------------------------ + +-- =================================== +-- Ex. 0 +-- =================================== + +toDigits: String -> List Int +toDigits x = + case String.uncons (String.filter Char.isDigit x) of + Nothing -> + [] + Just (head, tail) -> + Maybe.withDefault 0 (String.toInt (String.fromChar head)) :: toDigits tail + +-- =================================== +-- Ex. 1 +-- =================================== + +toDigitsRev: String -> List Int +toDigitsRev x = + List.foldl (::) [] (toDigits x) + +-- =================================== +-- Ex. 2 +-- =================================== + +doubleSecond: List Int -> List Int +doubleSecond xs = + {- + + -} + case xs of + [] -> + [] + y :: z :: ys -> + y :: z * 2 :: doubleSecond ys + y :: ys -> + y :: doubleSecond ys + + +-- =================================== +-- Ex. 3 +-- =================================== + +sumDigits: List Int -> Int +sumDigits xs = + {- + Using a lambda function we split double-digit numbers + and sum all of the digits of the list. + We use interger division to get the tens digit and + modulo to get the remaining digit. + -} + List.foldr (\x acc -> (x // 10) + (modBy 10 x) + acc) 0 xs + + +-- =================================== +-- Ex. 4 +-- =================================== + +isValid: String -> Bool +isValid x = + modBy 10 (sumDigits (doubleSecond (toDigitsRev x))) == 0 + + +-- =================================== +-- Ex. 5 +-- =================================== + +numValid: List String -> Int +numValid xs = + -- haskell: sum . map (\_ -> 1) $ filter isValid xs + List.length (List.filter isValid xs) + +countValidCards: List Int -> Int +countValidCards testCards = + numValid (List.map String.fromInt testCards) + +creditcards: List Int +creditcards = [ 4716347184862961, + 4532899082537349, + 4485429517622493, + 4320635998241421, + 4929778869082405, + 5256283618614517, + 5507514403575522, + 5191806267524120, + 5396452857080331, + 5567798501168013, + 6011798764103720, + 6011970953092861, + 6011486447384806, + 6011337752144550, + 6011442159205994, + 4916188093226163, + 4916699537435624, + 4024607115319476, + 4556945538735693, + 4532818294886666, + 5349308918130507, + 5156469512589415, + 5210896944802939, + 5442782486960998, + 5385907818416901, + 6011920409800508, + 6011978316213975, + 6011221666280064, + 6011285399268094, + 6011111757787451, + 4024007106747875, + 4916148692391990, + 4916918116659358, + 4024007109091313, + 4716815014741522, + 5370975221279675, + 5586822747605880, + 5446122675080587, + 5361718970369004, + 5543878863367027, + 6011996932510178, + 6011475323876084, + 6011358905586117, + 6011672107152563, + 6011660634944997, + 4532917110736356, + 4485548499291791, + 4532098581822262, + 4018626753711468, + 4454290525773941, + 5593710059099297, + 5275213041261476, + 5244162726358685, + 5583726743957726, + 5108718020905086, + 6011887079002610, + 6011119104045333, + 6011296087222376, + 6011183539053619, + 6011067418196187, + 4532462702719400, + 4420029044272063, + 4716494048062261, + 4916853817750471, + 4327554795485824, + 5138477489321723, + 5452898762612993, + 5246310677063212, + 5211257116158320, + 5230793016257272, + 6011265295282522, + 6011034443437754, + 6011582769987164, + 6011821695998586, + 6011420220198992, + 4716625186530516, + 4485290399115271, + 4556449305907296, + 4532036228186543, + 4916950537496300, + 5188481717181072, + 5535021441100707, + 5331217916806887, + 5212754109160056, + 5580039541241472, + 6011450326200252, + 6011141461689343, + 6011886911067144, + 6011835735645726, + 6011063209139742, + 379517444387209, + 377250784667541, + 347171902952673, + 379852678889749, + 345449316207827, + 349968440887576, + 347727987370269, + 370147776002793, + 374465794689268, + 340860752032008, + 349569393937707, + 379610201376008, + 346590844560212, + 376638943222680, + 378753384029375, + 348159548355291, + 345714137642682, + 347556554119626, + 370919740116903, + 375059255910682, + 373129538038460, + 346734548488728, + 370697814213115, + 377968192654740, + 379127496780069, + 375213257576161, + 379055805946370, + 345835454524671, + 377851536227201, + 345763240913232 + ] + +-- collecting results for printing: + +my_results = + [ + "calculations:", + "-- end --" + ] + +-- create main method (Boiler-plate) + +to_div my_value = + Html.div [] [ my_value |> Html.text ] + +main = Html.div + [] + (List.map to_div my_results) +