如何使用 TDD 解决未知答案的难题?
Posted
技术标签:
【中文标题】如何使用 TDD 解决未知答案的难题?【英文标题】:How can I use TDD to solve a puzzle with an unknown answer? 【发布时间】: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 上:
测试:https://github.com/mattdsteele/scramblesquares-solver/blob/master/golf-creator-spec.rb 生产代码:https://github.com/mattdsteele/scramblesquares-solver/blob/master/game.rb【问题讨论】:
【参考方案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
【讨论】:
以上是关于如何使用 TDD 解决未知答案的难题?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 newtonsoft json 解决有关无法反序列化当前(例如 “name”:“value”)的难题 [关闭]