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
|
# File 'ext/haystack_worker/haystack_worker.c', line 5
static VALUE surpluses(VALUE self, VALUE rb_ary) {
int i, j, ranges[26][2];
for (i = 0; i < 26; i++) {
for (j = 0; j < 2; j++) {
ranges[i][j] = FIX2INT(RARRAY_PTR(RARRAY_PTR(rb_ary)[i])[j]);
}
}
int blocks = 16, position = 0, *array = NULL, bytes;
YIELD_ATTEMPTS {
int total[26] = {};
for (i = 0; i < 26; i++) {
for (j = 0; j < 26; j++) {
total[j] += WORD_LOOKUP[attempt[i]][i][j];
}
}
int satisfiable = 1, surplus[26];
for (i = 0; i < 26; i++) {
surplus[i] = attempt[i] - total[i];
if (surplus[i] < 0) {
satisfiable = 0;
break;
}
}
if (satisfiable) {
if (position + 26 > blocks) {
blocks *= 2, bytes = blocks * sizeof(int);
array = realloc(array, bytes);
if (array == NULL) {
rb_raise(rb_eNoMemError, "Failed to allocate %d bytes", bytes);
}
}
for (i = 0; i < 26; i++) {
array[position + i] = attempt[i];
}
position += 26;
}
}
VALUE rb_solutions = rb_ary_new();
if (position != 0) {
VALUE rb_solution;
for (i = 0; i < position / 26; i++) {
rb_solution = rb_ary_new();
for (j = 0; j < 26; j++) {
rb_ary_push(rb_solution, INT2FIX(array[i * 26 + j]));
}
rb_ary_push(rb_solutions, rb_solution);
}
free(array);
}
return rb_solutions;
}
|