Skip to content

Commit

Permalink
Day 23 Part 2 solution
Browse files Browse the repository at this point in the history
  • Loading branch information
dancarroll committed Dec 23, 2024
1 parent a05b61e commit e6f217d
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 1 deletion.
3 changes: 2 additions & 1 deletion bin/day23.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import 'package:aoc_2024/lib.dart';
import 'package:aoc_2024/day23/part_1.dart' as part1;
import 'package:aoc_2024/day23/part_2.dart' as part2;

Future<void> main(List<String> arguments) async {
await runDay(
day: Day.day23,
part1: part1.calculate,
part2: (_) => Future.value(0),
part2: part2.calculate,
);
}
95 changes: 95 additions & 0 deletions lib/day23/part_2.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import 'dart:io';

import 'package:collection/collection.dart';

import 'shared.dart';

/// Represents an interconnected group of computers.
final class Group {
final Set<String> computers;
String? _cachedString;

Group(String name, String connection) : computers = {} {
computers.add(name);
computers.add(connection);
}

Group.fromSet(this.computers);

/// Returns true if the group contains the specified pair of computers.
bool containsPair(String a, String b) =>
computers.contains(a) && computers.contains(b);

/// Add a new computer to this group.
void add(String name) {
computers.add(name);
_cachedString = null;
}

@override
bool operator ==(Object other) {
if (other is Group) {
return toString() == other.toString();
}
return false;
}

@override
int get hashCode => toString().hashCode;

@override
String toString() {
_cachedString ??= computers.sorted().join(',');
return _cachedString!;
}
}

/// Continuing from part 1, rather than finding all groups of three computers,
/// find the largest interconnected group.
///
/// Return the sorted, comma-separated list of all computers in that group.
Future<String> calculate(File file) async {
final network = await loadData(file);

Set<Group> groups = {};
for (final computer in network.entries) {
final connections = computer.value;
for (final connection in connections) {
final existingGroups = groups
.where((g) => g.containsPair(computer.key, connection))
.toList();
// If we haven't encountered this pair before, add a new group
// and continue to the new pair.
if (existingGroups.isEmpty) {
final group = Group(computer.key, connection);
groups.add(group);
continue;
}

// For each group containing this pair, check which potential connections
// are also interconnected with this group.
for (final existingGroup in existingGroups) {
var allPotentialConnections = existingGroup.computers
.toList()
.fold(<String>{}, (e, v) => e.union(network[v]!)).where(
(c) => c != computer.key && c != connection);

// For all potential connections, if they connect to every computer in
// the group, create a new group with the existing members plus the
// new connection.
for (final potentialConnection in allPotentialConnections) {
if (existingGroup.computers
.every((c) => network[c]!.contains(potentialConnection))) {
groups.add(Group.fromSet(
{...existingGroup.computers, potentialConnection}));
}
}
}
}
}

return groups
.sorted((g1, g2) => g2.computers.length.compareTo(g1.computers.length))
.first
.toString();
}
21 changes: 21 additions & 0 deletions lib/day23/shared.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,24 @@ Future<Map<String, Set<String>>> loadData(File file) async {

return network;
}

Map<String, Set<String>> loadNetwork(List<String> lines) {
final network = <String, Set<String>>{};
for (final line in lines) {
final computers = line.split('-');
assert(computers.length == 2, 'Only two names expected');

network.update(computers[0], (l) => l..add(computers[1]),
ifAbsent: () => {computers[1]});
network.update(computers[1], (l) => l..add(computers[0]),
ifAbsent: () => {computers[0]});
}

return network;
}

Future<List<String>> loadFile(File file, int skipLine) async {
final lines = await file.readAsLines();
lines.removeAt(skipLine);
return lines;
}
10 changes: 10 additions & 0 deletions test/day23_test.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:aoc_2024/lib.dart';
import 'package:aoc_2024/day23/part_1.dart' as part1;
import 'package:aoc_2024/day23/part_2.dart' as part2;
import 'package:test/test.dart';

void main() {
Expand All @@ -12,6 +13,10 @@ void main() {
test('part1', () async {
expect(await part1.calculate(file), 7);
});

test('part2', () async {
expect(await part2.calculate(file), 'co,de,ka,ta');
});
});

group('real data', tags: 'real-data', () {
Expand All @@ -21,5 +26,10 @@ void main() {
test('part1', () async {
expect(await part1.calculate(file), 1151);
});

test('part2', () async {
expect(await part2.calculate(file),
'ar,cd,hl,iw,jm,ku,qo,rz,vo,xe,xm,xv,ys');
});
});
}

0 comments on commit e6f217d

Please sign in to comment.