Skip to content

Commit fb3db25

Browse files
committed
graph coloring algororithm can now color sudoku. Added a worst-case puzzle which solves in 0.4s, still need to implement a function to free the graph, leaks like a sieve.
1 parent 5cc6eb0 commit fb3db25

File tree

6 files changed

+90
-139
lines changed

6 files changed

+90
-139
lines changed

graph.c

Lines changed: 35 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,20 @@ struct graph *create_graph()
66
{
77
struct graph *created = malloc(sizeof(struct graph));
88
created->vertices = NULL;
9-
created->vertex_count = 0;
9+
created->vertex_index = 1;
1010

1111
return created;
1212
}
1313

14-
struct vertex *add_single_value_vertex(struct graph *graph, int value)
14+
struct vertex *add_vertex(struct graph *graph, int num_possible, int value)
1515
{
1616
struct vertex *next = malloc(sizeof(struct vertex));
17-
next->possibilities = malloc(sizeof(int));
18-
*next->possibilities = value;
19-
next->num_possible = 1;
17+
next->index = graph->vertex_index++;
18+
next->current_value = value;
19+
next->num_possible = num_possible;
2020
next->edges = NULL;
2121
next->next = graph->vertices;
2222
graph->vertices = next;
23-
graph->vertex_count++;
24-
25-
return next;
26-
}
27-
28-
struct vertex *add_multiple_value_vertex(struct graph *graph, int *possible_values, int count)
29-
{
30-
struct vertex *next = malloc(sizeof(struct vertex));
31-
32-
next->possibilities = possible_values;
33-
next->num_possible = count;
34-
next->edges = NULL;
35-
next->next = graph->vertices;
36-
graph->vertices = next;
37-
graph->vertex_count++;
3823

3924
return next;
4025
}
@@ -47,41 +32,20 @@ void add_edge(struct vertex *vertex1, struct vertex *vertex2)
4732
vertex1->edges = next;
4833
}
4934

50-
// create a new array of colors
51-
int *make_colors(int count)
52-
{
53-
int *possible_values = malloc(sizeof(int) * count);
54-
55-
int c = 1;
56-
for (c = 1; c <= count; c++)
57-
possible_values[c - 1] = c;
58-
59-
return possible_values;
60-
}
61-
6235
void print_graph(struct graph *graph)
6336
{
6437
int edge_count = 0;
6538
struct vertex *last_vertex = graph->vertices;
6639

6740
while (last_vertex != NULL) {
68-
printf("Vertex [");
69-
int i = 0;
70-
for (i = 0; i < last_vertex->num_possible; i++)
71-
printf("%d, ", last_vertex->possibilities[i]);
72-
printf("] connects to vertices: ");
73-
41+
printf("Vertex %d[%d] connects to vertices: ", last_vertex->index, last_vertex->current_value);
7442
struct edge *last_edge = last_vertex->edges;
7543

7644
while (last_edge != NULL) {
7745
if (last_edge->connects_to != NULL) {
7846
edge_count++;
79-
80-
int j = 0;
81-
printf("[");
82-
for (j = 0; j < last_edge->connects_to->num_possible; j++)
83-
printf("%d, ", last_edge->connects_to->possibilities[j]);
84-
printf("], ");
47+
printf("%d[%d], ", last_edge->connects_to->index,
48+
last_edge->connects_to->current_value);
8549
}
8650

8751
last_edge = last_edge->next;
@@ -95,3 +59,30 @@ void print_graph(struct graph *graph)
9559
printf("Total edge count: %d\n", edge_count);
9660
}
9761

62+
63+
void print_sudoku(struct graph *graph, int size)
64+
{
65+
int *output = malloc(sizeof(int) * (size * size));
66+
67+
struct vertex *last_vertex = graph->vertices;
68+
69+
int index = 0;
70+
while (last_vertex != NULL) {
71+
output[index] = last_vertex->current_value;
72+
73+
last_vertex = last_vertex->next;
74+
index++;
75+
}
76+
77+
index--;
78+
for (; index >= 0; index--)
79+
printf("%d", output[index]);
80+
81+
printf("\n");
82+
}
83+
84+
85+
86+
87+
88+

graph.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22

33
struct graph {
44
struct vertex *vertices;
5-
int vertex_count;
5+
int vertex_index;
66
};
77

88
struct vertex {
9-
int *possibilities;
9+
int current_value;
1010
int num_possible;
11+
int index;
1112

1213
struct edge *edges;
1314
struct vertex *next;
@@ -21,11 +22,10 @@ struct edge {
2122

2223

2324
struct graph *create_graph();
24-
struct vertex *add_single_value_vertex(struct graph *graph, int value);
25-
struct vertex *add_multiple_value_vertex(struct graph *graph, int *possible_values, int count);
25+
struct vertex *add_vertex(struct graph *graph, int num_possible, int value);
2626
void add_edge(struct vertex *vertex1, struct vertex *vertex2);
27-
int *make_colors(int count);
2827
void print_graph(struct graph *graph);
28+
void print_sudoku(struct graph *graph, int size);
2929

30-
bool color_graph(struct vertex *vertex);
30+
bool color_graph(struct vertex *vertex, int num_colors);
3131
bool graph_colored(struct graph *graph);

graph_color.c

Lines changed: 43 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,22 @@
33
#include <stdio.h>
44
#include "graph.h"
55

6+
// check if an array contains a value
7+
bool array_contains(int *array, int count, int value)
8+
{
9+
int i = 0;
10+
for (i = 0; i < count; i++)
11+
if (array[i] == value)
12+
return true;
13+
14+
return false;
15+
}
16+
617

718
// determine is a vertex is constrained to only a single given color
819
bool vertex_must_be(struct vertex *vertex, int color)
920
{
10-
if (vertex->num_possible == 1 && vertex->possibilities[0] == color)
21+
if (vertex->num_possible == 1 && vertex->current_value == color)
1122
return true;
1223

1324
return false;
@@ -36,80 +47,57 @@ bool edges_disallow_color(struct vertex *vertex, int color)
3647
}
3748

3849

39-
// Pick a color for a vertex to try next
40-
int choose_color(struct vertex *vertex)
41-
{
42-
if (vertex->num_possible == 1)
43-
return 0;
44-
else {
45-
int chosen_index;
46-
for (chosen_index = 0; chosen_index < vertex->num_possible; chosen_index++) {
47-
if (edges_disallow_color(vertex, vertex->possibilities[chosen_index]))
48-
continue;
49-
else
50-
return chosen_index;
51-
}
52-
}
53-
54-
return -1;
55-
}
56-
57-
int *remove_possibility(int *possibilities, int count, int color)
50+
// See if a color is valid for a cell, not contained in any neighbors and not been removed
51+
int is_valid_color(struct vertex *vertex, int *removed, int removed_count, int color)
5852
{
59-
int *new_possible = malloc(sizeof(int) * (count - 1));
53+
if (vertex->num_possible == 1 && vertex->current_value == color)
54+
return true;
55+
else
56+
if (!array_contains(removed, removed_count, color))
57+
return !edges_disallow_color(vertex, color);
6058

61-
int i, j;
62-
for (j = 0, i = 0; i < count; i++) {
63-
if (possibilities[i] == color)
64-
continue;
65-
66-
new_possible[j] = possibilities[i];
67-
j++;
68-
}
69-
70-
return new_possible;
59+
return false;
7160
}
7261

7362

74-
bool color_graph(struct vertex *vertex)
63+
// Recursive backtracking algorithm
64+
bool color_graph(struct vertex *vertex, int num_colors)
7565
{
7666
if (vertex == NULL)
7767
return true;
7868

79-
while (vertex->num_possible > 1) {
80-
int *saved_possible = vertex->possibilities;
81-
int saved_num = vertex->num_possible;
69+
int removed_index = 0;
70+
int removed_colors[num_colors];
71+
72+
int original_value = vertex->current_value;
73+
int original_num = vertex->num_possible;
8274

83-
int next_candidate = choose_color(vertex);
8475

85-
if (next_candidate == -1)
86-
return false;
76+
if (original_num == 1)
77+
return color_graph(vertex->next, num_colors);
8778

88-
int *next_color = malloc(sizeof(int));
89-
*next_color = saved_possible[next_candidate];
79+
int i = 0;
80+
for (i = 1; i <= original_num; i++) {
81+
if (!is_valid_color(vertex, removed_colors, removed_index, i))
82+
continue;
9083

91-
vertex->possibilities = next_color;
84+
vertex->current_value = i;
9285
vertex->num_possible = 1;
9386

94-
bool success = color_graph(vertex->next);
87+
bool success = color_graph(vertex->next, num_colors);
9588

9689
if (success == false) {
97-
int *new_possible = remove_possibility(
98-
saved_possible,
99-
saved_num,
100-
*next_color);
101-
102-
vertex->possibilities = new_possible;
103-
vertex->num_possible = saved_num - 1;
90+
removed_colors[removed_index] = i;
91+
removed_index++;
92+
vertex->num_possible = original_num;
93+
vertex->current_value = original_value;
94+
}
95+
else {
96+
return true;
10497
}
105-
else
106-
break;
10798
}
10899

109-
if (edges_disallow_color(vertex, vertex->possibilities[0]))
110-
return false;
111-
else
112-
return color_graph(vertex->next);
100+
return false;
113101
}
114102

115103

@@ -127,4 +115,3 @@ bool graph_colored(struct graph *graph)
127115
return true;
128116
}
129117

130-
File renamed without changes.

sample_worst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
000000000000003085001020000000507000004000100090000000500000073002010000000040009

solver.c

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,11 @@ struct graph *load_initial()
105105
for (i = 0; i < num_boxes; i++) {
106106
// add all 9 color possibilities if we get a 0, which is an unfilled cell
107107
if (buffer[i] == '0') {
108-
vertices[i] = add_multiple_value_vertex(graph, make_colors(9), 9);
108+
vertices[i] = add_vertex(graph, 9, 0);
109109
}
110110
else {
111111
// add a single possibility if we get a pre-filled cell
112-
vertices[i] = add_single_value_vertex(graph, buffer[i] - '0');
112+
vertices[i] = add_vertex(graph, 1, buffer[i] - '0');
113113
}
114114
}
115115

@@ -123,44 +123,16 @@ struct graph *load_initial()
123123

124124
int main(int argc, char **argv)
125125
{
126-
struct graph *graph = create_graph();
127-
128-
struct vertex *vertex1 = add_multiple_value_vertex(graph, make_colors(4), 4);
129-
struct vertex *vertex2 = add_multiple_value_vertex(graph, make_colors(4), 4);
130-
struct vertex *vertex3 = add_multiple_value_vertex(graph, make_colors(4), 4);
131-
struct vertex *vertex4 = add_multiple_value_vertex(graph, make_colors(4), 4);
132-
133-
struct vertex *vertex5 = add_multiple_value_vertex(graph, make_colors(4), 4);
134-
135-
add_edge(vertex1, vertex2);
136-
add_edge(vertex1, vertex3);
137-
add_edge(vertex1, vertex4);
138-
139-
add_edge(vertex2, vertex1);
140-
add_edge(vertex2, vertex3);
141-
add_edge(vertex2, vertex4);
142-
143-
add_edge(vertex3, vertex1);
144-
add_edge(vertex3, vertex2);
145-
add_edge(vertex3, vertex4);
146-
147-
add_edge(vertex4, vertex1);
148-
add_edge(vertex4, vertex2);
149-
add_edge(vertex4, vertex3);
150-
151-
add_edge(vertex3, vertex5);
152-
add_edge(vertex5, vertex3);
153-
154-
print_graph(graph);
126+
struct graph *graph = load_initial();
155127

156-
color_graph(graph->vertices);
128+
color_graph(graph->vertices, 9);
157129

158130
if (graph_colored(graph))
159131
printf("Graph is colored.\n");
160132
else
161133
printf("Graph is not colored.\n");
162134

163-
print_graph(graph);
135+
print_sudoku(graph, 9);
164136

165137
return 0;
166138
}

0 commit comments

Comments
 (0)