Backtracking solution for programming exercise (fitting pipes)

旧城冷巷雨未停 提交于 2019-12-03 12:21:56
andrew cooke

original reply

do you have to write all the code yourself or are you interested in exploring other tools? because i would suggest looking at constraint propagation / linear programming. you already have a lot of boundary constraints - that the outer edges cannot have pipes, plus the inner edges - so i imagine this will work quite efficiently. also, the constraints look like they will be simple equalities, so it should be pretty easy to set up.

i don't have enough experience with this to give more details here (although if i have time in the next week i may give it a go at some point), but if this kind of thing is interesting there's a bit more background in another answer i wrote some time ago.

ps interesting question; thanks for posting this.

[edit: if you cannot use other libraries then you can do the constraint propagation yourself. there's a wonderful article by norvig that shows how to do this for sudoku. i would strongly suggest reading that - i think you will see how to carry the techniques across, even though it's sudoku and python.]

updated reply (2012-04-06 - updated with blog references; old comments were buggy)

a depth-first search, where the next empty cell is filled with each available, consistent tile, and the consistency check includes both edge constraints (no pipes off the edge) and nearest neighbours, is quite efficient.  i have an unoptimized implementation in clojure that will solve the smaller example in around 0.4ms (1000 in 360ms after JVM warmup) and the larger in 3ms (cedric van goethem reports 1ms for an optimised - but still OO - java implementation, which seems reasonable).  it can solve a 10x10 puzzle (concentric circles of tubes with no initial hints) in 12s.

i also spent time looking at a "smart" approach, which tracks constraints on each cell, much like in norvig's paper above. and then i tried using choco. all this is described in much more detail in blog posts here (i did have more details in an update to this answer, but they were based on buggy code - the blog has more, better information). the source is also available for download.

the general conclusion from all this was that direct search is fine up to 10x10. after that, more smarts may help, but it's difficult to be sure because generating test cases is hard (they tend to be ambiguous, even when lots of cells are given).

Nice problem. I've found a solution in O(n·m·8^m), which seems to be sufficent.

  1. Focus on the border between the first and the second row. There are 2^m possibilities (outgoing line or not, for each side). This will be the upper border line, the lower border line will be no connection at each side.

  2. For each pair of lower border line and upper border line (which will be 2^m·2^m = 4^m pairs), calculate each row that fits in. If you come from the left, you are given the left side, the top side and the bottom side, so you only have 2 possibilities. If the tile you look at is fixed in the map, check that it fits in and abort otherwise. Call this recursively and you get 2^m rows each or 4^m*2^m=8^m in total.

  3. While the last step was pure brute force, we use DP this time. Safe the tuple (border, bricks used, row) in an array of arrays. array[0] will contain a single tuple (empty-border, no-brick-used, nothing). array[n] contains all 8^m generated rows in row n (starting at 1) combined with each item in array[n-1] it fits on (i.e. the border of the item is the same as the lower border of the row) Notice that if you smartly combine this condition with the loop in step 2, this costs you nothing.

  4. Remove all tuples which needs more bricks of one sort than available and sort the array. Then continue on step 2 until all rows are handled.

  5. If you have finished, check in array[n] for the tuple (empty-border, all-bricks-used, row). Since your task description implies that it exists, print out its row. Then look at the lower border of row and search for that in array[n-1] and print it too, and so on.

Hope you understand my English.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!