-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathMain.hs
92 lines (81 loc) · 2.75 KB
/
Main.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import Debug.Trace
import qualified Lib.Inputs
import System.IO
main :: IO ()
main = do
handle <- openFile "input.txt" ReadMode
contents <- hGetContents handle
let linesList = lines contents
let res = fn1 linesList linesList 0
print res
fn1 :: [String] -> [String] -> Int -> Int
fn1 _ [] _ = 0
fn1 all (x:xs) row =
parseLine all x (Position row 0) False (Position row 0) + fn1 all xs (row + 1)
data Position =
Position Int Int
deriving (Show)
isDigit :: Char -> Bool
isDigit x = x >= '0' && x <= '9'
getLineFromRow :: [String] -> Int -> String
getLineFromRow all row
| row < 0 = []
| row >= length all = []
| otherwise = all !! row
parseLine :: [String] -> String -> Position -> Bool -> Position -> Int
parseLine _ [] _ False _ = 0
parseLine all [] (Position row col) True p =
check all p (Position row $ col - 1)
parseLine all (x:xs) (Position row col) False p
| isDigit x =
parseLine all xs (Position row $ col + 1) True (Position row col)
| otherwise = parseLine all xs (Position row $ col + 1) False p
parseLine all (x:xs) (Position row col) True p
| isDigit x = parseLine all xs (Position row $ col + 1) True p
| otherwise =
check all p (Position row $ col - 1)
+ parseLine all xs (Position row $ col + 1) False (Position 0 0)
check :: [String] -> Position -> Position -> Int
check all (Position fromRow fromCol) (Position toRow toCol) =
if found
then number
else 0
where
number = parseNumber all (Position fromRow fromCol) (Position toRow toCol)
found =
(containsSign (getLineFromRow all fromRow) (fromCol - 1))
|| (containsSign (getLineFromRow all fromRow) (toCol + 1))
|| (containsSignRange
(getLineFromRow all (fromRow - 1))
(fromCol - 1)
(toCol + 1))
|| (containsSignRange
(getLineFromRow all (fromRow + 1))
(fromCol - 1)
(toCol + 1))
containsSignRange :: String -> Int -> Int -> Bool
containsSignRange line col toCol
| col > toCol = False
| otherwise =
if containsSign line col
then True
else containsSignRange line (col + 1) (toCol)
containsSign :: String -> Int -> Bool
containsSign [] _ = False
containsSign line col =
if not inside
then False
else let v = line !! col
in v /= '.'
where
inside = col >= 0 && col < length line
parseNumber :: [String] -> Position -> Position -> Int
parseNumber all from to = foldl (\acc a -> acc * 10 + a) 0 numbers
where
numbers = parseNumber' all from to
parseNumber' :: [String] -> Position -> Position -> [Int]
parseNumber' all (Position row col) (Position toRow toCol)
| col > toCol = []
| otherwise =
fromEnum (all !! row !! col) - fromEnum '0'
: parseNumber' all (Position row $ col + 1) (Position toRow toCol)