@@ -23,38 +23,11 @@ def initialize(tiles, width, height)
2323 @width = width . to_i
2424 @height = height . to_i
2525 @cells = [ ]
26- build_tile_adjacencies
2726 @height . times { |y | @width . times { |x | @cells << Cell . new ( x , y , @tiles . shuffle ) } }
2827 @uncollapsed_cells = @cells . reject ( &:collapsed )
2928 @max_entropy = @tiles . length
3029 end
3130
32- def build_tile_adjacencies
33- # Pre-compute which tiles can be adjacent in each direction
34- # This transforms the O(n²) runtime matching into O(1) lookup
35- # We build a mapping from edge hash -> list of tiles with that edge in opposite direction
36- @edge_to_tiles = { }
37-
38- [ :up , :right , :down , :left ] . each do |direction |
39- @edge_to_tiles [ direction ] = { }
40-
41- opposite_direction = OPPOSITE_OF [ direction ]
42-
43- # For each tile, index it by its opposite edge
44- @tiles . each do |tile |
45- opposite_edge = case opposite_direction
46- when :up then tile . up
47- when :right then tile . right
48- when :down then tile . down
49- when :left then tile . left
50- end
51-
52- @edge_to_tiles [ direction ] [ opposite_edge ] ||= [ ]
53- @edge_to_tiles [ direction ] [ opposite_edge ] << tile
54- end
55- end
56- end
57-
5831 def cell_at ( x , y )
5932 @cells [ @width * y + x ]
6033 end
@@ -140,33 +113,41 @@ def evaluate_neighbor(source_cell, evaluation_direction)
140113 return if neighbor_cell . collapsed
141114
142115 original_tile_count = neighbor_cell . tiles . length
116+ opposite_direction = OPPOSITE_OF [ evaluation_direction ]
143117 neighbor_tiles = neighbor_cell . tiles
144118
145- # Collect all valid adjacent tiles from all source tiles
146- # Using pre-computed edge-to-tiles lookup with fast intersection via object_id
147- valid_tile_ids = { }
148- source_cell . tiles . each do |source_tile |
149- # Get the edge of this source tile in the evaluation direction
150- source_edge = case evaluation_direction
119+ source_tile_edges = source_cell . tiles . map do |source_tile |
120+ case evaluation_direction
151121 when :up then source_tile . up
152122 when :right then source_tile . right
153123 when :down then source_tile . down
154124 when :left then source_tile . left
155125 end
126+ end
156127
157- # Look up all tiles that can be adjacent (pre-computed)
158- compatible_tiles = @edge_to_tiles [ evaluation_direction ] [ source_edge ]
159- if compatible_tiles
160- compatible_tiles . each do | tile |
161- valid_tile_ids [ tile . __id__ ] = tile
162- end
128+ opposite_tile_edges = neighbor_tiles . map do | opposite_tile |
129+ case opposite_direction
130+ when :up then opposite_tile . up
131+ when :right then opposite_tile . right
132+ when :down then opposite_tile . down
133+ when :left then opposite_tile . left
163134 end
164135 end
165136
166- # Keep only neighbor tiles that are in the valid set (O(n) intersection)
167137 new_tiles = [ ]
168- neighbor_tiles . each do |neighbor_tile |
169- new_tiles << neighbor_tile if valid_tile_ids [ neighbor_tile . __id__ ]
138+ ntc = neighbor_tiles . length
139+ i = 0
140+ while i < ntc
141+ ii = 0
142+ stel = source_tile_edges . length
143+ while ii < stel
144+ if source_tile_edges [ ii ] == opposite_tile_edges [ i ]
145+ new_tiles << neighbor_tiles [ i ]
146+ break
147+ end
148+ ii = ii . succ
149+ end
150+ i = i . succ
170151 end
171152
172153 neighbor_cell . tiles = new_tiles unless new_tiles . empty?
0 commit comments