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

View File

@@ -2,21 +2,21 @@ module Day6Spec (spec) where
import Test.Hspec
import Day6
import qualified Data.Sequence as S
spec :: Spec
spec =
describe "Day6" $ do
describe "Part1" $ do
it "finds unique lists" $ do
isUnique "abc" `shouldBe` True
isUnique "abca" `shouldBe` False
isUnique "cabc" `shouldBe` False
it "finds nothing if nothing is there" $ do
findEnd "abcb" `shouldBe` Nothing
findEnd "abcabcb" `shouldBe` Nothing
it "finds the marker just after the beginning" $ do
findEnd "aabcd" `shouldBe` Just 5
it "finds the marker in the beginning" $ do
findEnd "abcd" `shouldBe` Just 4
findEnd "aabcd" `shouldBe` Just 5
it "finds nothing if nothing is there" $ do
findEnd "abc" `shouldBe` Nothing
findEnd "abcb" `shouldBe` Nothing
findEnd "abcabcb" `shouldBe` Nothing
it "finds a marker" $ do
findEnd "mjqjpqmgbljsphdztnvjfqwrcgsmlb"`shouldBe` Just 7
findEnd "bvwbjplbgvbhsrlpgdmjqwftvncz" `shouldBe` Just 5