-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDay01.hs
More file actions
59 lines (51 loc) · 2.11 KB
/
Day01.hs
File metadata and controls
59 lines (51 loc) · 2.11 KB
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
module Day01 (task01, task02) where
import Utils
task01 :: String -> String
task01 content =
let lineList = lines content
count = zeroCount lineList 50 0
in show count
task02 :: String -> String
task02 content =
let lineList = lines content
count = zeroCountOver lineList 50 0
in show count
zeroCount :: [String] -> Int -> Int -> Int
zeroCount [] _ count = count
zeroCount (op:new_lines) position count =
let new_position = updatePosition op position
new_count = count + if new_position == 0 then 1 else 0
in zeroCount new_lines new_position new_count
zeroCountOver :: [String] -> Int -> Int -> Int
zeroCountOver [] _ count = count
zeroCountOver (op:new_lines) position count =
let (cycles, remainder) = extractCyclesRemainder op
signed_new_position = position + remainder
{-
If remainder is zero, we did not mov -> no click
If position is zero, we counted last time and cannot cross another boundary
In the remaining cases, we need to check for out of bounds
-}
extra_count = if (remainder /= 0) && position /= 0 && ((signed_new_position <= 0) || (signed_new_position >= 100))
then 1
else 0
new_position = signed_new_position `mod` 100
new_count = count + cycles + extra_count
in zeroCountOver new_lines new_position new_count
updatePosition :: String -> Int -> Int
updatePosition [] _ = error "Empty string"
updatePosition (direction:offset_str) position =
let offset = stringToInt offset_str
sign = if direction == 'R' then 1 else -1
in (position + sign*offset) `mod` 100
extractCyclesRemainder :: String -> (Int, Int)
extractCyclesRemainder [] = error "Empty string"
extractCyclesRemainder (direction:offset_str) =
let offset = stringToInt offset_str
sign = if direction == 'R' then 1 else -1
signed_offset = sign*offset
cycles = offset `div` 100
remainder = signed_offset `mod` 100
-- Need to exclude remainder == -100 in the negative sign case
signed_remainder = if (sign > 0) || (remainder == 0) then remainder else remainder - 100
in (cycles, signed_remainder)