godfat-ludy 0.1.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. data/CHANGES +226 -0
  2. data/LICENSE +201 -0
  3. data/NOTICE +21 -0
  4. data/README +212 -0
  5. data/Rakefile +56 -0
  6. data/TODO +21 -0
  7. data/bin/ludy +11 -0
  8. data/lib/ludy.rb +74 -0
  9. data/lib/ludy/all.rb +3 -0
  10. data/lib/ludy/array.rb +3 -0
  11. data/lib/ludy/array/body.rb +9 -0
  12. data/lib/ludy/array/choice.rb +16 -0
  13. data/lib/ludy/array/combine.rb +17 -0
  14. data/lib/ludy/array/combos.rb +35 -0
  15. data/lib/ludy/array/count.rb +9 -0
  16. data/lib/ludy/array/filter.rb +4 -0
  17. data/lib/ludy/array/foldl.rb +5 -0
  18. data/lib/ludy/array/foldr.rb +8 -0
  19. data/lib/ludy/array/head.rb +4 -0
  20. data/lib/ludy/array/map_with_index.rb +8 -0
  21. data/lib/ludy/array/pad.rb +13 -0
  22. data/lib/ludy/array/product.rb +16 -0
  23. data/lib/ludy/array/rotate.rb +21 -0
  24. data/lib/ludy/array/tail.rb +8 -0
  25. data/lib/ludy/blackhole.rb +17 -0
  26. data/lib/ludy/class.rb +3 -0
  27. data/lib/ludy/class/undef_all_methods.rb +9 -0
  28. data/lib/ludy/deprecated/aspect.rb +26 -0
  29. data/lib/ludy/deprecated/callstack.rb +24 -0
  30. data/lib/ludy/deprecated/curry.rb +29 -0
  31. data/lib/ludy/deprecated/rambda.rb +23 -0
  32. data/lib/ludy/deprecated/this.rb +14 -0
  33. data/lib/ludy/deprecated/untranspose.rb +12 -0
  34. data/lib/ludy/deprecated/unzip.rb +7 -0
  35. data/lib/ludy/dices.rb +66 -0
  36. data/lib/ludy/hash.rb +3 -0
  37. data/lib/ludy/hash/reverse_merge.rb +11 -0
  38. data/lib/ludy/helpers/check_box.rb +24 -0
  39. data/lib/ludy/kernel.rb +3 -0
  40. data/lib/ludy/kernel/deep_copy.rb +8 -0
  41. data/lib/ludy/kernel/defun.rb +10 -0
  42. data/lib/ludy/kernel/ergo.rb +16 -0
  43. data/lib/ludy/kernel/id.rb +8 -0
  44. data/lib/ludy/kernel/if_else.rb +14 -0
  45. data/lib/ludy/kernel/m.rb +5 -0
  46. data/lib/ludy/kernel/maybe.rb +9 -0
  47. data/lib/ludy/kernel/public_send.rb +15 -0
  48. data/lib/ludy/kernel/singleton_method.rb +15 -0
  49. data/lib/ludy/kernel/tap.rb +12 -0
  50. data/lib/ludy/lazy.rb +32 -0
  51. data/lib/ludy/list.rb +21 -0
  52. data/lib/ludy/message_dispatcher.rb +57 -0
  53. data/lib/ludy/namespace.rb +71 -0
  54. data/lib/ludy/paginator.rb +145 -0
  55. data/lib/ludy/pattern_matcher.rb +41 -0
  56. data/lib/ludy/proc.rb +3 -0
  57. data/lib/ludy/proc/bind.rb +21 -0
  58. data/lib/ludy/proc/chain.rb +17 -0
  59. data/lib/ludy/proc/compose.rb +9 -0
  60. data/lib/ludy/proc/curry.rb +42 -0
  61. data/lib/ludy/symbol.rb +3 -0
  62. data/lib/ludy/symbol/curry.rb +10 -0
  63. data/lib/ludy/symbol/to_msg.rb +10 -0
  64. data/lib/ludy/symbol/to_proc.rb +9 -0
  65. data/lib/ludy/tasks.rb +3 -0
  66. data/lib/ludy/tasks/common.rb +7 -0
  67. data/lib/ludy/tasks/preprocess_cpp.rb +70 -0
  68. data/lib/ludy/tasks/preprocess_cpp/attr_builder.rb +49 -0
  69. data/lib/ludy/tasks/preprocess_cpp/debug_hook.rb +36 -0
  70. data/lib/ludy/tasks/preprocess_cpp/header_guard.rb +17 -0
  71. data/lib/ludy/tasks/preprocess_cpp/template_forward_parameters.rb +45 -0
  72. data/lib/ludy/timer.rb +30 -0
  73. data/lib/ludy/variable.rb +29 -0
  74. data/lib/ludy/version.rb +9 -0
  75. data/lib/ludy/y_combinator.rb +11 -0
  76. data/lib/ludy/z_combinator.rb +11 -0
  77. data/lib/puzzle_generator.rb +53 -0
  78. data/lib/puzzle_generator/chain.rb +35 -0
  79. data/lib/puzzle_generator/chained_map.rb +113 -0
  80. data/lib/puzzle_generator/colored_map.rb +59 -0
  81. data/lib/puzzle_generator/map.rb +126 -0
  82. data/lib/puzzle_generator/misc.rb +137 -0
  83. data/lib/puzzle_generator/puzzle.rb +65 -0
  84. data/ludy.gemspec +25 -0
  85. data/spec/ludy_spec.rb +30 -0
  86. data/spec/spec_helper.rb +17 -0
  87. data/tasks/ann.rake +81 -0
  88. data/tasks/bones.rake +21 -0
  89. data/tasks/gem.rake +126 -0
  90. data/tasks/git.rake +41 -0
  91. data/tasks/manifest.rake +49 -0
  92. data/tasks/notes.rake +28 -0
  93. data/tasks/post_load.rake +39 -0
  94. data/tasks/rdoc.rake +51 -0
  95. data/tasks/rubyforge.rake +57 -0
  96. data/tasks/setup.rb +268 -0
  97. data/tasks/spec.rake +55 -0
  98. data/tasks/svn.rake +48 -0
  99. data/tasks/test.rake +38 -0
  100. data/test/deprecated/callstack.rb +18 -0
  101. data/test/deprecated/curry.rb +34 -0
  102. data/test/deprecated/rambda.rb +15 -0
  103. data/test/deprecated/this.rb +69 -0
  104. data/test/deprecated/ts_ludy.rb +26 -0
  105. data/test/deprecated/unzip_and_untranspose.rb +13 -0
  106. data/test/example_puzzle.rb +178 -0
  107. data/test/helper.rb +3 -0
  108. data/test/ludy/test_array.rb +63 -0
  109. data/test/ludy/test_class.rb +13 -0
  110. data/test/ludy/test_defun.rb +37 -0
  111. data/test/ludy/test_dices.rb +32 -0
  112. data/test/ludy/test_hash.rb +13 -0
  113. data/test/ludy/test_kernel.rb +36 -0
  114. data/test/ludy/test_lazy.rb +18 -0
  115. data/test/ludy/test_paginator.rb +84 -0
  116. data/test/ludy/test_proc.rb +58 -0
  117. data/test/ludy/test_require_all.rb +21 -0
  118. data/test/ludy/test_symbol.rb +15 -0
  119. data/test/ludy/test_variable.rb +39 -0
  120. data/test/ludy/test_y_combinator.rb +21 -0
  121. data/test/ludy/test_z_combinator.rb +20 -0
  122. data/test/multiruby.sh +2 -0
  123. metadata +252 -0
@@ -0,0 +1,49 @@
1
+
2
+ module Kernel
3
+ private
4
+ # just like attr_accessor for c++
5
+ def accessor type, *pros
6
+ (reader_only type, *pros) +
7
+ (writer_only type, *pros) +
8
+ (member_only type, *pros)
9
+ end
10
+
11
+ # just like attr_reader for c++
12
+ def reader type, *pros
13
+ (reader_only type, *pros) +
14
+ (member_only type, *pros)
15
+ end
16
+
17
+ # just like attr_writer for c++
18
+ def writer type, *pros
19
+ (writer_only type, *pros) +
20
+ (member_only type, *pros)
21
+ end
22
+
23
+ # create only reader(getter), no member and no writer(setter)
24
+ def reader_only type, *pros
25
+ result = "#{@prefix}public:\n"
26
+ pros.each{ |p|
27
+ # getter
28
+ result << "#{@prefix}#{@indent}#{type} #{p}() const{ return #{p}_; }\n"
29
+ }
30
+ result
31
+ end
32
+
33
+ # create only writer(setter), no member and no reader(getter)
34
+ def writer_only type, *pros
35
+ result = "#{@prefix}public:\n"
36
+ pros.each{ |p|
37
+ # setter
38
+ result << "#{@prefix}#{@indent}#{@class}& #{p}(#{type} const& new_#{p}){ #{p}_ = new_#{p}; return *this; }\n"
39
+ }
40
+ result
41
+ end
42
+
43
+ # create only member, no writer(setter) and no reader(getter)
44
+ def member_only type, *pros
45
+ result = "#{@prefix}private:\n"
46
+ result << "#{@prefix}#{@indent}#{type} #{pros.map{|p|"#{p}_"}.join(", ")};\n"
47
+ end
48
+
49
+ end # of Kernel
@@ -0,0 +1,36 @@
1
+
2
+ require 'ludy/tasks/common'
3
+
4
+ module Kernel
5
+ private
6
+ # it simply output:
7
+ # #ifndef NDEBUG
8
+ # #include <iostream>
9
+ # #endif
10
+ def debug_include
11
+ '#ifndef NDEBUG
12
+ #include <iostream>
13
+ #endif'
14
+ end
15
+ # example usage:
16
+ # void <% debug_hook 'C::f' do %>(){
17
+ # <% end %>
18
+ # std::cout << "hello" << std::endl;
19
+ # }
20
+ # became:
21
+ # void C::f(){
22
+ # #ifndef NDEBUG
23
+ # std::cerr << "method C::f called, for " << this << " at c.cpp: 12\n"
24
+ # #endif
25
+ # std::cout << "hello" << std::endl;
26
+ # }
27
+ def debug_hook name, &block
28
+ Ludy::erbout name, block.binding
29
+ block.call
30
+ Ludy::erbout "
31
+ #ifndef NDEBUG
32
+ std::clog << \"method #{name} called, for \" << this << \" at #{@file}: #{eval '__LINE__', block.binding}\\n\";
33
+ #endif
34
+ ", block.binding
35
+ end
36
+ end # of Kernel
@@ -0,0 +1,17 @@
1
+
2
+ require 'ludy/tasks/common'
3
+
4
+ module Kernel
5
+ private
6
+ # C/C++ header guard generator, you shold provide the final #endif yourself,
7
+ # and you should provide PROJ name for header guard prefix
8
+ def header_guard random_suffix = nil, &block
9
+ defined = "_#{Project.name.upcase}_#{@dir.upcase}_#{@class.upcase}_#{random_suffix.nil? ? '' : rand.to_s[2..-1]+'_'}"
10
+
11
+ Ludy::erbout "#ifndef #{defined}
12
+ #define #{defined}", block.binding
13
+ block.call
14
+ Ludy::erbout '#endif', block.binding
15
+ end
16
+
17
+ end # of Kernel
@@ -0,0 +1,45 @@
1
+
2
+ require 'ludy/array/combos'
3
+ require 'ludy/array/map_with_index'
4
+ require 'ludy/array/tail'
5
+
6
+ module Kernel
7
+ private
8
+ # forward template functions' generator
9
+ def for_template_parameters_within range, modifiers = ['volatile', 'const volatile']
10
+ modifiers = ['', 'const'] + modifiers
11
+ range.to_a.map_with_index{ |size, i|
12
+ ([(["T"]*modifiers.size).zip(
13
+ modifiers,
14
+ ['&']*modifiers.size)]*size).
15
+ map_with_index{ |args, arg_i|
16
+ args.map{ |arg|
17
+ # e.g., T0 const& a
18
+ "#{arg.first}#{arg_i} #{arg.tail.join} #{(arg_i+10).to_s(36)}"
19
+ }
20
+ }.combos.map{ |arg| arg.kind_of?(Array) ? arg.join(', ') : arg }
21
+ }.flatten.each{ |args_list| yield args_list }
22
+ end
23
+
24
+ # parameter for template
25
+ def template_parameters args_list
26
+ size = args_list.count(',') + 1
27
+ '<' + (['class T']*size).map_with_index{ |t, index|
28
+ "#{t}#{index}"
29
+ }.join(', ') + '>'
30
+ end
31
+
32
+ # the parameters' list
33
+ def forward_parameters args_list
34
+ args_list
35
+ end
36
+
37
+ # the arguments it passed
38
+ def arguments args_list
39
+ size = args_list.count(',') + 1
40
+ Array.new(size).map_with_index{ |not_important, i|
41
+ (i+10).to_s 36
42
+ }.join(', ')
43
+ end
44
+
45
+ end # of Kernel
@@ -0,0 +1,30 @@
1
+
2
+ module Ludy
3
+ # whenever a Timer was timeout, it was thrown
4
+ class Timeout < Exception; end
5
+ # simple and stupid timer for puzzle_generator...
6
+ class Timer
7
+ # create a timer for timeout seconds.
8
+ def initialize timeout
9
+ @timeout = timeout
10
+ end
11
+ # start ticking
12
+ def start
13
+ @now = Time.now
14
+ @parent = Thread.current
15
+ @thread = Thread.new{
16
+ sleep @timeout
17
+ @parent.raise Timeout.new("timeout for #{@timeout} seconds.")
18
+ }
19
+ self
20
+ end
21
+ # total time until start ticking
22
+ def total_time
23
+ Time.now - @now
24
+ end
25
+ # stop ticking
26
+ def stop
27
+ @thread.kill
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,29 @@
1
+
2
+ require 'ludy/kernel/public_send'
3
+ require 'ludy/class/undef_all_methods'
4
+
5
+ module Ludy
6
+
7
+ # a variable reference, used for side effect...
8
+ class Variable
9
+ undef_all_methods
10
+
11
+ # init the refered instance
12
+ def initialize obj
13
+ @__obj__ = obj
14
+ end
15
+
16
+ # delegator
17
+ def method_missing msg, *arg, &block
18
+ @__obj__.public_send msg, *arg, &block
19
+ end
20
+
21
+ attr_accessor :__obj__
22
+ end
23
+
24
+ # provided for creating lazy object more convient
25
+ def var arg
26
+ Variable.new arg
27
+ end
28
+
29
+ end # of Ludy
@@ -0,0 +1,9 @@
1
+
2
+ require 'rubygems'
3
+ module Ludy
4
+ GEM_RUBY_VERSION = Gem::Version.new(::RUBY_VERSION)
5
+ module_function
6
+ def ruby_before ver
7
+ GEM_RUBY_VERSION < Gem::Version.new(ver)
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+
2
+ require 'ludy/lazy'
3
+
4
+ module Ludy
5
+
6
+ # the Y combinator, with lazy stuff
7
+ Y = lambda{|f|
8
+ lambda{|x| lazy{f[x[x]]} }[lambda{|x| lazy{f[x[x]]} }]
9
+ }
10
+
11
+ end # of Ludy
@@ -0,0 +1,11 @@
1
+
2
+ module Ludy
3
+
4
+ # the Z combinator, without lazy stuff
5
+ Z = lambda{|f|
6
+ lambda{|x| f[lambda{|y| x[x][y]}]}[
7
+ lambda{|x| f[lambda{|y| x[x][y]}]}
8
+ ]
9
+ }
10
+
11
+ end # of Ludy
@@ -0,0 +1,53 @@
1
+
2
+ # alpha at 2007.10.14
3
+
4
+ require 'puzzle_generator/puzzle'
5
+
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....
11
+
12
+ # puzzle generator for shooting-cubes[http://shooting-cubes.googlecodes.com],
13
+ # example usage:
14
+ # PuzzleGenerator.debug = true
15
+ # pg = PuzzleGenerator::Puzzle.new :level => 4, :timeout => 2, :invoke_max => 5
16
+ # begin
17
+ # pg.generate
18
+ # pg.display_map
19
+ # rescue Ludy::Timeout => e
20
+ # puts e
21
+ # ensure
22
+ # p pg.tried_times
23
+ # p pg.tried_duration
24
+ # end
25
+ module PuzzleGenerator
26
+
27
+ def self.generate_chained_map option = {} #:nodoc:
28
+ generate_klass ChainedMap, option
29
+ end
30
+ def self.generate_klass klass, option = {} #:nodoc:
31
+ option.reverse_merge! :timeout => 5
32
+ generate(option[:timeout]){ klass.new option }
33
+ end
34
+
35
+ LastTriedInfo = {} # :nodoc:
36
+ # generate someing with generator with timeout, used in Puzzle#generate
37
+ def self.generate timeout = 5, &generator
38
+ timer = Ludy::Timer.new(timeout).start
39
+ tried_times = 1
40
+ begin
41
+ result = generator.call
42
+ until result.result_map.kind_of? Array
43
+ tried_times += 1
44
+ result = generator.call
45
+ end
46
+ ensure
47
+ # timer.stop
48
+ LastTriedInfo.merge! :tried_times => tried_times, :tried_duration => timer.total_time
49
+ end
50
+ result
51
+ end
52
+
53
+ end
@@ -0,0 +1,35 @@
1
+
2
+ require 'puzzle_generator/misc'
3
+
4
+ module PuzzleGenerator
5
+
6
+ class Chain # :nodoc:
7
+ include Enumerable
8
+ def initialize position = [0, 0], direct = Up, invoke = DefaultOption[:invoke]
9
+ @direct = direct
10
+ x, y = position
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)
15
+ end
16
+ end
17
+ def <=> rhs; @data <=> rhs.instance_variable_get('@data'); end
18
+ def == rhs; (self <=> rhs) == 0; end
19
+ alias_method :eql?, :==
20
+ def hash; @data.hash; end
21
+ def each &block; @data.each &block; self end
22
+ def [] index; @data[index]; end
23
+ def to_a; @data.clone; end
24
+ def up?; @direct == Up; end
25
+ def bound_ok? max_width, max_height
26
+ not @data.find{ |i|
27
+ i.first >= max_width ||
28
+ i.last >= max_height ||
29
+ i.first < 0 ||
30
+ i.last < 0
31
+ }
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,113 @@
1
+
2
+ require 'puzzle_generator/misc'
3
+ require 'puzzle_generator/chain'
4
+ require 'puzzle_generator/map'
5
+
6
+ require 'ludy/kernel/deep_copy'
7
+ require 'ludy/array/combine'
8
+ require 'ludy/array/rotate'
9
+ require 'ludy/array/choice' # for Array#choice!
10
+ require 'ludy/array/product'
11
+
12
+ module PuzzleGenerator
13
+
14
+ # 1. put a chain
15
+ # 2. destroy a chain by chain
16
+ # 2. a. choose a position by last map
17
+ # 2. b. choose a direct from 3 direct (memo p+d)
18
+ # 2. c. check if the position + direct is ok? ok pass, failed choose again
19
+ # 2. d. goto 2
20
+
21
+ class ChainedMap # :nodoc:
22
+ include DisplayMap, MapUtils
23
+ attr_reader :maps, :option
24
+ def initialize option = {}
25
+ @option = DefaultOption.merge option
26
+ raise_if_bad_argument
27
+ init_map
28
+ @result_map = begin next_level until @maps.size >= @option[:level]; put_fire_point
29
+ rescue GenerationFailed; $! end
30
+ end
31
+
32
+ private
33
+ def raise_if_bad_argument
34
+ msg = []
35
+ @option.each{ |name, value| msg << "#{name} should be greater than 1." if value <= 1 }
36
+ raise ArgumentError.new(msg.join("\n")) unless msg.empty?
37
+ end
38
+ def make_map; Map.new @option; end
39
+ def init_map
40
+ @maps = [make_map]
41
+ @result_map = make_map_array
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
+ put_picked_chain_on @maps
45
+ resolve_map
46
+ end
47
+ # please make this init chain to variable length chain
48
+ def make_init_chains positions
49
+ positions.inject([]){ |result, pos| result << Chain.new(pos, Right, @option[:invoke]) }
50
+ end
51
+
52
+ def chain_ok?
53
+ raise GenerationFailed.new("ChainedMap: last result_map: #{@result_map.inspect}") if @picked_chain.nil?
54
+ @maps_preview = @maps.deep_copy
55
+ put_picked_chain_on @maps_preview
56
+
57
+ result = check_overlap_and_resolve_it &&
58
+ check_broken_except_last &&
59
+ check_answer_correctness(@result_map_preview) # need this if you gen variable length chain
60
+
61
+ @maps_preview = nil
62
+ @result_map_preview = nil
63
+ result
64
+ end
65
+ def next_level new_map = nil
66
+ @maps << (new_map || make_map)
67
+ chains = @maps[-1].break_chains @maps[-2], @result_map
68
+
69
+ @picked_chain = chains.choice!
70
+ @picked_chain = chains.choice! until chain_ok?
71
+
72
+ put_picked_chain_on @maps
73
+ @picked_chain = nil
74
+ resolve_map
75
+ end
76
+ def put_fire_point; next_level Map.new(@option.merge(:invoke => 1, :invoke_max => 1)); end
77
+ def put_picked_chain_on maps
78
+ maps.last.chains << @picked_chain
79
+ @picked_chain.each{ |pos|
80
+ x, y = pos
81
+ maps.each{ |map|
82
+ column = map[x]
83
+ column.replace(column[0...y] + column[y..-1].rotate)
84
+ }
85
+ maps.last[x, y] = maps.size
86
+ }
87
+ end
88
+ def check_overlap_and_resolve_it
89
+ @result_map_preview = @maps_preview[0...-1].inject(make_map_array){ |result, map|
90
+ result.each_with_index{ |column, x|
91
+ column.each_with_index{ |value, y|
92
+ # assert one of them is zero or they are all zero
93
+ return false unless value * map[x, y] == 0
94
+ }
95
+ }
96
+ combine_map result, map
97
+ }
98
+ end
99
+ def check_broken_except_last
100
+ @maps_preview[0...-1].all?{ |map|
101
+ result = true
102
+ map.each_with_index_2d{ |i, x, y|
103
+ result &&= !check_left_chain( map, x, y) &&
104
+ !check_right_chain(map, x, y) &&
105
+ !check_up_chain( map, x, y) &&
106
+ !check_down_chain( map, x, y)
107
+ }
108
+ result
109
+ }
110
+ end
111
+ end
112
+
113
+ end