Skip to content

Commit

Permalink
Add day 23 of year 2024 🤶
Browse files Browse the repository at this point in the history
  • Loading branch information
letelete committed Dec 23, 2024
1 parent 0b0a734 commit b224365
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 0 deletions.
21 changes: 21 additions & 0 deletions 2024/days/day-23/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Benchmark

```
Platform: darwin arm64
CPU: Apple M3 Pro 11 Cores
Memory: 18.00 GB
```

## Sample 1

| part | time (~) | μs |
| ---- | -------- | ------------------ |
| 1 | 15.51ms | 15.505959000000004 |
| 2 | 0.67ms | 0.6694579999999917 |

## Answer

| part | time (~) | μs |
| ---- | -------- | ------------------ |
| 1 | 22.17ms | 22.172333999999992 |
| 2 | 8.70ms | 8.701333000000005 |
32 changes: 32 additions & 0 deletions 2024/days/day-23/in.sample.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
kh-tc
qp-kh
de-cg
ka-co
yn-aq
qp-ub
cg-tb
vc-aq
tb-ka
wh-tc
yn-cg
kh-ub
ta-co
de-co
tc-td
tb-wq
wh-td
ta-ka
td-qp
aq-cg
wq-ub
ub-vc
de-ta
wq-aq
wq-vc
wh-yn
ka-de
kh-ta
co-tc
wh-qp
tb-vc
td-yn
124 changes: 124 additions & 0 deletions 2024/days/day-23/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
function parse(source) {
return source
.trim()
.split('\n')
.map((line) => line.split('-'));
}

function buildNetworkGraph(relations) {
const graph = new Map();

relations.forEach(([a, b]) => {
if (!graph.has(a)) {
graph.set(a, new Set());
}
if (!graph.has(b)) {
graph.set(b, new Set());
}
graph.get(a).add(b);
graph.get(b).add(a);
});

return graph;
}

function localeComparator(a, b) {
return a.localeCompare(b);
}

function intersection(a, b) {
return new Set([...a].filter((value) => b.has(value)));
}

function difference(a, b) {
return new Set([...a].filter((value) => !b.has(value)));
}

function union(a, b) {
return new Set([...a, ...b]);
}

function findGroupsOfThree(graph, node) {
const result = new Set();

graph.get(node).forEach((neighbor, _, nodeNeighbors) => {
intersection(nodeNeighbors, graph.get(neighbor)).forEach(
(commonNeighbor) => {
result.add(
[node, neighbor, commonNeighbor].sort(localeComparator).join(',')
);
}
);
});

return result;
}

function findAllGroupsOfThree(graph) {
return [...graph.keys()].reduce((groups, node) => {
findGroupsOfThree(graph, node).forEach((group) => groups.add(group));
return groups;
}, new Set());
}

function findLargestGroup(graph) {
/**
* Performs Randomized Selection to select a pivot vertex for the Bron-Kerbosh algorithm.
*/
const choosePivot = (P, X) => {
const candidates = [...union(P, X)];
return candidates[Math.floor(candidates.length / 2)];
};

/**
* An implementation of the Bron-Kerbosh algorithm with Pivoting.
* @see {@link https://www.wikiwand.com/en/articles/Bron%E2%80%93Kerbosch_algorithm}
*/
const findAllMaximalCliques = (
N,
R = new Set(),
P = new Set(N.keys()),
X = new Set(),
result = []
) => {
if (!P.size && !X.size) {
result.push(R);
return result;
}

const u = choosePivot(P, X);
const Nu = graph.get(u);
difference(P, Nu).forEach((v) => {
const Nv = graph.get(v);
findAllMaximalCliques(
N,
union(R, new Set([v])),
intersection(P, Nv),
intersection(X, Nv),
result
);

P.delete(v);
X.add(v);
});

return result;
};

const cliques = findAllMaximalCliques(graph);
const largestCliqueSize = Math.max(...cliques.map((clique) => clique.size));
return cliques.find((clique) => clique.size === largestCliqueSize);
}

function part1(data) {
const graph = buildNetworkGraph(data);
return [...findAllGroupsOfThree(graph)].filter((g) => g.match(/t[a-z]/))
.length;
}

function part2(data) {
const graph = buildNetworkGraph(data);
return [...findLargestGroup(graph)].sort(localeComparator).join(',');
}

module.exports = { parse, part1, part2 };

0 comments on commit b224365

Please sign in to comment.