Day6 with better algorithm

This commit is contained in:
Jens Kadenbach
2022-12-06 18:14:27 +01:00
parent 95f13675dd
commit 001ffc6789
2 changed files with 28 additions and 25 deletions

View File

@@ -1,32 +1,35 @@
module Day6 (
findEnd,
findStart,
isUnique,
day6
) where
findMarker :: Int -> String -> Maybe Int
findMarker windowSize = findMarker' 0 ""
where
findMarker' :: Int -> String -> String -> Maybe Int
findMarker' offset window []
| isUnique window && length window == windowSize = Just offset
| otherwise = Nothing
findMarker' offset window (c:cs)
| length window < windowSize = findMarker' (offset + 1) (c:window) cs
| not (isUnique window) = findMarker' (offset + 1) (c:init window) cs
| isUnique window = Just offset
| otherwise = Nothing
import qualified Data.Sequence as S
import Data.Sequence (Seq (..), (|>))
findStart :: String -> Maybe Int
findStart = findMarker 14
findStart = findUniqueSubstring 14
findEnd :: String -> Maybe Int
findEnd = findMarker 4
findEnd = findUniqueSubstring 4
isUnique :: (Eq a) => [a] -> Bool
isUnique [] = True
isUnique (c:cs) = c `notElem` cs && isUnique cs
findUniqueSubstring :: Int -> String -> Maybe Int
findUniqueSubstring size input
| length input < size = Nothing -- imposible to find a substring because input is too small
| otherwise = find 0 S.empty $ S.fromList input
where
find :: Int -> Seq Char -> Seq Char -> Maybe Int
find _ _ Empty = Nothing
find off window (r :<| rs)
= case S.elemIndexL r window of -- is new element in window?
Nothing -> if S.length window == size -1 -- Element not found, but is our window large nough?
then Just nextOff -- Large enough, we got a winner!
else find nextOff enlargedWindow rs -- Not large enough, push new element to the end of the window
Just i -> find nextOff (removeConflict (i + 1)) rs -- continue after clearing window
where
nextOff = off + 1
enlargedWindow = window |> r
removeConflict i = S.drop i enlargedWindow
day6 :: IO ()
day6 = do