Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions src/main/kotlin/me/peckb/aoc/_2024/calendar/day23/Day23.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package me.peckb.aoc._2024.calendar.day23

import javax.inject.Inject
import me.peckb.aoc.generators.InputGenerator.InputGeneratorFactory

class Day23 @Inject constructor(
private val generatorFactory: InputGeneratorFactory,
) {
fun partOne(filename: String) = generatorFactory.forFile(filename).readAs(::connection) { input ->
val connections = findFriends(input)
val triplets = mutableSetOf<Set<String>>()

findCommonFriend(connections) { me, them, ourFriends ->
ourFriends.forEach { ourFriend -> triplets.add(setOf(me, them, ourFriend)) }
}

triplets.count { group -> group.any { it.startsWith('t') } }
}

fun partTwo(filename: String) = generatorFactory.forFile(filename).readAs(::connection) { input ->
val connections = findFriends(input)
val friends = mutableSetOf<Set<String>>()

findCommonFriend(connections) { me, them, ourFriends ->
if (ourFriends.isNotEmpty()) {
val everyFriend = ourFriends.all { maybeMutual ->
ourFriends.minus(maybeMutual).all {
(maybeMutual in connections[it]!!)
}
}
if (everyFriend) {
friends.add(ourFriends.plus(me).plus(them))
}
}
}

friends.maxBy { it.size }.toList().sorted().joinToString(",")
}

private fun connection(line: String) : Pair<String, String> {
return line.split("-").let { (a, b) -> a to b }
}

private fun findFriends(input: Sequence<Pair<String, String>>): MutableMap<String, Set<String>> {
val connections = mutableMapOf<String, Set<String>>()

input.forEach { (c1, c2) ->
connections.merge(c1, setOf(c2)) { a, b -> a + b }
connections.merge(c2, setOf(c1)) { a, b -> a + b }
}

return connections
}

private fun findCommonFriend(connections: Map<String, Set<String>>, handleFriends: (String, String, Set<String>) -> Unit) {
val keys = connections.keys.toList()
(0 until keys.size - 2).forEach { i ->
val me = keys[i]
val myFriends = connections[me]!!

(i + 1 until keys.size - 1).forEach { j ->
val them = keys[j]
val theirFriends = connections[them]!!

if (me in theirFriends) {
handleFriends(me, them, myFriends.intersect(theirFriends))
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
## [Day 23: LAN Party](https://adventofcode.com/2024/day/23)
2 changes: 2 additions & 0 deletions src/test/kotlin/me/peckb/aoc/_2024/TestDayComponent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import me.peckb.aoc._2024.calendar.day19.Day19Test
import me.peckb.aoc._2024.calendar.day20.Day20Test
import me.peckb.aoc._2024.calendar.day21.Day21Test
import me.peckb.aoc._2024.calendar.day22.Day22Test
import me.peckb.aoc._2024.calendar.day23.Day23Test
import javax.inject.Singleton
import me.peckb.aoc.DayComponent
import me.peckb.aoc.InputModule
Expand Down Expand Up @@ -52,4 +53,5 @@ internal interface TestDayComponent : DayComponent {
fun inject(day20Test: Day20Test)
fun inject(day21Test: Day21Test)
fun inject(day22Test: Day22Test)
fun inject(day23Test: Day23Test)
}
32 changes: 32 additions & 0 deletions src/test/kotlin/me/peckb/aoc/_2024/calendar/day23/Day23Test.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package me.peckb.aoc._2024.calendar.day23

import javax.inject.Inject

import me.peckb.aoc._2024.DaggerTestDayComponent
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test

internal class Day23Test {
@Inject
lateinit var day23: Day23

@BeforeEach
fun setup() {
DaggerTestDayComponent.create().inject(this)
}

@Test
fun testDay23PartOne() {
assertEquals(998, day23.partOne(DAY_23))
}

@Test
fun testDay23PartTwo() {
assertEquals("cc,ff,fh,fr,ny,oa,pl,rg,uj,wd,xn,xs,zw", day23.partTwo(DAY_23))
}

companion object {
private const val DAY_23: String = "advent-of-code-input/2024/day23.input"
}
}
Loading