Skip to content

Commit cb63751

Browse files
committed
Merge branch 'main' into add-deno
2 parents 854185a + 0f9a55d commit cb63751

File tree

8 files changed

+304
-4
lines changed

8 files changed

+304
-4
lines changed

days/day-06/test.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ $D/../../languages/go.sh $D/input.txt $D/output.txt $D/solutions/day06.stekt
1010
$D/../../languages/go.sh $D/input.txt $D/output.txt $D/solutions/tholok97.go
1111
$D/../../languages/python.sh $D/input.txt $D/output.txt $D/solutions/one-liner.stektpotet.py
1212
$D/../../languages/sml.sh $D/input.txt $D/output.txt $D/solutions/day06.sml
13+
$D/../../languages/python.sh $D/input.txt $D/output.txt $D/solutions/one-liner.stektpotet.py
1314
$D/../../languages/python.sh $D/input.txt $D/output.txt $D/solutions/day06.stektpotet.py
1415
$D/../../languages/python.sh $D/input.txt $D/output.txt $D/solutions/day06.preng.py
1516
$D/../../languages/deno.sh $D/input.txt $D/output.txt $D/solutions/day06.ts

days/day-07/solutions/.keep

Whitespace-only changes.

days/day-07/solutions/day07.mjs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { readFileSync } from "fs";
2+
import { resolve } from "path";
3+
4+
const STANDARD_IN = 0
5+
const input = readFileSync(STANDARD_IN)
6+
.toString();
7+
8+
// (light red) bags contain (1) (bright white) bag, (2) muted yellow bags.
9+
// /^([\w]+ [\w]+) bags contain (.*)[.]$/g
10+
11+
const bags = [
12+
...input.matchAll(/([\w]+ [\w]+) bags contain (\d (.*)[.]|no other bags)/g)
13+
].map(([,color, rest]) => {
14+
15+
const bags_inside = ([
16+
...rest.matchAll(/(\d) ([\w]+ [\w]+)/g)
17+
])
18+
.map(([,count, color]) => ({count, color}))
19+
20+
return ({color, bags_inside})
21+
})
22+
23+
const COLOR_SHINY_GOLD = "shiny gold";
24+
25+
26+
27+
// --- Part 1 ----
28+
// Recursively find shiny golden bags
29+
function findShinyGoldenBag(bag_refs) {
30+
if (bag_refs.length === 0) {
31+
return 0;
32+
}
33+
34+
const resolved_bags = bag_refs.map(bag => bags.find(({color}) => color === bag.color))
35+
36+
for (const { color, bags_inside } of resolved_bags) {
37+
if (color === COLOR_SHINY_GOLD) {
38+
return 1;
39+
} else {
40+
const found = findShinyGoldenBag(bags_inside);
41+
if (found) {
42+
return 1;
43+
} else {
44+
continue;
45+
}
46+
}
47+
}
48+
return 0;
49+
}
50+
51+
const bagContainingShinyGoldeBagCount = bags
52+
.reduce((count, bag) => count + findShinyGoldenBag(bag.bags_inside), 0);
53+
54+
55+
// --- Part 2 ---
56+
// Recursively count bags inside
57+
function countBagsInside(bag_refs) {
58+
if (bag_refs.length === 0) {
59+
return 1;
60+
}
61+
62+
const resolved_bags = bag_refs
63+
.map(bag => [bag.count, bags.find(({color}) => color === bag.color)])
64+
65+
66+
const count = resolved_bags
67+
.reduce((acc, [bag_count, bag]) => acc + bag_count * countBagsInside(bag.bags_inside), 1)
68+
69+
return count;
70+
}
71+
72+
const shinyGoldenBag = bags.find(({color}) => color === COLOR_SHINY_GOLD);
73+
74+
75+
const shinyGoldBagInsideCount = countBagsInside(shinyGoldenBag.bags_inside) - 1;
76+
77+
78+
console.log(bagContainingShinyGoldeBagCount)
79+
console.log(shinyGoldBagInsideCount)
80+
81+
82+
83+

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
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import fileinput
2+
3+
def line_processor(l: str):
4+
k, vals = l.split(" bags contain ")
5+
vals = vals.split()
6+
vals = [(vals[i], ' '.join(vals[i+1:i + 3])) for i in range(0, len(vals), 4)]
7+
return k, vals
8+
9+
rules = dict(line_processor(line) for line in fileinput.input())
10+
11+
candidates = set()
12+
last_len = len(candidates)
13+
while True:
14+
for k, c in rules.items():
15+
for n, e in c:
16+
if e == 'shiny gold' or e in candidates:
17+
candidates.add(k)
18+
if len(candidates) == last_len:
19+
break
20+
last_len = len(candidates)
21+
22+
print(len(candidates))
23+
24+
def recurse(bag_rule) -> int:
25+
count = 0
26+
for num, contained_bag in bag_rule:
27+
if num == 'no':
28+
continue
29+
count += int(num) + int(num) * recurse(rules[contained_bag])
30+
return count
31+
32+
print(recurse(rules['shiny gold']))

days/day-07/solutions/tholok97.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"fmt"
6+
"os"
7+
"regexp"
8+
"strconv"
9+
)
10+
11+
type pair struct {
12+
amount int
13+
color string
14+
}
15+
16+
func main() {
17+
scanner := bufio.NewScanner(os.Stdin)
18+
19+
rules := make(map[string][]pair)
20+
21+
for scanner.Scan() {
22+
ruleString := scanner.Text()
23+
color, contained := parseRule(ruleString)
24+
rules[color] = contained
25+
}
26+
27+
sum := 0
28+
29+
for key := range rules {
30+
if contains(rules, key, "shiny gold") {
31+
sum++
32+
}
33+
}
34+
35+
fmt.Println(sum)
36+
37+
// subtract one cost as we care about the cost of the bags **within** the
38+
// initial bag
39+
fmt.Println(colorCost(rules, "shiny gold") - 1)
40+
}
41+
42+
func parseRule(s string) (color string, contained []pair) {
43+
reBagColor := regexp.MustCompile(`^([\w ]*) bags contain`)
44+
reBagColorMatches := reBagColor.FindStringSubmatch(s)
45+
color = reBagColorMatches[1]
46+
reNoOther := regexp.MustCompile(`no other bags`)
47+
48+
if reNoOther.MatchString(s) {
49+
// No bags are contained, return early
50+
return color, make([]pair, 0)
51+
}
52+
53+
reBagContains := regexp.MustCompile(`(,? (\d+) ([\w ]*) bags?)`)
54+
reBagContainsMatches := reBagContains.FindAllStringSubmatch(s, -1)
55+
contained = make([]pair, len(reBagContainsMatches))
56+
57+
for i, matches := range reBagContainsMatches {
58+
amount, err := strconv.Atoi(matches[2])
59+
60+
if err != nil {
61+
panic("misbehaving number string >:(")
62+
}
63+
64+
contained[i] = pair{
65+
amount: amount, // don't care about this one
66+
color: matches[3],
67+
}
68+
}
69+
70+
return color, contained
71+
}
72+
73+
// does 'color' contain 'target'?
74+
// assume X can't contain X
75+
func contains(rules map[string][]pair, color, target string) bool {
76+
for _, contained := range rules[color] {
77+
if contained.color == target {
78+
return true
79+
}
80+
81+
if contains(rules, contained.color, target) {
82+
return true
83+
}
84+
}
85+
return false
86+
}
87+
88+
// what's the total cost of 'color'?
89+
func colorCost(rules map[string][]pair, color string) int {
90+
// myself
91+
cost := 1
92+
93+
for _, contained := range rules[color] {
94+
// + the cost of each of my bags
95+
cost += contained.amount * colorCost(rules, contained.color)
96+
}
97+
98+
return cost
99+
}

days/day-07/test.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,8 @@ D=$(dirname $(realpath $0))
66

77
echo ""
88
echo "--- Day 7: Handy Haversacks ---"
9+
$D/../../languages/sml.sh $D/input.txt $D/output.txt $D/solutions/day07.sml
10+
$D/../../languages/go.sh $D/input.txt $D/output.txt $D/solutions/tholok97.go
11+
$D/../../languages/python.sh $D/input.txt $D/output.txt $D/solutions/day07.stektpotet.py
12+
$D/../../languages/node.sh $D/input.txt $D/output.txt $D/solutions/day07.mjs
913
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)