diff options
[FP/HW4] Drastically simplified exercise 1 and added comments
1 files changed, 23 insertions, 35 deletions
| -rw-r--r-- | Year 2/Functional Programming/hw4.hs | 58 |
diff --git a/Year 2/Functional Programming/hw4.hs b/Year 2/Functional Programming/hw4.hs index c0c4d1a..8e35f4d 100644 --- a/Year 2/Functional Programming/hw4.hs +++ b/Year 2/Functional Programming/hw4.hs @@ -1,42 +1,30 @@ --- Exercise 1 +-- Задача 1 import Data.List subtr :: String -> String -> String subtr a b = filter (\c -> not (c `elem` b)) a -subRange :: [a] -> Int -> Int -> [a] -subRange l start end = (take (end - start + 1) (drop start l)) - -findNotContain :: [String] -> String -> String -findNotContain arr ch = (filter (\s -> not (ch `isSubstrUn` s)) arr) !! 0 - where - isSubstrUn :: String -> String -> Bool - isSubstrUn a b = all (\c -> c `elem` b) a +hasAllCharsIn :: String -> String -> Bool +hasAllCharsIn a b = all (\c -> c `elem` b) a decode :: String -> Int -decode i = read $ find_a [] (sortBy (\s1 s2 -> compare (length s1) (length s2)) (take 10 (words i))) (drop 11 (words i)) +decode i = read $ parseNumbers (getSegments $ sortBy (\s1 s2 -> compare (length s1) (length s2)) + (take 10 (words i))) + (drop 11 (words i)) where - -- 7-1 = segment a - find_a seg nums parse = find_bd [subtr (nums!!1) (nums!!0)] nums parse - - -- 4-1 = segments b and d - find_bd seg nums parse = find_eg (seg ++ [subtr (nums!!2) (nums!!0)]) nums parse - - -- 8-4-a = segments e and g - find_eg seg nums parse = find_d (seg ++ [subtr (subtr (nums!!9) (nums!!2)) (seg!!0)]) nums parse - - -- From the 6-segment numbers, only number 0 has one of b and d (so we search for number that doesn't have both), and 8-0 = d - add_d seg d = head seg : (subtr (seg!!1) d) : d : drop 2 seg - find_d seg nums parse = find_c (add_d seg (subtr (nums!!9) (findNotContain (subRange nums 6 8) (seg!!1)))) nums parse - - -- From the 6-segment numbers, only number 6 has one of c and f (so we search for number that doesn't have both; number 1 uses both), and 8-6 = c - add_c seg c nums = take 2 seg ++ [c] ++ drop 2 seg ++ [subtr (nums!!0) c] - find_c seg nums parse = find_e (add_c seg (subtr (nums!!9) (findNotContain (subRange nums 6 8) (nums!!0))) nums) nums parse + -- След като написах огромна имплементация, която намира всеки сегмент какъв му е знака, забелязах че + -- може да използваме само "групи" сегменти, за да различим всички цифри с еднакви дължини. + -- Тоест, вземаме двойките сегменти bd, eg и cf (наименования от "работещия" циферблат), като не се интересуваме от тяхната наредба, + -- и казваме че двойка се съдържа в дадена цифра, ако и двете букви се съдържат в цифрата (тоест, ако има само b, но не d, значи не съдържа bd). + -- + -- За 1, 4, 7, 8 не разглеждаме това свойство, понеже тях ги различаваме по дължина. + -- При 5 сегментни цифри, забелязваме че 2 съдържа eg, 5 съдържа bd, 3 не съдържа нищо (и трите съдържат cf, но това не ни интересува) + -- При 6 сегментни цифри, забелязваме че 6 съдържа bd и eg, 9 съдържа bd и cf, 0 съдържа eg и cf - -- From the 6-segment numbers, only number 9 has one of e and g, and 8-9 = e - add_e seg e = take 4 seg ++ [e, seg!!5, subtr (seg!!4) e] - find_e seg nums parse = parseNumbers (add_e seg (subtr (nums!!9) (findNotContain (subRange nums 6 8) (seg!!4)))) parse + getSegments nums = [subtr (nums!!2) (nums!!0), -- сегменти b и d + subtr (subtr (nums!!9) (nums!!1)) (nums!!2), -- сегменти e и g + nums!!0] -- сегменти c и f parseNumbers _ [] = [] parseNumbers seg parse = (parseDigit seg (head parse)) : parseNumbers seg (tail parse) @@ -46,12 +34,12 @@ decode i = read $ find_a [] (sortBy (\s1 s2 -> compare (length s1) (length s2)) | length d == 3 = '7' | length d == 4 = '4' | length d == 7 = '8' - | length d == 5 = if (seg!!1!!0) `elem` d then '5' - else if (seg!!4!!0) `elem` d then '2' - else '3' - | otherwise = if not ((seg!!2!!0) `elem` d) then '6' - else if not ((seg!!4!!0) `elem` d) then '9' - else '0' + | length d == 5 = if (seg!!0) `hasAllCharsIn` d then '5' -- ако bd се съдържа + else if (seg!!1) `hasAllCharsIn` d then '2' -- ако eg се съдържа + else '3' + | otherwise = if not ((seg!!0) `hasAllCharsIn` d) then '0' -- ако bd не се съдържа (съдържа eg и cf) + else if (seg!!2) `hasAllCharsIn` d then '9' -- ако cf се съдържа (и bd се съдържа) + else '6' |
