ludy 0.1.8 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. data/CHANGES +26 -0
  2. data/Manifest.txt +28 -15
  3. data/NOTICE +9 -1
  4. data/README +7 -4
  5. data/Rakefile +11 -7
  6. data/lib/ludy.rb +3 -4
  7. data/lib/ludy/array/choice.rb +14 -0
  8. data/lib/ludy/array/combine.rb +1 -1
  9. data/lib/ludy/array/combos.rb +28 -19
  10. data/lib/ludy/array/count.rb +7 -0
  11. data/lib/ludy/array/head.rb +4 -0
  12. data/lib/ludy/array/pad.rb +13 -0
  13. data/lib/ludy/array/product.rb +14 -0
  14. data/lib/ludy/array/rotate.rb +3 -4
  15. data/lib/ludy/array/tail.rb +1 -0
  16. data/lib/ludy/hash.rb +3 -0
  17. data/lib/ludy/hash/reverse_merge.rb +11 -0
  18. data/lib/ludy/kernel/deep_copy.rb +6 -0
  19. data/lib/ludy/kernel/maybe.rb +6 -0
  20. data/lib/ludy/paginator.rb +1 -1
  21. data/lib/ludy/timer.rb +29 -0
  22. data/lib/puzzle_generator.rb +7 -5
  23. data/lib/puzzle_generator/chain.rb +5 -3
  24. data/lib/puzzle_generator/chained_map.rb +11 -11
  25. data/lib/puzzle_generator/map.rb +7 -7
  26. data/lib/puzzle_generator/misc.rb +7 -6
  27. data/lib/puzzle_generator/puzzle.rb +1 -4
  28. data/spec/ludy_spec.rb +8 -0
  29. data/spec/spec_helper.rb +17 -0
  30. data/tasks/doc.rake +1 -3
  31. data/tasks/gem.rake +2 -2
  32. data/tasks/manifest.rake +16 -2
  33. data/tasks/post_load.rake +18 -0
  34. data/tasks/setup.rb +47 -9
  35. data/tasks/spec.rake +3 -0
  36. data/test/example_puzzle.rb +7 -7
  37. data/test/helper.rb +3 -0
  38. data/test/{test_array.rb → ludy/test_array.rb} +12 -2
  39. data/test/{test_class.rb → ludy/test_class.rb} +1 -1
  40. data/test/{test_defun.rb → ludy/test_defun.rb} +1 -1
  41. data/test/{test_dices.rb → ludy/test_dices.rb} +1 -1
  42. data/test/ludy/test_hash.rb +13 -0
  43. data/test/{test_kernel.rb → ludy/test_kernel.rb} +1 -1
  44. data/test/{test_lazy.rb → ludy/test_lazy.rb} +1 -1
  45. data/test/{test_paginator.rb → ludy/test_paginator.rb} +2 -2
  46. data/test/{test_proc.rb → ludy/test_proc.rb} +2 -1
  47. data/test/{test_require_all.rb → ludy/test_require_all.rb} +1 -1
  48. data/test/{test_symbol.rb → ludy/test_symbol.rb} +1 -1
  49. data/test/{test_variable.rb → ludy/test_variable.rb} +1 -1
  50. data/test/{test_y_combinator.rb → ludy/test_y_combinator.rb} +1 -1
  51. data/test/{test_z_combinator.rb → ludy/test_z_combinator.rb} +1 -1
  52. data/test/multiruby.sh +2 -0
  53. metadata +54 -41
  54. data/lib/ludy/array/reverse_map.rb +0 -7
  55. data/lib/ludy/test/helper.rb +0 -3
@@ -3,9 +3,11 @@
3
3
 
4
4
  require 'puzzle_generator/puzzle'
5
5
 
6
- require 'rubygems'
7
- require 'facets/hash/reverse_merge'
8
- require 'facets/timer'
6
+ require 'ludy/hash/reverse_merge'
7
+
8
+ # require 'rubygems' if RUBY_VERSION < '1.9.0'
9
+ # require 'facets/timer'
10
+ require 'ludy/timer' # simple and stupid timer....
9
11
 
10
12
  module PuzzleGenerator
11
13
 
@@ -17,7 +19,7 @@ module PuzzleGenerator
17
19
 
18
20
  LastTriedInfo = {}
19
21
  def self.generate timeout = 5, &generator
20
- timer = Timer.new(timeout).start
22
+ timer = Ludy::Timer.new(timeout).start
21
23
  tried_times = 1
22
24
  begin
23
25
  result = generator.call
@@ -26,7 +28,7 @@ module PuzzleGenerator
26
28
  result = generator.call
27
29
  end
28
30
  ensure
29
- timer.stop
31
+ # timer.stop
30
32
  LastTriedInfo.merge! :tried_times => tried_times, :tried_duration => timer.total_time
31
33
  end
32
34
  result
@@ -9,13 +9,15 @@ module PuzzleGenerator
9
9
  @direct = direct
10
10
  x, y = position
11
11
  @data = case @direct
12
- when Up : ([x]*invoke).zip((y...y+invoke).to_a)
13
- when Right: (x...x+invoke).to_a.zip([y]*invoke)
14
- when Left : (x-invoke+1..x).to_a.zip([y]*invoke)
12
+ when Up ; ([x]*invoke).zip((y...y+invoke).to_a)
13
+ when Right; (x...x+invoke).to_a.zip([y]*invoke)
14
+ when Left ; (x-invoke+1..x).to_a.zip([y]*invoke)
15
15
  end
16
16
  end
17
17
  def <=> rhs; @data <=> rhs.instance_variable_get('@data'); end
18
18
  def == rhs; (self <=> rhs) == 0; end
19
+ alias_method :eql?, :==
20
+ def hash; @data.hash; end
19
21
  def each &block; @data.each &block; self end
20
22
  def [] index; @data[index]; end
21
23
  def to_a; @data.clone; end
@@ -3,12 +3,11 @@ require 'puzzle_generator/misc'
3
3
  require 'puzzle_generator/chain'
4
4
  require 'puzzle_generator/map'
5
5
 
6
+ require 'ludy/kernel/deep_copy'
6
7
  require 'ludy/array/combine'
7
-
8
- require 'rubygems'
9
- gem 'facets', '>=2.0.0'
10
- require 'facets/enumerable/combos'
11
- require 'facets/random' # for Array#pick
8
+ require 'ludy/array/rotate'
9
+ require 'ludy/array/choice' # for Array#choice!
10
+ require 'ludy/array/product' if RUBY_VERSION < '1.9.0'
12
11
 
13
12
  module PuzzleGenerator
14
13
 
@@ -40,7 +39,8 @@ module PuzzleGenerator
40
39
  def init_map
41
40
  @maps = [make_map]
42
41
  @result_map = make_map_array
43
- @picked_chain = make_init_chains([(0..@option[:width]-@option[:invoke]), [0]].combos).pick
42
+ # @picked_chain = make_init_chains([(0..@option[:width]-@option[:invoke]), [0]].combos).pick
43
+ @picked_chain = make_init_chains((0..@option[:width]-@option[:invoke]).to_a.product([0])).choice
44
44
  put_picked_chain_on @maps
45
45
  resolve_map
46
46
  end
@@ -51,7 +51,7 @@ module PuzzleGenerator
51
51
 
52
52
  def chain_ok?
53
53
  raise GenerationFailed.new("ChainedMap: last result_map: #{@result_map.inspect}") if @picked_chain.nil?
54
- @maps_preview = @maps.deep_clone
54
+ @maps_preview = @maps.deep_copy
55
55
  put_picked_chain_on @maps_preview
56
56
 
57
57
  result = check_overlap_and_resolve_it &&
@@ -66,8 +66,8 @@ module PuzzleGenerator
66
66
  @maps << (new_map || make_map)
67
67
  chains = @maps[-1].break_chains @maps[-2], @result_map
68
68
 
69
- @picked_chain = chains.pick!
70
- @picked_chain = chains.pick! until chain_ok?
69
+ @picked_chain = chains.choice!
70
+ @picked_chain = chains.choice! until chain_ok?
71
71
 
72
72
  put_picked_chain_on @maps
73
73
  @picked_chain = nil
@@ -86,7 +86,7 @@ module PuzzleGenerator
86
86
  }
87
87
  end
88
88
  def check_overlap_and_resolve_it
89
- @result_map_preview = @maps_preview.body.inject(make_map_array){ |result, map|
89
+ @result_map_preview = @maps_preview[0...-1].inject(make_map_array){ |result, map|
90
90
  result.each_with_index{ |column, x|
91
91
  column.each_with_index{ |value, y|
92
92
  # assert one of them is zero or they are all zero
@@ -97,7 +97,7 @@ module PuzzleGenerator
97
97
  }
98
98
  end
99
99
  def check_broken_except_last
100
- @maps_preview.body.all?{ |map|
100
+ @maps_preview[0...-1].all?{ |map|
101
101
  result = true
102
102
  map.each_with_index_2d{ |i, x, y|
103
103
  result &&= !check_left_chain( map, x, y) &&
@@ -2,11 +2,9 @@
2
2
  require 'puzzle_generator/misc'
3
3
  require 'puzzle_generator/chain'
4
4
 
5
- require 'rubygems'
6
- gem 'facets', '>=2.0.0'
7
- require 'facets/enumerable/combos'
8
- require 'facets/enumerable/uniq_by'
9
- require 'facets/random' # for Kernel#maybe
5
+ require 'ludy/kernel/maybe'
6
+ require 'ludy/array/count' if RUBY_VERSION < '1.9.0'
7
+ require 'ludy/array/product' if RUBY_VERSION < '1.9.0'
10
8
 
11
9
  # a = [[1,2],[3,4],[5,6]]
12
10
  # [a, [1,2,3]].combos
@@ -88,7 +86,8 @@ module PuzzleGenerator
88
86
  end
89
87
  def with_directs target
90
88
  # [target, [Up] + [Right, Left]*10].combos
91
- [target, [Up, Right, Left]].combos
89
+ # [target, [Up, Right, Left]].combos
90
+ target.product [Up, Right, Left]
92
91
  # e.g., [[[0, 0], Up], [[0, 0], Right], [[0, 0], Left], [[1, 0], Up], ...]
93
92
  end
94
93
  def to_chains target
@@ -101,7 +100,8 @@ module PuzzleGenerator
101
100
  def strip_duplicated_chain target
102
101
  # target.uniq never works for non-num nor non-string :(
103
102
  # target.sort.inject([]){ |r, i| r.last == i ? r : r<<i }
104
- target.uniq_by{|i|i}
103
+ # target.uniq_by{|i|i}
104
+ target.uniq # it works when hash and eql? take effect...
105
105
  end
106
106
  def strip_out_bounded_chain target
107
107
  target.select{ |chain| chain.bound_ok? @option[:width], @option[:height] }
@@ -1,8 +1,6 @@
1
1
 
2
- require 'rubygems'
3
- gem 'facets', '>=2.0.0'
4
- require 'facets/kernel/deep_clone'
5
- require 'facets/array/pad'
2
+ require 'ludy/kernel/deep_copy'
3
+ require 'ludy/array/pad'
6
4
 
7
5
  module PuzzleGenerator
8
6
  Up, Right, Left = (0..2).to_a
@@ -36,7 +34,7 @@ module PuzzleGenerator
36
34
  }
37
35
  end
38
36
  def check_answer_correctness result_map = @result_map
39
- map = Map.new @option.merge(:data => result_map.deep_clone)
37
+ map = Map.new @option.merge(:data => result_map.deep_copy)
40
38
  drop_blocks map # because of answer is stripped
41
39
 
42
40
  @chained = true
@@ -81,7 +79,10 @@ module PuzzleGenerator
81
79
  }
82
80
  end
83
81
  def drop_blocks map
84
- map.each_column{ |column| column.map!{ |i| i==0 ? nil : i }.compact!.pad!(@option[:height], 0) }
82
+ map.each_column{ |column|
83
+ column.map!{ |i| i==0 ? nil : i }.compact!
84
+ column.pad!(@option[:height], 0)
85
+ }
85
86
  end
86
87
  def check_left_chain map, x, y
87
88
  # this should be rewrited
@@ -3,10 +3,7 @@ require 'puzzle_generator/misc'
3
3
  require 'puzzle_generator/chained_map'
4
4
  require 'puzzle_generator/colored_map'
5
5
 
6
- require 'rubygems'
7
- gem 'facets', '>=2.0.0'
8
- require 'facets/array/rotate'
9
- require 'facets/timer'
6
+ require 'ludy/array/rotate'
10
7
 
11
8
  module PuzzleGenerator
12
9
 
@@ -1,3 +1,9 @@
1
+ # $Id$
2
+
3
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
4
+
5
+ describe Ludy do
6
+ end
1
7
 
2
8
  # bowling.rb
3
9
  class Bowling # :nodoc:
@@ -20,3 +26,5 @@ describe Bowling do
20
26
  @bowling.score.should == 0
21
27
  end
22
28
  end
29
+
30
+ # EOF
@@ -0,0 +1,17 @@
1
+ # $Id$
2
+
3
+ require File.expand_path(
4
+ File.join(File.dirname(__FILE__), %w[.. lib tmp]))
5
+
6
+ Spec::Runner.configure do |config|
7
+ # == Mock Framework
8
+ #
9
+ # RSpec uses it's own mocking framework by default. If you prefer to
10
+ # use mocha, flexmock or RR, uncomment the appropriate line:
11
+ #
12
+ # config.mock_with :mocha
13
+ # config.mock_with :flexmock
14
+ # config.mock_with :rr
15
+ end
16
+
17
+ # EOF
@@ -7,7 +7,6 @@ namespace :doc do
7
7
  desc 'Generate RDoc documentation'
8
8
  Rake::RDocTask.new do |rd|
9
9
  rd.main = PROJ.rdoc_main
10
- rd.options << '-d' if !WIN32 and `which dot` =~ %r/\/dot/
11
10
  rd.rdoc_dir = PROJ.rdoc_dir
12
11
 
13
12
  incl = Regexp.new(PROJ.rdoc_include.join('|'))
@@ -24,8 +23,7 @@ namespace :doc do
24
23
  title = "#{PROJ.rubyforge_name}'s " + title if PROJ.rubyforge_name != title
25
24
 
26
25
  rd.options << "-t #{title}"
27
- # FIXME: please add rdoc option to Rakefile, then i don't have to add this line.
28
- rd.options << '--charset=utf-8' << '--inline-source' << '--line-numbers'
26
+ rd.options.concat(PROJ.rdoc_opts)
29
27
  end
30
28
 
31
29
  desc 'Generate ri locally for testing'
@@ -69,12 +69,12 @@ namespace :gem do
69
69
 
70
70
  desc 'Install the gem'
71
71
  task :install => [:clobber, :package] do
72
- sh "#{SUDO} #{GEM} install pkg/#{PROJ.spec.file_name}"
72
+ sh "#{SUDO} #{GEM} install pkg/#{PROJ.spec.full_name}"
73
73
  end
74
74
 
75
75
  desc 'Uninstall the gem'
76
76
  task :uninstall do
77
- sh "#{SUDO} #{GEM} uninstall -v '#{PROJ.version}' #{PROJ.name}"
77
+ sh "#{SUDO} #{GEM} uninstall -v '#{PROJ.version}' -x #{PROJ.name}"
78
78
  end
79
79
 
80
80
  end # namespace :gem
@@ -17,7 +17,18 @@ namespace :manifest do
17
17
  end
18
18
 
19
19
  File.open(fn, 'w') {|fp| fp.puts files.sort}
20
- system "#{DIFF} -du Manifest.txt #{fn}"
20
+ lines = %x(#{DIFF} -du Manifest.txt #{fn}).split("\n")
21
+ if HAVE_FACETS_ANSICODE and ENV.has_key?('TERM')
22
+ lines.map! do |line|
23
+ case line
24
+ when %r/^(-{3}|\+{3})/; nil
25
+ when %r/^@/; Console::ANSICode.blue line
26
+ when %r/^\+/; Console::ANSICode.green line
27
+ when %r/^\-/; Console::ANSICode.red line
28
+ else line end
29
+ end
30
+ end
31
+ puts lines.compact
21
32
  rm fn rescue nil
22
33
  end
23
34
 
@@ -36,6 +47,9 @@ namespace :manifest do
36
47
  files << fn unless test ?f, fn
37
48
  File.open(fn, 'w') {|fp| fp.puts files.sort}
38
49
  end
39
- end
50
+ end # namespace :manifest
51
+
52
+ desc 'Alias to manifest:check'
53
+ task :manifest => 'manifest:check'
40
54
 
41
55
  # EOF
@@ -0,0 +1,18 @@
1
+ # $Id$
2
+
3
+ # This file does not define any rake tasks. It is used to load some project
4
+ # settings if they are not defined by the user.
5
+
6
+ unless PROJ.changes
7
+ PROJ.changes = paragraphs_of('History.txt', 0..1).join("\n\n")
8
+ end
9
+
10
+ unless PROJ.description
11
+ PROJ.description = paragraphs_of('README.txt', 'description').join("\n\n")
12
+ end
13
+
14
+ unless PROJ.summary
15
+ PROJ.summary = PROJ.description.split('.').first
16
+ end
17
+
18
+ # EOF
@@ -68,10 +68,12 @@ PROJ.svn_tags = 'tags'
68
68
  PROJ.svn_branches = 'branches'
69
69
 
70
70
  # Load the other rake files in the tasks folder
71
- Dir.glob('tasks/*.rake').sort.each {|fn| import fn}
71
+ rakefiles = Dir.glob('tasks/*.rake').sort
72
+ rakefiles.unshift(rakefiles.delete('tasks/post_load.rake')).compact!
73
+ import(*rakefiles)
72
74
 
73
75
  # Setup some constants
74
- WIN32 = %r/win32/ =~ RUBY_PLATFORM unless defined? WIN32
76
+ WIN32 = %r/djgpp|(cyg|ms|bcc)win|mingw/ =~ RUBY_PLATFORM unless defined? WIN32
75
77
 
76
78
  DEV_NULL = WIN32 ? 'NUL:' : '/dev/null'
77
79
 
@@ -100,7 +102,7 @@ SUDO = if WIN32 then ''
100
102
  RCOV = WIN32 ? 'rcov.cmd' : 'rcov'
101
103
  GEM = WIN32 ? 'gem.cmd' : 'gem'
102
104
 
103
- %w(rcov spec/rake/spectask rubyforge bones).each do |lib|
105
+ %w(rcov spec/rake/spectask rubyforge bones facets/ansicode).each do |lib|
104
106
  begin
105
107
  require lib
106
108
  Object.instance_eval {const_set "HAVE_#{lib.tr('/','_').upcase}", true}
@@ -115,8 +117,28 @@ end
115
117
  # changes = paragraphs_of('History.txt', 0..1).join("\n\n")
116
118
  # summary, *description = paragraphs_of('README.txt', 3, 3..8)
117
119
  #
118
- def paragraphs_of(path, *paragraphs)
119
- File.read(path).delete("\r").split(/\n\n+/).values_at(*paragraphs)
120
+ def paragraphs_of( path, *paragraphs )
121
+ title = String === paragraphs.first ? paragraphs.shift : nil
122
+ ary = File.read(path).delete("\r").split(/\n\n+/)
123
+
124
+ result = if title
125
+ tmp, matching = [], false
126
+ rgxp = %r/^=+\s*#{Regexp.escape(title)}/i
127
+ paragraphs << (0..-1) if paragraphs.empty?
128
+
129
+ ary.each do |val|
130
+ if val =~ rgxp
131
+ break if matching
132
+ matching = true
133
+ rgxp = %r/^=+/i
134
+ elsif matching
135
+ tmp << val
136
+ end
137
+ end
138
+ tmp
139
+ else ary end
140
+
141
+ result.values_at(*paragraphs)
120
142
  end
121
143
 
122
144
  # Adds the given gem _name_ to the current project's dependency list. An
@@ -130,11 +152,13 @@ def depend_on( name, version = nil )
130
152
  PROJ.dependencies << (version.nil? ? [name] : [name, ">= #{version}"])
131
153
  end
132
154
 
133
- # Adds the given _path_ to the include path if it is not already there
155
+ # Adds the given arguments to the include path if they are not already there
134
156
  #
135
- def ensure_in_path( path )
136
- path = File.expand_path(path)
137
- $:.unshift(path) if test(?d, path) and not $:.include?(path)
157
+ def ensure_in_path( *args )
158
+ args.each do |path|
159
+ path = File.expand_path(path)
160
+ $:.unshift(path) if test(?d, path) and not $:.include?(path)
161
+ end
138
162
  end
139
163
 
140
164
  # Find a rake task using the task name and remove any description text. This
@@ -148,4 +172,18 @@ def remove_desc_for_task( names )
148
172
  end
149
173
  end
150
174
 
175
+ # Change working directories to _dir_, call the _block_ of code, and then
176
+ # change back to the original working directory (the current directory when
177
+ # this method was called).
178
+ #
179
+ def in_directory( dir, &block )
180
+ curdir = pwd
181
+ begin
182
+ cd dir
183
+ return block.call
184
+ ensure
185
+ cd curdir
186
+ end
187
+ end
188
+
151
189
  # EOF
@@ -8,12 +8,14 @@ namespace :spec do
8
8
  Spec::Rake::SpecTask.new(:run) do |t|
9
9
  t.spec_opts = PROJ.spec_opts
10
10
  t.spec_files = PROJ.specs
11
+ t.libs += PROJ.libs
11
12
  end
12
13
 
13
14
  desc 'Run all specs with text output'
14
15
  Spec::Rake::SpecTask.new(:specdoc) do |t|
15
16
  t.spec_opts = PROJ.spec_opts + ['--format', 'specdoc']
16
17
  t.spec_files = PROJ.specs
18
+ t.libs += PROJ.libs
17
19
  end
18
20
 
19
21
  if HAVE_RCOV
@@ -21,6 +23,7 @@ namespace :spec do
21
23
  Spec::Rake::SpecTask.new(:rcov) do |t|
22
24
  t.spec_opts = PROJ.spec_opts
23
25
  t.spec_files = PROJ.specs
26
+ t.libs += PROJ.libs
24
27
  t.rcov = true
25
28
  t.rcov_opts = PROJ.rcov_opts + ['--exclude', 'spec']
26
29
  end
@@ -3,15 +3,15 @@ require File.join(File.dirname(__FILE__), '..', 'lib', 'ludy')
3
3
  require 'puzzle_generator'
4
4
 
5
5
  PuzzleGenerator.debug = true
6
- p = PuzzleGenerator::Puzzle.new :level => 4, :timeout => 10, :invoke_max => 5
6
+ pg = PuzzleGenerator::Puzzle.new :level => 4, :timeout => 2, :invoke_max => 5
7
7
  begin
8
- p.generate
9
- p.display_map
10
- rescue Timeout::Error
11
- puts 'Timeout!!'
8
+ pg.generate
9
+ pg.display_map
10
+ rescue Ludy::Timeout => e
11
+ puts e
12
12
  ensure
13
- p p.tried_times
14
- p p.tried_duration
13
+ p pg.tried_times
14
+ p pg.tried_duration
15
15
  end
16
16
 
17
17
  # level => 7