feat: part 1-1
This commit is contained in:
commit
f40862fc1e
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
*.ibc
|
||||||
|
*.o
|
||||||
|
|
||||||
|
.direnv/
|
||||||
|
|
||||||
|
build/
|
||||||
|
*.*~
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Kiana Sheibani
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
18
advent-of-code-2024.ipkg
Normal file
18
advent-of-code-2024.ipkg
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
package advent-of-code-2024
|
||||||
|
version = 0.0
|
||||||
|
|
||||||
|
brief = "Advent of Code 2024"
|
||||||
|
|
||||||
|
authors = "Kiana Sheibani"
|
||||||
|
license = "MIT"
|
||||||
|
|
||||||
|
sourcedir = "src"
|
||||||
|
|
||||||
|
langversion >= 0.6.0
|
||||||
|
|
||||||
|
executable = advent-of-code-2024
|
||||||
|
main = Main
|
||||||
|
modules = Main, Utils, AllDays,
|
||||||
|
Data.Problem,
|
||||||
|
Day1.Part1
|
||||||
|
|
98
flake.lock
Normal file
98
flake.lock
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1731533236,
|
||||||
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idris": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": [
|
||||||
|
"flake-utils"
|
||||||
|
],
|
||||||
|
"idris-emacs-src": "idris-emacs-src",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1733093802,
|
||||||
|
"narHash": "sha256-bUjIOLocDumq6XdJ5mAuS4t3SMht9JKVYZ88BSQSiGs=",
|
||||||
|
"owner": "idris-lang",
|
||||||
|
"repo": "Idris2",
|
||||||
|
"rev": "d176ab4108a42cd8423466a0e2450e17cc693b7c",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "idris-lang",
|
||||||
|
"repo": "Idris2",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idris-emacs-src": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1666078909,
|
||||||
|
"narHash": "sha256-oYNHFIpcrFfPb4sXJwEBFKeH+PB4AGCrAFrfBrSTCeo=",
|
||||||
|
"owner": "redfish64",
|
||||||
|
"repo": "idris2-mode",
|
||||||
|
"rev": "3bcb52a65c488f31c99d20f235f6050418a84c9d",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "redfish64",
|
||||||
|
"repo": "idris2-mode",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1719371271,
|
||||||
|
"narHash": "sha256-G3tm/ttP6PxnrrpCYIi4VBpJdGrwqr2pqRKuZlvTg2s=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "267d115a04e93a3487d3c2c26e3af5704a0144cc",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"idris": "idris"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
30
flake.nix
Normal file
30
flake.nix
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
description = "Advent of Code 2024 in Idris2";
|
||||||
|
|
||||||
|
inputs.flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
inputs.idris = {
|
||||||
|
url = "github:idris-lang/Idris2";
|
||||||
|
inputs.flake-utils.follows = "flake-utils";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, idris, flake-utils }:
|
||||||
|
flake-utils.lib.eachDefaultSystem (system:
|
||||||
|
let
|
||||||
|
npkgs = import idris.inputs.nixpkgs { inherit system; };
|
||||||
|
idrisPkgs = idris.packages.${system};
|
||||||
|
buildIdris = idris.buildIdris.${system};
|
||||||
|
pkgs = buildIdris {
|
||||||
|
ipkgName = "advent-of-code-2024";
|
||||||
|
src = ./.;
|
||||||
|
idrisLibraries = [];
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
packages.default = pkgs.executable;
|
||||||
|
devShell = npkgs.mkShell {
|
||||||
|
buildInputs = [ idrisPkgs.idris2 npkgs.rlwrap ];
|
||||||
|
shellHook = ''
|
||||||
|
alias idris2="rlwrap -s 1000 idris2 --no-banner"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
3
src/AllDays.idr
Normal file
3
src/AllDays.idr
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
module AllDays
|
||||||
|
|
||||||
|
import public Day1.Part1
|
88
src/Data/Problem.idr
Normal file
88
src/Data/Problem.idr
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
module Data.Problem
|
||||||
|
|
||||||
|
import Data.List1
|
||||||
|
import Data.String
|
||||||
|
import Data.Maybe
|
||||||
|
import Data.SortedMap
|
||||||
|
import Language.Reflection
|
||||||
|
|
||||||
|
%language ElabReflection
|
||||||
|
%default total
|
||||||
|
|
||||||
|
|
||||||
|
public export
|
||||||
|
data Part = Part1 | Part2
|
||||||
|
|
||||||
|
public export
|
||||||
|
Eq Part where
|
||||||
|
Part1 == Part1 = True
|
||||||
|
Part1 == Part2 = False
|
||||||
|
Part2 == Part2 = True
|
||||||
|
Part2 == Part1 = False
|
||||||
|
|
||||||
|
public export
|
||||||
|
Ord Part where
|
||||||
|
compare Part1 Part1 = EQ
|
||||||
|
compare Part1 Part2 = LT
|
||||||
|
compare Part2 Part2 = EQ
|
||||||
|
compare Part2 Part1 = GT
|
||||||
|
|
||||||
|
public export
|
||||||
|
record Problem where
|
||||||
|
constructor Pr
|
||||||
|
day : Nat
|
||||||
|
part : Part
|
||||||
|
|
||||||
|
public export
|
||||||
|
Eq Problem where
|
||||||
|
Pr d1 p1 == Pr d2 p2 = d1 == d2 && p1 == p2
|
||||||
|
|
||||||
|
public export
|
||||||
|
Ord Problem where
|
||||||
|
compare (Pr d1 p1) (Pr d2 p2) = compare d1 d2 <+> compare p1 p2
|
||||||
|
|
||||||
|
|
||||||
|
public export
|
||||||
|
partNat : Part -> Nat
|
||||||
|
partNat Part1 = 1
|
||||||
|
partNat Part2 = 2
|
||||||
|
|
||||||
|
public export
|
||||||
|
parsePart : String -> Maybe Part
|
||||||
|
parsePart "1" = Just Part1
|
||||||
|
parsePart "2" = Just Part2
|
||||||
|
parsePart _ = Nothing
|
||||||
|
|
||||||
|
public export
|
||||||
|
parseProblem : String -> Maybe Problem
|
||||||
|
parseProblem str =
|
||||||
|
let (day ::: [part]) = split (=='-') str
|
||||||
|
| _ => Nothing
|
||||||
|
dayInt = parseInteger day
|
||||||
|
dayNat = cast <$> filter (> 0) dayInt
|
||||||
|
in Pr <$> dayNat <*> parsePart part
|
||||||
|
|
||||||
|
|
||||||
|
||| Generate a list of all problems given the latest problem solved.
|
||||||
|
public export
|
||||||
|
allProblems : (latest : Problem) -> List Problem
|
||||||
|
allProblems (Pr day' part') = do
|
||||||
|
day <- [1..day']
|
||||||
|
part <- filter (<= part') [Part1, Part2]
|
||||||
|
pure $ Pr day part
|
||||||
|
|
||||||
|
--- REFLECTION
|
||||||
|
|
||||||
|
public export
|
||||||
|
fetchSolution : Problem -> Elab (String -> String)
|
||||||
|
fetchSolution (Pr day part) = do
|
||||||
|
let name =
|
||||||
|
NS (MkNS ["Part" ++ show (partNat part),
|
||||||
|
"Day" ++ show day]) `{solution}
|
||||||
|
check `(\s => show (~(IVar EmptyFC name) s))
|
||||||
|
<|> fail "\{show name} does not exist as a valid solution"
|
||||||
|
|
||||||
|
public export
|
||||||
|
fetchAllSols : (latest : Problem) -> Elab (SortedMap Problem (String -> String))
|
||||||
|
fetchAllSols pr =
|
||||||
|
fromList <$> traverse (\p => (p,) <$> fetchSolution p) (allProblems pr)
|
39
src/Day1/Part1.idr
Normal file
39
src/Day1/Part1.idr
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
module Day1.Part1
|
||||||
|
|
||||||
|
import Data.List
|
||||||
|
import Data.List1
|
||||||
|
import Data.String
|
||||||
|
import Data.Maybe
|
||||||
|
import Utils
|
||||||
|
|
||||||
|
%default total
|
||||||
|
|
||||||
|
|
||||||
|
--- PARSING
|
||||||
|
|
||||||
|
parseLine : String -> Maybe (Nat, Nat)
|
||||||
|
parseLine str =
|
||||||
|
let [n1,n2] = filter (/="") $ forget $ split (==' ') str
|
||||||
|
| _ => Nothing
|
||||||
|
in (,) <$> parseNat n1 <*> parseNat n2
|
||||||
|
|
||||||
|
parseInput : String -> Maybe (List Nat, List Nat)
|
||||||
|
parseInput = map unzip . traverse (parseLine) . lines
|
||||||
|
|
||||||
|
|
||||||
|
--- UTILS
|
||||||
|
|
||||||
|
distance : Nat -> Nat -> Nat
|
||||||
|
distance x y =
|
||||||
|
cast $ abs $ natToInteger x - natToInteger y
|
||||||
|
|
||||||
|
|
||||||
|
--- SOLUTION
|
||||||
|
|
||||||
|
export
|
||||||
|
solution : String -> Maybe Nat
|
||||||
|
solution input = do
|
||||||
|
(list1, list2) <- parseInput input
|
||||||
|
let list1 = sort list1
|
||||||
|
list2 = sort list2
|
||||||
|
pure $ sum $ zipWith distance list1 list2
|
46
src/Main.idr
Normal file
46
src/Main.idr
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
module Main
|
||||||
|
|
||||||
|
import Data.List1
|
||||||
|
import Data.Maybe
|
||||||
|
import Data.String
|
||||||
|
import Data.SortedMap
|
||||||
|
import Data.SortedMap.Dependent
|
||||||
|
import Data.Problem
|
||||||
|
|
||||||
|
import Language.Reflection
|
||||||
|
|
||||||
|
import AllDays
|
||||||
|
|
||||||
|
%language ElabReflection
|
||||||
|
|
||||||
|
|
||||||
|
||| The latest problem that has been solved.
|
||||||
|
-- NOTE: UPDATE AFTER EACH SOLUTION
|
||||||
|
latest : Problem
|
||||||
|
latest = Pr 1 Part1
|
||||||
|
|
||||||
|
|
||||||
|
solMap : SortedMap Problem (String -> String)
|
||||||
|
solMap = %runElab fetchAllSols latest
|
||||||
|
|
||||||
|
getInput : IO String
|
||||||
|
getInput = go ""
|
||||||
|
where
|
||||||
|
go : String -> IO String
|
||||||
|
go str = do
|
||||||
|
line <- getLine
|
||||||
|
if trim line == "\\"
|
||||||
|
then pure str
|
||||||
|
else go (str ++ "\n" ++ line)
|
||||||
|
|
||||||
|
main : IO ()
|
||||||
|
main = do
|
||||||
|
putStr "Solution: "
|
||||||
|
Just pr <- parseProblem <$> getLine
|
||||||
|
| Nothing => putStrLn "Invalid solution ID"
|
||||||
|
let Just func = lookup pr solMap
|
||||||
|
| Nothing => putStrLn "This part is not implemented yet!"
|
||||||
|
|
||||||
|
putStrLn "Input (end with \\):"
|
||||||
|
input <- trim <$> getInput
|
||||||
|
putStrLn $ func input
|
10
src/Utils.idr
Normal file
10
src/Utils.idr
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
module Utils
|
||||||
|
|
||||||
|
import Data.Maybe
|
||||||
|
import Data.String
|
||||||
|
|
||||||
|
%default total
|
||||||
|
|
||||||
|
export
|
||||||
|
parseNat : String -> Maybe Nat
|
||||||
|
parseNat = map cast . filter (> 0) . parseInteger
|
Loading…
Reference in a new issue