pressletter 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ bundler_args: --without productivity
3
+ script: 'bundle exec rspec'
4
+ notifications:
5
+ recipients:
6
+ - justin@testdouble.com
data/Gemfile CHANGED
@@ -3,7 +3,7 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in pressletter.gemspec
4
4
  gemspec
5
5
 
6
- group :development do
6
+ group :productivity do
7
7
  gem 'guard'
8
8
  gem 'guard-rspec'
9
9
  gem 'growl'
data/README.md CHANGED
@@ -1,16 +1,46 @@
1
1
  # Pressletter
2
2
 
3
+ [![Build Status](https://secure.travis-ci.org/searls/pressletter.png)](http://travis-ci.org/searls/pressletter)
4
+
3
5
  Letterpress is a fantastic game for iOS written by [Loren Brichter](http://www.atebits.com). Pressletter is a gem that solves Letterpress boards using an included plaintext dictionary of words.
4
6
 
7
+ ## Installation
8
+
9
+ ### global install
10
+
11
+ To install pressletter to your system, run:
12
+
13
+ ```
14
+ $ gem install pressletter
15
+ ```
16
+
17
+ ### bundler
18
+
19
+ If you're using [Bundler](http://gembundler.com), add the pressletter gem to your Gemfile:
20
+
21
+ ``` ruby
22
+ source 'https://rubygems.org'
23
+
24
+ gem 'pressletter'
25
+ ```
26
+
27
+ and then run:
28
+
29
+ ```
30
+ $ bundle install
31
+ ```
32
+
33
+ Inside your Bundler project, the binary can then be accessed with `bundle exec pressletter`.
34
+
5
35
  ## Example
6
36
 
7
- Here's what a board looked like in a game I played with @steveklabnik:
37
+ Here's what a board looked like in a game I played with [@steveklabnik](https://github.com/steveklabnik):
8
38
 
9
39
  ![pressletter Screen](http://i.minus.com/ibv4sMC7Msl5Fv.png)
10
40
 
11
- Using the pressletter gem, you can take a look at what words *would* have been possible to play by passing in all 25 available letters (including any repeats, since the rules dictate that each letter is consumed as it is used).
41
+ Using the pressletter gem, you can search for playable words by providing the 25 letters on the game board (even any repeats, since the game rules stipulate that each letter can only be used as many times as it appears on the board).
12
42
 
13
- As you can see in the screen, those letters (in lexical order) are: `E I P T C T B N T Y M E I P H O X V I T K M Z I B`.
43
+ For instance, the letters in the provided screenshot are: `E I P T C T B N T Y M E I P H O X V I T K M Z I B`.
14
44
 
15
45
  ### command-line
16
46
 
@@ -37,13 +67,30 @@ E I P T C T B N T Y M E I P H O X V I T K M Z I B
37
67
 
38
68
  ```
39
69
 
40
- ### ruby
70
+ In each case, the results will print in order of largest-to-smallest length (with secondary alphabetical order for words of the same length). The output looks like:
71
+
72
+ ```
73
+ $ pressletter eiptctbntymeiphoxvitkmzib
74
+ COMPETITIVITE
75
+ BIOETHICIEN
76
+ ...
77
+ XI
78
+ ```
79
+
80
+ ### Ruby
81
+
82
+ You can, of course, also look for solutions using pure ruby. The public API is exceedingly simple:
83
+
84
+ **Pressletter.solve(letters[, config])**
85
+
86
+ For input, all that's needed is a string or array of candidate letters. A config object that responds to `dictionary_location` with a path of a dictionary file can also be optionally provided. An array (sorted largest-to-smallest) of valid words is returned.
41
87
 
42
- Here's an interactive shell session that uses the gem programmatically:
88
+ Here's an interactive session that uses the gem programmatically:
43
89
 
44
90
  ``` ruby
45
91
  $ irb
46
92
  irb(main):001:0> require 'pressletter'
93
+ => true
47
94
  irb(main):002:0> letters = ["e", "i", "p", "t", "c", "t", "b", "n", "t", "y", "m", "e", "i", "p", "h", "o", "x", "v", "i", "t", "k", "m", "z", "i", "b"]
48
95
  => ["e", "i", "p", "t", "c", "t", "b", "n", "t", "y", "m", "e", "i", "p", "h", "o", "x", "v", "i", "t", "k", "m", "z", "i", "b"]
49
96
  irb(main):003:0> Pressletter.solve(letters)
@@ -0,0 +1,92 @@
1
+ module Bench
2
+ def self.mark(name, &experiment)
3
+ @marks ||= Marks.new
4
+ @marks.add(name, &experiment)
5
+ end
6
+
7
+ def self.run
8
+ return unless @marks
9
+ @marks.run
10
+ end
11
+
12
+ class Marks
13
+ def initialize
14
+ @marks = {}
15
+ end
16
+
17
+ def add(name, &experiment)
18
+ raise "Benchmark named \"#{name}\" was already defined!" if @marks.has_key?(name)
19
+ @marks[name] = {:experiment => experiment }
20
+ end
21
+
22
+ def run
23
+ require 'benchmark'
24
+
25
+ Results.new(
26
+ @marks.map do |(name, mark)|
27
+ begin
28
+ {
29
+ :name => name,
30
+ :errors => nil,
31
+ :time => Benchmark.measure(&mark[:experiment]).total
32
+ }
33
+ rescue
34
+ {
35
+ :name => name,
36
+ :errors => [$!.message],
37
+ :time => nil
38
+ }
39
+ end
40
+ end
41
+ )
42
+ end
43
+ end
44
+
45
+ class Results
46
+ def initialize(results)
47
+ @results = results
48
+ end
49
+
50
+ def as_array
51
+ @results
52
+ end
53
+
54
+ def total_time
55
+ raise failure_message if failures?
56
+ @results.map {|r| r[:time] }.inject(&:+)
57
+ end
58
+
59
+ def average_time
60
+ total_time / @results.size
61
+ end
62
+
63
+ private
64
+
65
+ def failure_message
66
+ "Errors occurred, total benchmark time is meaningless:\n\n #{errors}"
67
+ end
68
+
69
+ def failures?
70
+ @results.any? {|r| r[:errors] }
71
+ end
72
+
73
+ def errors
74
+ @results.map { |r| r[:errors] }.flatten.compact.join("\n")
75
+ end
76
+ end
77
+
78
+
79
+ end
80
+
81
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
82
+ require 'pressletter'
83
+
84
+ Bench.mark "eiptctbntymeiphoxvitkmzib" do
85
+ Pressletter.solve("eiptctbntymeiphoxvitkmzib")
86
+ end
87
+
88
+ # Bench.mark "agslumxaeyylyuwfoszmddjhi" do
89
+ # Pressletter.solve("agslumxaeyylyuwfoszmddjhi")
90
+ # end
91
+
92
+ puts Bench.run.total_time
@@ -10,6 +10,7 @@ module Pressletter::Core
10
10
  private
11
11
 
12
12
  def letters_can_buy?(letters, word)
13
+ return if impossible?(letters, word)
13
14
  letters = letters.as_hash.dup
14
15
  word.dup.split('').all? do |char|
15
16
  decrement_char!(char, letters)
@@ -20,4 +21,8 @@ private
20
21
  letters[char] -= 1 if letters[char] && letters[char] > 0
21
22
  end
22
23
 
24
+ def impossible?(letters, word)
25
+ word.split('').any? { |c| !letters.as_array.include?(c) }
26
+ end
27
+
23
28
  end
@@ -1,3 +1,3 @@
1
1
  module Pressletter
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pressletter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -73,12 +73,14 @@ extra_rdoc_files: []
73
73
  files:
74
74
  - .gitignore
75
75
  - .rspec
76
+ - .travis.yml
76
77
  - Gemfile
77
78
  - Guardfile
78
79
  - LICENSE.txt
79
80
  - README.md
80
81
  - Rakefile
81
82
  - assets/dictionary.txt
83
+ - benchmarks/benchmark.rb
82
84
  - bin/pressletter
83
85
  - lib/pressletter.rb
84
86
  - lib/pressletter/core/create_letters.rb