-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathb.test.ts
162 lines (135 loc) · 5 KB
/
b.test.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import { expect, test } from "bun:test";
const charMap = (s: string): Map<string, number> => {
const memo = new Map<string, number>();
for (const char of s.split("")) {
const amount = memo.get(char);
memo.set(char, amount ? amount + 1 : 1);
}
return memo;
};
const handByType = {
"five-of-a-kind": (s: string): boolean => {
const map = charMap(s);
const jokerCount = map.get("J");
if (!jokerCount || jokerCount === 5) {
return map.size === 1;
}
const hasFive = Array.from(map.entries()).some(([key, amount]) => amount + jokerCount === 5);
return map.size === 2 && hasFive;
},
"four-of-a-kind": (s: string): boolean => {
const map = charMap(s);
const jokerCount = map.get("J");
if (!jokerCount) {
const hasFour = Array.from(map.values()).some((amount) => amount === 4);
return map.size === 2 && hasFour;
}
const hasFour = Array.from(map.values()).some((amount) => amount + jokerCount === 4);
return map.size === 3 && hasFour;
},
"full-house": (s: string): boolean => {
const map = charMap(s);
const jokerCount = map.get("J");
if (!jokerCount) {
const hasThree = Array.from(map.values()).some((amount) => amount === 3);
return map.size === 2 && hasThree;
}
const hasThree = Array.from(map.entries()).some(([key, amount]) => amount + jokerCount === 3);
return map.size === 3 && hasThree;
},
"three-of-a-kind": (s: string): boolean => {
const map = charMap(s);
const jokerCount = map.get("J");
if (!jokerCount) {
const hasThree = Array.from(map.values()).some((amount) => amount === 3);
return map.size === 3 && hasThree;
}
const hasThree = Array.from(map.entries()).some(([key, amount]) => amount + jokerCount === 3);
return map.size === 4 && hasThree;
},
"two-pair": (s: string): boolean => {
const map = charMap(s);
const jokerCount = map.get("J");
if (!jokerCount) {
const hasTwo = Array.from(map.values()).some((value) => value === 2);
return map.size === 3 && hasTwo;
}
const hasTwo = Array.from(map.entries()).some(([key, amount]) => amount + jokerCount === 2);
return map.size === 4 && hasTwo;
},
"one-pair": (s: string): boolean => {
const map = charMap(s);
const jokerCount = map.get("J");
if (!jokerCount) {
const hasTwo = Array.from(map.values()).some((value) => value === 2);
return map.size === 4 && hasTwo;
}
const hasTwo = Array.from(map.values()).some((value) => value + jokerCount === 2);
return map.size === 5 && hasTwo;
},
high: (s: string): boolean => {
const map = charMap(s);
return map.size === 5;
},
};
const order = "AKQT98765432J";
function solution(input: string) {
const hands = input.split("\n").map((line) => {
const [hand, scoreString] = line.split(" ");
return [hand, Number(scoreString)] as const;
});
const indexByType = Object.fromEntries(Object.entries(handByType).map(([key, _]) => [key, [] as number[]]));
const indexes = hands.reduce((acc, [hand], index) => {
for (const key in handByType) {
if (handByType[key as keyof typeof handByType](hand)) {
acc[key].push(index);
break;
}
}
return acc;
}, indexByType);
let rank = 1;
const ans = Object.values(indexes)
.filter((val) => val.length > 0)
.reverse()
.flatMap((arr) => {
if (arr.length === 1) {
const score = hands[arr[0]][1];
return score * rank++;
}
const sorted = arr.slice().sort((a, b) => {
const [handsA] = hands[a];
const [handsB] = hands[b];
for (let i = 0; i < handsA.length; i++) {
if (handsA[i] === handsB[i]) {
continue;
}
if (order.indexOf(handsA[i]) > order.indexOf(handsB[i])) {
return -1;
}
return 1;
}
return 0;
});
return sorted.map((idx) => {
const score = hands[idx][1];
return score * rank++;
});
})
.reduce((acc, val, arr) => acc + val, 0);
return ans;
}
test("example", async () => {
const file = Bun.file(`${import.meta.dir}/example.txt`);
const input = await file.text();
const actual = solution(input);
const expected = 5905;
expect(actual).toBe(expected);
});
test("puzzle input", async () => {
const file = Bun.file(`${import.meta.dir}/input.txt`);
const input = await file.text();
const actual = solution(input);
const expected = 249356515;
expect(actual).toBe(expected);
});