godfat-ludy 0.1.13
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +226 -0
- data/LICENSE +201 -0
- data/NOTICE +21 -0
- data/README +212 -0
- data/Rakefile +56 -0
- data/TODO +21 -0
- data/bin/ludy +11 -0
- data/lib/ludy.rb +74 -0
- data/lib/ludy/all.rb +3 -0
- data/lib/ludy/array.rb +3 -0
- data/lib/ludy/array/body.rb +9 -0
- data/lib/ludy/array/choice.rb +16 -0
- data/lib/ludy/array/combine.rb +17 -0
- data/lib/ludy/array/combos.rb +35 -0
- data/lib/ludy/array/count.rb +9 -0
- data/lib/ludy/array/filter.rb +4 -0
- data/lib/ludy/array/foldl.rb +5 -0
- data/lib/ludy/array/foldr.rb +8 -0
- data/lib/ludy/array/head.rb +4 -0
- data/lib/ludy/array/map_with_index.rb +8 -0
- data/lib/ludy/array/pad.rb +13 -0
- data/lib/ludy/array/product.rb +16 -0
- data/lib/ludy/array/rotate.rb +21 -0
- data/lib/ludy/array/tail.rb +8 -0
- data/lib/ludy/blackhole.rb +17 -0
- data/lib/ludy/class.rb +3 -0
- data/lib/ludy/class/undef_all_methods.rb +9 -0
- data/lib/ludy/deprecated/aspect.rb +26 -0
- data/lib/ludy/deprecated/callstack.rb +24 -0
- data/lib/ludy/deprecated/curry.rb +29 -0
- data/lib/ludy/deprecated/rambda.rb +23 -0
- data/lib/ludy/deprecated/this.rb +14 -0
- data/lib/ludy/deprecated/untranspose.rb +12 -0
- data/lib/ludy/deprecated/unzip.rb +7 -0
- data/lib/ludy/dices.rb +66 -0
- data/lib/ludy/hash.rb +3 -0
- data/lib/ludy/hash/reverse_merge.rb +11 -0
- data/lib/ludy/helpers/check_box.rb +24 -0
- data/lib/ludy/kernel.rb +3 -0
- data/lib/ludy/kernel/deep_copy.rb +8 -0
- data/lib/ludy/kernel/defun.rb +10 -0
- data/lib/ludy/kernel/ergo.rb +16 -0
- data/lib/ludy/kernel/id.rb +8 -0
- data/lib/ludy/kernel/if_else.rb +14 -0
- data/lib/ludy/kernel/m.rb +5 -0
- data/lib/ludy/kernel/maybe.rb +9 -0
- data/lib/ludy/kernel/public_send.rb +15 -0
- data/lib/ludy/kernel/singleton_method.rb +15 -0
- data/lib/ludy/kernel/tap.rb +12 -0
- data/lib/ludy/lazy.rb +32 -0
- data/lib/ludy/list.rb +21 -0
- data/lib/ludy/message_dispatcher.rb +57 -0
- data/lib/ludy/namespace.rb +71 -0
- data/lib/ludy/paginator.rb +145 -0
- data/lib/ludy/pattern_matcher.rb +41 -0
- data/lib/ludy/proc.rb +3 -0
- data/lib/ludy/proc/bind.rb +21 -0
- data/lib/ludy/proc/chain.rb +17 -0
- data/lib/ludy/proc/compose.rb +9 -0
- data/lib/ludy/proc/curry.rb +42 -0
- data/lib/ludy/symbol.rb +3 -0
- data/lib/ludy/symbol/curry.rb +10 -0
- data/lib/ludy/symbol/to_msg.rb +10 -0
- data/lib/ludy/symbol/to_proc.rb +9 -0
- data/lib/ludy/tasks.rb +3 -0
- data/lib/ludy/tasks/common.rb +7 -0
- data/lib/ludy/tasks/preprocess_cpp.rb +70 -0
- data/lib/ludy/tasks/preprocess_cpp/attr_builder.rb +49 -0
- data/lib/ludy/tasks/preprocess_cpp/debug_hook.rb +36 -0
- data/lib/ludy/tasks/preprocess_cpp/header_guard.rb +17 -0
- data/lib/ludy/tasks/preprocess_cpp/template_forward_parameters.rb +45 -0
- data/lib/ludy/timer.rb +30 -0
- data/lib/ludy/variable.rb +29 -0
- data/lib/ludy/version.rb +9 -0
- data/lib/ludy/y_combinator.rb +11 -0
- data/lib/ludy/z_combinator.rb +11 -0
- data/lib/puzzle_generator.rb +53 -0
- data/lib/puzzle_generator/chain.rb +35 -0
- data/lib/puzzle_generator/chained_map.rb +113 -0
- data/lib/puzzle_generator/colored_map.rb +59 -0
- data/lib/puzzle_generator/map.rb +126 -0
- data/lib/puzzle_generator/misc.rb +137 -0
- data/lib/puzzle_generator/puzzle.rb +65 -0
- data/ludy.gemspec +25 -0
- data/spec/ludy_spec.rb +30 -0
- data/spec/spec_helper.rb +17 -0
- data/tasks/ann.rake +81 -0
- data/tasks/bones.rake +21 -0
- data/tasks/gem.rake +126 -0
- data/tasks/git.rake +41 -0
- data/tasks/manifest.rake +49 -0
- data/tasks/notes.rake +28 -0
- data/tasks/post_load.rake +39 -0
- data/tasks/rdoc.rake +51 -0
- data/tasks/rubyforge.rake +57 -0
- data/tasks/setup.rb +268 -0
- data/tasks/spec.rake +55 -0
- data/tasks/svn.rake +48 -0
- data/tasks/test.rake +38 -0
- data/test/deprecated/callstack.rb +18 -0
- data/test/deprecated/curry.rb +34 -0
- data/test/deprecated/rambda.rb +15 -0
- data/test/deprecated/this.rb +69 -0
- data/test/deprecated/ts_ludy.rb +26 -0
- data/test/deprecated/unzip_and_untranspose.rb +13 -0
- data/test/example_puzzle.rb +178 -0
- data/test/helper.rb +3 -0
- data/test/ludy/test_array.rb +63 -0
- data/test/ludy/test_class.rb +13 -0
- data/test/ludy/test_defun.rb +37 -0
- data/test/ludy/test_dices.rb +32 -0
- data/test/ludy/test_hash.rb +13 -0
- data/test/ludy/test_kernel.rb +36 -0
- data/test/ludy/test_lazy.rb +18 -0
- data/test/ludy/test_paginator.rb +84 -0
- data/test/ludy/test_proc.rb +58 -0
- data/test/ludy/test_require_all.rb +21 -0
- data/test/ludy/test_symbol.rb +15 -0
- data/test/ludy/test_variable.rb +39 -0
- data/test/ludy/test_y_combinator.rb +21 -0
- data/test/ludy/test_z_combinator.rb +20 -0
- data/test/multiruby.sh +2 -0
- 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
|
data/lib/ludy/timer.rb
ADDED
@@ -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
|
data/lib/ludy/version.rb
ADDED
@@ -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 █ @data.each █ 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
|