package day_10
//import "core:container/queue"
import "core:log"
import "core:os"
import "core:strconv"
import "core:strings"
Machine :: struct {
lights: int `fmt:"10b"`,
combinations: []int,
buttons: [][]int,
joltages: []int,
}
Input :: struct {
machines: []Machine,
}
Result1 :: int
Result2 :: int
// --- Input --- //
print_input :: proc(input: Input) {
log.infof("%v", input)
}
parse_input_file :: proc(filepath: string) -> Input {
input: Input
raw_data, ok := os.read_entire_file_from_filename(filepath)
if !ok {
panic("oh no, could not read file")
}
defer delete(raw_data)
lines, err := strings.split_lines(strings.trim_space(string(raw_data)))
if err != .None {
panic("oh no, failed splitting into lines")
}
defer delete(lines)
input.machines = make([]Machine, len(lines))
for line, i in lines {
chunks := strings.split(line, " ")
defer delete(chunks)
machine: Machine
for l, l_i in chunks[0][1:len(chunks[0]) - 1] {
machine.lights |= (1 if l == '#' else 0) << uint(l_i)
}
machine.buttons = make([][]int, len(chunks) - 2)
machine.combinations = make([]int, len(chunks) - 2)
for c, c_i in chunks[1:len(chunks) - 1] {
num_splits := strings.count(c, ",")
machine.buttons[c_i] = make([]int, len(c) - 2 - num_splits)
val: int
s_i: int
for s in c[1:len(c) - 1] {
if s == ',' {
continue
}
b := s - '0'
val |= 1 << uint(b)
machine.buttons[c_i][s_i] = int(b)
s_i += 1
}
machine.combinations[c_i] = val
log.debugf("%s -> %10b [%d]", c, val, val)
log.debugf("%s -> %v", c, machine.buttons[c_i])
}
joltages := strings.split(chunks[len(chunks) - 1][1:len(chunks[len(chunks) - 1]) - 1], ",")
log.debugf("%v", joltages)
defer delete(joltages)
machine.joltages = make([]int, len(joltages))
for j, j_i in joltages {
machine.joltages[j_i] = strconv.parse_int(j) or_else 0
}
input.machines[i] = machine
}
log.debugf("%v", input.machines)
return input
}
free_input :: proc(input: ^Input) {
for machine in input.machines {
for button in machine.buttons {
delete(button)
}
delete(machine.buttons)
delete(machine.combinations)
delete(machine.joltages)
}
delete(input.machines)
}
// --- Input --- //
// --- Helpers --- //
bit_count := proc(x: int) -> int {
x := x
count: int
for x != 0 {
count += int(x & 1)
x >>= 1
}
return count
}
// --- Helpers --- //
// --- Task 1 --- //
run_task1 :: proc(input: Input) -> Result1 {
result: Result1
for machine in input.machines {
m := uint(len(machine.combinations))
best := 9999
total_subsets := 1 << m
for subset in 0 ..< total_subsets {
presses := bit_count(subset)
if presses >= best {
continue
}
state: int
for i in 0 ..< m {
if ((subset >> i) & 1) != 0 {
state ~= machine.combinations[i]
}
}
if state == machine.lights {
best = presses
}
}
log.debugf("%10b -> %d", machine.lights, best)
result += best
}
return result
}
print_result1 :: proc(result: Result1) {
log.infof("Task 1: %d", result)
}
// --- Task 1 --- //
// --- Task 2 --- //
State :: struct {
counters: [10]int,
}
run_task2 :: proc(input: Input) -> Result2 {
result: Result2
/*q: queue.Queue(State)
queue.init(&q, 128)
defer queue.destroy(&q)
next: for machine, m_i in input.machines {
log.debugf("machine %v", m_i)
queue.clear(&q)
start: State
queue.push_back(&q, start)
dist := make(map[[10]int]int)
defer delete(dist)
visited := make(map[[10]int]bool)
defer delete(visited)
for queue.len(q) > 0 {
current := queue.pop_front(&q)
done := true
for j, j_i in machine.joltages {
if current.counters[j_i] != j {
done = false
break
}
}
if done {
log.infof("FOUND %d", dist[current.counters])
result += dist[current.counters]
continue next
}
for button in machine.buttons {
next: [10]int
copy(next[:], current.counters[:])
for b in button {
next[b] += 1
}
exceeds: bool
for j, j_i in machine.joltages {
if next[j_i] > j {
exceeds = true
break
}
}
if exceeds {
continue
}
if _, ok := visited[next]; !ok {
visited[next] = true
dist[next] = dist[current.counters] + 1
queue.push_back(&q, State{counters = next})
}
}
}
}*/
return result
}
print_result2 :: proc(result: Result2) {
log.infof("Task 2: %d", result)
}
// --- Task 2 --- //
run :: proc() {
input := parse_input_file("input/day_10.txt")
defer free_input(&input)
result1 := run_task1(input)
print_result1(result1)
result2 := run_task2(input)
print_result2(result2)
}