Skip to content

Commit 08a5d0e

Browse files
committed
feat(2024/Day09)
1 parent 25bf65e commit 08a5d0e

File tree

5 files changed

+132
-0
lines changed

5 files changed

+132
-0
lines changed

2024/Day09/Day09.hs

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
module Main where
2+
import Debug.Trace
3+
import System.Environment
4+
5+
type Input = [Int]
6+
type Output = Int
7+
8+
parseInput :: String -> Input
9+
parseInput = map (\c -> read [c]) . filter (/= '\n')
10+
11+
expand :: [Int] -> [Int]
12+
expand = concat . map (\(i, n) -> replicate n (if i `mod` 2 == 0 then (i `div` 2) else -1)) . zip [0..]
13+
14+
exchangeAt :: [a] -> Int -> a -> [a]
15+
exchangeAt arr i e = elsBefore ++ [e] ++ elsAfter
16+
where
17+
(elsBefore, _:elsAfter) = splitAt i arr
18+
19+
retract :: [Int] -> [Int]
20+
retract arr = sub arr (reverse arr) 0 (length arr - 1)
21+
where
22+
sub arr rev i j
23+
| i == j = [head arr]
24+
| head arr /= -1 = head arr : sub (drop 1 arr) rev (i+1) j
25+
| head rev == -1 = sub arr (drop 1 rev) i (j-1)
26+
| otherwise = head rev: sub (drop 1 arr) (drop 1 rev) (i+1) (j-1)
27+
28+
29+
part1 :: Input -> Int
30+
part1 = sum . map (uncurry (*)) . zip [0..] . retract . expand
31+
32+
33+
-- Artifact of previous version in which I segmented the drive as (id, size) (id -1 beeing free) but had the issue of [(-1, 2), (-1, 3)] which should be converted to [(-1, 5)]
34+
-- and meant to pass onee more time on the array => seemed either slow or more complicated even if doable
35+
-- expand2 :: [Int] -> [(Int, Int)]
36+
-- expand2 = map (\(i, n) -> (if i `mod` 2 == 0 then (i `div` 2) else -1, n)) . zip [0..]
37+
38+
-- retract2 :: [(Int, Int)] -> [(Int, Int)]
39+
-- retract2 arr = foldl (\res (j, (idi, size)) -> sub res 0 j (idi, size)) arr $ zip (reverse [0..length arr - 1]) arr
40+
-- where
41+
-- sub :: [(Int, Int)] -> Int -> Int -> (Int, Int) -> Bool -> [(Int, Int)]
42+
-- sub arr i j (idi, size) added
43+
-- | added && i == j = (-1, size) : (drop 1 arr)
44+
-- | i >= j = arr
45+
-- | idi == -1 = arr
46+
-- | (fst $ head arr) /= -1 = head arr : sub (drop 1 arr) (i+1) j (idi, size) added
47+
-- | (snd $ head arr) < size = head arr : sub (drop 1 arr) (i+1) j (idi, size) added
48+
-- | (snd $ head arr) == size = (idi, size) : sub (drop 1 arr) (i+1) j (idi, size) True
49+
-- | (snd $ head arr) > size = (idi, size) : (-1, (snd $ head arr) - size) : sub (drop 1 arr) (i+1) j (idi, size) True
50+
-- sub2 arr rev j
51+
-- | rev == [] = arr
52+
-- | (fst $ head rev) == -1 = sub2 arr (drop 1 rev) (j-1)
53+
-- | otherwise = sub arr 0 j head (rev)
54+
55+
56+
-- exchangeAt :: [a] -> Int -> a -> [a]
57+
-- exchangeAt arr i e = elsBefore ++ [e] ++ elsAfter
58+
-- where
59+
-- (elsBefore, _:elsAfter) = splitAt i arr
60+
61+
retract2 :: [Int] -> [Int]
62+
retract2 arr = {-# SCC sub2 #-} sub2 arr (reverse arr) (length arr -1)
63+
where
64+
sub arr jBlock i j
65+
| i >= j = arr
66+
| head arr /= -1 = iBlock ++ {-# SCC notFreeSubCall #-} sub (drop leni arr) jBlock (i+leni) j
67+
| leni < lenj = iBlock ++ {-# SCC tooSmallSubCall #-} sub (drop leni arr) jBlock (i+leni) j
68+
| otherwise = jBlock ++ {-# SCC removeElt #-} removeElt (head jBlock) (drop lenj arr)
69+
where
70+
iBlock = takeWhile (== (head arr)) arr
71+
leni = length iBlock
72+
lenj = length jBlock
73+
74+
removeElt elt arr = map (\e -> if e == elt then -1 else e) arr
75+
76+
sub2 arr rev j
77+
| j <= 0 = arr
78+
| head rev == -1 = sub2 arr (drop lenj rev) (j - lenj)
79+
| otherwise = sub2 ({-# SCC firstSubCall #-} sub arr jBlock 0 (j-lenj)) (drop lenj rev) (j - lenj)
80+
where
81+
jBlock = takeWhile (== (head rev)) rev
82+
lenj = length jBlock
83+
84+
85+
part2 :: Input -> Output
86+
part2 = sum . map (uncurry (*)) . filter ((/= -1) . snd) . zip [0..] . retract2 . expand
87+
88+
main :: IO ()
89+
main = do
90+
args <- getArgs
91+
content <- readFile (last args)
92+
let input = parseInput content
93+
94+
print $ part1 input
95+
print $ part2 input

2024/Day09/Makefile

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
CONTAINER_NAME=haskell-aoc
2+
SRC=./Day09.hs
3+
TARGET=Day09
4+
all: $(TARGET)
5+
6+
$(TARGET): $(SRC)
7+
ghc -O3 $(SRC)
8+
9+
profile: $(SRC)
10+
11+
12+
clean:
13+
$(RM) ./Day09 ./Day09.o ./Day09.hi
14+
15+
setup: $(SRC)
16+
docker cp $(SRC) $(CONTAINER_NAME):/home/haskell/Main.hs
17+
docker cp input.txt $(CONTAINER_NAME):/home/haskell/input.txt
18+
docker cp shortinput.txt $(CONTAINER_NAME):/home/haskell/shortinput.txt
19+
20+
profiling: setup
21+
docker exec -it $(CONTAINER_NAME) cabal build --enable-profiling
22+
docker exec -it $(CONTAINER_NAME) ./profile input.txt
23+
24+
run: setup
25+
docker exec -it $(CONTAINER_NAME) cabal build
26+
docker exec -it $(CONTAINER_NAME) ./run input.txt
27+
28+
.PHONY: all $(TARGET) clean setup profiling run

0 commit comments

Comments
 (0)