เส้นทางที่สั้นที่สุดของ Portal Maze


16

เป้าหมายของคุณคือการเขียนโปรแกรมที่สร้างแบบสุ่ม 10x10 แผนที่ใช้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

Mathematica (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

Mathematica, 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

และ〚 〛สำหรับวงเล็บ (มันเป็นสัญลักษณ์ที่ถูกต้อง Unicode)
ybeltukov

คุณช่วยอธิบายเกณฑ์การคัดเลือกได้ไหมNorm[# - #2] & @@ # < 2 || # \[Union] u == u &
DavidC

@DavidCarraher Norm[# - #2] & @@ # < 2หมายถึงระยะห่างระหว่างสองจุดน้อยกว่า 2 ดังนั้นพวกเขาจึงต้องอยู่ติดกัน # ⋃ u == uหมายถึงจุดทั้งสองอยู่ในคุณ
alephalpha

2

Python 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

Mathematica 316 279 275

วัตถุพื้นฐานคืออาร์เรย์ 10x10 ที่มีประมาณ 60 0, 30 1 และ 10 2 อาร์เรย์ใช้สำหรับปรับเปลี่ยน 10x10 GridGraphโดยเชื่อมต่อกับขอบทั้งหมด โหนดเหล่านั้นที่สอดคล้องกับเซลล์ที่ถือ 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

Python (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

ฮ่าฮ่าใช่ฉันไม่ได้ยุ่งกับการเล่นกอล์ฟหรือพยายามหาวิธีการที่สั้นที่สุด แต่ให้ความสำคัญกับตัวละครเพื่อให้ผู้คนรู้ว่าพวกเขาสามารถเพิกเฉยต่อวิธีนี้ได้ มันดูเหมือนเป็นปัญหาที่สนุก
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

ตัวอย่างผลลัพธ์:

> node maze.js
[0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0]
[0, 1, 1, 0, 0, 1, 0, 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]
> node 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, 0]
5

0

Python 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

Python 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 ขั้นตอน?
Reinstate Monica

@ WolframH แน่นอน: en.wikipedia.org/wiki/…
Sanjeev Murty

ฉันจะทำให้มันprint '\n'.join(map(str,a)); ฉันทำprint aเพื่อประโยชน์ของกอล์ฟ
Sanjeev Murty

ฉันไม่สงสัยในความถูกต้องของอัลกอริทึม :-) ฉันเพิ่งไม่ได้ตระหนักว่าคุณวนซ้ำบ่อยพอ (ซึ่งคุณทำ; r*10มี 100 องค์ประกอบ)
Reinstate Monica

ใช่. อันที่จริง 100 คือ overkill; 99 คือทั้งหมดที่จำเป็น
Sanjeev Murty
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.