Portami fuori di qui


12

Sfida

Date le dimensioni della griglia, le posizioni degli ostacoli, la posizione del giocatore e la posizione del bersaglio, il tuo compito è quello di trovare un percorso per il giocatore per raggiungere il bersaglio ed evitare gli ostacoli allo stesso tempo (se necessario).

inserisci qui la descrizione dell'immagine


Ingresso

  • N : dimensione della grigliaN x N
  • P : Posizione del giocatore[playerposx, playerposy]
  • T : posizione del bersaglio[targetposx, targetposy]
  • O : posizioni degli ostacoli[[x1, y1], [x2, y2],...,[xn, yn]]

Produzione

Percorso : un giocatore di percorso può usare per raggiungere il bersaglio[[x1, y1], [x2, y2],...,[xn, yn]]


Regole

  1. Il punto si [0,0]trova nell'angolo in alto a sinistra della griglia.
  2. La posizione del giocatore sarà sempre sul lato sinistro della griglia.
  3. La posizione del bersaglio sarà sempre sul lato destro della griglia.
  4. La griglia avrà sempre almeno un ostacolo.
  5. Puoi presumere che nessun ostacolo si sovrapponga al giocatore o alla posizione del bersaglio.
  6. Non è necessario necessariamente trovare il percorso minimo.
  7. Il giocatore può solo spostarsi a sinistra, a destra, in alto e in basso, non in diagonale.
  8. Puoi prendere l'input in qualsiasi modo conveniente.
  9. Puoi presumere che esista sempre un percorso per raggiungere il bersaglio.
  10. Ovviamente, per ogni input esistono più percorsi validi, scegline uno.
  11. Supponiamo che N > 2la griglia sia almeno 3 x 3.

Esempi

Ingresso: 9, [6, 0], [3, 8], [[0, 5], [2, 2], [6, 4], [8, 2], [8, 7]]
Possibile uscita:[[6, 0], [6, 1], [6, 2], [6, 3], [5, 3], [5, 4], [5, 5], [5, 6], [5, 7], [5, 8], [4, 8], [3, 8]]

Ingresso: 6, [1, 0], [3, 5], [[1, 2], [2, 5], [5, 1]]
Possibile uscita:[[1, 0], [1, 1], [2, 1], [2, 2], [2, 3], [2, 4], [3, 4], [3, 5]]


Nota

Si noti che Xè per le righe e Yper i col. Non confonderli con le coordinate in un'immagine.

modificare

Come sottolineato da @digEmAll, a causa delle regole #2e #3, playerY = 0e targetY = N-1. Quindi, se vuoi, puoi prendere solo come input playerXe e targetX(se questo accorcia il tuo codice).


1
"La posizione del giocatore sarà sempre sul lato sinistro e il bersaglio sul lato destro": significa che giocatore-y = 0 e bersaglio-y = N-1? In tal caso, possiamo semplicemente accettare la coordinata x (un numero) per giocatore e bersaglio?
digEmAll

1
@digEmAll Buon punto. Onestamente, non ci ho pensato e sì, puoi modificarlo.
DimChtz,

Correlato ma più semplice. Correlato ma più difficile.
user202729

Il percorso deve essere dall'inizio alla fine o può essere in ordine inverso?
kamoroso94

1
@ kamoroso94 Sì, inizia a destinazione (fine) :)
DimChtz,

Risposte:


5

JavaScript (ES6), 135 byte

Accetta input come (width, [target_x, target_y], obstacles)(source_x, source_y), dove ostacoli è una matrice di stringhe in "X,Y"formato.

Restituisce una matrice di stringhe nel "X,Y"formato.

(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

Provalo online!

Commentate

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

Provalo online!

Non molto breve e sicuramente non fornisce il percorso più breve (ad esempio, controlla il primo esempio).
Esegue sostanzialmente una ricerca ricorsiva in profondità e si interrompe non appena viene raggiunto l'obiettivo, stampando il percorso.

Grazie a JayCe per il miglioramento della formattazione dell'output


+1 Mi piace il modo in cui stampi l'output (non il tipico elenco noioso di elenchi) :)
DimChtz

@DimChtz: bene grazie ma ... questa è la funzione helper, la funzione code-golf stampa solo un elenco di coordinate x1 y1 x2 y2 ... xn yn: D
digEmAll

1
Sì, lo so: P ma comunque carino.
DimChtz,

1
d'accordo con @DimChtz ... e penso che sia ancora meglio se write(t(mx),1,N)invece di printing :)
JayCe

@JayCe: buona idea, è cambiato!
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]

Provalo online!


3

Haskell , 133 131 130 byte

  • -1 byte grazie a 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])

Provalo online! (con alcune prove)

Una funzione che !accetta come input

  • n :: Int dimensione della griglia
  • p :: [Int] posizione del giocatore come lista [xp, yp]
  • o :: [[Int]] posizione degli ostacoli come elenco [[x1, y1], [x2, y2], ...]
  • t :: [[[Int]]](implicito) posizione del target come lista [[[xt, yt]]](tripla lista solo per comodità)

e restituendo un percorso valido come elenco [[xp, yp], [x1, y1], ..., [xt, yt]].

Come bonus, trova (uno dei) percorsi più brevi e funziona per la posizione di qualsiasi giocatore e bersaglio. D'altra parte, è molto inefficiente (ma gli esempi forniti vengono eseguiti in un periodo di tempo ragionevole).

Spiegazione

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

L'espressione apparentemente oscura [id, map (+ 1)] <*> [[x - 1,y], [x, y - 1]]è solo una versione "da golf" (-1 byte) di [[x + 1, y], [x, y + 1], [x - 1, y], [x, y - 1]].


2
Benvenuti in PPCG! Bella prima risposta!
Arnauld,

1
@Arnauld Grazie! In realtà ho trascorso diverse ore cercando di spremere alcuni byte dalla mia soluzione solo per battere il tuo 135 ^^
Delfad0r

1
Bel golf! Puoi salvare un byte usando un operatore invece di una funzione: provalo online!
ბიმო

@BWO Grazie per la punta. Sono nuovo qui, quindi ci sono molti trucchi di cui non ho mai sentito parlare
Delfad0r

1
Btw. c'è una sezione con suggerimenti per Haskell in particolare dove puoi trovare questo e molti altri trucchi. Oh, e c'è sempre anche la chat: 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

Provalo online! Non sono sicuro se il formato I / O è idoneo. Spiegazione:

.
$&$&

Duplica ogni cella. La copia di sinistra viene utilizzata come area di lavoro temporanea.

@@
s@

Segna l'inizio del labirinto come visitato.

##
.#

Segna la fine del labirinto come vuota.

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

Mentre esistono celle di lavoro disponibili, puntale verso celle adiacenti precedentemente visitate.

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

Traccia il percorso dall'uscita all'inizio utilizzando le celle di lavoro come guida.

.(.)
$1

Elimina le celle di lavoro.


1

JavaScript, 450 byte

Accetta input come (n, {playerx, playery}, {targetx, targety}, [{obstaclex, obstacley}]). Restituisce una matrice di {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;}

Ecco una versione non offuscata sul mio pasticcio:

// 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;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.