Búsqueda profunda en una lista

19

Para este desafío, una lista se considera válida si y solo si consiste enteramente de enteros y listas válidas (definiciones recursivas \ o /). Para este desafío, dada una lista válida y un número entero, devuelve una lista de todas las profundidades a las que se puede encontrar el número entero.

Ejemplo

Consideremos la lista [1, [2, [3, [1, 2, 3], 4], 1], 1]y el entero 1. Entonces, podemos dibujar la lista así:

Depth 0 1 2 3
Num   1
        2
          3
            1
            2
            3
          4
        1
      1

Notarás que 1aparece en las profundidades 0, 1, 3. Por lo tanto, su salida debe estar 0, 1, 3en algún formato razonable (el orden no importa).

La profundidad puede ser 0 o 1 indexada, pero especifique en su envío cuál es.

Casos de prueba (indexados 0)

Para la lista [1,[2,[3,4],5,[6,7],1],[[[[5,2],4,[5,2]]],6],3]:

1 -> [0, 1]
2 -> [1, 4]
3 -> [0, 2]
4 -> [2, 3]
5 -> [1, 4]
6 -> [1, 2]
7 -> [2]

Para la lista [[[[[1],0],1],0],1]:

0 -> 1, 3
1 -> 0, 2, 4

Para la lista [11,22,[33,44]]:

11 -> [0]
22 -> [0]
33 -> [1]
44 -> [1]

Devuelve una lista vacía si el término de búsqueda no existe en la lista en ninguna parte.

Los valores negativos y cero son válidos en la lista de entrada y el término.

Hiperneutrino
fuente
Si el número entero aparece a una profundidad varias veces, ¿tenemos que devolver ese número de profundidad solo una vez?
Giuseppe
@Giuseppe sí, eso es correcto.
HyperNeutrino
1
@ Adám Bueno, dado que uno de mis casos de prueba tiene ceros, no. También agregaré que los enteros negativos son un juego justo.
HyperNeutrino
1
Los números de varios dígitos también deben agregarse en un caso de prueba, si pueden ocurrir.
Zgarb
1
@KevinCruijssen Sí, sí, no y sí. Por lo tanto, puede tomar entradas como cadenas, y puede mostrar la profundidad en cualquier orden, pero no varias veces.
HyperNeutrino

Respuestas:

7

Mathematica, 25 bytes

Tr/@Union[1^Position@##]&

(devuelve salida indexada 1)

Explicación

                         test  {1, {2, {3, {1, 2, 3}, 4}, 1}, 1}
             Position[test,1]  {{1}, {2, 2, 2, 1}, {2, 3}, {3}}
           1^Position[test,1]  {{1}, {1, 1, 1, 1}, {1, 1}, {1}}
    Union[1^Position[test,1]]  {{1}, {1, 1}, {1, 1, 1, 1}}
Tr/@Union[1^Position[test,1]]  {1, 2, 4}
Misha Lavrov
fuente
7

Haskell , 102 93 80 76 bytes

Gracias Bruce Forte por guardar algunos bytes, y Laikoni por guardar algunos más.

Gracias 4castle por guardar 4 bytes.

Haskell no tiene ningún tipo de datos para este tipo de lista, así que hice el mío.

Esta solución es 1-indexed

import Data.List
data T=E Int|L[T]
E n%x=[0|x==n]
L s%x=nub$map(+1).(%x)=<<s

Pruébalo en línea!

Primero defino (recursivamente) un tipo de datos T

Ttiene tipo E Int(elemento único de tipo Int) o L[L](lista de tipo T).

(%)es una función que toma 2argumentos, de tipo T, la lista a través de la cual estamos buscando y xla Intque estamos buscando.

Siempre que (%)encuentra algo que es un elemento único E n, comprueba la nigualdad con xy devuelve 0si es verdadero.

Cuando (%)se aplica a un L s(donde stiene tipo [T]) se ejecuta (%)en todos los elementos se incrementa el resultado (a medida que aumenta la profundidad ya que estamos mirando hacia adentro s), y concatena el resultado.

nub luego elimina los duplicados de la lista

NÓTESE BIEN. import Data.Listes solo para nub.

H.PWiz
fuente
Se me ocurrió una solución bastante similar para 81 bytes: ¡ Pruébelo en línea!
Laikoni
@Laikoni Muy bien, ¿quieres publicarlo tú mismo o sugieres que actualice el mío?
H.PWiz
Siéntase libre de actualizar su respuesta. :)
Laikoni
En cuanto al NB: intenté deshacerme de la importación, pero terminé en 88 bytes: ¡ Pruébelo en línea!
Laikoni
2
Puede quitar el paréntesis alrededor E nyL s .
4castle
4

Jalea , 11 8 bytes

WẎÐĿċ€IT

Pruébalo en línea!

Cómo funciona

WẎÐĿċ€IT  Main link. Left argument: A (array). Right argument: n (integer)

W         Wrap; yield [A].
  ÐĿ      Repeatedly apply the link to the left until the results are no longer
          unique. Yield the array of all unique results.
 Ẏ          Concatenate all elements at depth 1 in the array.
          The last array of the array of results is completely flat.
    ċ€    Count the occurrences of n in each intermediate result.
      I   Compute all forward differences.
       T  Truth; yield the array of all indices of non-zero differences.

Ejecución de ejemplo

Para argumento izquierdo

[1, [2, [3, [1, 2, 3], 4], 1], 1]

W primero produce la siguiente matriz.

[[1, [2, [3, [1, 2, 3], 4], 1], 1]]

ẎÐĿconcatena repetidamente todos los elementos en la profundidad 1 , reduciendo la profundidad de la matriz en 1 en cada paso. Esto produce el siguiente conjunto de resultados intermedios.

[
 [[1, [2, [3, [1, 2, 3], 4], 1], 1]],
 [ 1, [2, [3, [1, 2, 3], 4], 1], 1 ],
 [ 1,  2, [3, [1, 2, 3], 4], 1,  1 ],
 [ 1,  2,  3, [1, 2, 3], 4,  1, 1  ],
 [ 1,  2,  3,  1, 2, 3,  4,  1, 1  ]
]

Para el argumento correcto 1 , ċ€cuenta las ocurrencias de 1 en cada resultado intermedio.

[0, 2, 3, 3, 4]

I ahora lleva todas las diferencias hacia adelante.

[2, 1, 0, 1]

Las diferencias distintas de cero corresponden a los pasos en los que se agregó al menos otro 1 a la profundidad 1 . Por lo tanto, una diferencia distinta de cero en el índice k indica la presencia de un 1 en la profundidad k . Tencuentra los índices de todos los elementos de verdad, produciendo el resultado deseado:

[1, 2, 4]
Dennis
fuente
\ / / esta fue mi solución exacta al comparar Jelly con Python. ¡Hurra! : P
HyperNeutrino
4

R , 101 95 92 100 bytes

f=function(L,n,d=0)unique(unlist(Map(function(x)if(n%in%unlist(x))"if"(is.list(x),f(x,n,d+1),d),L)))

Pruébalo en línea!

Solución recursiva; es bastante ineficiente en bytes, pero Rlists es muy molesto trabajar con

Básicamente, toma L, y para cada elemento xde L, (que es listo un atomicvector de un elemento), verifica si nes %in% x, luego verifica si xes a list. Si no es así, entonces x==ndevolvemos la profundidad d; de lo contrario, de forma recursiva llamamos fen x, incrementandod .

Esto, por supuesto, devuelve a list, que nosotros unlisty uniquepara garantizar la salida correcta (devolviendo un vector de profundidades enteras); devuelve NULL(una lista vacía) para inválidon .

Aparentemente, %in%no busca de forma recursiva a través de lo listque pensé, así que tengo que unlist(x)buscar +8 bytes :(

Giuseppe
fuente
3

APL (Dyalog) , 39 bytes *

Programa completo Solicita la lista, luego el número. Imprime la lista basada en 1 en STDOUT.

2÷⍨⍸∨⌿⍞⍷⎕FMTJSON'Compact'0⊢⎕

Pruébalo en línea!

 solicitud de lista

 rendimiento que (separa 0y )

⎕JSON⍠'Compact'0 convertir a una cadena JSON sangrada con nuevas líneas

⎕FMT convertir a matriz (una línea delimitada por nueva línea por fila)

⍞⍷ solicite el número como cadena e indique dónde comienza en ese

∨⌿ reducción OR vertical (es decir, en qué columnas comienza)

 índices de esos comienzos

2÷⍨ reducir a la mitad eso (los niveles están sangrados con dos espacios)

 redondear hacia abajo (porque la primera columna de datos es la columna 3)


* En Dyalog Classic, contando como ⎕U2378y como ⎕OPT.

Adán
fuente
2

PHP , 117 bytes

$r;function z($a,&$r,$i=0){foreach($a as $v){is_int($v)?(@in_array($i,$r[$v])?:$r[$v][]=$i):z($v,$r,$i+1);}}z($s,$r);

Pruébalo en línea!

Calimero
fuente
2

JavaScript (ES6), 79 68 bytes

f=(a,n,r=new Set,d=0)=>a.map(e=>e.map?f(e,n,r,d+1):e-n||r.add(d))&&r

Devuelve un conjunto. Si esto es inaceptable, úselo &&[...r]a un costo de 5 bytes.

Neil
fuente
1

Jalea ,  17  16 bytes

⁴e®;©ȧ⁸ḟ⁴ẎµÐĿȧ®T’

Un programa completo que toma dos argumentos de línea de comando de la lista y un elemento para verificar, e imprime la profundidad o las profundidades (si las hay) en las que existe el elemento. Los resultados están indexados en 1.

Pruébalo en línea!

¿Cómo?

⁴e®;©ȧḟ⁴ẎµÐĿȧ®T’ - Main link: list, L
          µÐĿ    - loop, collecting updated values of L, until a fixed point is reached:
⁴                -   4th argument (2nd program input) = the number
 e               -   exists in (the current version of) L?
  ®              -   recall value from the register (initially 0)
   ;             -   concatenate the two
    ©            -   (copy this result to the register)
       ⁴         -   4th argument (2nd program input) again
      ḟ          -   filter out (discard any instances of the number)
     ȧ           -   logical and (non-vectorising)
        Ẏ        -   tighten (flatten the filtered L by one level to create the next L)
             ®   - recall value from the register
            ȧ    - logical and (non-vectorising)
              T  - truthy indexes (1-indexed)
               ’ - decrement (account for the leading zero from the initial register)
Jonathan Allan
fuente
¡Agradable! Dato curioso: al usar un enfoque muy similar pero al cambiar un poco el orden de las cosas, puedes obtener 8 bytes. editar el enfoque es en realidad un poco diferente, nvm
HyperNeutrino
Esto no funciona del todo: tio.run/##y0rNyan8//9R45ZU60MrD607sfxR446HO@YDBR7u6ju09fCEI/…
HyperNeutrino
Hmm encontró errores durante la redacción ... borrando por ahora.
Jonathan Allan
Ah, de alguna manera había cambiado el orden de mi concatenación: debería estar trabajando ahora
Jonathan Allan
1

JavaScript (ES6), 73 74 bytes

f=(a,n,i=0,o={})=>a.map(e=>e.pop?f(e,n,i+1,o):e-n||o[i]++)&&Object.keys(o)

Explicación:

f=(a,                             //input array
   n,                             //input number to search
   i=0,                           //start at first level
   o={}                           //object to store the finds
  )=>
    a.map(                        //loop through the array
      e => e.pop ?                //is this element an array?
             f(e, n, i+1, o) :    //if so, recurse on it to the next level
             e-n || o[i]++        //otherwise, update o if element equals the number
    ) &&
    Object.keys(o)                //return o's keys

Casos de prueba

Rick Hitchcock
fuente
Aunque no hay casos de prueba [todavía], mi lectura de la pregunta sugiere que es válido e[0]ser cero, lo que anularía su prueba.
Neil
@Neil, excelente punto. Ahora cambió a e.poppor una pérdida de un byte.
Rick Hitchcock
1

Python 3 , 123 86 82 bytes

def f(a,n,l=[],d=0):
 for e in a:l+=[d]*(e==n);0*e==[]and f(e,n,l,d+1)
 return{*l}

Pruébalo en línea!

-37 bytes gracias a Hyper Neutrino y ovs

-4 bytes gracias a Jonathan Frech

caird coinheringaahing
fuente
Prueba if type(a[i])!=intpor -1 byte
HyperNeutrino
Prueba l+=[d]por -5 bytes
HyperNeutrino
Intente l+=[d]*(a[i]==n)con -whatever_number_of_bytes_it_is
HyperNeutrino
1
[]==a[i]*0para un cheque de tipo más corto
ovs
Intente iterar en alugar de un rango y use getitemtanto para - ~ 20 bytes
HyperNeutrino
0

Octava , 126122 bytes

function n=r(p,t,l)n=[];if nargin<3
l=0;end
for x=p
if iscell(q=x{1})a=r(q,t,l+1);else
a=l*find(q==t);end
n=union(n,a);end

Pruébalo en línea!

Para facilitar la lectura, reemplacé espacios o ;'s con extremos de línea siempre que sea posible. Explicación del código no golfizado:

function n=r(p,t,l) % Declare function with list p, integer t and optional recursion depth l
n=[];
if nargin<3
    l=0;            % If l is not given (first iteration), set l to zero (or one for 1-indexing)
end
for x=p             % Loop over list
if iscell(q=x{1})   % If loop variable x is a cell, we must go down one level.
     a=r(q,t,l+1);  % So recurse to l+1.
else
    a=l*find(q==t); % Empty if q~=t (because find(false)==[], and l*[]==[]), else equal to l*1==l.
end
n=union(n,a);       % Append to list of levels, make sure we only get distinct values.
end
Sanchises
fuente
0

Java, 154 + 19 = 173 bytes

import java.util.*;

Set<Long>f(List l,long n){Set s=new HashSet();if(l.contains(n))s.add(0l);for(Object o:l)if(o instanceof List)for(long d:f((List)o,n))s.add(d+1);return s;}

Pruébalo en línea

Método sin golf

Set<Long> f(List l, long n) {
    Set s = new HashSet();
    if (l.contains(n))
        s.add(0l);
    for (Object o : l)
        if (o instanceof List)
            for (long d : f((List) o, n))
                s.add(d + 1);
    return s;
}
Jakob
fuente