aboutsummaryrefslogtreecommitdiff
path: root/src/pattern/pattern.c
blob: 85e21c7b8212595fb90d77bb019ef30bc58c5839 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include "pattern.h"
#include <stdlib.h>
#include "utils/utilities.h"

/*
 * Inline functions
 */
bool len_is_max(struct pattern *pattern);
bool len_is_min(struct pattern *pattern);
int coord_to_index(int width, struct coord point);
struct coord index_to_coord(int width, int index);
int pattern_point_to_index(struct pattern *pattern, int index);

struct pattern_type gen_pattern_type(int side_len, int min, int max)
{
    struct pattern_type result;
    result.width = side_len;
    result.height = side_len;

    int max_possible = side_len * side_len;
    result.min_length = min >= 0 ? min : max_possible;
    if (max >= 0 && max <= max_possible)
        result.max_length = max;
    else
        result.max_length = max_possible;
    return result;
}

int coord_cmp(const void *a, const void *b)
{
    const struct coord *ac = a;
    const struct coord *bc = b;
    if (ac->x == bc->x && ac->y == bc->y)
        return 0;
    //TODO: Handle when the inputs are not equal!
    return -1;
}

bool is_in_line(struct coord a, struct coord c, struct coord b)
{
    if (!(monotonic(a.x, b.x, c.x) && monotonic(a.y, b.y, c.y)))
        return false;
    return ((b.x - a.x) * (c.y - a.y)) + ((b.y - a.y) * (a.x - c.x)) == 0;
}

int find_in_pattern(struct pattern *pattern, struct coord *coord)
{
    for (int i = 0; i < pattern->length; i++)
    {
        struct coord *current = &pattern->path[i];
        if (current->x == coord->x && current->y == coord->y)
            return i;
    }
    return -1;
}

int inbetween(int width, int height, struct coord *from, struct coord *to, struct coord *arr)
{
    int length = 0;
    struct coord current;
    for (current.y = 0; current.y < height; current.y++)
        for (current.x = 0; current.x < width; current.x++)
            if ((current.x != from->x || current.y != from->y) &&
                (current.x != to->x || current.y != to->y))
                if (is_in_line(*from, *to, current))
                    arr[length++] = current;
    return length;
}

bool nothing_inbetween(struct pattern *pattern, struct coord *next)
{
    if (pattern->length == 0)
        return true;
    struct coord *last = &pattern->path[pattern->length - 1];
    struct coord arr[pattern->type.width * pattern->type.height];
    size_t length = inbetween(pattern->type.width, pattern->type.height, last, next, arr);
    if (length > pattern->length)
        return false;
    for (int i = 0; i < length; i++)
        if (find_in_pattern(pattern, &arr[i]) < 0)
            return false;
    return true;
}