This commit is contained in:
orion kindel
2025-12-02 15:33:01 -06:00
parent 0eec34737d
commit 1d23bef4bd
5 changed files with 299 additions and 0 deletions

View File

@@ -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",

View File

@@ -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
View 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
View 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 /\ [])

View File

@@ -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