Skip to content

Commit e8b2434

Browse files
committed
feat(2024/Day12)
1 parent ddebfdb commit e8b2434

8 files changed

+273
-3
lines changed

2024/Day12/Day12.hs

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
module Main where
2+
3+
import Data.List
4+
import Data.Matrix (Matrix, (!))
5+
import Data.Matrix qualified as Mat
6+
import Data.Set (Set)
7+
import Data.Set qualified as S
8+
import Data.Tuple.Extra
9+
import Debug.Trace
10+
import System.Environment
11+
import Text.Regex.TDFA ((=~))
12+
13+
type Input = Matrix Char
14+
15+
type Output = Int
16+
17+
data Dir = UP | LEFT | RIGHT | DOWN deriving (Show, Eq, Ord)
18+
19+
parseInput :: String -> Input
20+
parseInput = Mat.fromLists . lines
21+
22+
indices :: Matrix a -> [(Int, Int)]
23+
indices grid = [(y, x) | y <- [1 .. Mat.nrows grid], x <- [1 .. Mat.ncols grid]]
24+
25+
move :: (Int, Int) -> Dir -> (Int, Int)
26+
move (y, x) UP = (y - 1, x)
27+
move (y, x) DOWN = (y + 1, x)
28+
move (y, x) LEFT = (y, x - 1)
29+
move (y, x) RIGHT = (y, x + 1)
30+
31+
isOut :: (Int, Int) -> (Int, Int) -> Bool
32+
isOut (width, height) (y, x) = x <= 0 || y <= 0 || x > width || y > height
33+
34+
mapOutRegion :: Matrix Char -> Char -> (Int, Int) -> Dir -> Set (Int, Int) -> (Set (Int, Int), Set ((Int, Int), Dir))
35+
mapOutRegion grid plant yx dir seen
36+
| yx `S.member` seen = (seen, S.empty)
37+
| isOut (Mat.ncols grid, Mat.nrows grid) yx = (seen, S.singleton (yx, dir))
38+
| grid ! yx /= plant = (seen, S.singleton (yx, dir))
39+
| otherwise = foldl (\res dir' -> second (S.union (snd res)) $ mapOutRegion grid plant (move yx dir') dir' (fst res)) (S.insert yx seen, S.empty) [UP, LEFT, RIGHT, DOWN]
40+
41+
algo :: (Set ((Int, Int), Dir) -> Int) -> Input -> Output
42+
algo wallCounter grid = sum . fst . foldl folder ([], S.empty) $ indices grid
43+
where
44+
folder :: ([Int], Set (Int, Int)) -> (Int, Int) -> ([Int], Set (Int, Int))
45+
folder (prices, seen) yx
46+
| yx `S.member` seen = (prices, seen)
47+
| otherwise = ((S.size iteSeen * wallCounter wallSeen) : prices, S.union iteSeen seen)
48+
where
49+
(iteSeen, wallSeen) = mapOutRegion grid (grid ! yx) yx UP S.empty
50+
51+
part1 :: Input -> Output
52+
part1 = algo S.size
53+
54+
nbSides :: Set ((Int, Int), Dir) -> Int
55+
nbSides walls = sum $ map (uncurry nbWallLength) groupedWallLst
56+
where
57+
wallLst :: [((Int, Int), Dir)]
58+
wallLst = S.toList walls
59+
60+
sidedWallLst :: [[((Int, Int), Dir)]]
61+
sidedWallLst = groupBy (\a b -> snd a == snd b) $ sortOn snd wallLst
62+
63+
groupedWallLst :: [(Dir, [(Int, Int)])]
64+
groupedWallLst = map (\arr -> (snd $ head arr, map fst arr)) sidedWallLst
65+
66+
nbWallLength UP = nbOn . sort
67+
nbWallLength DOWN = nbOn . sort
68+
nbWallLength LEFT = nbOn . sort . map swap
69+
nbWallLength RIGHT = nbOn . sort . map swap
70+
71+
nbOn = snd . foldl folder ((-1, -1), 0)
72+
where
73+
folder (lastYX, nbWalls) yx
74+
| fst yx /= fst lastYX = (yx, nbWalls + 1)
75+
| snd yx /= snd lastYX + 1 = (yx, nbWalls + 1)
76+
| otherwise = (yx, nbWalls)
77+
78+
part2 :: Input -> Output
79+
part2 = algo nbSides
80+
81+
main :: IO ()
82+
main = do
83+
args <- getArgs
84+
content <- readFile (last args)
85+
let input = parseInput content
86+
87+
-- print $ Mat.toLists input
88+
89+
print $ (== 1465112) $ part1 input
90+
print $ (== 893790) $ part2 input

2024/Day12/input.txt

+140
Large diffs are not rendered by default.

2024/Day12/shortinput.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
AAAA
2+
BBCD
3+
BBCC
4+
EEEC

2024/Day12/shortinput2.txt

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
OOOOO
2+
OXOXO
3+
OOOOO
4+
OXOXO
5+
OOOOO

2024/Day12/shortinput3.txt

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
RRRRIICCFF
2+
RRRRIICCCF
3+
VVRRRCCFFF
4+
VVRCCCJFFF
5+
VVVVCJJCFE
6+
VVIVCCJJEE
7+
VVIIICJJEE
8+
MIIIIIJJEE
9+
MIIISIJEEE
10+
MMMISSJEEE

2024/Day12/shortinput4.txt

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
EEEEE
2+
EXXXX
3+
EEEEE
4+
EXXXX
5+
EEEEE

2024/Day12/shortinput5.txt

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
AAAAAA
2+
AAABBA
3+
AAABBA
4+
ABBAAA
5+
ABBAAA
6+
AAAAAA

2024/README.md

+13-3
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ This year will do it in Haskell, but might try few days in Rust as well
1111
- [x] Day 7
1212
- [x] Day 8
1313
- [x] Day 9
14-
- [ ] Day 10
15-
- [ ] Day 11
16-
- [ ] Day 12
14+
- [x] Day 10
15+
- [x] Day 11
16+
- [x] Day 12
1717
- [ ] Day 13
1818
- [ ] Day 14
1919
- [ ] Day 15
@@ -157,3 +157,13 @@ At first I had 2 maps :
157157
Since the first map didn't help, I tried to clean up and realized it was really useless so I removed it completely
158158

159159
Had fun doing it in python as well, strangely python is faster than haskell
160+
161+
### Day 12:
162+
163+
That was a nice puzzle.
164+
165+
Might have been a bit easy but was interesting and difficult enough to have to think about it.
166+
167+
The only downside is what my solution looks like...
168+
169+
Cleaned that up a bit but still not great

0 commit comments

Comments
 (0)