ludy 0.1.8 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
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