Districare i dati doppiamente collegati


12

Un elenco doppiamente collegato è una struttura di dati in cui ciascun nodo ha valuesia "collegamenti" sia a quello previoussuccessivo nodesnell'elenco. Ad esempio, considerare i seguenti nodi con valori 12, 99 e 37:

Qui, i nodi con valori 12 e 99 puntano ai rispettivi nextnodi, con valori 99 e 37 . Il nodo con valore 37 non ha nextpuntatore perché è l'ultimo nodo nell'elenco. Allo stesso modo, i nodi con valori 99 e 37 puntano ai rispettivi previousnodi, 12 e 99 , ma 12 non ha previouspuntatore perché è il primo nodo dell'elenco.

Il set up

In pratica, i "collegamenti" di un nodo sono implementati come puntatori alla posizione del nodo precedente e successivo in memoria. Per i nostri scopi, la "memoria" sarà una matrice di nodi e la posizione di un nodo sarà il suo indice nella matrice. Un nodo può essere pensato come una 3 tupla del modulo ( prev value next ). L'esempio sopra, quindi, potrebbe assomigliare a questo:

Ma potrebbe apparire così, invece:

A partire da qualsiasi nodo, è possibile seguire i previouscollegamenti (mostrati come origini delle frecce rosse) per arrivare ai nodi che lo precedono e nextcollegamenti (frecce verdi) per trovare i nodi successivi al fine di ottenere tutti i valori dei nodi in ordine: [12, 99, 37].

Il primo diagramma sopra potrebbe essere rappresentato in un array come [[null, 12, 1], [0, 99, 2], [1, 37, null]]. Il secondo, quindi, sarebbe [[2, 99, 1], [0, 37, null], [null, 12, 0]].

La sfida

Scrivere un programma che accetta come input una matrice di nodi e l'indice di un nodo e restituisce, in ordine di lista, i valori dei nodi nella stessa lista doppiamente collegata.

Una complicazione

La "memoria" non conterrà sempre i nodi di un solo elenco. Potrebbe contenere diversi elenchi:

L'array sopra contiene tre elenchi doppiamente collegati, codificati a colori per comodità:

  1. I nodi a indici 7, 10, 1, 4, 3, 12(mostrando solo nexti collegamenti per ridurre l'ingombro, clicca per ingrandire):

    Dato questo array e uno qualsiasi di questi indici, il programma dovrebbe restituire, nell'ordine, i valori [0, 1, 1, 2, 3, 5, 8].

  2. Il nodo all'indice 9:

    Dato l'indice 9, il tuo programma dovrebbe tornare [99].

  3. I nodi a indici 11, 8, 0, 6, 2:

    Dato uno di questi indici, dovrebbe tornare [2, 3, 5, 7, 11].

Regole

Ingresso

Il tuo programma riceverà come input:

  1. Un elenco di nodi ((3-tuple come descritto sopra), dove 1 ≤ 𝒏 ≤ 1.000, in qualsiasi formato conveniente, ad esempio una matrice di matrici, una matrice "piatta" di numeri interi con lunghezza 3𝒏, ecc.

    Elementi 3-tuple possono essere in qualsiasi ordine: ( prev value next ), ( next prev value ), ecc Per ogni nodo, preve nextsaranno null(o un altro valore conveniente, per esempio -1), che indica il primo o l'ultimo nodo in una lista doppiamente concatenata, o un indice valido del elenco, basato su 0 o 1 come è conveniente. valuesarà un numero intero a 32 bit con segno o il tipo intero più grande supportato dalla tua lingua, a seconda di quale sia il più piccolo.

  2. L'indice 𝒑 di un nodo nell'elenco (1). Il nodo indicato può essere il primo nodo in un elenco doppiamente collegato, l'ultimo nodo, un nodo centrale o persino l'unico nodo.

L'elenco di input (1) può contenere dati patologici (ad es. Cicli, nodi indicati da più altri nodi, ecc.), Ma l'indice di input (2) punterà sempre a un nodo dal quale può essere un singolo output ben formato dedotta.

Produzione

Il programma dovrebbe generare i valori dei nodi dell'elenco doppiamente collegato di cui è membro il nodo all'indice 𝒑, in ordine di lista. L'output può essere in qualsiasi formato conveniente, ma i suoi dati devono includere solo i nodi value.

vincente

Questo è . Vince la risposta più breve in byte. Si applicano scappatoie standard.

Casi test

Di seguito, ciascun caso di test è nel formato:

X)
prev value next, prev value next, ...
index
value value value ...

... dove Xc'è una lettera per identificare il caso di test, la seconda riga è l'elenco di input, la terza riga è l'indice di input basato su 0 e la quarta riga è l'output.

A) null 12 1, 0 99 2, 1 37 null
   1
   12 99 37

B) 2 99 1, 0 37 null, null 12 0
   1
   12 99 37

C) 8 5 6, 10 1 4, 6 11 null, 4 3 12, 1 2 3, 12 8 null, 0 7 2, null 0 10, 11 3 0, null 99 null, 7 1 1, null 2 8, 3 5 5
   4
   0 1 1 2 3 5 8

D) 8 5 6, 10 1 4, 6 11 null, 4 3 12, 1 2 3, 12 8 null, 0 7 2, null 0 10, 11 3 0, null 99 null, 7 1 1, null 2 8, 3 5 5
   0
   2 3 5 7 11

E) 8 5 6, 10 1 4, 6 11 null, 4 3 12, 1 2 3, 12 8 null, 0 7 2, null 0 10, 11 3 0, null 99 null, 7 1 1, null 2 8, 3 5 5
   9
   99

F) 13 80 18, 18 71 null, 5 10 19, 12 1 8, 19 21 null, 31 6 2, 17 5 26, 26 0 30, 3 -1 25, null 1 23, 27 6 17, 14 1 24, 28 -1 3, null 80 0, 20 4 11, 33 6 29, 24 9 33, 10 7 6, 0 67 1, 2 15 4, 32 1 14, null 1 31, 29 3 null, 9 -1 28, 11 5 16, 8 1 null, 6 3 7, null 8 10, 23 1 12, 15 5 22, 7 9 null, 21 3 5, null 3 20, 16 2 15
   18
   80 80 67 71

G) 13 80 18, 18 71 null, 5 10 19, 12 1 8, 19 21 null, 31 6 2, 17 5 26, 26 0 30, 3 -1 25, null 1 23, 27 6 17, 14 1 24, 28 -1 3, null 80 0, 20 4 11, 33 6 29, 24 9 33, 10 7 6, 0 67 1, 2 15 4, 32 1 14, null 1 31, 29 3 null, 9 -1 28, 11 5 16, 8 1 null, 6 3 7, null 8 10, 23 1 12, 15 5 22, 7 9 null, 21 3 5, null 3 20, 16 2 15
   8
   1 -1 1 -1 1 -1 1

H) 13 80 18, 18 71 null, 5 10 19, 12 1 8, 19 21 null, 31 6 2, 17 5 26, 26 0 30, 3 -1 25, null 1 23, 27 6 17, 14 1 24, 28 -1 3, null 80 0, 20 4 11, 33 6 29, 24 9 33, 10 7 6, 0 67 1, 2 15 4, 32 1 14, null 1 31, 29 3 null, 9 -1 28, 11 5 16, 8 1 null, 6 3 7, null 8 10, 23 1 12, 15 5 22, 7 9 null, 21 3 5, null 3 20, 16 2 15
   4
   1 3 6 10 15 21

I) 13 80 18, 18 71 null, 5 10 19, 12 1 8, 19 21 null, 31 6 2, 17 5 26, 26 0 30, 3 -1 25, null 1 23, 27 6 17, 14 1 24, 28 -1 3, null 80 0, 20 4 11, 33 6 29, 24 9 33, 10 7 6, 0 67 1, 2 15 4, 32 1 14, null 1 31, 29 3 null, 9 -1 28, 11 5 16, 8 1 null, 6 3 7, null 8 10, 23 1 12, 15 5 22, 7 9 null, 21 3 5, null 3 20, 16 2 15
   14
   3 1 4 1 5 9 2 6 5 3

J) 13 80 18, 18 71 null, 5 10 19, 12 1 8, 19 21 null, 31 6 2, 17 5 26, 26 0 30, 3 -1 25, null 1 23, 27 6 17, 14 1 24, 28 -1 3, null 80 0, 20 4 11, 33 6 29, 24 9 33, 10 7 6, 0 67 1, 2 15 4, 32 1 14, null 1 31, 29 3 null, 9 -1 28, 11 5 16, 8 1 null, 6 3 7, null 8 10, 23 1 12, 15 5 22, 7 9 null, 21 3 5, null 3 20, 16 2 15
   17
   8 6 7 5 3 0 9

K) 4 11 0, null 22 3, null 33 3, 1 44 4, 3 55 null, 7 66 7, 6 77 6
   3
   22 44 55

L) null -123 null
   0
   -123



È consentito l'input come tre matrici (una contenente tutti i nodi precedenti in ordine, un valore e un nodo successivo) o è troppo lontana dal concetto di tuple?
Sanchises,

@Sanchise Siamo spiacenti, troppo lontano per me.
Giordania,

Va tutto bene! Pensavo di sì, ma volevo essere davanti a qualsiasi commento sulla mia risposta dicendo che avrei potuto radere due byte prendendo array separati.
Sanchises,

Risposte:


1

05AB1E , 25 byte

è[¬D0‹#Isè]\[`sˆD0‹#Isè]¯

Provalo online!

Spiegazione

è[¬D0‹#Isè]\[`sˆD0‹#Isè]¯   # Arguments n, a
è                           # Get element at index n in a
 [¬D0‹#Isè]                 # Find the first element in the list
 [                          # While true, do
  ¬                         #   Head (get index of previous element)
   D0‹#                     #   Break if lower than 0
       Isè                  #   Get the element at that index
          ]                 # End loop
           \                # Delete top element of stack
            [`sˆD0‹#Isè]    # Iterate through list
            [               # While true, do
             `sˆ            #   Add value to global array and keep next index on stack
                D0‹#Isè     #   Same as above
                       ]    # End loop
                        ¯   # Push global array

3

Haskell , 79 65 59 55 byte

-6 byte grazie a Brute Force .

x#i|let-1!d=[];i!d=i:x!!i!!d!d=[x!!i!!1|i<-last(i!0)!2]

Definisce la funzione #che accetta un elenco di elenchi di numeri interi, dove nullè rappresentato come -1, e restituisce un elenco di valori di nodo.

Provalo online!

Spiegazione

let-1!d=[];i!d=i:x!!i!!d!d

Definire la funzione !che scorre tra i nodi a partire dal nodo ie restituisce un elenco di indici visitati. Accetta il secondo argomento dche specifica quale indice della "tupla" usa come indice del nodo successivo ( d==2per iterare in avanti, d==0per iterare indietro).

(i!0)

Scorrere indietro a partire dall'indice indicato e restituire gli indici visitati.

last(i!0)

Prendi l'ultimo indice visitato, che è l'inizio dell'elenco.

last(i!0)!2

Scorrere dall'inizio della lista.

[x!!i!!1|i<-last(i!0)!2]

Sostituisci ogni indice visitato con il valore del nodo.


Potresti quasi scrivere x!!i!!1come i!1!!1, ma si rompe a causa degli -1output. Se scegli semplicemente un altro valore sentinella da rappresentare null(diciamo, -9), funzionerà, ma si romperà sempre per alcuni input, il che è abbastanza fastidioso.
Lynn,

3

Python 2 , 60 byte

l,n=input()
while~n:m=n;n=l[n][0]
while~m:p,v,m=l[m];print v

Provalo online!

Questa è praticamente la risposta di Chas Brown, meno questi campi da golf:

  • Riutilizzo n, salvando un compito
  • Conservo l'ultimo n valido in m, permettendomi di farlo
  • posizionare la stampa dopo l'assegnazione nella riga 3, salvandomi la stampa finale
  • Uso solo ~ n invece di - ~ n, perché i valori negativi sono veri quanto quelli positivi, salvandomi 2 caratteri.


2

MATL , 39 byte

XHx`HwI3$)t]x6Mt`Hwl3$)tbhwt]x4L)Hw2I$)

Provalo online!

Quasi una porta diretta della mia risposta Octave, ma questa versione trova prima la fine e poi torna indietro, piuttosto che viceversa, risparmiando un byte.

XHx           % Store array in H.
`HwI3$)t]     % Work to the end of the array
x6Mt          % Delete the end of array delimiter, and push the array end index twice
`Hwl3$)    t] % Work to the beginning of the array
       tbhw   % Append all indices found.
Hw2I$)        % Index into original array.

1

PHP, 132 byte

<?list(,$x,$y)=$argv;parse_str($x);while(($q=$x[$y*3+1])>=0)$y=$q;do{$n[]=$x[$y*3+2];$y=$x[$y*3];}while($x[$y*3]);echo join(' ',$n);

Provalo online!

Ingresso è preso come querystring x[]=-1&x[]=1&x[]=1...(tutti i nodi in una matrice piatta), nell'ordine next, prevquindi valueper ogni nodo con -1 usato per terminare nodi.


1

Python 2 , 81 77 byte

a,n=input()
u=a[n][0]
while-~u:u,v,w=a[u]
while-~w:print v;u,v,w=a[w]
print v

Provalo online!

EDIT: Grazie a Mr. Xcoder per 4 byte ...

Prende un elenco di tuple [u, v, w] in cui u e w sono -1 per rappresentare l'inizio / fine del segmento dell'elenco collegato.


77 byte Provalo online! . I booleani sono sottoclassi di int, quindi solo 0Falsy, e quindi u>=0può essere giocato a golf u+1e questo può essere ulteriormente abbreviato -~uper rimuovere lo spazio bianco.
Mr. Xcoder il

@Sig. Xcoder - Sì, proprio così!
Chas Brown,

1

Ottava , 81 78 76 byte

function o=f(a,n)while q=a(n,1)o=a(n=q,2);end
while n=a(n,3)o=[o a(n,2)];end

Provalo online!

Versione piuttosto semplice. La spiegazione è lasciata come esercizio al lettore. Una versione molto più divertente è presentata di seguito:

Ottava , 142 99 92 byte

@(a,n)[(p=@(b,c,z){q=a(z,2),@()[b(b,c,a(z,c)),q]}{2-~a(z,c)}())(p,1,n),p(p,3,n)(end-1:-1:1)]

Provalo online!

Yo, ho sentito che ti sono piaciute le funzioni anonime ...

Prende un nx3array, con la prima colonna il predecessore, la seconda colonna il valore e il terzo valore i nodi successivi. Tutti gli indici dei nodi sono basati su 1, che è l'impostazione predefinita in Octave.

% Create an anonymous function, taking an array a and first node n
@(a,n)
% Returns an array containing the predecessor and sucessor nodes
      [                                                                     ,                     ]
% Defines an recursive anonymous function (by supplying itself to the local namespace)
% which looks at the first column (c=1) or last column (c=3) of the input array to get the next nodes
       (p=@(p,c,z)                                                   )(p,1,n)
% Create a cell array, either containing the end node,
                    {q=a(z,2),                       
% ...or an array with all next  next nodes and the current node
% (note the use of an anonymous function taking no parameters to defer array access, in case of the last node)                
                              @()[p(p,c,a(z,c)),q]}
% depending whether the next node number is nonzero (followed by () to execute the deferred array access)
                                                    {2-~a(z,c)}()
% Do the same with c=3, reverse (function p builds the array right-to-left) and drop the current node to prevent a duplicate.                                                                             
                                                                             p(p,3,n)(end-1:-1:1)

1

Kotlin , 85 byte

{g,S->generateSequence(generateSequence(S){g[it][0]}.last()){g[it][2]}.map{g[it][1]}}

Abbellire

{g,S->
    generateSequence(generateSequence(S){g[it][0]}.last()){ g[it][2]}.map { g[it][1] }
}

Test

typealias Node=Triple<Int?,Int?,Int?>
data class Test(val input: List<Node>, val start:Int, val result: List<Int>)
val TEST = listOf<Test>(
Test(
listOf(Node(null, 12, 1), Node(0, 99, 2), Node(1, 37, null)),
1,
listOf(12, 99, 37)
),
Test(listOf(
Node(2, 99, 1), Node(0, 37, null), Node(null, 12, 0)),
1,
listOf(12, 99, 37)
),
Test(
listOf(Node(8, 5, 6), Node(10, 1, 4), Node(6, 11, null), Node(4, 3, 12), Node(1, 2, 3), Node(12, 8, null), Node(0, 7, 2), Node(null, 0, 10), Node(11, 3, 0), Node(null, 99, null), Node(7, 1, 1), Node(null, 2, 8), Node(3, 5, 5)),
4,
listOf(0, 1, 1, 2, 3, 5, 8)
),
Test(
listOf(Node(8, 5, 6), Node(10, 1, 4), Node(6, 11, null), Node(4, 3, 12), Node(1, 2, 3), Node(12, 8, null), Node(0, 7, 2), Node(null, 0, 10), Node(11, 3, 0), Node(null, 99, null), Node(7, 1, 1), Node(null, 2, 8), Node(3, 5, 5)),
0,
listOf(2, 3, 5, 7, 11)
),
Test(
listOf(Node(8, 5, 6), Node(10, 1, 4), Node(6, 11, null), Node(4, 3, 12), Node(1, 2, 3), Node(12, 8, null), Node(0, 7, 2), Node(null, 0, 10), Node(11, 3, 0), Node(null, 99, null), Node(7, 1, 1), Node(null, 2, 8), Node(3, 5, 5)),
9,
listOf(99)
),
Test(
listOf(Node(13, 80, 18), Node(18, 71, null), Node(5, 10, 19), Node(12, 1, 8), Node(19, 21, null), Node(31, 6, 2), Node(17, 5, 26), Node(26, 0, 30), Node(3, -1, 25), Node(null, 1, 23), Node(27, 6, 17), Node(14, 1, 24), Node(28, -1, 3), Node(null, 80, 0), Node(20, 4, 11), Node(33, 6, 29), Node(24, 9, 33), Node(10, 7, 6), Node(0, 67, 1), Node(2, 15, 4), Node(32, 1, 14), Node(null, 1, 31), Node(29, 3, null), Node(9, -1, 28), Node(11, 5, 16), Node(8, 1, null), Node(6, 3, 7), Node(null, 8, 10), Node(23, 1, 12), Node(15, 5, 22), Node(7, 9, null), Node(21, 3, 5), Node(null, 3, 20), Node(16, 2, 15)),
18,
listOf(80, 80, 67, 71)
),
Test(
listOf(Node(13, 80, 18), Node(18, 71, null), Node(5, 10, 19), Node(12, 1, 8), Node(19, 21, null), Node(31, 6, 2), Node(17, 5, 26), Node(26, 0, 30), Node(3, -1, 25), Node(null, 1, 23), Node(27, 6, 17), Node(14, 1, 24), Node(28, -1, 3), Node(null, 80, 0), Node(20, 4, 11), Node(33, 6, 29), Node(24, 9, 33), Node(10, 7, 6), Node(0, 67, 1), Node(2, 15, 4), Node(32, 1, 14), Node(null, 1, 31), Node(29, 3, null), Node(9, -1, 28), Node(11, 5, 16), Node(8, 1, null), Node(6, 3, 7), Node(null, 8, 10), Node(23, 1, 12), Node(15, 5, 22), Node(7, 9, null), Node(21, 3, 5), Node(null, 3, 20), Node(16, 2, 15)),
8,
listOf(1, -1, 1, -1, 1, -1, 1)
),
Test(
listOf(Node(13, 80, 18), Node(18, 71, null), Node(5, 10, 19), Node(12, 1, 8), Node(19, 21, null), Node(31, 6, 2), Node(17, 5, 26), Node(26, 0, 30), Node(3, -1, 25), Node(null, 1, 23), Node(27, 6, 17), Node(14, 1, 24), Node(28, -1, 3), Node(null, 80, 0), Node(20, 4, 11), Node(33, 6, 29), Node(24, 9, 33), Node(10, 7, 6), Node(0, 67, 1), Node(2, 15, 4), Node(32, 1, 14), Node(null, 1, 31), Node(29, 3, null), Node(9, -1, 28), Node(11, 5, 16), Node(8, 1, null), Node(6, 3, 7), Node(null, 8, 10), Node(23, 1, 12), Node(15, 5, 22), Node(7, 9, null), Node(21, 3, 5), Node(null, 3, 20), Node(16, 2, 15)),
4,
listOf(1, 3, 6, 10, 15, 21)
),
Test(
listOf(Node(13, 80, 18), Node(18, 71, null), Node(5, 10, 19), Node(12, 1, 8), Node(19, 21, null), Node(31, 6, 2), Node(17, 5, 26), Node(26, 0, 30), Node(3, -1, 25), Node(null, 1, 23), Node(27, 6, 17), Node(14, 1, 24), Node(28, -1, 3), Node(null, 80, 0), Node(20, 4, 11), Node(33, 6, 29), Node(24, 9, 33), Node(10, 7, 6), Node(0, 67, 1), Node(2, 15, 4), Node(32, 1, 14), Node(null, 1, 31), Node(29, 3, null), Node(9, -1, 28), Node(11, 5, 16), Node(8, 1, null), Node(6, 3, 7), Node(null, 8, 10), Node(23, 1, 12), Node(15, 5, 22), Node(7, 9, null), Node(21, 3, 5), Node(null, 3, 20), Node(16, 2, 15)),
14,
listOf(3, 1, 4, 1, 5, 9, 2, 6, 5, 3)
),
Test(
listOf(Node(13, 80, 18), Node(18, 71, null), Node(5, 10, 19), Node(12, 1, 8), Node(19, 21, null), Node(31, 6, 2), Node(17, 5, 26), Node(26, 0, 30), Node(3, -1, 25), Node(null, 1, 23), Node(27, 6, 17), Node(14, 1, 24), Node(28, -1, 3), Node(null, 80, 0), Node(20, 4, 11), Node(33, 6, 29), Node(24, 9, 33), Node(10, 7, 6), Node(0, 67, 1), Node(2, 15, 4), Node(32, 1, 14), Node(null, 1, 31), Node(29, 3, null), Node(9, -1, 28), Node(11, 5, 16), Node(8, 1, null), Node(6, 3, 7), Node(null, 8, 10), Node(23, 1, 12), Node(15, 5, 22), Node(7, 9, null), Node(21, 3, 5), Node(null, 3, 20), Node(16, 2, 15)),
17,
listOf(8, 6, 7, 5, 3, 0, 9)
),
Test(
listOf(Node(4, 11, 0), Node(null, 22, 3), Node(null, 33, 3), Node(1, 44, 4), Node(3, 55, null), Node(7, 66, 7), Node(6, 77, 6)),
3,
listOf(22, 44, 55)
),
Test(
listOf(Node(null, -123, null)),
0,
listOf(-123)
)
)

var f:(List<List<Int?>>,Int)-> Sequence<Int?> =
{g,S->generateSequence(generateSequence(S){g[it][0]}.last()){g[it][2]}.map{g[it][1]}}

fun main(args: Array<String>) {
    for ((input, start, result) in TEST) {
        val out = f(input.map { it.toList() }, start).toList()
        if (out != result) {
            throw AssertionError("$input $start $result $out")
        }
    }
}

TIO

TryItOnline


Vorrei solo che generateSequence fosse più breve
jrtapsell

0

JavaScript ES6, 70 63 byte

(x,i,a)=>(h=_=>i&&h(a(x[i].v),i=x[i].n))(x.map(_=>i=x[i].p||i))

Caso di prova:

F([undefined,{p:0,v:12,n:2},{p:1,v:99,n:3},{p:2,v:37,n:0}],1,alert)

Le alertnecessità di essere nel corpo principale della funzione e contate verso il totale di byte.
Shaggy


+10 / -9 non è un consenso.
Shaggy

Non vedo i + e - s esatti. Inoltre, è il modo di output previsto da javascript e l'unico modo in cui l'output ha qualche ritardo
l4m2
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.