带我离开这里


12

挑战

在给定网格大小,障碍物位置,玩家位置和目标位置的情况下,您的任务是为玩家找到一条到达目标并同时避开障碍物的路径(如有必要)。

在此处输入图片说明


输入值

  • N:网格大小N x N
  • P:球员位置[playerposx, playerposy]
  • T:目标位置[targetposx, targetposy]
  • O:障碍物位置[[x1, y1], [x2, y2],...,[xn, yn]]

输出量

路径:玩家可以用来达到目标​​的路径[[x1, y1], [x2, y2],...,[xn, yn]]


规则

  1. 该点[0,0]位于网格的左上角。
  2. 玩家的位置将始终位于网格的左侧。
  3. 目标的位置将始终在网格的右侧。
  4. 网格将始终至少具有一个障碍。
  5. 您可以假设没有障碍重叠在玩家或目标位置上。
  6. 您不一定需要找到最小路径。
  7. 玩家只能左右移动,不能左右移动。
  8. 您可以通过任何方便的方式进行输入。
  9. 您可以假设玩家始终可以到达目标的路径。
  10. 显然,对于每个输入,存在多个有效路径,请选择一个。
  11. 假设N > 2网格至少为3 x 3

例子

输入:9[6, 0][3, 8][[0, 5], [2, 2], [6, 4], [8, 2], [8, 7]]
可能的输出:[[6, 0], [6, 1], [6, 2], [6, 3], [5, 3], [5, 4], [5, 5], [5, 6], [5, 7], [5, 8], [4, 8], [3, 8]]

输入:6[1, 0][3, 5][[1, 2], [2, 5], [5, 1]]
可能的输出:[[1, 0], [1, 1], [2, 1], [2, 2], [2, 3], [2, 4], [3, 4], [3, 5]]


注意

请注意,这X是针对行和列的Y。不要将它们与图像中的坐标混淆。

编辑

正如@digEmAll指出的,由于规则#2#3playerY = 0以及targetY = N-1。因此,如果需要,您只能将playerXand和作为输入targetX(如果这样会使您的代码更短)。


1
“玩家位置将始终在左侧,目标始终在右侧”:这是否意味着玩家y = 0且目标y = N-1?如果是这样,我们可以接受玩家和目标的x坐标(一个数字)吗?
digEmAll

1
@digEmAll好点。老实说,我没有想到这一点,是的,我可以编辑它。
DimChtz '18

相关但容易。相关但困难。
user202729'9

路径必须是从头到尾,还是可以相反?
kamoroso94'9

1
@ kamoroso94是的,开始瞄准(完成):)
DimChtz

Answers:


5

JavaScript(ES6),135个字节

将输入作为(width, [target_x, target_y], obstacles)(source_x, source_y),其中障碍"X,Y"格式为字符串的数组。

返回"X,Y"格式为字符串的数组。

(n,t,o)=>g=(x,y,p=[],P=[...p,v=x+','+y])=>v==t?P:~x&~y&&x<n&y<n&[...o,...p].indexOf(v)<0&&[0,-1,0,1].some((d,i)=>r=g(x+d,y-~-i%2,P))&&r

在线尝试!

已评论

(n, t, o) =>              // n = width of maze, t[] = target coordinates, o[] = obstacles
  g = (                   // g() = recursive search function taking:
    x, y,                 //   (x, y) = current coordinates of the player
    p = [],               //   p[] = path (a list of visited coordinates, initially empty)
    P = [                 //   P[] = new path made of:
      ...p,               //     all previous entries in p
      v = x + ',' + y     //     the current coordinates coerced to a string v = "x,y"
    ]                     //
  ) =>                    //
    v == t ?              // if v is equal to the target coordinates:
      P                   //   stop recursion and return P
    :                     // else:
      ~x & ~y             //   if neither x nor y is equal to -1
      && x < n & y < n    //   and both x and y are less than n
      & [...o, ...p]      //   and neither the list of obstacles nor the path
        .indexOf(v) < 0   //   contains a position equal to the current one:
      && [0, -1, 0, 1]    //     iterate on all 4 possible directions
        .some((d, i) =>   //     for each of them:
          r = g(          //       do a recursive call with:
            x + d,        //         the updated x
            y - ~-i % 2,  //         the updated y
            P             //         the new path
          )               //       end of recursive call
        ) && r            //     if a solution was found, return it

5

R,227字节

function(N,P,G,O){M=diag(N+2)*0
M[O+2]=1
b=c(1,N+2)
M[row(M)%in%b|col(M)%in%b]=1
H=function(V,L){if(all(V==G+2))stop(cat(L))
M[t(V)]=2
M<<-M
for(i in 0:3){C=V+(-1)^(i%/%2)*(0:1+i)%%2
if(!M[t(C)])H(C,c(L,C-2))}}
try(H(P+2,P),T)}

在线尝试!

不是很短,并且绝对不会给出最短的路径(例如,检查第一个示例)。
它基本上执行递归的深度优先搜索,并在到达目标后立即停止并打印路径。

感谢JayCe对输出格式的改进


+1我喜欢打印输出的方式(不是典型的无聊列表):)
DimChtz

@DimChtz:谢谢,但是...这是辅助函数,代码高尔夫球函数仅打印坐标列表x1 y1 x2 y2 ... xn yn:D
digEmAll

1
是的,我知道:P但还是不错。
DimChtz '18

1
同意@DimChtz ...,我认为如果您write(t(mx),1,N)不使用它,它看起来会更好print:)
JayCe

@JayCe:好主意,变了!
digEmAll

4

Python 2中151个 149字节

N,s,e,o=input()
P=[[s]]
for p in P:x,y=k=p[-1];k==e>exit(p);P+=[p+[[x+a,y+b]]for a,b in((0,1),(0,-1),(1,0),(-1,0))if([x+a,y+b]in o)==0<=x+a<N>y+b>-1]

在线尝试!


3

哈斯克尔133个 131 130字节

  • -1字节归功于BWO
(n!p)o=head.(>>=filter(elem p)).iterate(\q->[u:v|v@([x,y]:_)<-q,u<-[id,map(+1)]<*>[[x-1,y],[x,y-1]],all(/=u)o,x`div`n+y`div`n==0])

在线尝试!(带有一些测试用例)

!以输入为函数

  • n :: Int 网格大小
  • p :: [Int] 玩家位置列表 [xp, yp]
  • o :: [[Int]] 障碍物位置列表 [[x1, y1], [x2, y2], ...]
  • t :: [[[Int]]](隐式)将目标的位置作为列表[[[xt, yt]]](为方便起见,使用三重列表)

并返回有效路径作为列表[[xp, yp], [x1, y1], ..., [xt, yt]]

作为奖励,它找到最短的路径(其中之一),并且适用于任何玩家和目标的位置。在另一方面,这是非常低效的(但是提供的实例在合理时间内运行)。

说明

(n ! p) o =                                                         -- function !, taking n, p, o and t (implicit by point-free style) as input
    head .                                                          -- take the first element of
    (>>= filter (elem p)) .                                         -- for each list, take only paths containing p and concatenate the results
    iterate (                                                       -- iterate the following function (on t) and collect the results in a list
        \q ->                                                       -- the function that takes a list of paths q...
            [u : v |                                                -- ... and returns the list of paths (u : v) such that:
                v@([x, y] : _) <- q,                                -- * v is an element of q (i.e. a path); also let [x, y] be the first cell of v
                u <- [id, map (+ 1)] <*> [[x - 1,y], [x, y - 1]],   -- * u is one of the neighbouring cells of [x, y]
                all (/= u) o,                                       -- * u is not an obstacle
                x `div` n + y `div` n == 0                          -- * [x, y] is inside the grid
            ]
    )

iteratekk1[[xt, yt]]

表面上晦涩难懂的表达式[id, map (+ 1)] <*> [[x - 1,y], [x, y - 1]]只是的“ golfy”(-1字节)版本[[x + 1, y], [x, y + 1], [x - 1, y], [x, y - 1]]


2
欢迎来到PPCG!不错的第一答案!
Arnauld

1
@Arnauld谢谢!我实际上花了几个小时试图从我的解决方案中压缩几个字节,只是为了击败您的135 ^^
Delfad0r

1
高尔夫不错!您可以使用运算符而不是函数来保存一个字节:在线尝试!
ბიმო

@BWO感谢您的提示。我是新来的,所以有许多我从未听说过的技巧
Delfad0r

1
顺便说一句。这里有专门介绍Haskell技巧的部分,您可以在其中找到此技巧以及更多技巧。哦,总是有聊过:单子和男人
ბიმო

1

视网膜0.8.2,229字节

.
$&$&
@@
s@
##
.#
{`(\w.)\.
$1l
\.(.\w)
r$1
(?<=(.)*)\.(?=.*¶(?<-1>.)*(?(1)$)\w)
d
}`\.(?=(.)*)(?<=\w(?(1)$)(?<-1>.)*¶.*)
u
+T`.`#`.(?=(.)*)(?<=d#(?(1)$)(?<-1>.)*¶.*)|(?<=(.)*.).(?=.*¶(?<-2>.)*(?(2)$)u#)|(?<=#r).|.(?=l#)
.(.)
$1

在线尝试!不确定I / O格式是否合格。说明:

.
$&$&

复制每个单元格。左副本用作临时工作区。

@@
s@

将迷宫的开始标记为已访问。

##
.#

将迷宫的末端标记为空。

{`(\w.)\.
$1l
\.(.\w)
r$1
(?<=(.)*)\.(?=.*¶(?<-1>.)*(?(1)$)\w)
d
}`\.(?=(.)*)(?<=\w(?(1)$)(?<-1>.)*¶.*)
u

当存在可用的工作单元时,将它们指向相邻的先前访问的单元。

+T`.`#`.(?=(.)*)(?<=d#(?(1)$)(?<-1>.)*¶.*)|(?<=(.)*.).(?=.*¶(?<-2>.)*(?(2)$)u#)|(?<=#r).|.(?=l#)

使用工作单元作为指导,跟踪从出口到起点的路径。

.(.)
$1

删除工作单元。


1

JavaScript,450字节

将输入作为(n, {playerx, playery}, {targetx, targety}, [{obstaclex, obstacley}])。返回的数组{hopx, hopy}

j=o=>JSON.stringify(o);l=a=>a.length;c=(a,o)=>{let i=l(a);while(i>0){i--;if(j(a[i])==j(o)){return 1;}}return 0;}h=(p,t,o)=>{if(p.y<t.y&&!c(o,{x:p.x,y:p.y+1})){return{x:p.x,y:p.y+1};}if(p.y>t.y&&!c(o,{x:p.x,y:p.y-1})){return{x:p.x,y:p.y-1};}if(p.x<t.x&&!c(o,{x:p.x+1,y:p.y})){return{x:p.x+1,y:p.y};}if(p.x>t.x&&!c(o,{x:p.x-1,y:p.y})){return{x:p.x-1,y:p.y};}return t;}w=(n,p,t,o)=>{let r=[];r.push(p);while(j(p)!==j(t)){p=h(p,t,o);r.push(p);}return r;}

这是我的混乱情况的清晰版本:

// defining some Array's function for proper comparaisons
json = (object) => { return JSON.stringify(object) };
length = (array) => { return array.length; }
contains = (array, object) => {
    let i = length(array);
    while (i > 0) {
    i--;
        if (json(array[i]) == json(object)) { return true; }
    }
    return false;
}
//return next found hop
getNextHop = (player, target, obstacles) => {
    //uggly serie of conditions
    //check where do we have to go and if there is an obstacle there
    if(player.y<target.y && !contains(obstacles, [x:player.x, y:player.y+1])) { return [x:player.x, y:player.y+1]; }
    if(player.y>target.y && !contains(obstacles, [x:player.x, y:player.y-1])) { return [x:player.x, y:player.y-1]; }
    if(player.x<target.x && !contains(obstacles, [x:player.x+1, y:player.y])) { return [x:player.x+1, y:player.y]; }
    if(player.x>target.x && !contains(obstacles, [x:player.x-1, y:player.y])) { return [x:player.x-1, y:player.y]; }
    return target;
}
//return found path
getPath = (gridsize, player, target, obstacles) => {
    let path = [];
    path.push(player);
    //while player is not on target
    while(json(player)!=json(target)) {
        player = getNextHop(player, target, obstacles); //gridsize is never used as player and target are in the grid boundaries
        path.push(player);
    }
    return path;
}
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.