Bestimmen Sie, welcher Wert welche Richtung in einem Pfad darstellt

10

Wichtige Änderung: Früher gab es in Beispiel 1 einen falschen Wert. Dieser wurde behoben.

Sie erhalten ein zweidimensionales Array, in dem jede Zelle einen von vier Werten enthält.

Beispiele:

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

Die vier Werte stehen für Richtungspfeile (nach oben, unten, links und rechts), obwohl Sie nicht wissen, welcher Wert welche Richtung darstellt.

Die Richtungspfeile bilden einen ununterbrochenen Pfad, der jede Zelle im Array enthält, obwohl Sie nicht wissen, wo sich die Start- oder Endpunkte befinden.

Schreiben Sie einen Code, der bestimmt, welche Richtung jeder der vier Werte darstellt und wo sich die Start- und Endpunkte befinden.

Ein akzeptabler Rückgabewert für ein Array, das die Werte A, B, C und D enthält, wäre etwa:

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

Da Sie den Pfad in beide Richtungen durchlaufen können (von Anfang bis Ende und von Ende bis Anfang), gibt es immer mehr als eine richtige Lösung und möglicherweise mehr als zwei. Angenommen, die Eingaben, die Sie erhalten (wie in den obigen Beispielen), haben immer mindestens eine richtige Lösung. In Fällen, in denen es mehr als eine richtige Lösung gibt, ist es ausreichend, nur eine der richtigen Lösungen zurückzugeben.

Der kürzeste Code gewinnt. Ich werde den Gewinner nach 7 Tagen oder 24 Stunden ohne neue Einreichung auswählen, je nachdem, was zuerst eintritt.

Ich füge Lösungen zu den obigen Beispielen hinzu, aber ich möchte Sie ermutigen, diese erst zu überprüfen, wenn Sie Ihren Code geschrieben haben:

Einer:

{up: 3, down: 1, left: 4, right: 2, start: [0,0], end: [2,5]}

Zwei:

{up: '@', down: 'e', ​​left: '.', right: 'H', start: [1,1], end: [0,0]}

Drei:

{hoch: 'I', runter: 'V', links: 'C', rechts: 'X', Anfang: [0,2], Ende: [4,2]}

jawns317
quelle
1
"Sie können den Pfad in beide Richtungen durchqueren" - wenn die Richtungen absolut und nicht relativ sind, ist dies nicht wahr. Sind die Richtungen absolut oder relativ? Ist auch bekannt, dass Start und Ende außerhalb des Arrays liegen?
John Dvorak
@JanDvorak Die Start- und Endpunkte sind Zellen innerhalb des Arrays. Nehmen Sie an, dass die Richtungen immer eine Bewegung in eine benachbarte Zelle (Nord, Süd, Ost oder West) anzeigen.
jawns317
In diesem Fall ist es nicht möglich, einen Pfad rückwärts zu durchlaufen. Ich kann keine Garantie sehen, dass es immer mehr als eine Lösung geben wird.
John Dvorak
1
Wenn wir "davon ausgehen, dass sie immer eine Bewegung in eine benachbarte Zelle anzeigen", ist Ihr zweites Beispiel noch gültig? Ich vermisse vielleicht etwas, aber es scheint, als könnte @ keine der vier Richtungen sein, ohne "außerhalb der Grenzen" zu gehen.
Nick Sarabyn
1
Beispiel 1 hat keine Lösung.
DavidC

Antworten:

6

C #

BEARBEITEN: Eine Unterteilung und Formatierung wurde behoben. Und fügte die Helferklasse hinzu.

Dies ist der Golfcode, 807 Zeichen

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

Ergebnisse für die drei Testfälle:

Unten: '1', Rechts: '2', Oben: '3', Links: '4' Start (0: 0) Ende (5: 2)
Oben: '@', Links: '.', Unten: ' e ', rechts:' H 'Start (1: 1) Ende (0: 0)
Rechts:' X ', unten:' V ', oben:' I ', links:' C 'Start (0: 2) Ende (2: 4)

Dies ist der Rohcode ohne "Golf", fast 4.000 Zeichen:

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

Dies sind die Ergebnisse für die drei Beispiele:

Lösung nicht gefunden

Start (1: 1) Ende (0: 0) '@': Oben, '.': Links, 'e': Unten, 'H': Rechts

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

Start (0: 0) Ende (1: 1) '0': Rechts, '1': Unten, '3': Oben, '2': Links

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

Blau
quelle
Vielleicht möchten Sie Ihren Code spielen, da dies ein Code-Golf-Wettbewerb ist.
Timtech
Ich mache es :)
Blau
Okay, keine Eile :) Es ist nur so, dass einige Leute einen neuen Benutzer ohne Golfcode sehen und dazu neigen, abzustimmen.
Timtech
2
Es ist mein erstes Mal ... aber ich rate, dass noch nicht Golf gespielt wird ... obwohl ich denke, dass ich den Matemathica-Code nicht schlagen werde ... :)
Blau
Jede Antwort auf diese Frage erfordert Geschicklichkeit. +1
Timtech
5

Mathematica 278

Leerzeichen für "Klarheit" hinzugefügt

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

Sitzung & Ausgabe:

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

Welches ist der Startvertex, Endvertex und die Übergangsregeln, die jedem Symbol zugeordnet sind.

Hier ist der ergänzende Code zur Darstellung des orientierten Diagramms:

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]

Mathematica-Grafiken

Dr. Belisarius
quelle
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}}

Es werden Startpunkt-, Endpunkt- und Übergangsregeln zurückgegeben. Der erste Index ist Zeile, der zweite ist Spalte

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

Beachten Sie, dass mein Code auch mit funktioniert {-1,0,1}~Tuples~{4,2}. Zum Beschleunigen können Sie Permutations@{{1, 0}, {0, 1}, {-1, 0}, {0, -1}}stattdessen verwenden.

ybeltukov
quelle
0

APL (207)

Ich konnte es nicht kürzer als Mathematica machen, weil ich nicht in Bezug auf TopologicalSort und so weiter argumentieren konnte. Klügere Leute sind herzlich eingeladen, es weiter zu drücken.

Golf:

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

Beispiele:

(Indizes beginnen bei 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 
Tobia
quelle