Skip to content

Commit f631be4

Browse files
authored
Merge pull request #67 from hypirion/jn-day-07
Day 7 in Standard ML
2 parents eb9561d + b3254ac commit f631be4

File tree

3 files changed

+87
-5
lines changed

3 files changed

+87
-5
lines changed

days/day-07/solutions/day07.sml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
use "../../../util.sml";
2+
3+
local
4+
structure SS = StringSet
5+
structure SM = StringMap
6+
in
7+
8+
fun toDigit c = Char.ord c - Char.ord #"0"
9+
fun toRule s =
10+
let
11+
val (parent, rawChildClauses) =
12+
case String.substring (s, 0, String.size s - 1)
13+
>> String.fields (fn c => c = #" ")
14+
>> splitWith (fn x => x = "contain") of
15+
[a, b] => (String.concatWith " " a, String.concatWith " " b)
16+
| _ => raise Fail $ "bad input: " ^ s
17+
(* sigh *)
18+
fun clause 0 (#" " :: rest) = clause 0 rest
19+
| clause 1 (#" " :: name) = SOME (1, (String.implode name) ^ "s")
20+
| clause n (#" " :: name) = SOME (n, String.implode name)
21+
| clause n (#"n" :: _) = NONE
22+
| clause n (x :: rest) = clause (n*10 + toDigit x) rest
23+
| clause _ _ = NONE
24+
25+
val childClauses = String.fields (fn c => c = #",") rawChildClauses
26+
>> List.mapPartial (clause 0 o String.explode)
27+
in
28+
(parent, childClauses)
29+
end
30+
31+
fun solve1 clauses =
32+
let fun consRule s p c = SM.updateWithDefault [] (fn xs => p :: xs) c s
33+
fun invertRules ((p, cs), s) = List.foldl (fn ((_, c), s) => consRule s p c) s cs
34+
val rules = List.foldl invertRules SM.empty clauses
35+
fun dfs n seen [] = n
36+
| dfs n seen (x :: xs) =
37+
if SS.contains x seen then
38+
dfs n seen xs
39+
else
40+
let val children = getOpt (SM.lookup x rules, [])
41+
in
42+
dfs (n + 1) (SS.insert x seen) (children @ xs)
43+
end
44+
in
45+
dfs ~1 SS.empty ["shiny gold bags"]
46+
end
47+
48+
fun solve2 clauses =
49+
let val rules = SM.fromList clauses
50+
fun sum ((count, name), acc) = acc + count + count * dfs name
51+
and dfs k = List.foldl sum 0 $ valOf $ SM.lookup k rules
52+
in
53+
dfs "shiny gold bags"
54+
end
55+
56+
fun main () =
57+
let val input = TextIO.inputAll TextIO.stdIn
58+
>> String.tokens (fn c => c = #"\n")
59+
>> List.map toRule
60+
in
61+
println $ Int.toString $ solve1 input;
62+
println $ Int.toString $ solve2 input
63+
end
64+
end

days/day-07/test.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ D=$(dirname $(realpath $0))
66

77
echo ""
88
echo "--- Day 7: Handy Haversacks ---"
9-
$D/../../languages/node.sh $D/input.txt $D/output.txt $D/solutions/day07.mjs
9+
$D/../../languages/sml.sh $D/input.txt $D/output.txt $D/solutions/day07.sml
1010
$D/../../languages/python.sh $D/input.txt $D/output.txt $D/solutions/day07.stektpotet.py
11+
$D/../../languages/node.sh $D/input.txt $D/output.txt $D/solutions/day07.mjs
1112
echo ""

util.sml

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@ fun println x = print $ x ^ "\n"
66
fun splitWith pred list =
77
let
88
fun acc done [] [] = done
9-
| acc done last [] = last :: done
9+
| acc done last [] = List.rev last :: done
1010
| acc done last (x :: xs) =
1111
if pred x then
12-
acc (last :: done) [] xs
12+
acc (List.rev last :: done) [] xs
1313
else
1414
acc done (x :: last) xs
1515
in
16-
acc [] [] list
16+
List.rev $ acc [] [] list
1717
end
1818

1919
fun foldl' f (x :: xs) = List.foldl f x xs
@@ -22,6 +22,7 @@ fun foldl' f (x :: xs) = List.foldl f x xs
2222
val listSum = List.foldl (op +) 0
2323
val listProduct = List.foldl (op *) 1
2424

25+
2526
signature ORD =
2627
sig
2728
type t
@@ -37,6 +38,8 @@ sig
3738
val empty : 'a Coll
3839
val lookup : K -> 'a Coll -> 'a option
3940
val insert : K -> 'a -> 'a Coll -> 'a Coll
41+
val update : ('a option -> 'a) -> K -> 'a Coll -> 'a Coll
42+
val updateWithDefault : 'a -> ('a -> 'a) -> K -> 'a Coll -> 'a Coll
4043
val foldl : (K * 'a * 'b -> 'b) -> 'b -> 'a Coll -> 'b
4144
val size : 'a Coll -> int
4245
val fromList : (K * 'a) list -> 'a Coll
@@ -83,6 +86,13 @@ fun insert k v s =
8386
T (B, a, y, b)
8487
end
8588

89+
fun update f k coll =
90+
insert k (f $ lookup k coll) coll
91+
92+
fun updateWithDefault default f k coll =
93+
update (fn v => f $ getOpt (v, default)) k coll
94+
95+
8696
fun foldl f acc E = acc
8797
| foldl f acc (T(_, a, (k, v), b)) =
8898
let
@@ -97,7 +107,6 @@ fun size coll = foldl (fn (_, _, n) => n + 1) 0 coll
97107
fun fromList list = List.foldl (fn ((k, v), s) => insert k v s) empty list
98108
end
99109

100-
101110
signature SET =
102111
sig
103112
type V
@@ -136,3 +145,11 @@ structure CharMap = Map(
136145
end)
137146

138147
structure CharSet = Set(CharMap)
148+
149+
structure StringMap = Map(
150+
struct
151+
type t = string
152+
val cmp = String.compare
153+
end)
154+
155+
structure StringSet = Set(StringMap)

0 commit comments

Comments
 (0)