给定一组填字游戏线索,生成兼容的填字游戏网格

时间:2015-09-18 09:57:33

标签: ruby algorithm combinations

我在两个数组中有多个填字游戏线索,用于上下线索(每个线索都是一对 - [clue_number,clue_length]。我正在尝试为这个填字游戏找到一个兼容的网格,(假设所有的答案单词都是相同的字母,即不要打扰实际的答案 - 只需使用长度和数字来找到兼容的网格。

我假设网格是13 x 13(这个测试示例,我知道,有一个13 x 13的解决方案)。到目前为止,我正在计算所有组合,用于在黑色方块中定位“跨”字。我们的想法是检查每个选项,如果它也适合下行线索,接受它。然而,这已经有~10 ^ 17种组合(网格尺寸为13 x 13和上述测试数据集)。我想知道是否有更有效的方法在合理的时间内解决这个问题。我到目前为止的代码如下所示:

ACROSS_CLUES = [
  [1, 5],  [6, 5],  [9, 7],  [10, 5],  [11, 5],  [12, 5],  [13, 7],  [15, 3], [17, 4],[18, 6],[19, 5],  [20, 6],  [22, 4],  [24, 3],  [25, 7],  [26, 5],  [27, 5], [28, 5],  [29, 7],  [30, 5],  [31, 5]]

DOWN_CLUES = [
  [2, 6],  [3, 6],  [4, 3],  [5, 5],  [6, 7],  [7, 4],  [8, 6],  [12, 5],  [13, 5],  [14, 5],  [15, 5],  [16, 5],  [18, 5],  [19, 7],  [21, 6], [22, 6],  [23, 6], [25, 5],  [26, 4],  [28, 3]
]

ACROSS_DIRECTION = :across
DOWN_DIRECTION = :down

# merge the across and down clues into a single array sorted by the clue number
CLUES = ACROSS_CLUES.map{|ac|ac + [:across]} + DOWN_CLUES.map{|dc| dc + [:down]}.sort_by{|c| c.first}

UNINITIALIZED = -2
BLACK = -1
BLANK = 0

SIDE = 13
SIZE = SIDE ** 2

# a fragment is a string of clue_length characters (number followed by blanks), which is rendered in the grid
def get_fragment(clue)
  clue_number = clue[0]
  clue_length = clue[1]
  fragment = [clue_number] + Array.new(clue_length - 1, BLANK)
end

# returns the first compatible grid found
def get_grid
  fragments = [] 
  ACROSS_CLUES.each do |clue|
    fragments << get_fragment(clue)
  end
  across_clues_length = fragments.flatten.count

  grid = Array.new(SIZE - across_clues_length + fragments.length, UNINITIALIZED) 
  grid_length = grid.length
  (0..(grid_length - 1)).to_a.combination(fragments.length).each do |num_locations|
    fragments.each_with_index do |fragment, fragment_index| 
      num_location = num_locations[fragment_index]
      grid[num_location] = fragment
    end
    grid.flatten!
    # TODO: check if grid is compatible, return if valid; reject if invalid
    grid = Array.new(SIZE - across_clues_length + fragments.length, UNINITIALIZED) 
  end
  grid
end

grid = get_grid

0 个答案:

没有答案