【问题标题】:How can I use TDD to solve a puzzle with an unknown answer?如何使用 TDD 解决未知答案的难题?
【发布时间】:2011-05-31 05:29:19
【问题描述】:

最近我写了一个 Ruby 程序来确定"Scramble Squares" 拼图的解决方案:

我使用 TDD 来实现其中的大部分内容,导致测试看起来像这样:

it "has top, bottom, left, right" do
  c = Cards.new
  card = c.cards[0]
  card.top.should == :CT
  card.bottom.should == :WB
  card.left.should == :MT
  card.right.should == :BT
end

这适用于较低级别的“辅助”方法:识别图块的“边”,确定图块是否可以有效地放置在网格中,等等。

但我在编写解决难题的实际算法时遇到了问题。由于我不知道问题的有效可能解决方案,我不知道如何先编写测试。

我最终写了一个非常丑陋的未经测试的算法来解决它:

  def play_game
    working_states = []
    after_1 = step_1
    i = 0
    after_1.each do |state_1|
      step_2(state_1).each do |state_2|
        step_3(state_2).each do |state_3|
          step_4(state_3).each do |state_4|
            step_5(state_4).each do |state_5|
              step_6(state_5).each do |state_6|
                step_7(state_6).each do |state_7|
                  step_8(state_7).each do |state_8|
                    step_9(state_8).each do |state_9|
                      working_states << state_9[0]
                    end
                  end
                end
              end
            end
          end
        end
      end
    end 

所以我的问题是:当您还不知道有效输出时,如何使用 TDD 编写方法?

如果你有兴趣,代码在 GitHub 上:

【问题讨论】:

    标签: tdd puzzle scramble


    【解决方案1】:

    来自puzzle website

    Scramble Squares® 的对象 益智游戏是排列九 色彩鲜艳的方形件 成一个 12" x 12" 的正方形,这样 作品上的逼真图形' 边缘完美匹配,形成一个 完成各个方向的设计。

    因此,我首先要寻找的是测试两个瓷砖是否以特定的排列方式相互匹配。这是关于你的有效性问题。如果该方法无法正常工作,您将无法评估谜题是否已解决。这似乎是一个不错的起点,是完整解决方案的一小部分。当然,这还不是算法。

    一旦match() 工作,我们从这里去哪里?好吧,一个明显的解决方案是蛮力:从网格内所有可能的瓷砖排列的集合中,拒绝任何两个相邻瓷砖不匹配的那些。这是一种算法,可以说是肯定会起作用(尽管在许多谜题中,宇宙的热寂发生在解决方案之前)。

    如何收集沿给定边缘匹配的所有图块对 (LTRB)?你能从那里更快地找到解决方案吗?当然,您可以轻松地对其进行测试(并试驾)。

    这些测试不太可能你一个算法,但它们可以帮助你思考算法,当然它们可以让你的方法更容易验证。

    【讨论】:

      【解决方案2】:

      这不是一个直接的答案,但这让我想起了 Peter Norvig 和 Ron Jeffries 编写的数独求解器之间的the comparison。 Ron Jeffries 的方法使用了经典的 TDD,但他从未真正找到一个好的解决方案。另一方面,Norvig 在没有 TDD 的情况下能够非常优雅地解决它。

      基本问题是:可以使用 TDD 出现算法吗?

      【讨论】:

      • 我认为您必须先了解算法(或至少了解其中的一部分),然后才能为其编写测试。 +1 链接,非常有趣。
      • pindancing.blogspot.com/2009/09/sudoku-in-coders-at-work.html 从您的链接链接似乎讨论了对 o.p. 的一种“答案”
      • 感谢大家的链接。似乎在这个特定问题空间(生成算法来解决难题)中,“使用测试来找出设计”的方法往往会导致笨拙或低效的解决方案。它让我想起了these criticisms of TDD。我不确定您是否可以对流程本身做出更全面的判断。至少,在深入解决实际问题之前,我非常很高兴有可用的(和测试过的)较低级别的方法。
      【解决方案3】:

      不知道这是否“回答”了这个问题

      解析“谜题”

      9 块瓷砖
      每个有 4 个面
      每块瓷砖都有半个图案/图片

      蛮力方法

      解决这个问题 你需要生成 9!组合(9 块 X 8 块 X 7 块...)

      受限于与当前图块匹配的边数

      考虑的方法

      Q 有多少边不同? IE 有多少匹配项?

      因此 9 X 4 = 36 边 / 2(因为每一边“必须”至少匹配另一边)
      否则这是一个无法完成的难题
      注意:对于 3 X 3 拼图,至少有 12 个必须“正确”匹配

      使用唯一的字母标记图块的每个匹配面

      然后建立一个包含每个瓷砖的桌子
      对于每个图块,您需要在表中输入 4 个条目
      4 个边(角)因此 4 个组合
      如果您将表格并排排序并索引到表格中

      边,tile_number
      ABcd tile_1
      BCda tile_1
      CDab tile_1
      DAbc tile_1

      使用表格可以加快速度
      因为您最多只需要匹配 1 或 2 个边
      这限制了它必须放置的非生产性瓷砖的数量

      取决于图案/图片的设计
      有 3 种组合(方向),因为每个图块可以使用 3 个方向放置
      - 相同(同一图块的多个副本)
      - 反射
      - 旋转

      如果他们决定让生活变得非常困难,上帝会帮助我们
      通过将相似的图案/图片放在同样需要匹配的另一侧
      或者甚至将瓷砖制成立方体并匹配 6 个面!!!

      使用 TDD,
      您将编写测试,然后编写代码来解决问题的每个小部分,
      如上所述并编写更多测试和代码来解决整个问题

      不,这并不容易,你需要坐下来编写测试和代码来练习

      注意:这是地图着色问题的变体
      http://en.wikipedia.org/wiki/Four_color_theorem

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-26
        • 2012-05-10
        • 1970-01-01
        相关资源
        最近更新 更多