我的障碍路线有多变化?


21

背景

我通过将盒子放在矩形房间中来构造一个简单的障碍物路线。现在,我想计算解决问题的本质上不同的方法。我需要你为此写一个程序。

输入项

您的输入是字符的非空矩形数组.#。点.是空白,#是障碍。

一个路径通过障碍课程开始在AT右下角的左上角和结束,并进入只向右或向下。同样,有效路径不能穿过障碍物。以下是一些使用+-characters 绘制的示例:

Valid path  Invalid path  Invalid path  Invalid path
++........   ++........    +++++.....    ..+.......
.++++++#..   .+.....#..    ....+++#++    ..++...#..
......+#..   .+.++++#..    .......#.+    ...+++.#..
....#.++++   .+++#.++++    ....#....+    ....#+....

两条路径是基本相似的1,如果可以通过移动一个被转化成其它+在时间。中间路径也必须有效,因此您不能在障碍物上弯曲路径。例如,这里的前两个路径本质上是相似的,但是第三个路径与它们本质上是不同的,因为它不能绕过两个障碍:

++........   +.........   +++++++++.
.+++++.#..   ++.....#..   .......#+.
.....+.#..   .++++++#..   .......#++
....#+++++   ....#.++++   ....#....+

输出量

您的输出是穿过障碍物路线的基本不同路径的数量。换句话说,如果将所有有效路径划分为本质上相似的路径类别,则输出为类别数。请注意,如果没有有效的路径,则此数字可能为0。

规则和计分

您可以编写完整的程序或函数。最低字节数获胜,并且不允许出现标准漏洞。没有时间限制,只是您应该在提交每个测试用例之前对程序进行评估。

测试用例

....
....
.... => 1

...#
....
...# => 0

#..#
..#.
.... => 0

......
......
..##..
......
...... => 2

......
...#..
......
..#...
#..... => 3

......
..#...
......
....#.
#..... => 4

.......
##.....
....###
...#...
..##.#.
#....#.
..#.... => 0

......#.
..##....
...#....
.......#
....#...
.##...#.
....#...
##...... => 7

.........
.#.#.#.#.
.........
#.#...#.#
.........
.#.#.#.#.
......... => 17

..........
.#........
..........
.....#....
#.........
........#.
......#...
.......... => 10

.........
.#.......
.........
...#.....
.........
.....#...
.........
.......#.
......... => 16

1正确的技术术语是“同位的”


1
你是什么意思“的意思是移动一个+在同一时间 ”?这是否意味着基本相似的路径必须具有相同的长度?
彼得·泰勒

3
@PeterTaylor所有路径都具有相同的长度,因为它们只能向下和向右移动。“移动一个+”实质上是指路径的一个角被倒置为相反方向的角。
Zgarb 2015年

1
@Peter:由于您只能向右或向下走,因此所有路径的长度均相同。
Deusovi

Answers:


8

蜗牛53 49字节

A^
\.+d!{.l\.+a3(.|~c!~}\.+r!(.u\.+e(.|~},\.,=~d~

有一次,我不必使用t可怕的传送指令。结果,测试用例立即完成而不是费时费力。

取消高尔夫:

A^
r\.+
{
    d\.+
    !{ r\.u \.+ a3 (.|~)}
    r\.+
    !{ d\.l \.+ a3 (.|~)}
},
d\.,
!(dr .)

这些选项A^意味着从左上角开始并计算所有匹配的路径。主要思想是检查路径的正则条件。老实说,我没想到它会起作用,但是它钉住了测试用例,所以....它试图检查的是,在当前路径中,选择了最贪婪的路径,即尽可能多地正确,尽可能降低等等,而不会越过任何障碍。这是通过在向右移动1次或多次,然后向下移1次或多次之后,检查是否可以通过在上一个向右路段再向右移动一次来到达下一个正方形(必须在右边)来完成的。向右移动然后向下移动之后,还将检查类似条件。


谈论适合工作的语言!
并非查尔斯(Charles)

10

Python 2 170 131 112字节

def f(C,t=1):i="#".join(C).find("#")+1;return([]<C)*(i<1or(i<t
and f([r[i:]for r in C],t-i))+(i>1)*f(C[1:],i-1))

函数,f将障碍物路线作为行列表,并返回本质上不同的路径数。

说明

基本概念是这样的:我们选择一个特定的障碍物o,以便在边界为o和左上角的框中没有其他障碍物。

+--+....
|..|....  
+--#<==== o
.....#..
.#......
........

然后,我们考虑o的东部和南部的两个子路线。如果o实际上可以从通向它们的方向越过,即仅从北越过以到达东方,而从西越过以达到南方,则仅考虑这两个子路线中的任何一个。我们为每个选定的子课程解决问题,然后返回结果的总和。当分别从左和从右穿过o时,这些数字分别对应于基本不同的路径数,因此,所得的两组路径本质上是不同的。既然有出发点和之间没有障碍物Ø,起点和进入这些区域中每个区域的任何入口点之间都有一条路径,所有通向同一点的此类路径本质上都是相似的,因此上述总和是整个过程中实质上不同路径的总数。

                               A
_
........       ...|////      |....
........       ...|////      |....
...#....  -->  ...#////  -->  ....
.#....#.       .#..//#/       ..#.
........       ....////       ....

   |                           |
   v                           v
                  B
........       ___
........       .#....#.
___#....  -->  ........  -->   +
/#////#/       
////////       

仅凭障碍物无法传达所有需要的信息这一事实使事情变得有些复杂。例如,考虑上图中的课程B。单独来看,我们无法确定是否可以从北方越过每个障碍。如果B是输入路线,则由于所有路径都从左上角开始,所以没有障碍物可以从北越过,但是,当我们从东面越过o时,我们可以从左障碍物的任一侧到达B,在解决路线时,应将障碍视为可以从北方越过;正确的障碍并不能解决这个问题,但是不能从这个方向越过。

我们通过指定障碍物路线以及障碍物路线(从左侧开始,沿着左边开始)的字符数来融合这些额外信息。在上图中,这是每个路线旁边的实线。尽管从技术上讲,我们还需要沿着路径开始的第一列指定相应的字符数,例如在子课程A的情况下,实际上我们总是选择最高的障碍物,因此不需要此信息。

o的实际选择如下:我们假装除最后一行外,每行后面都有一个障碍(即#附加了障碍),并按阅读顺序选择结果路线中的第一个障碍。对于最初没有障碍的行(最后一行除外),这实际上意味着我们跳过了它们(同时注意,下面的路径可能从顶行的任何字符开始)。最终,我们最终得到一门没有障碍的单行路线,为此只有一条可能的道路。


这几乎是我正在考虑的解决方案。我知道有人会在我有机会之前发布它。
quintopia,2015年

6

CJam,85 84 82 81 80 79字节

qN/:Q,(Qz,(:R_T]2/e~e!{'#Qs@{\(\@>}%s-},{_}{(a\L{@+_@\-_{2$\f.=0fe=2&},}h;}w;],

在线尝试。运行整个测试套件。

该解决方案的效率可能非常糟糕,但是它可以在几秒钟内解决每个测试用例。

说明

稍后我必须添加代码的完整细目分类,但是算法思想是这样的:

  • 让格的宽度和高度是WH分别。
  • 我们生成所有可能的路径,作为的W-1副本0和的H-1副本的不同排列W-1(其中0表示水平步和W-1垂直步)。我们通过重复获取网格的第一个元素,然后step按读取顺序跳过单元格(stepis 0W-1)来遍历所有这些路径。我们丢弃所有包含的路径#
  • 然后,我们重复删除一组相似的路径(所有路径都将类似于其余路径中的第一个)。稍微放松一下条件,检查相似路径会容易一些:x路径已经移动,而是检查路径是否恰好在两个地方不同。如果真是这样,这两个地方将在垂直和水平方向互换。这将导致这些移动之间的整个片段沿对角线移动一个单元格。但是,如果这两个路径均有效,则将路径的任何部分沿对角线移动一个单元都不能越过障碍,因此它们是相似的。我们仍然需要找到可传递的闭包,因此我们继续这样做,直到找到更多相似的路径,然后再进入下一组。
  • 最后,我们计算找到的组,这些组留在堆栈的底部。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.