Cổng mê cung ngắn nhất


16

Mục tiêu của bạn là để viết một chương trình tạo ra một bản đồ ngẫu nhiên 10x10 sử dụng 0, 12, và tìm thấy con đường đi ngắn nhất từ phía trên bên trái xuống dưới bên phải, giả định rằng:

0 đại diện cho một cánh đồng cỏ: bất cứ ai cũng có thể đi trên đó;
1 đại diện cho một bức tường: bạn không thể vượt qua nó;
2 đại diện cho một cổng thông tin: khi vào một cổng thông tin, bạn có thể di chuyển đến bất kỳ cổng thông tin nào khác trên bản đồ.

Thông số kỹ thuật:

  • Phần tử trên cùng bên trái và phần tử dưới cùng bên phải phải là 0 ;
  • Khi tạo bản đồ ngẫu nhiên, mọi trường sẽ có 60% cơ hội là 0 , 30% là 1 và 10% là 2 ;
  • Bạn có thể di chuyển trong bất kỳ trường liền kề (ngay cả những đường chéo);
  • Chương trình của bạn sẽ xuất bản đồ và số bước của con đường ngắn nhất;
  • Nếu không có đường dẫn hợp lệ dẫn đến trường dưới cùng bên phải, chương trình của bạn sẽ chỉ xuất bản đồ;
  • Bạn có thể sử dụng bất kỳ tài nguyên nào bạn muốn;
  • Mã ngắn nhất sẽ thắng.

Các bước tính toán:
Một bước là một chuyển động thực tế; Mỗi khi bạn thay đổi trường, bạn tăng bộ đếm.

Đầu ra:

0000100200
0100100010
1000000111
0002001000
1111100020
0001111111
0001001000
0020001111
1100110000
0000020100

9

Chúng ta không thể tạo ra chương trình cho con đường ngắn nhất sao? Tạo ra là một câu hỏi khác.
Mikaël Mayer

Bạn đã không xác định rằng bản đồ ngẫu nhiên phải khác nhau mỗi lần :)
bến

@marinus LoooL! Chà, trong thông số kỹ thuật tôi đã viết các cơ hội tạo ra, vì vậy tôi đoán rằng viết một bản đồ tiêu chuẩn với 60 0, 30 1 và 10 2 sẽ không phải là một giải pháp đúng: P
Vereos

@ MikaëlMayer Tôi đoán bạn đã có một điểm, nhưng tôi nghĩ nó sẽ khó khăn hơn như thế này. Tôi có lầm không?
Vereos

Vì đây là một câu hỏi về golf-code, tiêu chí chiến thắng là mã ngắn nhất. Điều gì xảy ra nếu mã đó thực sự chậm và mất nhiều thế kỷ để chạy?
Victor Stafusa

Câu trả lời:


3

GolfScript, 182 ký tự

;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<{;}*

Ví dụ:

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

Toán học (344)

Phần thưởng: làm nổi bật con đường

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]

nhập mô tả hình ảnh ở đây

Tôi tạo biểu đồ của tất cả các phim có thể tới các đỉnh lân cận và thêm tất cả các "dịch chuyển tức thời" có thể.


3

Toán học, 208 202 ký tự

Dựa trên các giải pháp của David Carraher và ybeltukov. Và cảm ơn lời đề nghị của 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]

Đẹp, +1! Tối ưu hóa thêm: n/nthay vì n/10:)
ybeltukov

Tinh giản đẹp. Và bạn in ra bản đồ ngay lập tức.
DavidC

〚 〛đối với dấu ngoặc (đó là ký hiệu unicode chính xác)
ybeltukov

Bạn có thể giải thích tiêu chí lựa chọn không,Norm[# - #2] & @@ # < 2 || # \[Union] u == u &
DavidC

@DavidCarraher Norm[# - #2] & @@ # < 2có nghĩa là khoảng cách giữa hai điểm nhỏ hơn 2, vì vậy chúng phải liền kề nhau. # ⋃ u == ucó nghĩa là cả hai điểm nằm trong u.
alephalpha

2

Trăn 3, 279

Một số biến thể Dijkstra. Xấu xí, nhưng chơi golf nhiều nhất có thể ...

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]

Chạy mẫu

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

Toán học 316 279 275

Đối tượng cơ bản là một mảng 10 x 10 với khoảng 60 0, 30 1 và 10 2. Mảng được sử dụng để sửa đổi một 10x10 GridGraph, với tất cả các cạnh được kết nối. Các nút tương ứng với các ô giữ 1 trong mảng sẽ bị xóa khỏi biểu đồ. Các nút "giữ 2" đều được kết nối với nhau. Sau đó, Đường dẫn ngắn nhất được tìm kiếm giữa đỉnh 1 và đỉnh 100. Nếu đường dẫn như vậy không tồn tại, bản đồ được trả về; nếu một đường dẫn như vậy tồn tại, bản đồ và độ dài đường dẫn ngắn nhất sẽ được hiển thị.

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]

Chạy mẫu :

đồ thị


1
"Bạn có thể di chuyển trong bất kỳ trường liền kề nào (ngay cả những đường chéo)".
alephalpha

0

Con trăn (1923)

Tìm kiếm quay lui

Phải thừa nhận rằng không phải là ngắn nhất hoặc hiệu quả nhất, mặc dù có một số ghi nhớ hiện tại.

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
Wow, bây giờ đó là số lượng nhân vật cho một mã golf! Tôi nghĩ rằng quả bóng của bạn hạ cánh trong thô.
Tim Seguine

Haha vâng, tôi không bận tâm đến việc chơi mã hoặc cố gắng tìm cách triển khai ngắn nhất, nhưng đặt ký tự lên để mọi người biết họ có thể bỏ qua giải pháp này. Nó chỉ có vẻ như là một vấn đề vui vẻ.
vinod

0

JavaScript (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)

Tạo đồ thị xảy ra trong năm dòng đầu tiên. fchứa các trường, pgiữ các cổng. Việc tìm kiếm thực tế được thực hiện thông qua BFS.

Ví dụ đầu ra:

> nút 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]
> nút 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

Con trăn 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!

Ví dụ đầu ra:

0000202000
2011000111
0000002000
0101001000
0000100110
1110100101
0020101000
0011200000
1010101010
0000001000

6

0

Con trăn

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)


Đó là một triển khai kinh tởm của Bellman-Ford. Thuật toán này là O (n ^ 6)! (Cái nào cũng được cho n = 10)


Bản đồ trông thật xấu xí. Điều này có hoạt động nếu cần nhiều hơn 10 bước không?
Phục hồi lại

@WolframH Tất nhiên: en.wikipedia.org/wiki/
Sanjeev Murty

Tôi có thể làm được print '\n'.join(map(str,a)); Tôi đã làm print avì lợi ích của golf.
Sanjeev Murty

Tôi không nghi ngờ tính chính xác của thuật toán :-). Tôi chỉ không nhận ra rằng bạn lặp thường xuyên đủ (mà bạn làm; r*10có 100 yếu tố).
Phục hồi

Vâng. Trên thực tế 100 là quá mức cần thiết; 99 là tất cả những gì cần thiết.
Sanjeev Murty
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.