day 2
This commit is contained in:
152
spago.lock
152
spago.lock
@@ -5,22 +5,31 @@
|
||||
"path": "./",
|
||||
"core": {
|
||||
"dependencies": [
|
||||
"arrays",
|
||||
"bifunctors",
|
||||
"bigints",
|
||||
"console",
|
||||
"control",
|
||||
"effect",
|
||||
"either",
|
||||
"exceptions",
|
||||
"filterable",
|
||||
"foldable-traversable",
|
||||
"lists",
|
||||
"maybe",
|
||||
"parsing",
|
||||
"partial",
|
||||
"prelude",
|
||||
"st",
|
||||
"strings",
|
||||
"transformers",
|
||||
"tuples"
|
||||
],
|
||||
"build_plan": [
|
||||
"arrays",
|
||||
"assert",
|
||||
"bifunctors",
|
||||
"bigints",
|
||||
"console",
|
||||
"const",
|
||||
"contravariant",
|
||||
@@ -31,6 +40,7 @@
|
||||
"enums",
|
||||
"exceptions",
|
||||
"exists",
|
||||
"filterable",
|
||||
"foldable-traversable",
|
||||
"functions",
|
||||
"functors",
|
||||
@@ -39,17 +49,23 @@
|
||||
"integers",
|
||||
"invariant",
|
||||
"lazy",
|
||||
"lcg",
|
||||
"lists",
|
||||
"maybe",
|
||||
"newtype",
|
||||
"nonempty",
|
||||
"nullable",
|
||||
"numbers",
|
||||
"ordered-collections",
|
||||
"orders",
|
||||
"parsing",
|
||||
"partial",
|
||||
"prelude",
|
||||
"profunctor",
|
||||
"quickcheck",
|
||||
"quickcheck-laws",
|
||||
"random",
|
||||
"record",
|
||||
"refs",
|
||||
"safe-coerce",
|
||||
"st",
|
||||
@@ -6596,6 +6612,16 @@
|
||||
"unsafe-coerce"
|
||||
]
|
||||
},
|
||||
"assert": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/purescript/purescript-assert.git",
|
||||
"rev": "27c0edb57d2ee497eb5fab664f5601c35b613eda",
|
||||
"dependencies": [
|
||||
"console",
|
||||
"effect",
|
||||
"prelude"
|
||||
]
|
||||
},
|
||||
"bifunctors": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/purescript/purescript-bifunctors.git",
|
||||
@@ -6608,6 +6634,26 @@
|
||||
"tuples"
|
||||
]
|
||||
},
|
||||
"bigints": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/purescript-contrib/purescript-bigints.git",
|
||||
"rev": "e73f55b866e437c7bf04c7d262de7c205c47bbca",
|
||||
"dependencies": [
|
||||
"arrays",
|
||||
"assert",
|
||||
"console",
|
||||
"effect",
|
||||
"foldable-traversable",
|
||||
"integers",
|
||||
"maybe",
|
||||
"numbers",
|
||||
"partial",
|
||||
"prelude",
|
||||
"quickcheck",
|
||||
"quickcheck-laws",
|
||||
"strings"
|
||||
]
|
||||
},
|
||||
"console": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/purescript/purescript-console.git",
|
||||
@@ -6715,6 +6761,19 @@
|
||||
"unsafe-coerce"
|
||||
]
|
||||
},
|
||||
"filterable": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/purescript/purescript-filterable.git",
|
||||
"rev": "7c5b8c72779997f2b17d12ce478ff81e7ddda285",
|
||||
"dependencies": [
|
||||
"arrays",
|
||||
"either",
|
||||
"foldable-traversable",
|
||||
"identity",
|
||||
"lists",
|
||||
"ordered-collections"
|
||||
]
|
||||
},
|
||||
"foldable-traversable": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/purescript/purescript-foldable-traversable.git",
|
||||
@@ -6819,6 +6878,19 @@
|
||||
"prelude"
|
||||
]
|
||||
},
|
||||
"lcg": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/purescript/purescript-lcg.git",
|
||||
"rev": "67c6c6483a563a59ae036d9dca0f1be2835326a5",
|
||||
"dependencies": [
|
||||
"effect",
|
||||
"integers",
|
||||
"maybe",
|
||||
"partial",
|
||||
"prelude",
|
||||
"random"
|
||||
]
|
||||
},
|
||||
"lists": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/purescript/purescript-lists.git",
|
||||
@@ -6890,6 +6962,24 @@
|
||||
"maybe"
|
||||
]
|
||||
},
|
||||
"ordered-collections": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/purescript/purescript-ordered-collections.git",
|
||||
"rev": "313ec0c3556854cd4e4752a77a86b102fc41ad05",
|
||||
"dependencies": [
|
||||
"arrays",
|
||||
"foldable-traversable",
|
||||
"gen",
|
||||
"lists",
|
||||
"maybe",
|
||||
"partial",
|
||||
"prelude",
|
||||
"st",
|
||||
"tailrec",
|
||||
"tuples",
|
||||
"unfoldable"
|
||||
]
|
||||
},
|
||||
"orders": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/purescript/purescript-orders.git",
|
||||
@@ -6958,6 +7048,68 @@
|
||||
"tuples"
|
||||
]
|
||||
},
|
||||
"quickcheck": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/purescript/purescript-quickcheck.git",
|
||||
"rev": "bf5029f97e6c0d7552d3a08d2ab793a19e2c5e3d",
|
||||
"dependencies": [
|
||||
"arrays",
|
||||
"console",
|
||||
"control",
|
||||
"effect",
|
||||
"either",
|
||||
"enums",
|
||||
"exceptions",
|
||||
"foldable-traversable",
|
||||
"gen",
|
||||
"identity",
|
||||
"integers",
|
||||
"lazy",
|
||||
"lcg",
|
||||
"lists",
|
||||
"maybe",
|
||||
"newtype",
|
||||
"nonempty",
|
||||
"numbers",
|
||||
"partial",
|
||||
"prelude",
|
||||
"record",
|
||||
"st",
|
||||
"strings",
|
||||
"tailrec",
|
||||
"transformers",
|
||||
"tuples",
|
||||
"unfoldable"
|
||||
]
|
||||
},
|
||||
"quickcheck-laws": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/purescript-contrib/purescript-quickcheck-laws.git",
|
||||
"rev": "04f00fb78d88f38a2f2bb73b75f97ce5bf5624fc",
|
||||
"dependencies": [
|
||||
"enums",
|
||||
"quickcheck"
|
||||
]
|
||||
},
|
||||
"random": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/purescript/purescript-random.git",
|
||||
"rev": "9540bc965a9596da02fefd9949418bb19c92533a",
|
||||
"dependencies": [
|
||||
"effect",
|
||||
"integers"
|
||||
]
|
||||
},
|
||||
"record": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/purescript/purescript-record.git",
|
||||
"rev": "c89cd1ada6b636692571fc374196b1c39c4c9f70",
|
||||
"dependencies": [
|
||||
"functions",
|
||||
"prelude",
|
||||
"unsafe-coerce"
|
||||
]
|
||||
},
|
||||
"refs": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/purescript/purescript-refs.git",
|
||||
|
||||
@@ -3,16 +3,23 @@ package:
|
||||
strict: true
|
||||
pedanticPackages: true
|
||||
dependencies:
|
||||
- arrays
|
||||
- bifunctors
|
||||
- bigints
|
||||
- console
|
||||
- control
|
||||
- effect
|
||||
- either
|
||||
- exceptions
|
||||
- filterable
|
||||
- foldable-traversable
|
||||
- lists
|
||||
- maybe
|
||||
- parsing
|
||||
- partial
|
||||
- prelude
|
||||
- st
|
||||
- strings
|
||||
- transformers
|
||||
- tuples
|
||||
name: project
|
||||
|
||||
34
src/Day2.purs
Normal file
34
src/Day2.purs
Normal file
@@ -0,0 +1,34 @@
|
||||
module Day2 where
|
||||
|
||||
import Prelude
|
||||
import Data.String as String
|
||||
|
||||
import Control.Monad.Error.Class (liftEither)
|
||||
import Data.Bifunctor (lmap)
|
||||
import Data.Filterable (filter)
|
||||
import Data.Foldable (sum)
|
||||
import Day2.Id as Id
|
||||
import Effect (Effect)
|
||||
import Effect.Console as Console
|
||||
import Effect.Exception (error)
|
||||
|
||||
main :: Effect Unit
|
||||
main = do
|
||||
Console.log "=== Day 2 ==="
|
||||
run exampleInput <#> ("[exampl] " <> _) >>= Console.log
|
||||
run fullInput <#> ("[actual] " <> _) >>= Console.log
|
||||
Console.log ""
|
||||
|
||||
run :: String -> Effect String
|
||||
run input = do
|
||||
idRanges <- liftEither $ lmap (error <<< show) $ Id.parseIds input
|
||||
let
|
||||
ids = Id.flat idRanges
|
||||
invalidIds = filter (not Id.isValid) ids
|
||||
pure $ show $ sum invalidIds
|
||||
|
||||
exampleInput :: String
|
||||
exampleInput = """11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124"""
|
||||
|
||||
fullInput :: String
|
||||
fullInput = String.trim """385350926-385403705,48047-60838,6328350434-6328506208,638913-698668,850292-870981,656-1074,742552-796850,4457-6851,138-206,4644076-4851885,3298025-3353031,8594410816-8594543341,396-498,1558-2274,888446-916096,12101205-12154422,2323146444-2323289192,37-57,101-137,46550018-46679958,79-96,317592-341913,495310-629360,33246-46690,14711-22848,1-17,2850-4167,3723700171-3723785996,190169-242137,272559-298768,275-365,7697-11193,61-78,75373-110112,425397-451337,9796507-9899607,991845-1013464,77531934-77616074"""
|
||||
104
src/Day2/Id.purs
Normal file
104
src/Day2/Id.purs
Normal file
@@ -0,0 +1,104 @@
|
||||
module Day2.Id where
|
||||
|
||||
import Prelude
|
||||
|
||||
import Control.Alt ((<|>))
|
||||
import Control.Monad.Rec.Class (Step(..), tailRec)
|
||||
import Control.Monad.ST as ST
|
||||
import Control.Monad.ST.Ref as ST.Ref
|
||||
import Data.Array (any)
|
||||
import Data.Array as Array
|
||||
import Data.Array.ST as ST.Array
|
||||
import Data.BigInt (BigInt)
|
||||
import Data.BigInt as BigInt
|
||||
import Data.Either (Either, either)
|
||||
import Data.Foldable (all)
|
||||
import Data.List as List
|
||||
import Data.Maybe (Maybe(..), fromJust)
|
||||
import Data.String as String
|
||||
import Data.Tuple.Nested (type (/\), (/\))
|
||||
import Parsing (ParseError(..), fail, region, runParser) as Parse
|
||||
import Parsing (Parser)
|
||||
import Parsing.Combinators (sepBy) as Parse
|
||||
import Parsing.String (regex, string) as Parse
|
||||
import Partial.Unsafe (unsafeCrashWith, unsafePartial)
|
||||
|
||||
type Id = BigInt
|
||||
type IdRange = Id /\ Id
|
||||
|
||||
flat :: Array IdRange -> Array Id
|
||||
flat ranges = do
|
||||
start /\ end <- ranges
|
||||
bigintRange start end
|
||||
|
||||
parseIds :: String -> Either Parse.ParseError (Array IdRange)
|
||||
parseIds = flip Parse.runParser parser
|
||||
|
||||
parser :: Parser String (Array IdRange)
|
||||
parser =
|
||||
let
|
||||
ctx :: forall a. String -> Parser String a -> Parser String a
|
||||
ctx c = Parse.region \(Parse.ParseError m pos) -> Parse.ParseError (c <> " > " <> m) pos
|
||||
|
||||
idRange = (/\) <$> (ctx "first id" $ bigint <* Parse.string "-") <*> (ctx "second id" bigint)
|
||||
in
|
||||
List.toUnfoldable <$> Parse.sepBy (ctx "id range" idRange) (Parse.string ",")
|
||||
|
||||
isValid :: Id -> Boolean
|
||||
isValid id =
|
||||
let
|
||||
idS = BigInt.toString id
|
||||
len = String.length idS
|
||||
candidates = Array.range 1 (len / 2)
|
||||
isRepeated cand
|
||||
| len `mod` cand /= 0 = false
|
||||
| otherwise =
|
||||
let
|
||||
strs = strChunks cand idS
|
||||
first = unsafePartial fromJust $ Array.head strs
|
||||
rest = unsafePartial fromJust $ Array.tail strs
|
||||
in
|
||||
all (_ == first) rest
|
||||
valid _ = not any isRepeated candidates
|
||||
|
||||
-- part 1
|
||||
_naiive =
|
||||
let
|
||||
init = String.take (String.length idS / 2) idS
|
||||
tail = String.drop (String.length idS / 2) idS
|
||||
in
|
||||
init /= tail
|
||||
in
|
||||
len <= 1 || valid unit
|
||||
|
||||
bigint :: Parser String BigInt
|
||||
bigint = do
|
||||
section <- bigintRegex <|> Parse.fail "Expected Int"
|
||||
case BigInt.fromString section of
|
||||
Nothing -> Parse.fail "Expected Int"
|
||||
Just x -> pure x
|
||||
|
||||
bigintRegex :: Parser String String
|
||||
bigintRegex =
|
||||
either unsafeCrashWith identity $ Parse.regex pattern mempty
|
||||
where
|
||||
pattern = "[+-]?[0-9]+"
|
||||
|
||||
-- might use a small amount of memory lol
|
||||
bigintRange :: BigInt -> BigInt -> Array BigInt
|
||||
bigintRange a b = ST.run do
|
||||
n <- ST.Ref.new a
|
||||
array <- ST.Array.new
|
||||
void $ ST.Array.push a array
|
||||
ST.while (ST.Ref.read n <#> (_ < b)) do
|
||||
n' <- ST.Ref.modify (_ + BigInt.fromInt 1) n
|
||||
ST.Array.push n' array
|
||||
ST.Array.freeze array
|
||||
|
||||
strChunks :: Int -> String -> Array String
|
||||
strChunks n s =
|
||||
let
|
||||
go ("" /\ as) = Done as
|
||||
go (s' /\ as) = Loop $ String.drop n s' /\ (as <> [String.take n s'])
|
||||
in
|
||||
tailRec go (s /\ [])
|
||||
@@ -3,8 +3,10 @@ module Main where
|
||||
import Prelude
|
||||
|
||||
import Day1 as Day1
|
||||
import Day2 as Day2
|
||||
import Effect (Effect)
|
||||
|
||||
main :: Effect Unit
|
||||
main = do
|
||||
Day1.main
|
||||
Day2.main
|
||||
|
||||
Reference in New Issue
Block a user