Głębokie wyszukiwanie listy

19

W przypadku tego wyzwania lista jest uważana za ważną tylko wtedy, gdy składa się wyłącznie z liczb całkowitych i prawidłowych list (definicje rekurencyjne \ o /). W przypadku tego wyzwania, podając prawidłową listę i liczbę całkowitą, zwróć listę wszystkich głębokości, na których można znaleźć liczbę całkowitą.

Przykład

Rozważmy listę [1, [2, [3, [1, 2, 3], 4], 1], 1]i liczbę całkowitą 1. Następnie możemy narysować listę w następujący sposób:

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

Zauważysz, że 1pojawia się na głębokościach 0, 1, 3. Dlatego twój wynik powinien mieć 0, 1, 3jakiś rozsądny format (kolejność nie ma znaczenia).

Głębokość może być indeksowana 0 lub 1, ale proszę podać w zgłoszeniu, która to jest.

Przypadki testowe (indeksowane 0)

Do listy [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]

Do listy [[[[[1],0],1],0],1]:

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

Do listy [11,22,[33,44]]:

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

Zwróć pustą listę, jeśli szukanego terminu nigdzie nie ma na liście.

Wartości ujemne i zerowe są prawidłowe na liście wejściowej i w terminie.

HyperNeutrino
źródło
Jeśli liczba całkowita pojawia się na jednej głębokości wiele razy, czy musimy zwrócić tę liczbę tylko raz?
Giuseppe,
@Giuseppe tak, to prawda.
HyperNeutrino,
1
@ Adám Cóż, biorąc pod uwagę, że jeden z moich przypadków testowych ma zera, nie. Dodam też, że ujemne liczby całkowite są uczciwą grą.
HyperNeutrino,
1
Liczby wielocyfrowe należy również dodać w przypadku testowym, jeśli mogą wystąpić.
Zgarb
1
@KevinCruijssen Tak, tak, nie i tak. Możesz więc przyjmować dane wejściowe zarówno jako łańcuchy, jak i wyświetlać głębokość w dowolnej kolejności, ale nie wiele razy.
HyperNeutrino,

Odpowiedzi:

7

Mathematica, 25 bajtów

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

(zwraca 1-indeksowane wyjście)

Wyjaśnienie

                         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}
Misza Ławrow
źródło
7

Haskell , 102 93 80 76 bajtów

Dzięki Bruce Forte za uratowanie niektórych bajtów, a Laikoni za uratowanie niektórych.

Dzięki 4castle za oszczędność 4 bajtów.

Haskell nie ma typu danych dla tego rodzaju listy, więc stworzyłem własny.

To rozwiązanie jest 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

Wypróbuj online!

Najpierw definiuję (rekurencyjnie) typ danych T

Tma albo typ E Int(pojedynczy element typu Int), albo L[L](lista typów T).

(%)jest funkcja, która bierze 2argumenty, o rodzaju T, listy, przez którą szukamy, i xThe Intszukamy.

Ilekroć (%)znajdzie coś, co jest pojedynczym elementem E n, sprawdza nrówność xi zwraca wartość 0True.

Po (%)zastosowaniu do L s(gdzie sma typ [T]), działa (%)na wszystkich elementach si zwiększa wynik (wraz ze wzrostem głębokości, ponieważ patrzymy do środka s) i konkatenuje wynik.

nub następnie usuwa duplikaty z listy

NB. import Data.Listjest tylko dla nub.

H.PWiz
źródło
Wymyśliłem dość podobne rozwiązanie dla 81 bajtów: Wypróbuj online!
Laikoni
@Laikoni Bardzo miło, czy chcesz to opublikować samodzielnie, czy sugerujesz, żebym zaktualizował mój?
H.PWiz
Zaktualizuj swoją odpowiedź. :)
Laikoni
Jeśli chodzi o NB: Próbowałem pozbyć się importu, ale skończyłem na 88 bajtach: Wypróbuj online!
Laikoni
2
Możesz usunąć nawias wokół E ni L s.
4castle 29.09.17
4

Python 2 , 72 bajty

f=lambda l,k,d=0:set([d]*(k in l)).union(*[f(x,k,d+1)for x in l if[]<x])

Wypróbuj online!

ovs
źródło
4

Galaretka , 11 8 bajtów

WẎÐĿċ€IT

Wypróbuj online!

Jak to działa

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.

Przykładowy przebieg

Za lewy argument

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

W najpierw daje następującą tablicę.

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

ẎÐĿwielokrotnie łączy wszystkie elementy na głębokości 1 , zmniejszając głębokość tablicy o 1 w każdym kroku. Daje to następującą tablicę wyników pośrednich.

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

Dla prawego argumentu 1 , ċ€zlicza wystąpienia 1 na każdym wyniku pośredniego.

[0, 2, 3, 3, 4]

I teraz bierze wszystkie różnice naprzód.

[2, 1, 0, 1]

Różnice niezerowe odpowiadają etapom, w których co najmniej jeden inny 1 został dodany do głębokości 1 . Zatem niezerowa różnica przy wskaźniku k wskazuje na obecność 1 na głębokości k . Tznajduje wskaźniki wszystkich prawdziwych elementów, dając pożądany rezultat:

[1, 2, 4]
Dennis
źródło
\ o / to było moje dokładne rozwiązanie przy porównywaniu Jelly do Pythona. tak! : P
HyperNeutrino,
4

R , 101 95 92 100 bajtów

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

Wypróbuj online!

Rozwiązanie rekurencyjne; w bajtach jest dość nieefektywny, ale listspraca z R jest bardzo denerwująca.

Zasadniczo, wykonuje Li dla każdego elementu xz L, (który jest albo listalbo atomicwektor jeden element) sprawdza, czy nznajduje się %in% x, a następnie sprawdza, czy xjest to list. Jeśli nie, to x==nzwracamy głębokość d; inaczej nazwać rekurencyjnie fna x, zwiększając d.

To, oczywiście, zwraca a list, które my unlisti uniquedla zapewnienia prawidłowego wyniku (zwracanie wektora głębokości całkowitych); zwraca NULL(pusta lista) za niepoprawną n.

Najwyraźniej %in%nie wyszukuje rekurencyjnie w listtaki sposób, jak myślałem, więc muszę znaleźć unlist(x)+8 bajtów :(

Giuseppe
źródło
3

APL (Dyalog) , 39 bajtów *

Pełny program Monity o listę, a następnie o numer. Drukuje listę opartą na 1 do STDOUT.

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

Wypróbuj online!

 monit o listę

 wydajność, która (oddziela 0i )

⎕JSON⍠'Compact'0 konwertuj na wcięty ciąg JSON z nowymi liniami

⎕FMT konwertuj na macierz (jedna linia rozdzielana znakiem nowej linii na wiersz)

⍞⍷ monituj o numer jako ciąg znaków i wskaż, od czego zaczyna się od tego

∨⌿ pionowa redukcja OR (tj. w których kolumnach zaczyna się)

 wskaźniki tych początków

2÷⍨ zmniejszyć o połowę (poziomy są wcięte dwoma spacjami)

 zaokrąglanie w dół (ponieważ pierwsza kolumna danych to kolumna 3)


* W Dyalog Classic, licząc jako ⎕U2378i jako ⎕OPT.

Adám
źródło
2

PHP , 117 bajtów

$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);

Wypróbuj online!

Calimero
źródło
2

JavaScript (ES6), 79 68 bajtów

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

Zwraca zestaw. Jeśli jest to niedopuszczalne, użyj &&[...r]za cenę 5 bajtów.

Neil
źródło
1

Galaretka ,  17  16 bajtów

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

Pełny program pobierający dwa argumenty wiersza poleceń z listą i elementem do sprawdzenia oraz drukujący głębokość lub głębokości (jeśli występują), na których element istnieje. Wyniki są indeksowane 1.

Wypróbuj online!

W jaki sposób?

⁴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
źródło
Ładny! Ciekawostka: stosując bardzo podobne podejście, ale zmieniając nieco porządek rzeczy, możesz uzyskać 8 bajtów. Podejście do edycji jest trochę inne, nvm
HyperNeutrino,
To nie do końca działa: tio.run/##y0rNyan8//9R45ZU60MrD607sfxR446HO@YDBR7u6ju09fCEI/…
HyperNeutrino
Hmm znalazł błędy podczas pisania ... na razie usuwam.
Jonathan Allan
Ach, jakoś zmieniłem kolejność konkatenacji: / powinienem już działać
Jonathan Allan,
1

JavaScript (ES6), 73 74 bajty

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

Wyjaśnienie:

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

Przypadki testowe

Rick Hitchcock
źródło
Chociaż nie ma jeszcze przypadków testowych [jeszcze], moje odczytanie tego pytania sugeruje, że jest ważne, e[0]aby było zerowe, co zrzuciłoby twój test.
Neil
@Neil, doskonały punkt. Teraz zmieniono na e.popna utratę jednego bajtu.
Rick Hitchcock,
1

Python 3 , 123 86 82 bajtów

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}

Wypróbuj online!

-37 bajtów dzięki Hyper Neutrino i ovs

-4 bajty dzięki Jonathanowi Frechowi

Cairney Coheringaahing
źródło
Spróbuj if type(a[i])!=int-1 bajtu
HyperNeutrino,
Spróbuj l+=[d]-5 bajtów
HyperNeutrino,
Spróbuj l+=[d]*(a[i]==n)-cokolwiek_numer_z_bytes_it_is
HyperNeutrino
1
[]==a[i]*0krótszy czeku typu
OVS
Spróbuj iterować azamiast zakresu i getitem
zużywać
0

Oktawa , 126 122 bajtów

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

Wypróbuj online!

Aby zapewnić czytelność, w ;miarę możliwości zastąpiłem spacje lub końce linii. Objaśnienie niepoznanego kodu:

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
źródło
0

Java, 154 + 19 = 173 bajtów

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

Wypróbuj online

Metoda bez golfa

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
źródło