|
1 | 1 | module Main where
|
| 2 | + |
| 3 | +import Data.Set (Set) |
| 4 | +import Data.Set qualified as S |
2 | 5 | import Debug.Trace
|
3 | 6 | import System.Environment
|
4 | 7 |
|
5 | 8 | type Input = [Int]
|
| 9 | + |
6 | 10 | type Output = Int
|
7 | 11 |
|
8 | 12 | parseInput :: String -> Input
|
9 | 13 | parseInput = map (\c -> read [c]) . filter (/= '\n')
|
10 | 14 |
|
11 | 15 | expand :: [Int] -> [Int]
|
12 |
| -expand = concat . map (\(i, n) -> replicate n (if i `mod` 2 == 0 then (i `div` 2) else -1)) . zip [0..] |
| 16 | +expand = concat . map (\(i, n) -> replicate n (if i `mod` 2 == 0 then (i `div` 2) else -1)) . zip [0 ..] |
13 | 17 |
|
14 | 18 | exchangeAt :: [a] -> Int -> a -> [a]
|
15 | 19 | exchangeAt arr i e = elsBefore ++ [e] ++ elsAfter
|
16 | 20 | where
|
17 |
| - (elsBefore, _:elsAfter) = splitAt i arr |
| 21 | + (elsBefore, _ : elsAfter) = splitAt i arr |
18 | 22 |
|
19 | 23 | retract :: [Int] -> [Int]
|
20 | 24 | 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 |
| - |
| 25 | + where |
| 26 | + sub arr rev i j |
| 27 | + | i == j = [head arr] |
| 28 | + | head arr /= -1 = head arr : sub (drop 1 arr) rev (i + 1) j |
| 29 | + | head rev == -1 = sub arr (drop 1 rev) i (j - 1) |
| 30 | + | otherwise = head rev : sub (drop 1 arr) (drop 1 rev) (i + 1) (j - 1) |
28 | 31 |
|
29 | 32 | part1 :: Input -> Int
|
30 |
| -part1 = sum . map (uncurry (*)) . zip [0..] . retract . expand |
| 33 | +part1 = sum . map (uncurry (*)) . filter ((/= -1) . snd) . zip [0 ..] . retract . expand |
31 | 34 |
|
| 35 | +expand2 :: [Int] -> [(Int, Int)] |
| 36 | +expand2 = map (\(i, n) -> (if i `mod` 2 == 0 then (i `div` 2) else -1, n)) . zip [0 ..] |
32 | 37 |
|
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..] |
| 38 | +expandStr :: [(Int, Int)] -> String |
| 39 | +expandStr = concat . map (\d -> if d == (-1) then "." else show d) . concat . map (\(i, n) -> replicate n i) |
37 | 40 |
|
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) |
| 41 | +retract2 :: [(Int, Int)] -> [(Int, Int)] |
| 42 | +retract2 arr = {-# SCC sub2 #-} sub2 arr (reverse arr) |
| 43 | + where |
| 44 | + subAdded :: [(Int, Int)] -> (Int, Int) -> [(Int, Int)] |
| 45 | + subAdded arr (idi, size) |
| 46 | + | idi == currId = (-1, size) : (drop 1 arr) |
| 47 | + | otherwise = head arr : subAdded (drop 1 arr) (idi, size) |
| 48 | + where |
| 49 | + (currId, currSize) = head arr |
| 50 | + |
| 51 | + sub :: [(Int, Int)] -> (Int, Int) -> [(Int, Int)] |
| 52 | + sub arr (idi, size) |
| 53 | + | idi == currId = arr |
| 54 | + | currId /= -1 = head arr : resSkip1 |
| 55 | + | currId == -1 && nextId == -1 = {-# SCC subMergeMin1 #-} sub ((-1, currSize + nextSize) : arr) (idi, size) |
| 56 | + | currSize < size = head arr : resSkip1 |
| 57 | + | currSize == size = (idi, size) : resExactMatch |
| 58 | + | currSize > size = (idi, size) : (-1, currSize - size) : resExactMatch |
| 59 | + where |
| 60 | + resSkip1 = {-# SCC nextEmptyFromSub #-} sub (drop 1 arr) (idi, size) |
| 61 | + (resExactMatch) = {-# SCC subAdded #-} subAdded (drop 1 arr) (idi, size) |
| 62 | + (currId, currSize) = head arr |
| 63 | + (nextId, nextSize) = head $ tail arr |
| 64 | + |
| 65 | + sub2 :: [(Int, Int)] -> [(Int, Int)] -> [(Int, Int)] |
| 66 | + sub2 arr rev |
| 67 | + | rev == [] = arr |
| 68 | + | (fst $ head rev) == -1 = {-# SCC sub2OnMin1 #-} sub2 arr (drop 1 rev) |
| 69 | + | otherwise = {-# SCC sub2Next #-} sub2 (newArr) (drop 1 rev) |
| 70 | + where |
| 71 | + newArr = {-# SCC sub2CallsSub #-} sub (arr) (head rev) |
| 72 | + currId = fst $ head rev |
54 | 73 |
|
| 74 | +part2 :: Input -> Output |
| 75 | +part2 = sum . map (uncurry (*)) . filter ((/= -1) . snd) . zip [0 ..] . concat . map (\(i, n) -> replicate n i) . retract2 . expand2 |
55 | 76 |
|
56 | 77 | -- exchangeAt :: [a] -> Int -> a -> [a]
|
57 | 78 | -- exchangeAt arr i e = elsBefore ++ [e] ++ elsAfter
|
58 | 79 | -- 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 |
| 80 | +-- (elsBefore, _:elsAfter) = splitAt i arr |
83 | 81 |
|
| 82 | +-- Former Version : Was faster to do but is way slower |
| 83 | +-- Quite similar to other version except that I run using [Int] hence time to look for the sizes and loop through all those numbers |
| 84 | +-- retract2 :: [Int] -> [Int] |
| 85 | +-- retract2 arr = {-# SCC sub2 #-} sub2 arr (reverse arr) (length arr -1) |
| 86 | +-- where |
| 87 | +-- sub arr jBlock i j |
| 88 | +-- | i >= j = arr |
| 89 | +-- | head arr /= -1 = iBlock ++ {-# SCC notFreeSubCall #-} sub (drop leni arr) jBlock (i+leni) j |
| 90 | +-- | leni < lenj = iBlock ++ {-# SCC tooSmallSubCall #-} sub (drop leni arr) jBlock (i+leni) j |
| 91 | +-- | otherwise = jBlock ++ {-# SCC removeElt #-} removeElt (head jBlock) (drop lenj arr) |
| 92 | +-- where |
| 93 | +-- iBlock = takeWhile (== (head arr)) arr |
| 94 | +-- leni = length iBlock |
| 95 | +-- lenj = length jBlock |
84 | 96 |
|
85 |
| -part2 :: Input -> Output |
86 |
| -part2 = sum . map (uncurry (*)) . filter ((/= -1) . snd) . zip [0..] . retract2 . expand |
| 97 | +-- removeElt elt arr = map (\e -> if e == elt then -1 else e) arr |
| 98 | + |
| 99 | +-- sub2 arr rev j |
| 100 | +-- | j <= 0 = arr |
| 101 | +-- | head rev == -1 = sub2 arr (drop lenj rev) (j - lenj) |
| 102 | +-- | otherwise = sub2 ({-# SCC firstSubCall #-} sub arr jBlock 0 (j-lenj)) (drop lenj rev) (j - lenj) |
| 103 | +-- where |
| 104 | +-- jBlock = takeWhile (== (head rev)) rev |
| 105 | +-- lenj = length jBlock |
| 106 | + |
| 107 | +-- part2 :: Input -> Output |
| 108 | +-- part2 = sum . map (uncurry (*)) . filter ((/= -1) . snd) . zip [0..] . retract2 . expand |
87 | 109 |
|
88 | 110 | main :: IO ()
|
89 | 111 | main = do
|
90 |
| - args <- getArgs |
| 112 | + args <- getArgs |
91 | 113 | content <- readFile (last args)
|
92 | 114 | let input = parseInput content
|
93 | 115 |
|
|
0 commit comments