Tentukan nilai mana yang mewakili arah mana di jalur

10

Sunting penting: Sebelumnya, ada nilai yang salah dalam Contoh 1. Sudah diperbaiki.

Anda diberi array dua dimensi di mana setiap sel berisi satu dari empat nilai.

Contoh:

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

Keempat nilai mewakili panah arah (atas, bawah, kiri, dan kanan), meskipun Anda tidak tahu nilai mana yang mewakili arah mana.

Panah arah membentuk jalur tak terputus yang menyertakan setiap sel dalam array, meskipun Anda tidak tahu di mana titik awal atau akhir berada.

Tulis beberapa kode yang menentukan ke arah mana masing-masing dari empat nilai mewakili dan di mana titik awal dan akhir berada.

Nilai pengembalian yang dapat diterima untuk array yang berisi nilai-nilai A, B, C, dan D akan menjadi sesuatu seperti:

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

Karena Anda dapat melintasi jalur dengan dua arah (dari awal hingga akhir dan dari ujung ke awal), akan selalu ada lebih dari satu solusi yang benar, dan mungkin ada lebih dari dua. Asumsikan bahwa input yang Anda terima (seperti dalam contoh di atas) selalu memiliki setidaknya satu solusi yang benar. Dalam kasus di mana ada lebih dari satu solusi yang tepat, mengembalikan hanya satu dari solusi yang tepat sudah cukup.

Kode terpendek menang. Saya akan memilih pemenang setelah 7 hari atau 24 jam tanpa pengiriman baru, mana yang lebih dulu.

Saya menyertakan solusi untuk contoh di atas, tetapi saya mendorong Anda untuk hanya memeriksanya setelah Anda menulis kode Anda:

Satu:

{atas: 3, bawah: 1, kiri: 4, kanan: 2, mulai: [0,0], akhir: [2,5]}

Dua:

{atas: '@', bawah: 'e', ​​kiri: '.', kanan: 'H', mulai: [1,1], akhir: [0,0]}

Tiga:

{up: 'I', down: 'V', kiri: 'C', kanan: 'X', mulai: [0,2], akhir: [4,2]}

jawns317
sumber
1
"Anda dapat melintasi jalan dua arah" - jika arahnya absolut, bukan relatif, ini tidak benar. Apakah arahnya absolut, atau relatif? Juga, apakah awal dan akhir diketahui berada di luar array?
John Dvorak
@ JanDvorak Titik awal dan akhir adalah sel dalam array. Adapun arah, asumsikan mereka selalu menunjukkan pergerakan ke sel yang berdekatan (utara, selatan, timur, atau barat).
jawns317
Dalam hal ini tidak mungkin untuk melintasi jalan mundur. Saya tidak dapat melihat jaminan apa pun akan selalu ada lebih dari satu solusi.
John Dvorak
1
Jika kita "berasumsi mereka selalu menunjukkan perpindahan ke sel yang berdekatan", apakah contoh kedua Anda masih valid? Saya mungkin kehilangan sesuatu tetapi sepertinya @ tidak bisa salah satu dari empat arah tanpa "keluar batas".
Nick Sarabyn
1
Contoh 1 tidak memiliki solusi.
DavidC

Jawaban:

6

C #

EDIT: Memperbaiki divisi dan pemformatan. Dan menambahkan kelas pembantu.

Ini adalah kode golf, 807 karakter

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

Hasil untuk tiga kasus uji:

Bawah: '1', Kanan: '2', Atas: '3', Kiri: '4' Mulai (0: 0) Akhir (5: 2)
Atas: '@', Kiri: '.', Bawah: ' e ', Kanan:' H 'Mulai (1: 1) Akhir (0: 0)
Kanan:' X ', Bawah:' V ', Atas:' I ', Kiri:' C 'Mulai (0: 2) Akhir (2: 4)

Ini adalah kode mentah tanpa "golf", hampir 4.000 karakter:

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

Ini adalah hasil untuk tiga contoh:

Solusi tidak ditemukan

Mulai (1: 1) Akhir (0: 0) '@': Atas, '.': Kiri, 'e': Bawah, 'H': Kanan

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

Mulai (0: 0) Akhir (1: 1) '0': Kanan, '1': Bawah, '3': Atas, '2': Kiri

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

Blau
sumber
Anda mungkin ingin golf kode Anda, karena ini adalah kompetisi kode-golf.
Timtech
Saya melakukannya :)
Blau
Oke, jangan terburu-buru :) Hanya saja beberapa orang melihat pengguna baru tanpa kode golf dan cenderung downvote.
Timtech
2
Ini pertama kalinya saya ... tapi saya menyarankan agar tidak bermain golf ... walaupun saya pikir saya tidak akan mengalahkan kode matemathica ... :)
Blau
Setiap jawaban untuk pertanyaan ini membutuhkan keterampilan. +1
Timtech
5

Mathematica 278

Spaces ditambahkan untuk "clarity"

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

Sesi & Keluaran:

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

Yang merupakan awal Vertex, End Vertex dan aturan transisi yang terkait dengan masing-masing simbol.

Berikut ini adalah kode pelengkap untuk menunjukkan grafik yang berorientasi:

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]

Grafik Mathematica

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

Ini mengembalikan titik awal, titik akhir, dan aturan transisi. Indeks pertama adalah baris, yang kedua adalah kolom

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

Perhatikan bahwa kode saya berfungsi dengan baik {-1,0,1}~Tuples~{4,2}. Untuk mempercepat Anda bisa menggunakannya Permutations@{{1, 0}, {0, 1}, {-1, 0}, {0, -1}}.

ybeltukov
sumber
0

APL (207)

Saya tidak bisa membuatnya lebih pendek dari Mathematica, karena saya tidak bisa beralasan dalam hal TopologicalSort dan semacamnya. Orang yang lebih cerdas dipersilakan memerasnya lebih jauh.

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}

Tidak Disatukan:

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
}

Contoh:

(Indeks dimulai pada 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
sumber