debug_it :: false;
solve_day13 :: (test: bool) {
contents := read_entire_file(ifx test then "inputs/day13_test.txt" else "inputs/day13.txt");
sections := split(contents, "\n\n");
part1 := 0;
signal_lists: [..]Signal;
for section: sections {
section_lines := split(section, "\n");
parse_info: Parse_Info = .{
data = section_lines[0],
cursor = 0,
};
list\_left := parse_list(*parse_info);
parse_info = .{
data = section_lines[1],
cursor = 0,
};
list_right := parse_list(*parse_info);
array_add(*signal_lists, list_left);
array_add(*signal_lists, list_right);
if is_right_ordered(list_left, list_right) < 0 {
if debug_it print("Left side is smaller\n\n");
if debug_it print("Adding %\n", it_index + 1);
part1 += it_index + 1;
} else {
if debug_it print("Right side is smaller\n\n");
}
}
integer_divider := Signal.{
signal_type = .INTEGER,
integer = 2,
};
divider_1: Signal = .{
signal_type = .LIST,
};
divider_1_2: Signal = .{
signal_type = .LIST,
};
array_add(*divider_1_2.list, integer_divider);
array_add(*divider_1.list, divider_1_2);
divider_2: Signal = .{
signal_type = .LIST,
};
divider_2_2: Signal = .{
signal_type = .LIST,
};
defer {
array_free(divider_1_2.list);
array_free(divider_2_2.list);
array_free(divider_1.list);
array_free(divider_2.list);
}
integer_divider.integer = 6;
array_add(*divider_2_2.list, integer_divider);
array_add(*divider_2.list, divider_2_2);
array_add(*signal_lists, divider_1);
array_add(*signal_lists, divider_2);
quick_sort(signal_lists, is_right_ordered);
print("Part 1: %\n", part1);
part2 := 1;
for signal_lists {
if it.list.count == 1 && it.list[0].list.count == 1 && (it.list[0].list[0].integer == 2 || it.list[0].list[0].integer == 6) {
part2 *= (it_index + 1);
}
}
print("Part 2: %\n", part2);
}
is_right_ordered :: (left: Signal, right: Signal) -> s64 {
if (left.signal_type == .LIST && right.signal_type == .INTEGER) ||
(left.signal_type == .INTEGER && right.signal_type == .LIST) {
signal := Signal.{
signal_type = .LIST,
};
defer array_free(signal.list);
if left.signal_type == .INTEGER {
array_add(*signal.list, left);
if debug_it print("Mixed type; convert left side to [%] and retry comparison\n", left.integer);
if debug_it print("Compare ");
if debug_it print_list(signal);
if debug_it print(" vs ");
if debug_it print_list(right);
if debug_it print("\n");
return is_right_ordered(signal, right);
} else {
array_add(*signal.list, right);
if debug_it print("Mixed type; convert right side to [%] and retry comparison\n", right.integer);
if debug_it print("Compare ");
if debug_it print_list(left);
if debug_it print(" vs ");
if debug_it print_list(signal);
if debug_it print("\n");
return is_right_ordered(left, signal);
}
} else if left.signal_type == .INTEGER {
if debug_it print("Compare % vs %\n", left.integer, right.integer);
return left.integer - right.integer;
} else {
cursor := 0;
if debug_it print("Compare ");
if debug_it print_list(left);
if debug_it print(" vs ");
if debug_it print_list(right);
if debug_it print("\n");
while cursor < left.list.count {
if right.list.count <= cursor return 1;
res := is_right_ordered(left.list[cursor], right.list[cursor]);
if res != 0 return res;
cursor += 1;
}
if left.list.count == right.list.count return 0;
return -1;
}
return 0;
}
parse_list :: (parse_info: *Parse_Info) -> Signal {
parse_info.cursor += 1;
list: Signal;
list.signal_type = .LIST;
while true {
if is_digit(parse_info.data[parse_info.cursor]) {
array_add(*list.list, parse_integer(parse_info));
continue;
} else if parse_info.data[parse_info.cursor] == #char "," {
parse_info.cursor += 1;
continue;
} else if parse_info.data[parse_info.cursor] == #char "[" {
array_add(*list.list, parse_list(parse_info));
continue;
} else if parse_info.data[parse_info.cursor] == #char "]" {
parse_info.cursor += 1;
break;
} else {
assert(false, "Bad character: %", parse_info.data[parse_info.cursor]);
}
}
return list;
}
parse_integer :: (parse_info: *Parse_Info) -> Signal {
start := parse_info.cursor;
while is_digit(parse_info.data[parse_info.cursor]) {
parse_info.cursor += 1;
}
return .{
signal_type = .INTEGER,
integer = string_to_int(slice(parse_info.data, start, parse_info.cursor - start), 10, s64),
};
}
print_list :: (list: Signal) {
print("[");
for list.list {
if it.signal_type == .LIST {
print_list(it);
} else if it.signal_type == .INTEGER {
print("%", it.integer);
} else {
assert(false, "Unknown signal type '%'", it.signal_type);
}
if it_index != list.list.count - 1 print(",");
}
print("]");
}
Signal_Type :: enum {
INTEGER :: 0;
LIST :: 1;
}
Signal :: struct {
signal_type: Signal_Type;
integer: s64;
list: [..]Signal;
}
Parse_Info :: struct {
cursor: s64;
data: string;
}