matthewtodd-perquackey 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,4 +1,7 @@
1
- == 0.3.3 -- 2009-04-18
1
+ == 0.5.0 -- 2009-05-27
2
+ * Removed dependency on RubyInline. (So I can deploy to Heroku.)
3
+
4
+ == 0.4.0 -- 2009-04-18
2
5
  * Removed mongrel dependency.
3
6
  * Switched console to use readline instead of irb.
4
7
  * Remove stdout usage. Console is the default.
data/TODO CHANGED
@@ -1,2 +1,3 @@
1
- * remove dependency on RubyInline?
1
+ * Dictionary should take some kind of IO object.
2
+ * Server script should just use Rack.
2
3
  * tabtab_definitions --> except tabtab's not working well with -- options.
data/bin/perquackey CHANGED
@@ -15,8 +15,9 @@ end
15
15
 
16
16
  opts.parse! ARGV
17
17
 
18
- LIB_DIR = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
19
- $:.unshift LIB_DIR
18
+ %w(ext lib).each do |dir|
19
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__), '..', dir))
20
+ end
20
21
 
21
22
  case conf.mode
22
23
  when :console
@@ -0,0 +1,58 @@
1
+ // After finding YAWL, I pretty much lifted this algorithm straight from its
2
+ // anagram.c. It's certainly much faster than the Ruby code I wrote, since
3
+ // it's not making tons of throwaway strings. Fun stuff.
4
+ #include "ruby.h"
5
+
6
+ #define MAX_LENGTH 40
7
+ #define XOUT '@'
8
+ #define FALSE 0
9
+ #define TRUE 1
10
+
11
+ static VALUE mPerquackey;
12
+ static VALUE cDictionary;
13
+
14
+ int spell(char *word, char *letters) {
15
+ static char letter_set[MAX_LENGTH];
16
+ register char *letter;
17
+
18
+ strcpy(letter_set, letters);
19
+ strcat(letter_set, "\n");
20
+
21
+ while (*word) {
22
+ if ((letter = strchr(letter_set, *word++)) != NULL) {
23
+ *letter = XOUT;
24
+ } else {
25
+ return FALSE;
26
+ }
27
+ }
28
+
29
+ return TRUE;
30
+ }
31
+
32
+ VALUE Dictionary_initialize(VALUE self, VALUE filename) {
33
+ rb_iv_set(self, "@filename", filename);
34
+ return self;
35
+ }
36
+
37
+ VALUE Dictionary_words(VALUE self, VALUE letters) {
38
+ VALUE words = rb_ary_new();
39
+
40
+ char word[MAX_LENGTH];
41
+
42
+ FILE *file = fopen(RSTRING(rb_iv_get(self, "@filename"))->ptr, "rt");
43
+ while (fgets(word, MAX_LENGTH, file) != NULL) {
44
+ if (spell(word, RSTRING(letters)->ptr)) {
45
+ rb_ary_push(words, rb_str_new(word, strlen(word) - 1));
46
+ }
47
+ }
48
+ fclose(file);
49
+
50
+ return words;
51
+ }
52
+
53
+ void Init_dictionary() {
54
+ mPerquackey = rb_define_module("Perquackey");
55
+ cDictionary = rb_define_class_under(mPerquackey, "Dictionary", rb_cObject);
56
+ rb_define_method(cDictionary, "initialize", Dictionary_initialize, 1);
57
+ rb_define_method(cDictionary, "words", Dictionary_words, 1);
58
+ }
@@ -0,0 +1,2 @@
1
+ require 'mkmf'
2
+ create_makefile 'dictionary'
data/lib/perquackey.rb CHANGED
@@ -1,9 +1,51 @@
1
- require 'rubygems'
2
- require 'inline'
1
+ require 'perquackey/dictionary'
3
2
 
4
3
  module Perquackey
5
- end
4
+ class Game
5
+ YAWL = File.join(File.dirname(__FILE__), '..', 'resources', 'yawl-0.3.2-word.list')
6
6
 
7
- require 'perquackey/dictionary'
8
- require 'perquackey/game'
9
- require 'perquackey/word_table'
7
+ def initialize
8
+ @dictionary = Dictionary.new(YAWL)
9
+ end
10
+
11
+ def words(letters)
12
+ WordTable.new(@dictionary.words(letters).reject { |word| word.length < minimum_length(letters) })
13
+ end
14
+
15
+ private
16
+
17
+ def minimum_length(letters)
18
+ letters.length > 10 ? 4 : 3
19
+ end
20
+ end
21
+
22
+ class WordTable
23
+ include Enumerable
24
+
25
+ def initialize(list=[])
26
+ @table = Hash.new { |h, k| h[k] = [] }
27
+
28
+ list.each do |word|
29
+ @table[word.length] << word
30
+ end
31
+
32
+ if @table.empty?
33
+ @headers = []
34
+ @height = 0
35
+ else
36
+ @headers = @table.keys.min .. @table.keys.max
37
+ @height = @table.values.max { |a, b| a.length <=> b.length }.length
38
+ end
39
+ end
40
+
41
+ def headers
42
+ @headers
43
+ end
44
+
45
+ def each
46
+ @height.times do |row_number|
47
+ yield headers.collect { |length| @table[length][row_number] or ' ' * length}
48
+ end
49
+ end
50
+ end
51
+ end
@@ -1,4 +1,4 @@
1
- %w(rubygems camping perquackey).each { |lib| require lib }
1
+ require 'perquackey'
2
2
 
3
3
  Camping.goes :Perquackey
4
4
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: matthewtodd-perquackey
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Todd
@@ -9,19 +9,9 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-04-18 00:00:00 -07:00
12
+ date: 2009-05-27 00:00:00 -07:00
13
13
  default_executable: perquackey
14
14
  dependencies:
15
- - !ruby/object:Gem::Dependency
16
- name: RubyInline
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: "0"
24
- version:
25
15
  - !ruby/object:Gem::Dependency
26
16
  name: camping
27
17
  type: :runtime
@@ -36,8 +26,8 @@ description:
36
26
  email: matthew.todd@gmail.com
37
27
  executables:
38
28
  - perquackey
39
- extensions: []
40
-
29
+ extensions:
30
+ - ext/perquackey/extconf.rb
41
31
  extra_rdoc_files:
42
32
  - README
43
33
  - CHANGELOG
@@ -47,21 +37,20 @@ files:
47
37
  - CHANGELOG
48
38
  - TODO
49
39
  - bin/perquackey
40
+ - ext/perquackey/dictionary.c
41
+ - ext/perquackey/extconf.rb
50
42
  - lib/perquackey/console.rb
51
- - lib/perquackey/dictionary.rb
52
- - lib/perquackey/game.rb
53
43
  - lib/perquackey/server.rb
54
- - lib/perquackey/word_table.rb
55
44
  - lib/perquackey.rb
56
45
  - resources/yawl-0.3.2-word.list
57
- has_rdoc: true
46
+ has_rdoc: false
58
47
  homepage:
59
48
  post_install_message:
60
49
  rdoc_options:
61
50
  - --main
62
51
  - README
63
52
  - --title
64
- - perquackey-0.4.0
53
+ - perquackey-0.5.0
65
54
  - --inline-source
66
55
  - --line-numbers
67
56
  require_paths:
@@ -1,57 +0,0 @@
1
- class Perquackey::Dictionary
2
- YAWL = File.join(File.dirname(__FILE__), '..', '..', 'resources', 'yawl-0.3.2-word.list')
3
-
4
- def words(letters)
5
- c_words(letters, YAWL)
6
- end
7
-
8
- # After finding YAWL, I pretty much lifted this algorithm straight from its
9
- # anagram.c. It's certainly much faster than the Ruby code I wrote, since
10
- # it's not making tons of throwaway strings. Fun stuff.
11
- inline do |builder|
12
- builder.prefix <<-END
13
- #define MAX_LENGTH 40
14
- #define XOUT '@'
15
- #define FALSE 0
16
- #define TRUE 1
17
- END
18
-
19
- builder.c_raw <<-END
20
- int c_spell(char *word, char *letters) {
21
- static char letter_set[MAX_LENGTH];
22
- register char *letter;
23
-
24
- strcpy(letter_set, letters);
25
- strcat(letter_set, "\\n");
26
-
27
- while (*word) {
28
- if ((letter = strchr(letter_set, *word++)) != NULL) {
29
- *letter = XOUT;
30
- } else {
31
- return FALSE;
32
- }
33
- }
34
-
35
- return TRUE;
36
- }
37
- END
38
-
39
- builder.c <<-END
40
- VALUE c_words(VALUE letters, VALUE filename) {
41
- VALUE words = rb_ary_new();
42
-
43
- char word[MAX_LENGTH];
44
-
45
- FILE *file = fopen(RSTRING(filename)->ptr, "rt");
46
- while (fgets(word, MAX_LENGTH, file) != NULL) {
47
- if (c_spell(word, RSTRING(letters)->ptr)) {
48
- rb_ary_push(words, rb_str_new(word, strlen(word) - 1));
49
- }
50
- }
51
- fclose(file);
52
-
53
- return words;
54
- }
55
- END
56
- end
57
- end
@@ -1,15 +0,0 @@
1
- class Perquackey::Game
2
- def initialize
3
- @dictionary = Perquackey::Dictionary.new
4
- end
5
-
6
- def words(letters)
7
- Perquackey::WordTable.new(@dictionary.words(letters).reject { |word| word.length < minimum_length(letters) })
8
- end
9
-
10
- private
11
-
12
- def minimum_length(letters)
13
- letters.length > 10 ? 4 : 3
14
- end
15
- end
@@ -1,29 +0,0 @@
1
- class Perquackey::WordTable
2
- include Enumerable
3
-
4
- def initialize(list=[])
5
- @table = Hash.new { |h, k| h[k] = [] }
6
-
7
- list.each do |word|
8
- @table[word.length] << word
9
- end
10
-
11
- if @table.empty?
12
- @headers = []
13
- @height = 0
14
- else
15
- @headers = @table.keys.min .. @table.keys.max
16
- @height = @table.values.max { |a, b| a.length <=> b.length }.length
17
- end
18
- end
19
-
20
- def headers
21
- @headers
22
- end
23
-
24
- def each
25
- @height.times do |row_number|
26
- yield headers.collect { |length| @table[length][row_number] or ' ' * length}
27
- end
28
- end
29
- end