piscine-bsq/srcs/solution.c

101 lines
2.9 KiB
C

/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* solution.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: tischmid <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/04 21:46:57 by tischmid #+# #+# */
/* Updated: 2023/04/05 11:18:21 by tischmid ### ########.fr */
/* */
/* ************************************************************************** */
#include "solution.h"
// Replace each cell by the number of obstacles a rectangle starting
// from the top left cell, filling the board until the cell in question,
// covers. Border is inclusive. This will enable us to check if a given
// square contains obstacles or not in O(1) time, instead of O(n^2),
// namely by summing up the corner cells alternatingly (+, -, +, -, clockwise).
void preprocess_map(t_map *map)
{
int is_obstacle;
int idx;
idx = 0;
while (idx < map->meta.width * map->meta.height)
{
is_obstacle = get_cell(map, idx, 0, 0) == map->meta.obstacle;
map->data[idx] = is_obstacle + \
get_cell(map, idx, 0, -1) + \
get_cell(map, idx, -1, 0) - \
get_cell(map, idx, -1, -1);
idx++;
}
}
int count_obstacles(t_map *map, int idx, int sq_size)
{
int alternat_corner_sum;
if (sq_size == 0)
return (0);
if (sq_size == 1)
return (get_cell(map, idx, 0, 0));
if (idx + (sq_size - 1) * (map->meta.width + 1)
> map->meta.width * map->meta.height)
return (-1);
alternat_corner_sum = get_cell(map, idx, -1, -1) - \
get_cell(map, idx, -1, sq_size - 1) + \
get_cell(map, idx, sq_size - 1, sq_size - 1) - \
get_cell(map, idx, sq_size - 1, -1);
return (alternat_corner_sum);
}
void fill_with_full(t_map *map, int sq_idx, int sq_size)
{
int idx;
int idx_row;
int idx_col;
int sq_row;
int sq_col;
sq_row = itor(sq_idx, map->meta.width);
sq_col = itoc(sq_idx, map->meta.width);
idx = 0;
while (idx < map->meta.width * map->meta.height)
{
idx_row = itor(idx, map->meta.width);
idx_col = itoc(idx, map->meta.width);
if (idx_row >= sq_row && idx_row < sq_row + sq_size
&& idx_col >= sq_col && idx_col < sq_col + sq_size)
map->data[idx] = map->meta.full;
else
map->data[idx] = map->copy[idx];
idx++;
}
}
void solve(t_map *map)
{
int idx;
int sq_idx;
int sq_size;
preprocess_map(map);
idx = 0;
sq_size = 0;
sq_idx = 0;
while (idx < map->meta.width * map->meta.height)
{
while (count_obstacles(map, idx, sq_size) == 0)
{
sq_idx = idx;
sq_size++;
}
idx++;
}
sq_size--;
fill_with_full(map, sq_idx, sq_size);
}