Add Elm day 2

main
Bram 2023-12-28 12:05:45 +01:00
parent 2cf9264509
commit edcc3caf91
7 changed files with 1227 additions and 108 deletions

View File

@ -11,6 +11,7 @@
"elm/browser": "1.0.2",
"elm/core": "1.0.5",
"elm/html": "1.0.0",
"elm/parser": "1.1.0",
"elm/svg": "1.0.1",
"mdgriffith/elm-ui": "1.1.8",
"miniBill/elm-fast-dict": "1.1.0"

File diff suppressed because it is too large Load Diff

View File

@ -2,16 +2,16 @@ module Main exposing (main)
import Browser
import Element
import Tools.Colors as C
import Widget
import Widget.Material as Material
import Widget.Material.Typography as Typography
import Element.Background
import Element.Input
import Task
import Puzzles.Day1 as Day1
import Puzzles.Day2 as Day2
import Task
import Tools.Colors as C
import Widget
import Widget.Customize
import Widget.Material as Material
import Widget.Material.Typography as Typography
main : Program () Model Msg
@ -31,17 +31,22 @@ type alias Model =
, output2 : Calculating
}
type Calculating
= Outcome String
| Calculating
| InvalidInput String
| NoInput
type Window
= Home
| Day Int
type alias Puzzle = String -> Result String String
type alias Puzzle =
String -> Result String String
getFunctions : Window -> ( Puzzle, Puzzle )
getFunctions window =
@ -50,15 +55,19 @@ getFunctions window =
( always <| Err "There is no puzzle for this page!"
, always <| Err "There is no puzzle for this page!"
)
Day 1 ->
( Day1.puzzle1, Day1.puzzle2 )
Day 2 ->
( Day2.puzzle1, Day2.puzzle2 )
_ ->
( always <| Err "This puzzle has no implementation yet!"
, always <| Err "This puzzle has no implementation yet!"
)
init : () -> ( Model, Cmd Msg )
init () =
( { view = Home
@ -89,16 +98,17 @@ update msg model =
}
, Cmd.none
)
OnInput input ->
( { model
| input = input
, output1 = Calculating
, output2 = Calculating
| input = input
, output1 = Calculating
, output2 = Calculating
}
, if input == model.input then
Cmd.none
else
else
Cmd.batch
[ Task.succeed input
|> Task.map (getFunctions model.view |> Tuple.first)
@ -108,48 +118,47 @@ update msg model =
|> Task.perform (Calculate2 model.view)
]
)
DoNothing ->
( model, Cmd.none )
Calculate1 w (Ok s) ->
if w /= model.view then
( model, Cmd.none )
else
( { model | output1 = Outcome s }
, Cmd.none
)
Calculate1 w (Err s) ->
if w /= model.view then
( model, Cmd.none )
else
( { model | output1 = InvalidInput s }
, Cmd.none
)
Calculate2 w (Ok s) ->
if w /= model.view then
( model, Cmd.none )
else
( { model | output2 = Outcome s }
, Cmd.none
)
Calculate2 w (Err s) ->
if w /= model.view then
( model, Cmd.none )
else
( { model | output2 = InvalidInput s }
, Cmd.none
)
subscriptions : Model -> Sub Msg
subscriptions model =
Sub.none
@ -160,7 +169,7 @@ view model =
{ title = "Document Title"
, body =
[ Widget.menuBar
( Material.menuBar palette )
(Material.menuBar palette)
{ title =
"aoc2023"
|> Element.text
@ -180,10 +189,10 @@ view model =
|> Element.width
, Element.alignTop
]
( List.map
(\(window, text) ->
(List.map
(\( window, text ) ->
Widget.fullBleedItem
( Material.fullBleedItem palette )
(Material.fullBleedItem palette)
{ text = text
, onPress = Just (ChangeWindow window)
, icon = always Element.none
@ -203,32 +212,34 @@ view model =
, Element.padding 20
, Element.spacing 20
]
( case model.view of
(case model.view of
Home ->
[ "Advent of Code 2023"
|> Element.text
|> Element.el Typography.h3
]
Day i ->
[ [ "Using the following input for day " ++ String.fromInt i ++ ": "
|> Element.text
[ [ "Using the following input for day "
++ String.fromInt i
++ ": "
|> Element.text
, Element.Input.multiline
[ Element.fill
[ Element.fill
|> Element.maximum 500
|> Element.height
, Element.scrollbarX
]
{ onChange = OnInput
, text = model.input
, placeholder =
"Insert puzzle input here..."
|> Element.text
|> Element.Input.placeholder []
|> Just
, label = Element.Input.labelHidden "input"
, spellcheck = False
}
, Element.scrollbarX
]
{ onChange = OnInput
, text = model.input
, placeholder =
"Insert puzzle input here..."
|> Element.text
|> Element.Input.placeholder []
|> Just
, label = Element.Input.labelHidden "input"
, spellcheck = False
}
]
, case model.output1 of
Outcome s ->
@ -243,12 +254,12 @@ view model =
, spellcheck = False
}
]
Calculating ->
[ "Calculating part 1..."
|> Element.text
]
InvalidInput s ->
[ "INVALID INPUT FOR PART 1"
|> Element.text
@ -261,7 +272,7 @@ view model =
, spellcheck = False
}
]
NoInput ->
List.singleton Element.none
, case model.output2 of
@ -277,12 +288,12 @@ view model =
, spellcheck = False
}
]
Calculating ->
[ "Calculating part 2..."
|> Element.text
]
InvalidInput s ->
[ "INVALID INPUT FOR PART 2"
|> Element.text
@ -295,7 +306,7 @@ view model =
, spellcheck = False
}
]
NoInput ->
List.singleton Element.none
]
@ -308,10 +319,12 @@ view model =
|> List.singleton
}
picker : C.Picker
picker =
C.get C.Trichromatic C.LightMode
palette : Material.Palette
palette =
C.defaultPalette picker

View File

@ -1,5 +1,6 @@
module Puzzles.Day1 exposing (puzzle1, puzzle2)
puzzle1 : String -> Result String String
puzzle1 input =
input
@ -10,25 +11,25 @@ puzzle1 input =
case items of
head :: tail ->
Ok (calibrationValue head tail)
[] ->
Err i
)
|> List.foldl
(\value sum ->
case (value, sum) of
(_, Err _) ->
case ( value, sum ) of
( _, Err _ ) ->
sum
(Err i, Ok _) ->
( Err i, Ok _ ) ->
Err ("Line" ++ (String.fromInt <| i + 1) ++ "does not contain any numbers")
(Ok a, Ok b) ->
( Ok a, Ok b ) ->
Ok (a + b)
)
(Ok 0)
|> Result.map String.fromInt
puzzle1Nums : String -> List Int
puzzle1Nums s =
@ -37,13 +38,15 @@ puzzle1Nums s =
|> List.map String.fromChar
|> List.filterMap String.toInt
calibrationValue : Int -> List Int -> Int
calibrationValue head tail =
tail
|> List.reverse
|> List.head
|> Maybe.withDefault head
|> (+) ( head * 10 )
|> (+) (head * 10)
puzzle2 : String -> Result String String
puzzle2 input =

150
elm/src/Puzzles/Day2.elm Normal file
View File

@ -0,0 +1,150 @@
module Puzzles.Day2 exposing (puzzle1, puzzle2)
import Parser as P exposing ((|.), (|=), Parser)
type alias Game =
{ number : Int, games : List RGB }
type alias RGB =
{ red : Int, green : Int, blue : Int }
maxAllowed : RGB
maxAllowed =
{ red = 12, green = 13, blue = 14 }
puzzle1 : String -> Result String String
puzzle1 input =
case P.run parser input of
Err a ->
Debug.log "Output" a
|> always (Err "Invalid input")
Ok g ->
g
|> List.map
(\{ number, games } ->
let
isLegal : Bool
isLegal =
List.all
(\rgb ->
List.all
(\f -> f rgb <= f maxAllowed)
[ .red, .green, .blue ]
)
games
in
if isLegal then
number
else
0
)
|> List.sum
|> String.fromInt
|> Ok
puzzle2 : String -> Result String String
puzzle2 input =
case P.run parser input of
Err a ->
Debug.log "Output" a
|> always (Err "Invalid input")
-- 179502 too high
Ok g ->
g
|> List.map
(\{ games } ->
let
getMaximumFor : (RGB -> Int) -> Int
getMaximumFor f =
games
|> List.map f
|> List.maximum
|> Maybe.withDefault 0
in
[ .red, .green, .blue ]
|> List.map getMaximumFor
|> List.product
)
|> List.sum
|> String.fromInt
|> Ok
parser : Parser (List Game)
parser =
andOneMore
{ separator = "\n"
, item = gameParser
}
gameParser : Parser Game
gameParser =
P.succeed Game
|. P.keyword "Game"
|. P.spaces
|= P.int
|. P.symbol ":"
|. P.spaces
|= rgbLines
rgbLines : Parser (List RGB)
rgbLines =
andOneMore
{ separator = ";"
, item = rgbParser
}
rgbParser : Parser RGB
rgbParser =
P.succeed (List.foldl (<|) (RGB 0 0 0))
|= andOneMore
{ separator = ","
, item = rgbStmt
}
rgbStmt : Parser (RGB -> RGB)
rgbStmt =
P.succeed (|>)
|= P.int
|. P.spaces
|= P.oneOf
[ P.succeed (\i rgb -> { rgb | red = i })
|. P.keyword "red"
, P.succeed (\i rgb -> { rgb | blue = i })
|. P.keyword "blue"
, P.succeed (\i rgb -> { rgb | green = i })
|. P.keyword "green"
]
andOneMore : { separator : String, item : Parser a } -> Parser (List a)
andOneMore { separator, item } =
P.loop []
(\xs ->
P.succeed (\x state -> state (x :: xs))
|= item
|. onlySpaces
|= P.oneOf
[ P.succeed P.Loop
|. P.token separator
, P.succeed P.Done
]
|. onlySpaces
)
onlySpaces : Parser ()
onlySpaces =
P.chompWhile (\c -> c == ' ')

11
elm/src/Puzzles/DayX.elm Normal file
View File

@ -0,0 +1,11 @@
module Puzzles.DayX exposing (puzzle1, puzzle2)
puzzle1 : String -> Result String String
puzzle1 _ =
Err "Not implemented yet!"
puzzle2 : String -> Result String String
puzzle2 _ =
Err "Not implemented yet!"

View File

@ -409,6 +409,7 @@ transparent =
Color.rgba 0 0 0 0
-- PRIMARY COLOR