포털 미로 최단 경로


16

당신의 목표는 사용하여 임의의 10 × 10 맵을 생성하는 프로그램을 작성하는 것입니다 0, 1그리고 2, 그리고 왼쪽 상단 오른쪽 아래로는, 가정에서 최단 경로를 찾습니다

0 은 잔디밭을 나타냅니다. 누구나 걸을 수 있습니다.
1 은 벽을 나타냅니다. 교차 할 수 없습니다.
2 는 포털을 나타냅니다. 포털에 들어가면 맵의 다른 포털로 이동할 수 있습니다.

명세서:

  • 왼쪽 상단 요소와 오른쪽 하단 요소는 0 이어야합니다 .
  • 랜덤 맵을 생성 할 때, 모든 필드는 60 % 확률로 0 , 30 %는 1 , 10 %는 2입니다 .
  • 인접한 필드 (대각선 필드)에서도 이동할 수 있습니다.
  • 프로그램은 맵과 최단 경로의 단계 수를 출력해야합니다.
  • 오른쪽 아래 필드로 연결되는 유효한 경로가 없으면 프로그램은 맵만 출력해야합니다.
  • 원하는 모든 리소스를 사용할 수 있습니다.
  • 가장 짧은 코드가 승리합니다.

계산 단계 :
단계는 실제 움직임입니다. 필드를 변경할 때마다 카운터가 증가합니다.

산출:

0000100200
0100100010
1000000111
0002001000
1111100020
0001111111
0001001000
0020001111
1100110000
0000020100

9

최단 경로를위한 프로그램을 생산할 수는 없습니까? 생성은 또 다른 질문입니다.
Mikaël Mayer

매번 무작위 맵이 달라야한다고 지정하지 않았습니다. :)
marinus

@marinus LoooL! 글쎄, 스펙에서 생성 가능성을 썼기 때문에 60 0, 30 1 및 10 2로 표준 맵을 작성하는 것이 올바른 해결책이 아니라고 생각합니다 .P
Vereos

@ MikaëlMayer 나는 당신이 요점을 가지고 있다고 생각하지만, 나는 이것이 더 도전적이라고 생각합니다. 내가 잘못?
Vereos

이것은 코드 골프 질문이므로 당첨 기준은 가장 짧은 코드입니다. 해당 코드가 실제로 느리고 몇 세기가 걸리면 어떻게됩니까?
Victor Stafusa

답변:


3

GolfScript, 182 자

;0`{41 3 10rand?/3%`}98*0`]10/n*n+.[12n*.]*.0{[`/(,\+{,)1$+}*;]}:K~\2K:P+${[.12=(]}%.,,{.{\1==}+2$\,{~;.P?0<!P*3,{10+}%1+{2$1$-\3$+}%+~}%`{2$~0<@@?-1>&2$[~;@)](\@if}++%}/-1=1=.0<{;}*

예 :

0000001002
1010000001
0011010000
2001020000
0100100011
0110100000
0100000100
0010002010
0100110000
0012000210
6

0000100000
0100000001
1100000000
1011010000
0010001100
0101010200
0000200012
1100100110
0000011001
2201010000
11

0012010000
1000100122
0000001000
0111010100
0010012001
1020100110
1010101000
0102011111
0100100010
2102100110

4

매스 매 티카 (344)

보너스 : 경로 강조

n = 10;
m = RandomChoice[{6, 3, 1} -> {0, 1, 2}, {n, n}];
m[[1, 1]] = m[[n, n]] = 0;

p = FindShortestPath[Graph@DeleteDuplicates@Join[Cases[#, Rule[{ij__}, {k_, l_}] /; 
      0 < k <= n && 0 < l <= n && m[[ij]] != 1 && m[[k, l]] != 1] &@
   Flatten@Table[{i, j} -> {i, j} + d, {i, n}, {j, n}, {d, Tuples[{-1, 0, 1}, 2]}], 
  Rule @@@ Tuples[Position[m, 2], 2]], {1, 1}, {n, n}];

Grid@MapAt[Style[#, Red] &, m, p]
If[# > 0, #-1] &@Length[p]

여기에 이미지 설명을 입력하십시오

가능한 모든 영화의 그래프를 이웃 정점에 만들고 가능한 모든 "텔레포트"를 추가합니다.


3

매쓰, 208 개 202 문자

David Carraher와 ybeltukov의 솔루션을 기반으로합니다. 그리고 ybeltukov의 제안에 감사드립니다.

m=RandomChoice[{6,3,1}->{0,1,2},n={10,10}];m〚1,1〛=m〚10,10〛=0;Grid@m
{s,u}=m~Position~#&/@{0,2};If[#<∞,#]&@GraphDistance[Graph[{n/n,n},#<->#2&@@@Select[Subsets[s⋃u,{2}],Norm[#-#2]&@@#<2||#⋃u==u&]],n/n,n]

좋아, +1! 추가 최적화 : :) n/n대신n/10
ybeltukov

멋져요. 그리고 당신은 즉시지도를 인쇄합니다.
DavidC

그리고 〚 〛괄호 (올바른 유니 코드 기호)
ybeltukov

선택 기준을 설명해 주시겠습니까?Norm[# - #2] & @@ # < 2 || # \[Union] u == u &
DavidC

@DavidCarraher Norm[# - #2] & @@ # < 2는 두 점 사이의 거리가 2보다 작다는 것을 의미하므로 인접해야합니다. # ⋃ u == u두 지점이 모두 u임을 의미합니다.
alephalpha

2

파이썬 3, 279

일부 Dijkstra 변형. 못생긴,하지만 내가 할 수있는만큼 골프를 ...

from random import*
R=range(10)
A={(i,j):choice([0,0,1]*3+[2])for i in R for j in R}
A[0,0]=A[9,9]=0
for y in R:print(*(A[x,y]for x in R))
S=[(0,0,0,0)]
for x,y,a,c in S:A[x,y]=1;x*y-81or print(c)+exit();S+=[(X,Y,b,c+1)for(X,Y),b in A.items()if a+b>3or~-b and-2<X-x<2and-2<Y-y<2]

샘플 런

0 1 1 1 0 0 1 0 1 0
0 0 0 1 0 1 0 1 0 0
0 1 2 1 2 1 0 0 1 0
0 1 0 1 0 0 0 0 0 1
0 1 0 1 0 0 1 0 0 1
0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 1 0 1
1 0 0 1 0 0 1 1 1 0
0 0 0 0 1 0 0 0 0 1
0 1 2 1 0 1 1 0 0 0
10

1

매스 매 티카 (316) 279 (275)

기본 개체는 약 60 0, 30 1 및 10 2가있는 10x10 배열입니다. 배열은 GridGraph모든 가장자리가 연결된 10x10을 수정하는 데 사용됩니다 . 배열에서 1을 보유하는 셀에 해당하는 노드는 그래프에서 제거됩니다. "2를 보유한"노드는 모두 서로 연결되어 있습니다. 그런 다음 정점 1과 정점 100 사이에서 최단 경로를 찾습니다. 이러한 경로가 존재하지 않으면 맵이 반환됩니다. 이러한 경로가 존재하면 맵과 최단 경로 길이가 표시됩니다.

m = Join[{0}, RandomChoice[{6, 3, 1} -> {0, 1, 2}, 98], {0}];
{s,t,u}=(Flatten@Position[m,#]&/@{0,1,2});
g=Graph@Union[EdgeList[VertexDelete[GridGraph@{10,10},t]],Subsets[u,{2}] 
/.{a_,b_}:>a \[UndirectedEdge] b];
If[IntegerQ@GraphDistance[g,1,100],{w=Grid@Partition[m,10],  
Length@FindShortestPath[g,1,100]-1},w]

샘플 실행 :

그래프


1
"가까운 분야 (대각선)에서도 이동할 수 있습니다."
alephalpha

0

파이썬 (1923)

역 추적 검색

일부 메모가 있지만 가장 짧거나 가장 효율적인 것은 아닙니다.

import random
l = 10
map = [
    [(lambda i: 0 if i < 7 else 1 if i < 10 else 2)(random.randint(1, 10))
     for i in range(0, l)]
    for i in range(0, l)
    ]
map[0][0] = map[l-1][l-1] = 0
print "\n".join([" ".join([str(i) for i in x]) for x in map])

paths = {}
def step(past_path, x, y):
    shortest = float("inf")
    shortest_path = []

    current_path = past_path + [(x, y)]
    pos = map[x][y]
    if (x, y) != (0, 0):
        past_pos = map[past_path[-1][0]][past_path[-1][1]]

    if (((x, y) in paths or str(current_path) in paths)
        and (pos != 2 or past_pos == 2)):
        return paths[(x, y)]
    elif x == l-1 and y == l-1:
        return ([(x, y)], 1)

    if pos == 1:
        return (shortest_path, shortest)
    if pos == 2 and past_pos != 2:
        for i2 in range(0, l):
            for j2 in range(0, l):
                pos2 = map[i2][j2]
                if pos2 == 2 and (i2, j2) not in current_path:
                    path, dist = step(current_path, i2, j2)
                    if dist < shortest and (x, y) not in path:
                        shortest = dist
                        shortest_path = path
    else:
        for i in range(x - 1, x + 2):
            for j in range(y - 1, y + 2):
                if i in range(0, l) and j in range(0, l):
                    pos = map[i][j]
                    if pos in [0, 2] and (i, j) not in current_path:
                        path, dist = step(current_path, i, j)
                        if dist < shortest and (x, y) not in path:
                            shortest = dist
                            shortest_path = path
    dist = 1 + shortest
    path = [(x, y)] + shortest_path
    if dist != float("inf"):
        paths[(x, y)] = (path, dist)
    else:
        paths[str(current_path)] = (path, dist)
    return (path, dist)

p, d = step([], 0, 0)
if d != float("inf"):
    print p, d

1
와우, 이제 코드 골프의 캐릭터 수입니다! 나는 당신의 공이 거친 곳에 착륙했다고 생각합니다.
Tim Seguine

Haha yeah 나는 코드를 골퍼 링하거나 가장 짧은 구현을 찾으려고 노력하지 않았지만 사람들 이이 솔루션을 무시할 수 있음을 알 수 있도록 문자 수를 늘리십시오. 그것은 단지 재미있는 문제처럼 보였다.
vinod

0

자바 스크립트 (541)

z=10
l=[[0]]
p=[]
f=[[0]]
P=[]
for(i=0;++i<z;)l[i]=[],f[i]=[]
for(i=0;++i<99;)P[i]=0,l[i/z|0][i%z]=99,f[i/z|0][i%z]=(m=Math.random(),m<=.6?0:m<=.9?1:(p.push(i),2))
f[9][9]=0
l[9][9]=99
Q=[0]
for(o=Math.min;Q.length;){if(!P[s=Q.splice(0,1)[0]]){P[s]=1
for(i=-2;++i<2;)for(j=-2;++j<2;){a=i+s/z|0,b=j+s%z
if(!(a<0||a>9||b<0||b>9)){q=l[a][b]=o(l[s/z|0][s%z]+1,l[a][b])
if(f[a][b]>1){Q=Q.concat(p)
for(m=0;t=p[m];m++)l[t/z|0][t%z]=o(l[t/z|0][t%z],q+1)}!f[a][b]?Q.push(a*z+b):''}}}}for(i=0;i<z;)console.log(f[i++])
console.log((k=l[9][9])>98?"":k)

그래프 생성은 처음 다섯 줄에서 발생합니다. f필드를 포함 p하고 포털을 보유합니다. 실제 검색은 BFS를 통해 구현됩니다.

출력 예 :

> 노드 maze.js
[0, 0, 0, 0, 1, 0, 0, 0, 2, 0]
[0, 1, 1, 0, 0, 1, 0, 0, 0, 2]
[0, 0, 0, 1, 0, 0, 0, 0, 1, 0]
[1, 1, 1, 0, 2, 2, 0, 1, 0, 1]
[1, 1, 0, 0, 0, 0, 1, 0, 0, 0]
[1, 1, 0, 0, 1, 0, 0, 0, 1, 1]
[0, 0, 1, 1, 0, 1, 0, 0, 2, 0]
[0, 0, 1, 0, 1, 2, 0, 1, 0, 1]
[1, 0, 0, 0, 1, 1, 1, 0, 1, 1]
[0, 1, 0, 0, 0, 0, 0, 0, 1, 0]
> 노드 maze.js
[0, 0, 0, 0, 1, 0, 1, 0, 0, 1]
[0, 2, 0, 1, 1, 2, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
[0, 0, 0, 1, 2, 1, 1, 0, 1, 0]
[2, 0, 1, 0, 2, 2, 2, 0, 1, 0]
[1, 0, 0, 0, 1, 0, 0, 0, 1, 0]
[0, 0, 1, 0, 0, 1, 0, 1, 0, 0]
[0, 1, 2, 0, 0, 0, 0, 0, 0, 1]
[1, 0, 2, 1, 0, 1, 2, 0, 0, 1]
[0, 1, 2, 0, 0, 0, 0, 0, 0, 0]
5

0

파이썬 3 (695)

import random as r
if __name__=='__main__':
    x=144
    g,t=[1]*x,[]
    p=lambda i:12<i<131 and 0<i%12<11
    for i in range(x):
        if p(i):
            v=r.random()
            g[i]=int((v<=0.6 or i in (13,130)) and .1 or v<=0.9 and 1 or 2)
            if g[i]>1:t+=[i]
            print(g[i],end='\n' if i%12==10 else '')
    d=[99]*x
    d[13]=0
    n = list(range(x))
    m = lambda i:[i-1,i+1,i-12,i+12,i-13,i+11,i+11,i+13]
    while n:
        v = min(n,key=lambda x:d[x])
        n.remove(v)
        for s in m(v)+(t if g[v]==2 else []):
            if p(s) and g[s]!=1 and d[v]+(g[s]+g[v]<4)<d[s]:
                d[s]=d[v]+(g[s]+g[v]<3)
    if d[130]<99:print('\n'+str(d[130]))

Dijkstra!

출력 예 :

0000202000
2011000111
0000002000
0101001000
0000100110
1110100101
0020101000
0011200000
1010101010
0000001000

6

0

파이썬, 314

import random,itertools as t
r=range(10)
a,d=[[random.choice([0]*6+[1]*3+[2])for i in r]for j in r],eval(`[[99]*10]*10`)
a[0][0]=a[9][9]=d[0][0]=0
for q,i,j,m,n in t.product(r*10,r,r,r,r):
 if a[m][n]!=1and abs(m-i)<2and abs(n-j)<2or a[i][j]==a[m][n]==2:d[m][n]=min(d[i][j]+1,d[m][n])
w=d[9][9]
print a,`w`*(w!=99)


Bellman-Ford의 역겨운 구현입니다. 이 알고리즘은 O (n ^ 6)입니다! (n = 10에 대해서는 어느 것이 좋을까요)


지도가 정말 못 생겼어 10 단계 이상이 필요한 경우에도 작동합니까?
복원 상태 Monica


나는 그것을 만들 수 있었다 print '\n'.join(map(str,a)); 나는 print a골프를 위해서 했어요 .
Sanjeev Murty

나는 알고리즘의 정확성을 의심하지 않았다 :-). 나는 당신이 충분히 자주 반복한다는 것을 깨닫지 못했습니다 ( r*10100 개의 요소가 있음).
복원 Monica Monica

네. 실제로 100은 과잉입니다. 99 만 있으면됩니다.
Sanjeev Murty
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.