Determina quale valore rappresenta quale direzione in un percorso


10

Modifica importante: in precedenza, c'era un valore errato nell'esempio 1. È stato corretto.

Viene fornita una matrice bidimensionale in cui ogni cella contiene uno dei quattro valori.

Esempi:

1 2 2 2 2 1        @ . .        X X V
1 3 1 4 1 4        e . @        I C V
2 3 1 3 4 2        H H @        X I V
1 4 4 2 1 3                     V C C
2 2 2 3 2 3                     X X X

I quattro valori rappresentano le frecce direzionali (su, giù, sinistra e destra), sebbene non si sappia quale valore rappresenta quale direzione.

Le frecce direzionali formano un percorso ininterrotto che include ogni cella dell'array, sebbene non si sappia dove si trovano i punti iniziale o finale.

Scrivi un codice che determini quale direzione rappresenta ciascuno dei quattro valori e dove si trovano i punti iniziale e finale.

Un valore di ritorno accettabile per un array che contiene i valori A, B, C e D sarebbe simile a:

{ up: A, down: C, left: D, right: B, start: [2, 0], end: [4, 2] }

Poiché è possibile percorrere il percorso in entrambi i modi (dall'inizio alla fine e dall'inizio alla fine), ci sarà sempre più di una soluzione corretta e potrebbero essercene più di due. Supponiamo che gli input che ricevi (come negli esempi sopra) abbiano sempre almeno una soluzione corretta. Nei casi in cui esiste più di una soluzione corretta, è sufficiente restituire solo una delle soluzioni corrette.

Il codice più corto vince. Sceglierò il vincitore dopo 7 giorni o 24 ore senza una nuova presentazione, a seconda di quale evento si verifichi per primo.

Sto includendo soluzioni agli esempi sopra, ma ti incoraggio a controllarli solo dopo aver scritto il tuo codice:

Uno:

{su: 3, giù: 1, sinistra: 4, destra: 2, inizio: [0,0], fine: [2,5]}

Due:

{su: '@', giù: 'e', ​​sinistra: '.', destra: 'H', inizio: [1,1], fine: [0,0]}

Tre:

{su: 'I', giù: 'V', sinistra: 'C', destra: 'X', inizio: [0,2], fine: [4,2]}


1
"puoi attraversare il percorso in entrambi i modi" - se le direzioni sono assolute, non relative, questo non è vero. Le direzioni sono assolute o relative? Inoltre, l'inizio e la fine sono noti per essere al di fuori dell'array?
John Dvorak,

@JanDvorak I punti iniziale e finale sono celle all'interno dell'array. Per quanto riguarda le direzioni, supponiamo che indichino sempre il movimento in una cella adiacente (nord, sud, est o ovest).
jawns317,

In tal caso non è possibile attraversare un percorso all'indietro. Non vedo alcuna garanzia che ci sarà sempre più di una soluzione.
John Dvorak,

1
Se "assumiamo che indichino sempre il movimento in una cella adiacente", il tuo secondo esempio è ancora valido? Forse mi manca qualcosa, ma sembra che @ non possa essere una delle quattro direzioni senza "andare oltre i limiti".
Nick Sarabyn,

1
L'esempio 1 non ha soluzione.
DavidC,

Risposte:


6

C #

EDIT: risolti divisione e formattazione. E ha aggiunto la classe helper.

Questo è il codice golfizzato, 807 caratteri

class M{public int c,x,y,u;}
void G(string[] z){
M K;int[]x={0,0,-1,1},y={-1,1,0,0},I={0,0,0,0};
string[]T={"Up","Down","Left","Right"};
int X,Y,R,n=0,H=z.Length,W=z[0].Length;W-=W/2;var D= string.Join(" ", z).Where(c=>c!=' ').Select(c=>new M(){c=c,x=n%W,y=n++/W}).ToList();n=0;var S=D.GroupBy(k=>k.c).ToDictionary(k=>k.Key,k =>n++);
for(;I[0]<4;I[0]++)for(I[1]=0;I[1]<4;I[1]++)for(I[2]=0;I[2]<4;I[2]++)for(I[3]=0;I[3]<4;I[3]++){
if ((1<<I[0]|1<<I[1]|1<<I[2]|1<<I[3])!=15)continue;
foreach (var Q in D){D.ForEach(p=>p.u=-1);R=1;K=Q;j:if((X=K.x+x[n=I[S[K.c]]])>=0&&X<W&&(Y=K.y+y[n])>=0&&Y<H&&(K=D[X+Y*W]).u<0){
K.u=1;if(++R==D.Count){Console.WriteLine("{4} Start({0}:{1}) End({2}:{3})",Q.x,Q.y,K.x,K.y,string.Join(", ",S.Select(k=>string.Format("{1}: '{0}'",(char)k.Key,T[I[k.Value]])).ToArray()));return;}goto j;}}}
}    

Risultati per i tre casi di test:

Giù: '1', Destra: '2', Su: '3', Sinistra: '4' Inizio (0: 0) Fine (5: 2)
Su: '@', Sinistra: '.', Giù: ' e ', Destra:' H 'Inizio (1: 1) Fine (0: 0)
Destra:' X ', Giù:' V ', Su:' I ', Sinistra:' C 'Inizio (0: 2) Fine (2: 4)

Questo è il codice grezzo senza "golf", quasi 4.000 caratteri:

class Program
{
    static string[] input1 =  { "1 2 2 2 2 1",
               "1 3 4 4 1 4",       
               "2 3 1 3 4 2",
               "1 4 4 2 1 3",       
               "2 2 2 3 2 3"};

    static string[] input2 =  { "@ . .",
                                "e . @",       
                                "H H @",
               };

    static string[] input3 =  { "0 0 1",
                                "0 0 1",       
                                "3 2 2",
               };

    static void Main(string[] args)
    {
        Resolve(input1);
        Resolve(input2);
        Resolve(input3);
        Console.ReadLine();
    }


    class N { public int c; public int x, y, i, u; }

    static void Resolve(string[] input)
    {
        int[] ox = { -1, 1, 0, 0 }, oy = { 0, 0, -1, 1 }, I = { 0, 0, 0, 0 };
        string[] TXT = { "Left", "Right", "Up", "Down" };
        int X, Y, R, n = 0, H = input.Length, W = input[0].Length;
        W -= W / 2;
        N K = null;
        var data = string.Join(" ", input).Where(c => c != ' ').Select(c => new N() { c = c, x = (n % W), y = (n / W), i = n++, u = -1 }).ToList();
        n = 0;
       var S = data.GroupBy(k => k.c).ToDictionary(k => k.Key, k => n++);

        for (; I[0] < 4; I[0]++)
            for (I[1] = 0; I[1] < 4; I[1]++)
                for (I[2] = 0; I[2] < 4; I[2]++)
                    for (I[3] = 0; I[3] < 4; I[3]++)
                    {
                        if (((1 << I[0]) | (1 << I[1]) | (1 << I[2]) | (1 << I[3])) != 15) continue;
                        foreach(var Q in data)
                        {
                            data.ForEach(p => p.u = -1);
                            R = 0;
                            K = Q;
                            while (K != null)
                            {
                                n = I[S[K.c]];
                                X = K.x + ox[n];
                                Y = K.y + oy[n];
                                if (X >= 0 && X < W && Y >= 0 && Y < H)
                                {
                                    n = X + Y * W;
                                    if (data[n].u < 0)
                                    {
                                         data[n].u = K.i;
                                         K = data[n];
                                        R++;
                                        if (R == data.Count - 1)
                                        {
                                            Console.WriteLine();
                                            Console.WriteLine("Start({0}:{1}) End({2}:{3})", Q.x, Q.y, K.x, K.y);
                                            Console.WriteLine(string.Join(", ", S.Select(k => string.Format("'{0}': {1}", (char)k.Key, TXT[I[k.Value]])).ToArray()));
                                            Action<N> Write = null;
                                            Write = (k) =>
                                             {
                                                 if (k.u != -1)
                                                 {
                                                     Write(data[k.u]);
                                                 }
                                                 Console.Write(string.Format("({0}:{1}){2}", k.x, k.y, k == K ? "\n" : " => "));
                                             };

                                            Write(K);
                                            return;
                                        }
                                        continue;
                                    }
                                }
                                K = null;
                            }
                        }
                    }
        Console.WriteLine("Solution not found");
    }
 }
}

Questi sono i risultati per i tre esempi:

Soluzione non trovata

Inizio (1: 1) Fine (0: 0) '@': Su, '.': Sinistra, 'e': Giù, 'H': Destra

(1: 1) => (0: 1) => (0: 2) => (1: 2) => (2: 2) => (2: 1) => (2: 0) => ( 1: 0) => (0: 0)

Inizio (0: 0) Fine (1: 1) '0': Destra, '1': Giù, '3': Su, '2': Sinistra

(0: 0) => (1: 0) => (2: 0) => (2: 1) => (2: 2) => (1: 2) => (0: 2) => ( 0: 1) => (1: 1)


Potresti voler giocare a golf con il tuo codice, poiché si tratta di una competizione di code-golf.
Timtech,

Lo sto facendo :)
Blau

Va bene, niente fretta :) È solo che alcune persone vedono un nuovo utente senza codice golf e tendono a sottovalutare.
Timtech,

2
È la mia prima volta ... ma vi consiglio di non giocare ancora a golf ... anche se penso che non batterò il codice matematico ... :)
Blau

Qualsiasi risposta a questa domanda richiede abilità. +1
Timtech,

5

Mathematica 278

Spazi aggiunti per "chiarezza"

k@l_ := (s = #~Join~-# &@{{1, 0}, {0, 1}};
         f@r_ := Flatten[MapIndexed[#2 -> #2 + (#1 /. r) &, l, {2}], 1];
         g     = Subgraph[#, t = Tuples@Range@Dimensions@l] & /@ 
                       Graph /@ f /@ (r = Thread[# -> s] & /@ Permutations[Union @@ l]);
        {t[[#]] & /@ Ordering[Tr /@ IncidenceMatrix@g[[#]]][[{1, -1}]], r[[#]]} & @@@ 
                                                                 Position[PathGraphQ /@ g, True])

Sessione e uscita:

 l = l1 = {{1, 2, 2, 2, 2, 1}, {1, 3, 1, 4, 1, 4}, {2, 3, 1, 3, 4, 2}, 
            {1, 4, 4, 2, 1, 3}, {2, 2, 2, 3, 2, 3}}; ;
 k@l1
 {{{{1, 1}, {3, 6}}, 
    {1 -> {1, 0}, 2 -> {0, 1}, 3 -> {-1, 0},  4 -> {0, -1}}}}

Qual è il vertice iniziale, il vertice finale e le regole di transizione associate a ciascun simbolo.

Ecco il codice complementare per mostrare il grafico orientato:

sol = sg[[Position[PathGraphQ /@ sg, True][[1, 1]]]];
Framed@Graph[
  VertexList@sol,
  EdgeList@sol,
  VertexCoordinates -> VertexList@sol /. {x_, y_} :> {y, -x},
  VertexLabels -> MapThread[Rule, {VertexList@sol, Flatten@l}], 
  EdgeShapeFunction -> GraphElementData["FilledArcArrow", "ArrowSize" -> 0.03],
  ImagePadding -> 20]

Grafica Mathematica


2

Mathematica (151)

L = {{1, 2, 2, 2, 2, 1}, {1, 3, 1, 4, 1, 4}, {2, 3, 1, 3, 4, 2}, 
   {1, 4, 4, 2, 1, 3}, {2, 2, 2, 3, 2, 3}};

PathGraphQ@#~If~Print@{TopologicalSort[#]〚{1,-2}〛,r}&@
Graph@Flatten@MapIndexed[#2->#2+(#/.r)&,L,{2}]~Do~{r,
Thread[Union@@L->#]&/@{-1,0,1}~Tuples~{4,2}}

Restituisce il punto iniziale, il punto finale e le regole di transizione. Il primo indice è riga, il secondo è colonna

{{{1,1},{3,6}},{1->{1,0},2->{0,1},3->{-1,0},4->{0,-1}}}

Nota che il mio codice funziona anche con {-1,0,1}~Tuples~{4,2}. Per accelerare puoi Permutations@{{1, 0}, {0, 1}, {-1, 0}, {0, -1}}invece usare .


0

APL (207)

Non potevo renderlo più breve di Mathematica, perché non potevo ragionare in termini di TopologicalSort e simili. Le persone più intelligenti sono invitati a spremerlo ulteriormente.

golfed:

{u←∪,t←⍵⋄q r←↑(0≠+/¨r)/⊂[2]p,⍪r←{m←,⍵[u⍳t]⋄v r←⊂[1]⊃{{(↑⍴∪⍵),⊂(↑⍵)(↑⌽⍵)}n↑{3::⍬⋄i←↑⌽⍵⋄⍵,i+i⌷m}⍣n,⍵}¨⍳n←↑⍴,t⋄↑(v=n)/r}¨p←⊂[2]{1≥⍴⍵:⊃,↓⍵⋄⊃⍪/⍵,∘∇¨⍵∘~¨⍵}d←¯1 1,¯1 1×c←¯1↑⍴t⋄⊃('←→↑↓',¨u[q⍳d]),{1+(⌊⍵÷c)(c|⍵)}¨r-1}

Ungolfed:

D←{⎕ML ⎕IO←3 1
    pmat←{1≥⍴⍵:⊃,↓⍵⋄⊃⍪/⍵,∘∇¨⍵∘~¨⍵}   ⍝ utility: permutations of the given vector
    u←∪,t←⍵                    ⍝ the 4 unique symbols in t←⍵
    n←↑⍴,t                     ⍝ number of elements in t
    d←¯1 1,¯1 1×c←¯1↑⍴t        ⍝ the four ∆i (+1, -1, +cols, -cols)
    p←⊂[2]pmat d               ⍝ list of permutations of the four ∆i
    r←{                        ⍝ for each permutation ⍵∊p (=interpretation of the 4 symbols)
        m←,⍵[u⍳t]              ⍝ (ravelled) t-shaped matrix of ∆i, using interpretation ⍵
        v r←⊂[1]⊃{             ⍝ for each starting index ⍵∊⍳n
            v←n↑{              ⍝ trail of visited cells after n steps 
                3::⍬           ⍝ if index out of bounds return empty list
                i←↑⌽⍵          ⍝ take last visited index
                ⍵,i+i⌷m        ⍝ follow the directions and add it to the list
            }⍣n,⍵
            (↑⍴∪v),⊂(↑v),↑⌽v   ⍝ number of unique cells, plus start/end indices
        }¨⍳n
        ↑(v=n)/r               ⍝ 1st couple of start/end indices to visit all cells (if any)
    }¨p
    q r←↑(0≠+/¨r)/⊂[2]p,⍪r     ⍝ select first perm. and start/end indices to visit all cells
    ⊃('←→↑↓',¨u[q⍳d]),{1+(⌊⍵÷c)(c|⍵)}¨r-1   ⍝ return char mapping and start/end indices
}

Esempi:

(Gli indici iniziano da 1)

     D⊃'122221' '131414' '231342' '144213' '222323'
 ←  4 
 →  2 
 ↑  3 
 ↓  1 
 1  1 
 3  6 
     D⊃'@..' 'e.@' 'HH@'
 ←  . 
 →  H 
 ↑  @ 
 ↓  e 
 2  2 
 1  1 
     D⊃'XXV' 'ICV' 'XIV' 'VCC' 'XXX'
 ←  C 
 →  X 
 ↑  I 
 ↓  V 
 3  1 
 5  3 
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.