Глубокий поиск по списку


19

Для этой задачи список считается действительным, если и только если он полностью состоит из целых чисел и допустимых списков (рекурсивные определения \ o /). Для этой задачи, учитывая действительный список и целое число, возвращают список всех глубин, на которых можно найти целое число.

пример

Давайте рассмотрим список [1, [2, [3, [1, 2, 3], 4], 1], 1]и целое число 1. Затем мы можем составить список следующим образом:

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

Вы заметите, что 1появляется на глубине 0, 1, 3. Таким образом, ваш вывод должен быть 0, 1, 3в каком-то разумном формате (порядок не имеет значения).

Глубина может быть либо 0-, либо 1-индексированной, но, пожалуйста, укажите в своем представлении, какая она есть.

Тестовые случаи (0-indexed)

Для списка [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]

Для списка [[[[[1],0],1],0],1]:

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

Для списка [11,22,[33,44]]:

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

Вернуть пустой список, если поисковый термин не существует в списке нигде.

Отрицательные и нулевые значения действительны в списке ввода и сроке.


Если целое число появляется на одной глубине несколько раз, нужно ли возвращать это число только один раз?
Джузеппе

@ Джузеппе да, это правильно.
HyperNeutrino

1
@ Adám Хорошо, учитывая, что в одном из моих тестов есть нули, нет. Также добавлю, что отрицательные целые числа являются честной игрой.
HyperNeutrino

1
Многозначные числа также должны быть добавлены в тестовом случае, если они могут произойти.
Згарб

1
@KevinCruijssen Да, да, нет, и да. Таким образом, вы можете принимать входные данные как строки, и вы можете отображать глубину в любом порядке, но не несколько раз.
HyperNeutrino

Ответы:


7

Mathematica, 25 байтов

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

(возвращает 1-индексированный вывод)

объяснение

                         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}

7

Haskell , 102 93 80 76 байтов

Спасибо Брюсу Форте за сохранение нескольких байтов и Лайкони за сохранение еще нескольких.

Спасибо 4castle за сохранение 4 байта.

У Haskell нет типа данных для такого рода списков, поэтому я создал свой собственный.

Это решение 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

Попробуйте онлайн!

Сначала я определяю (рекурсивно) тип данных T

Tимеет либо тип E Int(один элемент типа Int), либо L[L](список типов T).

(%)это функция , которая принимает 2аргументы, по типу T, список , через которые мы искомые, и x, то Intмы ищем.

Всякий раз, когда (%)находит что-то, что является единственным элементом E n, он проверяет nравенство с xи возвращает значение 0True.

Когда (%)применяется к L s(где sимеет тип [T]), он запускается (%)на всех элементах sи увеличивает результат (поскольку глубина увеличивается, поскольку мы смотрим внутрь s), и объединяет результат.

nub затем удаляет дубликаты из списка

NB. import Data.Listтолько для nub.


Я придумал довольно похожее решение для 81 байта: попробуйте онлайн!
Лайкони

@Laikoni Очень приятно, ты хочешь опубликовать это сам или ты предлагаешь обновить мой?
H.PWiz

Не стесняйтесь обновить свой ответ. :)
Лайкони

Что касается NB: я пытался избавиться от импорта, но занял 88 байт: попробуйте онлайн!
Лайкони

2
Вы можете удалить скобки вокруг E nи L s.
4каста



4

Желе , 11 8 байт

WẎÐĿċ€IT

Попробуйте онлайн!

Как это устроено

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.

Пример запуска

Для левого аргумента

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

W Сначала выдает следующий массив.

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

ẎÐĿмногократно объединяет все элементы на глубине 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  ],
 [ 1,  2,  3,  1, 2, 3,  4,  1, 1  ]
]

Для правильного аргумента 1 , ċ€подсчитывает число вхождений 1 в каждом промежуточном результате.

[0, 2, 3, 3, 4]

I теперь берет все форвардные различия.

[2, 1, 0, 1]

Ненулевые различия соответствуют шагам, на которых по меньшей мере еще один 1 был добавлен на глубину 1 . Таким образом, ненулевая разность по индексу k указывает на наличие 1 на глубине k . Tнаходит индексы всех истинных элементов, дающих желаемый результат:

[1, 2, 4]

\ o / это было мое точное решение при сравнении Jelly с Python. ура! : P
HyperNeutrino

4

R , 101 95 92 100 байтов

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

Попробуйте онлайн!

Рекурсивное решение; это довольно неэффективно в байтах, но R listsочень раздражает в работе.

В основном, принимает L, и для каждого элемента xиз L, (который является либо listили atomicвектор одного элемента), проверяет , является ли nэто %in% x, а затем проверяет , является ли xэто list. Если это не так, то x==nмы возвращаем глубину d; в противном случае мы рекурсивный вызов fна x, приращении d.

Это, конечно, возвращает a list, который мы unlistи uniqueдля обеспечения правильного вывода (возвращаем вектор целочисленных глубин); возвращает NULL(пустой список) для недействительных n.

Видимо, %in%не ищет рекурсивно через то, listчто я думал, поэтому мне нужно unlist(x)+8 байт :(


3

APL (Dyalog) , 39 байт *

Полная программа. Запрашивает список, затем номер. Распечатывает 1-й список в STDOUT.

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

Попробуйте онлайн!

 запросить список

 дать это (отделяет 0и )

⎕JSON⍠'Compact'0 преобразовать в отступ строки JSON с символами новой строки

⎕FMT преобразовать в матрицу (одна строка с разделителем новой строки в строке)

⍞⍷ запросить число в виде строки и указать, где он начинается в этом

∨⌿ вертикальное уменьшение ИЛИ (то есть, в каких столбцах оно начинается)

 индексы тех начал

2÷⍨ разделить пополам (уровни имеют два пробела)

 округлить вниз (поскольку первый столбец данных - это столбец 3)


* В Dyalog Classic, считая как ⎕U2378и как ⎕OPT.



2

JavaScript (ES6), 79 68 байт

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

Возвращает набор. Если это неприемлемо, используйте &&[...r]по 5 байт.


1

Желе ,  17  16 байт

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

Полная программа, принимающая два аргумента командной строки: список и проверяемый элемент, и печать глубины или глубины (если есть), на которой существует элемент. Результаты 1-индексированы.

Попробуйте онлайн!

Как?

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

Ницца! Интересный факт: используя очень похожий подход, но, немного изменив порядок вещей, вы можете получить 8 байтов. изменить подход на самом деле немного по-другому, Н.В.М.
HyperNeutrino


Хм нашел ошибки во время записи ... удаление на данный момент.
Джонатан Аллан

Ах, я как-то изменил порядок своей конкатенации: / должен работать сейчас
Джонатан Аллан

1

JavaScript (ES6), 73 74 байта

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

Объяснение:

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

Контрольные примеры


Хотя тестовых случаев нет [пока], мое прочтение вопроса предполагает, что оно действительно для того, e[0]чтобы быть нулевым, что отбросило бы ваш тест.
Нил

@ Нейл, отлично. Теперь изменено на e.popпотерю одного байта.
Рик Хичкок,

1

Python 3 , 123 86 82 байта

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}

Попробуйте онлайн!

-37 байт благодаря Hyper Neutrino и овам

-4 байта благодаря Джонатану Фреху


Попробуй if type(a[i])!=int-1 байт
HyperNeutrino,

Попробуйте l+=[d]для -5 байт
HyperNeutrino

Попробуйте l+=[d]*(a[i]==n)для -whither_number_of_bytes_it_is
HyperNeutrino

1
[]==a[i]*0в течение более короткого проверки типа
OVS

Попробуйте перебрать aвместо диапазона и использовать getitemтак много для - ~ 20 байтов
HyperNeutrino


0

Октава , 126 122 байта

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

Попробуйте онлайн!

Для удобства чтения я заменил пробелы или ;концы строк, где это возможно. Объяснение негольфированного кода:

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

0

Java, 154 + 19 = 173 байта

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

Попробуйте онлайн

Метод без волка

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;
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.