haystack_worker 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ ## Haystack Worker
2
+
3
+ Works on behalf of a haystack server.
4
+
5
+ ## Concept
6
+
7
+ A haystack worker's sole responsibility is to calculate surpluses of characters that satisfy self-enumerating pangrams. It does this as quickly as possible and therefore makes use of a C-extension for a ~200x speed increase over Ruby.
8
+
9
+ It receives 'jobs' from a haystack server which come in the form:
10
+
11
+ ```ruby
12
+ { 'id' => 123, 'ranges' => [1..10, 3..4, 8..14, etc] }
13
+ ```
14
+
15
+ The ranges represent the search space that this worker has been assigned to explore. The ID is used by the haystack worker to keep track of jobs.
16
+
17
+ It posts data back to the haystack at /job/:id in the form:
18
+
19
+ ```ruby
20
+ [[1,3,8,etc],[6,4,14,etc]]
21
+ ```
22
+
23
+ It returns ```nil``` if the given search space doesn't contain any potential self-enumerating pangrams.
24
+
25
+ ## Usage
26
+
27
+ ```
28
+ gem install haystack_worker
29
+ haystack worker haystack.example.com
30
+ ```
31
+
32
+ At present, I haven't built the haystack server. When I have, I'll update the gem to point to it by default.
33
+
34
+ ## Resources
35
+
36
+ For more information or to gain some context, please see my pangram and frequency related projects.
37
+
38
+ ## Contribution
39
+
40
+ Feel free to contribute. No commit is too small.
41
+
42
+ You should follow me: [@cpatuzzo](https://twitter.com/cpatuzzo)
data/bin/haystack ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'haystack_worker'
4
+
5
+ ARGV[1] ||= 'localhost:9292'
6
+ HaystackWorker.work(ARGV[1])
@@ -0,0 +1,3 @@
1
+ require 'mkmf'
2
+
3
+ create_makefile('haystack_worker/haystack_worker')
@@ -0,0 +1,72 @@
1
+ #include <ruby.h>
2
+ #include "lookup.h"
3
+ #include "macros.h"
4
+
5
+ static VALUE surpluses(VALUE self, VALUE rb_ary) {
6
+ int i, j, ranges[26][2];
7
+ for (i = 0; i < 26; i++) {
8
+ for (j = 0; j < 2; j++) {
9
+ ranges[i][j] = FIX2INT(RARRAY_PTR(RARRAY_PTR(rb_ary)[i])[j]);
10
+ }
11
+ }
12
+
13
+ int blocks = 16, position = 0, *array = NULL, bytes;
14
+
15
+ YIELD_ATTEMPTS {
16
+ int total[26] = {};
17
+ for (i = 0; i < 26; i++) {
18
+ for (j = 0; j < 26; j++) {
19
+ total[j] += WORD_LOOKUP[attempt[i]][i][j];
20
+ }
21
+ }
22
+
23
+ int satisfiable = 1, surplus[26];
24
+ for (i = 0; i < 26; i++) {
25
+ surplus[i] = attempt[i] - total[i];
26
+ if (surplus[i] < 0) {
27
+ satisfiable = 0;
28
+ break;
29
+ }
30
+ }
31
+
32
+ if (satisfiable) {
33
+ if (position + 26 > blocks) {
34
+ blocks *= 2, bytes = blocks * sizeof(int);
35
+ array = realloc(array, bytes);
36
+
37
+ if (array == NULL) {
38
+ rb_raise(rb_eNoMemError, "Failed to allocate %d bytes", bytes);
39
+ }
40
+ }
41
+
42
+ for (i = 0; i < 26; i++) {
43
+ array[position + i] = attempt[i];
44
+ }
45
+
46
+ position += 26;
47
+ }
48
+ }
49
+
50
+ if (position == 0) {
51
+ return Qnil;
52
+ }
53
+ else {
54
+ VALUE rb_solutions = rb_ary_new(), rb_solution;
55
+
56
+ for (i = 0; i < position / 26; i++) {
57
+ rb_solution = rb_ary_new();
58
+ for (j = 0; j < 26; j++) {
59
+ rb_ary_push(rb_solution, INT2FIX(array[i * 26 + j]));
60
+ }
61
+ rb_ary_push(rb_solutions, rb_solution);
62
+ }
63
+
64
+ free(array);
65
+ return rb_solutions;
66
+ }
67
+ }
68
+
69
+ void Init_haystack_worker(void) {
70
+ VALUE klass = rb_define_class("HaystackWorker", rb_cObject);
71
+ rb_define_method(klass, "_surpluses", surpluses, 1);
72
+ }