如何使用 TDD 来解决答案未知的难题?

发布于 2024-10-09 07:46:43 字数 1970 浏览 8 评论 0原文

最近,我编写了一个 Ruby 程序来确定 “打乱方块” 方块拼图:

我使用 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:

Recently I wrote a Ruby program to determine solutions to a "Scramble Squares" tile puzzle:

I used TDD to implement most of it, leading to tests that looked like this:

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

This worked well for the lower-level "helper" methods: identifying the "sides" of a tile, determining if a tile can be validly placed in the grid, etc.

But I ran into a problem when coding the actual algorithm to solve the puzzle. Since I didn't know valid possible solutions to the problem, I didn't know how to write a test first.

I ended up writing a pretty ugly, untested, algorithm to solve it:

  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 

So my question is: how do you use TDD to write a method when you don't already know the valid outputs?

If you're interested, the code's on GitHub:

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

若相惜即相离 2024-10-16 07:46:43

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

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

This isn't a direct answer, but this reminds me of the comparison between the Sudoku solvers written by Peter Norvig and Ron Jeffries. Ron Jeffries' approach used classic TDD, but he never really got a good solution. Norvig, on the other hand, was able to solve it very elegantly without TDD.

The fundamental question is: can an algorithm emerge using TDD?

鹿童谣 2024-10-16 07:46:43

来自拼图网站

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

因此,我首先要寻找的事情之一就是测试特定排列中的两个图块是否彼此匹配。这是关于你的有效性问题。如果该方法不能正常工作,您就无法评估难题是否已解决。这似乎是一个很好的起点,是完整解决方案的一小部分。当然,它还不是一种算法。

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

收集沿着给定边 (LTRB) 匹配的所有图块对的集合怎么样?您能更快地找到解决方案吗?当然,您可以轻松地测试(并试驾)它。

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

From the puzzle website:

The object of the Scramble Squares®
puzzle game is to arrange the nine
colorfully illustrated square pieces
into a 12" x 12" square so that the
realistic graphics on the pieces'
edges match perfectly to form a
completed design in every direction.

So one of the first things I would look for is a test of whether two tiles, in a particular arrangement, match one another. This is with regard to your question of validity. Without that method working correctly, you can't evaluate whether the puzzle has been solved. That seems like a nice starting point, a nice bite-sized piece toward the full solution. It's not an algorithm yet, of course.

Once match() is working, where do we go from here? Well, an obvious solution is brute force: from the set of all possible arrangements of the tiles within the grid, reject those where any two adjacent tiles don't match. That's an algorithm, of sorts, and it's pretty certain to work (although in many puzzles the heat death of the universe occurs before a solution).

How about collecting the set of all pairs of tiles that match along a given edge (LTRB)? Could you get from there to a solution, quicker? Certainly you can test it (and test-drive it) easily enough.

The tests are unlikely to give you an algorithm, but they can help you to think about algorithms, and of course they can make validating your approach easier.

陈独秀 2024-10-16 07:46:43

不知道这是否“回答”了问题,或者

对“拼图”

9块的分析
每个都有 4 个面
每个瓷砖有一半的图案/图片

BRUTE FORCE APPROACH

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

受到与当前块已就位的匹配边数的限制

考虑的方法

问 有多少边不同?
IE 有多少个匹配项?

因此 9 X 4 = 36 边 / 2 (因为每一边“必须”与至少 1 个其他边匹配)
否则它就是一个无法完成的谜题
注意:对于 3 X 3 拼图,至少 12 个必须“正确”匹配,并且

使用唯一的字母在图块的每个匹配侧添加标签

,然后构建一个包含每个图块的表格
每个图块需要在表中输入 4 个条目
4 个边(角)因此有 4 种组合
如果您对表进行并排排序并将 INDEX 放入表

侧,tile_number
ABcd 瓷砖_1
BCda 图块_1
CDab 磁贴_1
DAbctile_1

使用表格应该会加快速度
因为您最多只需要匹配 1 或 2 条边
这限制了非生产性瓷砖的放置量,具体

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

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

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

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

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

dunno if this "answers" the question either

analysis of the "puzzle"

9 tiles
each has 4 sides
each tile has half a pattern / picture

BRUTE FORCE APPROACH

to solve this problem
you need to generate 9! combinations ( 9 tiles X 8 tiles X 7 tiles... )

limited by the number of matching sides to the current tile(s) already in place

CONSIDERED APPROACH

Q How many sides are different?
IE how many matches are there?

therefore 9 X 4 = 36 sides / 2 ( since each side "must" match at least 1 other side )
otherwise its an uncompleteable puzzle
NOTE: at least 12 must match "correctly" for a 3 X 3 puzzle

label each matching side of a tile using a unique letter

then build a table holding each tile
you will need 4 entries into the table for each tile
4 sides ( corners ) hence 4 combinations
if you sort the table by side and INDEX into the table

side,tile_number
ABcd tile_1
BCda tile_1
CDab tile_1
DAbc tile_1

using the table should speed things up
since you should only need to match 1 or 2 sides at most
this limits the amount of NON PRODUCTIVE tile placing it has to do

depending on the design of the pattern / picture
there are 3 combinations ( orientations ) since each tile can be placed using 3 orientations
- the same ( multiple copies of the same tile )
- reflection
- rotation

God help us if they decide to make life very difficult
by putting similar patterns / pictures on the other side that also need to match
OR even making the tiles into cubes and matching 6 sides!!!

Using TDD,
you would write tests and then code to solve each small part of the problem,
as outlined above and write more tests and code to solve the whole problem

NO its not easy, you need to sit and write tests and code to practice

NOTE: this is a variation of the map colouring problem
http://en.wikipedia.org/wiki/Four_color_theorem

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文