Keluarkan aku dari sini

12

Tantangan

Dengan ukuran kisi, posisi rintangan, posisi pemain, dan posisi target, tugas Anda adalah menemukan jalur bagi pemain untuk mencapai target dan menghindari rintangan pada saat yang bersamaan (jika perlu).

masukkan deskripsi gambar di sini


Memasukkan

  • N : Ukuran kisiN x N
  • P : Posisi pemain[playerposx, playerposy]
  • T : Posisi target[targetposx, targetposy]
  • O : Posisi penghalang[[x1, y1], [x2, y2],...,[xn, yn]]

Keluaran

Jalur : Pemain jalur dapat digunakan untuk mencapai target[[x1, y1], [x2, y2],...,[xn, yn]]


Aturan

  1. Intinya [0,0]adalah di sudut kiri atas grid.
  2. Posisi pemain akan selalu berada di sisi kiri kotak.
  3. Posisi target akan selalu berada di sisi kanan grid.
  4. Grid akan selalu memiliki setidaknya satu kendala.
  5. Anda dapat mengasumsikan bahwa tidak ada halangan yang menimpa pemain atau posisi target.
  6. Anda tidak perlu menemukan jalur min.
  7. Pemain hanya bisa bergerak ke kiri, kanan, atas dan bawah tidak secara diagonal.
  8. Anda dapat mengambil input dengan cara apa pun yang nyaman.
  9. Anda dapat mengasumsikan bahwa jalur untuk mencapai target selalu ada.
  10. Jelas, untuk setiap input beberapa jalur yang valid ada, pilih satu.
  11. Anggap N > 2saja kisi itu setidaknya 3 x 3.

Contohnya

Input: 9, [6, 0], [3, 8], [[0, 5], [2, 2], [6, 4], [8, 2], [8, 7]]
Kemungkinan Output:[[6, 0], [6, 1], [6, 2], [6, 3], [5, 3], [5, 4], [5, 5], [5, 6], [5, 7], [5, 8], [4, 8], [3, 8]]

Input: 6, [1, 0], [3, 5], [[1, 2], [2, 5], [5, 1]]
Kemungkinan Output:[[1, 0], [1, 1], [2, 1], [2, 2], [2, 3], [2, 4], [3, 4], [3, 5]]


Catatan

Perhatikan itu Xuntuk baris dan Yuntuk cols. Jangan membingungkan mereka dengan koordinat dalam gambar.

Edit

Seperti @digEmAll tunjukkan, karena aturan #2dan #3, playerY = 0dan targetY = N-1. Jadi, jika mau, Anda dapat mengambil sebagai input saja playerXdan dan targetX(jika itu membuat kode Anda lebih pendek).

DimChtz
sumber
1
"Posisi pemain akan selalu di sisi kiri dan target di sisi kanan": apakah ini berarti bahwa pemain-y = 0 dan target-y = N-1? Jika demikian, dapatkah kita menerima koordinat x (satu angka) untuk pemain dan target?
digEmAll
1
@ DigEmAll Poin bagus. Jujur, saya tidak memikirkan ini dan ya Anda bisa, saya akan mengedit ini.
DimChtz
Terkait tetapi lebih mudah. Terkait tetapi lebih sulit.
user202729
Apakah jalan harus dari awal hingga selesai, atau bisakah itu dalam urutan terbalik?
kamoroso94
1
@ kamoroso94 Ya, mulailah dari target (selesai) :)
DimChtz

Jawaban:

5

JavaScript (ES6), 135 byte

Mengambil input sebagai (width, [target_x, target_y], obstacles)(source_x, source_y), di mana hambatan adalah array string dalam "X,Y"format.

Mengembalikan array string dalam "X,Y"format.

(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

Cobalah online!

Berkomentar

(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
Arnauld
sumber
5

R , 227 byte

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)}

Cobalah online!

Tidak terlalu pendek, dan jelas tidak memberikan jalur terpendek (mis. Periksa contoh pertama).
Ini pada dasarnya melakukan pencarian kedalaman-rekursif pertama dan berhenti segera setelah target telah tercapai, mencetak path.

Terima kasih kepada JayCe untuk peningkatan format output

menggali semua
sumber
+1 Saya suka cara Anda mencetak hasilnya (bukan daftar daftar membosankan yang khas) :)
DimChtz
@DimChtz: terima kasih tapi ... itulah fungsi helper, fungsi kode-golf hanya mencetak daftar koordinat x1 y1 x2 y2 ... xn yn: D
digEmAll
1
Ya, saya tahu: P tapi masih bagus.
DimChtz
1
setuju dengan @DimChtz ... dan saya pikir itu terlihat lebih baik jika Anda write(t(mx),1,N)bukannya print:)
JayCe
@JayCe: ide bagus, berubah!
digEmAll
4

Python 2 , 151 149 byte

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]

Cobalah online!

ovs
sumber
3

Haskell , 133 131 130 byte

  • -1 byte terima kasih kepada 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])

Cobalah online! (dengan beberapa testcases)

Fungsi !mengambil sebagai input

  • n :: Int ukuran grid
  • p :: [Int] posisi pemain sebagai daftar [xp, yp]
  • o :: [[Int]] posisi rintangan sebagai daftar [[x1, y1], [x2, y2], ...]
  • t :: [[[Int]]](implisit) posisi target sebagai daftar [[[xt, yt]]](daftar tiga hanya untuk kenyamanan)

dan mengembalikan jalur yang valid sebagai daftar [[xp, yp], [x1, y1], ..., [xt, yt]].

Sebagai bonus, ia menemukan (salah satu) jalur terpendek dan berfungsi untuk posisi pemain dan target mana pun. Di sisi lain, ini sangat tidak efisien (tetapi contoh yang diberikan berjalan dalam jumlah waktu yang wajar).

Penjelasan

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

Ekspresi yang tampaknya tidak jelas [id, map (+ 1)] <*> [[x - 1,y], [x, y - 1]]hanyalah versi "golfy" (-1 byte) [[x + 1, y], [x, y + 1], [x - 1, y], [x, y - 1]].

Delfad0r
sumber
2
Selamat datang di PPCG! Jawaban pertama yang bagus!
Arnauld
1
@Arnauld Terima kasih! Saya benar-benar menghabiskan beberapa jam mencoba memeras beberapa byte dari solusi saya hanya untuk mengalahkan 135 Anda ^^
Delfad0r
1
Golf yang bagus! Anda dapat menyimpan satu byte dengan menggunakan operator alih-alih fungsi: Cobalah online!
ბიმო
@ BWO Terima kasih atas tipnya. Saya baru di sini, jadi ada banyak trik yang belum pernah saya dengar
Delfad0r
1
Btw. ada bagian dengan tips untuk Haskell khususnya di mana Anda dapat menemukan ini dan banyak lagi trik. Oh dan selalu ada obrolan juga: Of Monads and Men
ბიმო
1

Retina 0.8.2 , 229 byte

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

Cobalah online! Tidak yakin apakah format I / O memenuhi syarat. Penjelasan:

.
$&$&

Gandakan setiap sel. Salinan kiri digunakan sebagai area kerja sementara.

@@
s@

Tandai awal maze sebagai yang dikunjungi.

##
.#

Tandai ujung labirin sebagai kosong.

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

Sel-sel kerja yang tersedia ada, arahkan ke sel yang berdekatan yang dikunjungi sebelumnya.

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

Lacak jalur dari pintu keluar ke mulai menggunakan sel yang berfungsi sebagai panduan.

.(.)
$1

Hapus sel yang berfungsi.

Neil
sumber
1

JavaScript, 450 byte

Mengambil input sebagai (n, {playerx, playery}, {targetx, targety}, [{obstaclex, obstacley}]). Mengembalikan array {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;}

Ini adalah versi yang tidak diacak di mess saya:

// 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;
}
MinerBigWhale
sumber