day12 part 2

This commit is contained in:
m 2023-12-22 22:33:46 -05:00
parent 9a2731feca
commit 9354548658

250
src/day12/part2.pas Normal file
View File

@ -0,0 +1,250 @@
{$mode objfpc}
{$RANGECHECKS ON}
program day12part1;
uses sysutils;
type
int64array = array of int64;
stringarray = array of string;
function sum(l: array of int64; start: int64 = 0): int64;
var
i: int64;
begin
sum := 0;
for i := start to length(l) - 1 do
sum := l[i] + sum;
end;
function split_to_int(s: string; delim: char): int64array ;
var
i, last_delim, count : int64;
c: char;
begin
{ there will always be at least one number }
count := 1;
{ count number of delimeters }
for c in s do
begin
if c = delim then
count := count + 1;
end;
{ allocate enough space for count}
setlength(split_to_int, count);
count := 0;
last_delim := 0;
{ second interation }
for i := 1 to length(s) do
begin
{ if this is a delimeter }
if s[i] = delim then
begin
{ add the value between this delimiter and the previous one to splitted }
val(
copy(s, last_delim + 1, i - last_delim - 1), split_to_int[count]
);
count := count + 1;
last_delim := i;
end;
end;
{ don't forget the final value }
val(
copy(s, last_delim + 1, length(s) - last_delim), split_to_int[count]
);
end;
function split_to_str(s: string; delim: char): stringarray;
var
i, last_delim, count : int64;
c: char;
begin
{ there will always be at least one number }
count := 1;
{ count number of delimeters }
for c in s do
begin
if c = delim then
count := count + 1;
end;
{ allocate enough space for count}
setlength(split_to_str, count);
count := 0;
last_delim := 0;
{ second interation }
for i := 1 to length(s) do
begin
{ if this is a delimeter }
if s[i] = delim then
begin
{ add the value between this delimiter and the previous one to splitted }
split_to_str[count] := copy(s, last_delim + 1, i - last_delim - 1);
count := count + 1;
last_delim := i;
end;
end;
{ don't forget the final value }
split_to_str[count] := copy(s, last_delim + 1, length(s) - last_delim)
end;
function will_fit(s: string; idx, length: int64): boolean;
var
i: int64;
begin
will_fit := true;
for i := idx to idx + length - 1 do
begin
if s[i] = '.' then
begin
will_fit := false;
break;
end;
end;
end;
function all_after_not(s: string; idx: int64; c: char): boolean;
var
i: int64;
begin
all_after_not := true;
for i := idx to length(s) do
begin
if s[i] = c then
begin
all_after_not := false;
break;
end;
end;
end;
var
cache: array[0..1000, 0..1000] of int64;
procedure clear_cache();
var
i, j: int64;
begin
for i := 0 to 1000 do
begin
for j:= 0 to 1000 do
begin
cache[i, j] := -1;
end;
end;
end;
function possibilties(s: string; l: array of int64; start_s: int64 = 1; start_l: int64 = 0): int64;
var
i: int64;
begin
possibilties := 0;
{ clear the cache if we r starting }
if start_l = 0 then
clear_cache();
{ return cache if we have the value }
if cache[start_s, start_l] <> -1 then
begin
possibilties := cache[start_s, start_l];
exit;
end;
{ if there is only one spring left then }
if length(l) - start_l = 1 then
begin
{ check every possibility }
for i := start_s to length(s) - l[start_l] + 1 do
begin
{ if it will fit here, then it's valid }
if will_fit(s, i, l[start_l]) and all_after_not(s, i + l[start_l], '#') then
possibilties := possibilties + 1;
{ if we pass by a #, then it's not valid anymore as the # won't be filled }
if s[i] = '#' then
break;
end;
end
else
begin
for i := start_s to length(s) - sum(l, start_l) - length(l) + start_l + 2 do
begin
{ if it will fit and we aren't skipping a '#', recursively find possibilities }
if will_fit(s, i, l[start_l]) and (s[i + l[start_l]] <> '#') then
possibilties := possibilties + possibilties(s, l, i + l[start_l] + 1, start_l + 1);
{ if we pass by a #, then it's not valid anymore as the # won't be filled }
if s[i] = '#' then
break;
end;
end;
cache[start_s, start_l] := possibilties;
end;
function duplicate_int_array(arr: int64array; times: int64): int64array;
var
i: int64;
begin
setlength(duplicate_int_array, length(arr) * times);
for i := 0 to length(arr) * times - 1 do
begin
duplicate_int_array[i] := arr[i mod length(arr)];
end;
end;
var
s: string;
pattern: array of int64;
split: array of string;
file_: text;
total: int64;
begin
assign(file_, 'resources/day12.txt');
reset(file_);
total := 0;
while not EOF(file_) do
begin
readln(file_, s);
split := split_to_str(s, ' ');
pattern := split_to_int(split[1], ',');
//total := total + possibilties(split[0], pattern);
total := total + possibilties(split[0] + '?' + split[0] + '?' + split[0] + '?' + split[0] + '?' + split[0],
duplicate_int_array(pattern, 5));
end;
writeln('The sum is ', total);
end.