Визуализировать вложенный массив

15

Вам будет предоставлен вложенный массив. Ваша программа должна визуализировать массив.


Но как?

Например, давайте предположим, что у нас есть вложенный массив, например [["1","2"],[["1","2"],"3"],"4",[[[["5"]]]],"6"].

Этот вложенный массив может быть визуализирован как:

->1
->2
-->1
-->2
->3
>4
---->5
>6

Примеры

Input 1:
["Atom",["Proton",["Up Quark", "Up Quark", "Down Quark"], "Neutron", ["Up Quark", "Down Quark", "Down Quark"], "Electron"]]
Output 1:
>Atom
->Proton
-->Up Quark
-->Up Quark
-->Down Quark
->Neutron
-->Up Quark
-->Down Quark
-->Down Quark
->Electron

Input 2:
[["1","2"],["3","4"]]
Output 2:
->1
->2
->3
->4

правила

  • Вы можете использовать строку (или другие типы, которые работают как вложенный массив) в качестве входных данных.
  • Максимальный уровень «слоев» составляет 2 ^ 32-1.
Мэтью Ро
источник
Должна ли она иметь эту точную визуализацию?
пенальоса
@mnbvc Да, если я не заставлю это делать, люди начнут сильно искажать ввод-вывод. Поверьте мне, я попробовал это.
Мэтью Ро
Я чувствую, что сетчатка победит это.
Волшебный осьминог Урна
1
Есть ли какие-либо ограничения на то, какие символы могут появляться в строках?
Мартин Эндер
Дополнительные связанные вопросы 1 , 2
AdmBorkBork

Ответы:

12

APL, 32 байта

{1=≡⍺:⎕←⍺,⍨⍵↑1↓⍵/'->'⋄⍺∇¨⍵+1}∘0

Тестовое задание:

      r
┌────┬─────────────────────────────────────────────────────────────────────────────────────────┐
│Atom│┌──────┬──────────────────────────────┬───────┬────────────────────────────────┬────────┐│
│    ││Proton│┌────────┬────────┬──────────┐│Neutron│┌────────┬──────────┬──────────┐│Electron││
│    ││      ││Up Quark│Up Quark│Down Quark││       ││Up Quark│Down Quark│Down Quark││        ││
│    ││      │└────────┴────────┴──────────┘│       │└────────┴──────────┴──────────┘│        ││
│    │└──────┴──────────────────────────────┴───────┴────────────────────────────────┴────────┘│
└────┴─────────────────────────────────────────────────────────────────────────────────────────┘
      {1=≡⍺:⎕←⍺,⍨⍵↑1↓⍵/'->'⋄⍺∇¨⍵+1}∘0 ⊢ r 
>Atom
->Proton
-->Up Quark
-->Up Quark
-->Down Quark
->Neutron
-->Up Quark
-->Down Quark
-->Down Quark
->Electron

Объяснение:

  • {... }∘0: запустить следующую функцию с 0привязкой к :
    • 1=≡⍺:: если вход имеет глубину 1 (т.е. массив, который не содержит других массивов):
      • ⍵/'->': создать строку, содержащую -s и >s,
      • 1↓: отбросить первый элемент,
      • ⍵↑: и возьмите первые элементы. В результате получается строка, содержащая ⍵-1тире и единицу >.
      • ⍺,⍨: добавить вход к нему,
      • ⎕←: и вывести это на экран
    • : в противном случае,
      • ⍺∇¨⍵+1: добавить 1 и применить функцию к каждому вложенному массиву
Мэринус
источник
5
Подождите, это принимает вклад в этой форме ascii-art?
Rɪᴋᴇʀ
4
@Riker: Нет, для этого требуется обычный вложенный массив, однако именно так Dyalog APL отображает вложенный массив, и (как мне показалось) это делает очевидным, что происходит. Вы можете построить это, написав, например ('Atom' ('Proton' ('Up Quark' 'Up Quark' 'Down Quark') 'Neutron' ('Up Quark' 'Down Quark' 'Down Quark') 'Electron')).
Мэринус
9
Ах хорошо. Это проясняет это. Хотя сейчас
немного
7

Mathematica, 58 57 56 байт

Спасибо Грегу Мартину за сохранение 1 байта.

Спасибо ngenisis за сохранение 1 байта.

MapIndexed[Print[Table["-",Tr[1^#2]-1]<>">",#]&,#,{-1}]&
Мартин Эндер
источник
47
Добро пожаловать в PPCG! Вы должны знать, что ответы, которые дают мало объяснений или не дают их, автоматически помечаются системой и попадают в очередь проверки низкого качества . Это может удалить ваш ответ. Обратите внимание, что если у вас есть несколько удаленных ответов, вы можете получить временную приостановку. Просто немного на голову!
Стьюи Гриффин
20
@ StewieGriffin Спасибо за теплый прием, я буду иметь это в виду!
Мартин Эндер
6
@StewieGriffin вы приветствуете sitemod? Что здесь происходит? Это внутренняя шутка? #confused И хорошая весна для вас, ребята, если вы находитесь на севере.
Mindwin
4
@Mindwin: в Stack Exchange есть фильтр, предназначенный для сбора ответов, которые вряд ли будут полезны. Этот вид поста (заголовок + пример короткого кода, без комментариев), скорее всего, вызовет на нем ложные срабатывания, поскольку он очень похож на пост с небольшим усилием на компьютере (и комментарий Стьюи Гриффина содержит ссылку на скриншот, который указывает что ложный позитив действительно случился, это высмеивает ситуацию). Вот пример другого поста, который попал в фильтр.
8
@Titus Я хотел бы добавить один, но я не хочу лишать законной силы комментарий Стьюи. :(
Мартин Эндер
6

Java 7, 153 141 114 байт

String r="";<T,S>S c(S s,T o){for(T x:(T[])o)if(x instanceof Object[])c("-"+s,x);else r+=s+">"+x+"\n";return(S)r;}

-39 байт благодаря @ Barteks2x

Объяснение:

String r="";                         // Result String outside the method / on class-level
<T,S> S c(S s, T o){                 // Recursive Method with generic String and Object parameters and String return-type
  for(T x : (T[])o)                  //  Loop over the input-array
    if(x instanceof Object[])        //   If the current item is an array itself:
      c("-"+s, x);                   //    Recursive method-call with this array
    else                             //   Else:
      r += s+">"+x+"\n";             //    Append return-String with stripes String-input, ">", current item, and a new-line
                                     //  End of loop (implicit / single-line body)
  return (S)r;                       //  Return the result-String
}                                    // End of method

Тестовый код:

Попробуй это здесь.

class M{
  String r="";<T,S>S c(S s,T o){for(T x:(T[])o)if(x instanceof Object[])c("-"+s,x);else r+=s+">"+x+"\n";return(S)r;}

  public static void main(String[] a){
    M m = new M();
    System.out.println(m.c("", new Object[]{new Object[]{1,2},new Object[]{new Object[]{1,2},3},4,new Object[]{new Object[]{new Object[]{new Object[]{5}}}},6}));
    m.r = "";
    System.out.println(m.c("", new Object[]{"Atom",new Object[]{"Proton",new Object[]{"Up Quark","Up Quark","Down Quark"}},new Object[]{"Neutron",new Object[]{"Up Quark","Up Quark","Down Quark"}},"Electron"}));
  }
}

Выход:

->1
->2
-->1
-->2
->3
>4
---->5
>6

>Atom
->Proton
-->Up Quark
-->Up Quark
-->Down Quark
->Neutron
-->Up Quark
-->Up Quark
-->Down Quark
>Electron
Кевин Круйссен
источник
1
Вы можете получить его немного короче (143 или даже 142), используя тернарный оператор, for(int j=i;j-->0;r+="-");чтобы также делать то, что делает следующая строка, и используя универсальный аргумент вместо Object []: String r="";<T>String c(int i,T[] o){for(T x:o)if(x instanceof Object[])c(i+1,(T[])x);else for(int j=i;j-->=0;r+=j<0?">"+x+"\n":"-");return r;} и даже на 1 символ меньше, если передать 1 вместо 0 в качестве первого аргумент в порядке.
barteks2x
Я нашел способ сделать его еще короче, удалив [] из общего аргумента, он сохраняет дополнительные 2 символа (но не может редактировать комментарий через> 5 минут)
barteks2x
@ Barteks2x Спасибо! -12 байт благодаря вам. :) Кстати, удаление []из параметра для сохранения 1 дополнительного байта дает ошибку. Смотрите ошибку здесь > Отладка после запуска.
Кевин Круйссен
String r="";<T>String c(int i,T a){for(T x:(T[])a)if(x instanceof Object[])c(i+1,x);else for(int j=i;j-->0;r+=j<1?">"+x+"\n":"-");return r;}это работает. Также вы можете сделать аналогичный общий трюк со строкой, чтобы сохранить дополнительный байт, но требует либо сохранения результата в переменной перед его печатью, либо явного приведения (неоднозначный вызов метода):String r="";<T,S>S c(int i,T a){for(T x:(T[])a)if(x instanceof Object[])c(i+1,x);else for(int j=i;j-->0;r+=j<1?">"+x+"\n":"-");return(S)r;}
barteks2x
1
Я не уверен, что это считается разрешенным, но здесь 114 байтов, с пустой строкой в ​​качестве аргумента вместо нуля (может быть на 1 символ меньше, если «>» разрешено в качестве аргумента) String r="";<T,S>S c(S p,T a){for(T x:(T[])a)if(x instanceof Object[])c("-"+p,x);else r+=p+">"+x+"\n";return(S)r;}И требование для приведения строки к типу возврата при вызове это прошло.
barteks2x
6

PHP, 77 74 73 байта

4 байта сохранены благодаря @manatwork.

function f($a,$p=">"){foreach($a as$e)"$e"!=$e?f($e,"-$p"):print"$p$e
";}

рекурсивная функция, требует PHP 7.1 или новее для отрицательного индекса строки.
"$e"это Arrayдля массивов; так "$e"!=$eже, как is_array($e).

  • начать с префикса >
  • добавить -префикс к каждому уровню
  • префикс печати + элемент + перевод строки для атомов
Titus
источник
1
75 байтов:function f($a,$p=""){foreach($a as$e)echo$p,is_array($e)?f($e,"-"):">$e\n";}
Исмаэль Мигель
1
если это не требуется для требуемого форматирования, print_r ($ array) будет еще меньше :)
ivanivan
1
Сделал только быстрый тест, но, кажется, is_array($e)его можно заменить на $e[-1]!=="".
Манатворк
1
@manatwork Это PHP <7.1 ... в PHP 7.1, это можно сделать с помощью $e[-]==""... и с обратным условием $e[-1]>"". Хорошая находка!
Тит
1
Может быть , мне не хватает некоторых угловых случаев, но сейчас похоже , $e[-1]>""может быть заменен "$e"==$e. По крайней мере, в древнем PHP 5.6 я использую.
manatwork
5

C99 (GCC), 201 187 140 112 109

f(char*a){for(long d=1,j;j=d+=*++a>90?92-*a:0;)if(*a<35){for(;j||*++a^34;)putchar(j?"->"[!--j]:*a);puts("");}}

Расширенная форма:

f(char*a){
    for(long d=1,j;j=d+=*++a>90?92-*a:0;)
        if(*a<35){
            for(;j||*++a^34;)putchar(j?--j?45:62:*a);
            puts("");
        }
}

Это берет строку в правильном формате и завершается при поиске последнего соответствия ].

Он не использует рекурсию и использует длинные типы для достижения второго правила: 2 ^ 32-1 уровней . Большинство языков сценариев имеют ограниченную глубину рекурсии или просто аварийно завершают работу при переполнении стека.

Я не привык к гольфу в C, любая помощь приветствуется :)

Спасибо Болову за его советы! Особенно благодаря Титу, который всегда готов к хорошей игре в гольф (даже в C)!

Еще два байта сохраняются благодаря тому факту, что мы можем закончить, как только мы сопоставим последний ]и нам не нужно совпадать с нулевым символом.

Это можно проверить в Wandbox .

Christoph
источник
Не могли бы вы сократить вторую строку до for(int d=1 ...? longимеет 4 символа, в то время как intимеет только 3, и нет никаких причин, по которым вам нужно сделать так, чтобы оно превышало значение, 2^32 - 1чтобы отправка была действительной, сохраняя вам один байт.
Restioson
@Restioson int подписан и поэтому работает только до 2^31-1.
Кристоф
@ Кристоф, заявив, что вам не нужно идти дальше.
Restioson
@Restioson Задача утверждается как правило The maximum level of "layers" is 2^32-1.. 2^31-1намного меньше, чем 2^32-1. 2^32-1не подходит, в intто время как он соответствует unsignedили или long(это, конечно, на большинстве систем / компиляторов). Поэтому intне смог бы дать правильный ответ (как большинство ответов здесь не может быть).
Кристоф
4

JavaScript (ES6), 58 51 байт

f=(a,s='>')=>a.map(e=>e.map?f(e,'-'+s):s+e).join`
`

Редактировать: Сохранено 7 байт, когда @Arnauld указал, что я могу объединить два моих подхода.

Нил
источник
4

PHP, 129 123 112 109 95 93 91 байт

for(;a&$c=$argn[++$i];)$c<A?$c<"-"?a&$s?$s=!print"$p>$s
":0:$s.=$c:$p=substr("---$p",$c^i);

Итеративное решение берет строку из STDIN:
Запустите ее echo '<input>' | php -nR '<code>'или протестируйте онлайн .

сломать

for(;a&$c=$argn[++$i];)     // loop $c through input characters
    $c<A                        // not brackets?
        ?$c<"-"                     // comma or quote?
            ?a&$s?$s=!print"$p>$s\n":0  // if $s not empty, print and clear $s
            :$s.=$c                     // digit: append to $s
        :$p=substr("---$p",$c^i)    // prefix plus or minus one "-"
;

Рад, что цифры в кавычках; поэтому мне нужно только одно действие за раз.

ASCII возиться

char    ascii   binary/comment
 "       34
 ,       44
 [       91     0101 1011
 ]       93     0101 1101

 A       65     $c<A    true for comma, quote and digits
 -       45     $c<"-"  true for comma and quote

                =0011 1010 -> 50 -> "2"
i^"["   105^91  ^0101 1011
 i      105      0110 1001
i^"]"   105^93  ^0101 1101
                =0011 0100 -> 52 -> "4"

Добавление 3 штрихов $pи удаление 2 для [, 4 для ]добавляет один для [и удаляет один для ].

Titus
источник
Хорошая работа снова!
Кристоф
4

Python 2, 65 64 байта

f=lambda o,d=0:o<''and'\n'.join(f(e,d+1)for e in o)or'-'*d+'>'+o

Прямо сейчас мой ответ последовательно начинается без черточек, поэтому ["foo", "bar"]:

>foo
>bar
orlp
источник
import sys, pprint; pprint.pprint(sys.argv)43 байта, но я не знаю, нарушает ли он правила игры в гольф.
Карел
Это сохраняет один байт:f=lambda o,d=0:o<''and'\n'.join(f(e,d+1)for e in o)or'-'*d+'>'+o
Бен Франкель
@Carel вы не можете «импортировать pprint как p» или, может быть (не уверен, работает ли это) «import pprint.pprint как p» (боже, мне кажется, я не могу найти обратный тик на клавиатуре телефона)
Коул
@Cole Хмм .. import sys, pprint.pprint as p; p(sys.argv)все еще 43, но хорошее предложение тем не менее; D Попытка import sys.argv as vфактически удлиняет это приблизительно ~ 48 байтов. Если бы можно было устранить sys.argv, они бы сэкономили много, но тогда программа становится совершенно бесполезной. Рекурсивный подход довольно длинный def p(L,d=0): [p(i,d+1) if isinstance(i,list) else print(">"*d + i) for i in L], ~ 80 байт.
Карел
3

Perl 5 , 55 байт

53 байта кода + -nlфлаги.

/"/?print"-"x~-$v.">$_":/]/?$v--:$v++for/]|\[|".*?"/g

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

Не оптимально для регулярных выражений из-за некоторых острых случаев, которые могут произойти (в частности, если элемент массива содержит скобки внутри).
Хотя рекурсивная анонимная функция была бы чуть длиннее (61 байт):

sub f{my$v=pop;map{ref?f(@$_,$v+1):"-"x$v.">$_"}@_}sub{f@_,0}

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

Но то, как Perl обрабатывает параметры, не является оптимальным для функций игры в гольф: отсутствие дополнительных параметров означает, что мне нужно сделать вторую (анонимную) функцию, вызывающую первую, и я должен явно получить последний параметр с этой длинной my$v=pop.

папа
источник
3

Рубин, 49 45 46 байт

f=->c,p=?>{c.map{|x|x==[*x]?f[x,?-+p]:p+x}*$/}

Пример:

puts f[["Atom",["Proton",["Up Quark", "Up Quark", "Down Quark"], "Neutron", ["Up Quark", "Down Quark", "Down Quark"], "Electron"]]]

>Atom
->Proton
-->Up Quark
-->Up Quark
-->Down Quark
->Neutron
-->Up Quark
-->Down Quark
-->Down Quark
->Electron

Объяснение:

Рекурсивная функция: если x==[*x]тогда x является массивом, и мы перебираем его. Если нет, сделайте отступ.

гигабайт
источник
3

Haskell, 104 байта

l@(x:y)#(a:m)|[(h,t)]<-reads$a:m=y++h++l#t|a<'#'=l#m|a<'-'='\n':l#m|a>'['=y#m|q<-'-':l=q#m
l#_=""
(">"#)

У Haskell нет вложенных списков с разной глубиной, поэтому мне приходится разбирать входную строку самостоятельно. К счастью, библиотечная функция readsможет анализировать строки (т. "Е. -Замкнутая последовательность символов), поэтому здесь я немного помог.

Пример использования:

*Main> putStrLn $ (">"#) "[[\"1\",\"2\"],[\"3\",\"4\"]]" 
->1
->2
->3
->4

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

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

Функция #проходит строку char с помощью char и сохраняет уровень вложенности (первый параметр l) в виде строки -с финалом >. Если заголовок списка можно проанализировать как строку, возьмите lстроку и строку, а затем рекурсивный вызов со удаленной строкой. Если первый символ - пробел, пропустите его. Если это ,, возьмите новую строку и продолжайте, если это так ], снизьте уровень вложенности и продолжайте, а в противном случае (только [слева) поднимите уровень вложенности и продолжайте. Рекурсия заканчивается пустой строкой ввода. Основная функция (">"#)устанавливает уровень вложенности ">"и вызывает #.

Ними
источник
2

SWI-Пролог, 115 байт

p(L):-p(L,[>]).
p([],_):-!.
p([H|T],F):-p(H,[-|F]),p(T,F),!.
p(E,[_|F]):-w(F),w([E]),nl.
w([]).
w([H|T]):-write(H),w(T).

Разрывы строк добавлены только для удобства чтения, не включены в число байтов.

pПредикат рекурсивно обходит массивы, добавляя «-» к префиксу Fпри перемещении уровня глубже. wиспользуется для записи массива префиксов, а также фактического элемента в вывод.

Пример:

?- p(["Atom",["Proton",["Up Quark", "Up Quark", "Down Quark"], "Neutron", ["Up Quark", "Down Quark", "Down Quark"], "Electron"]]).
>Atom
->Proton
-->Up Quark
-->Up Quark
-->Down Quark
->Neutron
-->Up Quark
-->Down Quark
-->Down Quark
->Electron
Стивен
источник
2

Пакетный, 249 байт

@echo off
set/ps=
set i=
:t
set t=
:l
set c=%s:~,1%
set s=%s:~1%
if "%c%"=="[" set i=-%i%&goto l
if not "%c%"=="]" if not "%c%"=="," set t=%t%%c%&goto l
if not "%t%"=="" echo %i:~1%^>%t%
if "%c%"=="]" set i=%i:~1%
if not "%s%"=="" goto t

Досадно, что Пакет не может сравнивать запятые. Образец прогона:

[Atom,[Proton,[Up Quark,Up Quark,Down Quark],Neutron,[Up Quark,Down Quark,Down Quark],Electron]]
>Atom
->Proton
-->Up Quark
-->Up Quark
-->Down Quark
->Neutron
-->Up Quark
-->Down Quark
-->Down Quark
->Electron
Нил
источник
2

Сетчатка , 63 54 52 байта

Сохранено 2 байта благодаря Мартину Эндеру

.*?".*?"
$`$&¶
T`[] -~`-]_`.(?=.*".*")
-]

-"
>
T`]"

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

объяснение

.*?".*?"
$`$&¶

Во-первых, массив разбивается путем замены каждой строки в кавычках на все, что было до нее, а также на себя и на новую строку. Разбивая его так, можно найти непревзойденные открывающие скобки перед каждой строкой.

T`[] -~`-]_`.(?=.*".*")

Эта транслитерации заменит [с -, оставить ]без изменений, а также удалить любой другой символ (  -~все печати ASCII). Однако он заменяет только символы, появляющиеся перед последней строкой в ​​каждой строке.

-]

Далее все экземпляры -]удаляются. Они соответствуют совпадающим парам скобок, и нам нужны только несопоставимые скобки. После их удаления каждая строка имеет число -s, равное количеству непревзойденных открывающих скобок перед ней.

-"
>

Последний -перед a "заменяется на >, чтобы сформировать стрелки.

T`]"

Наконец, все остальные ]s и "s удаляются.

Бизнес Кот
источник
Это выглядит так, как будто предполагается, что внутри строк не будет (экранированных) кавычек. Я не уверен, что это законно, но я попросил разъяснений.
Мартин Эндер
@MartinEnder Хороший улов, я буду следить за ним
Business Cat
1

Röda , 54 байта

f d=""{{|n|{n|f d=`$d-`}if[n is list]else[`$d>$n
`]}_}

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

Это функция, которая читает входной массив из потока. Для каждого элемента он либо вызывает себя рекурсивно, либо печатает элемент.

fergusq
источник
1

Python 3, 80 байт

Кажется, кто-то знал рекурсию поддержки лямбд Python.

p=lambda l,d=1:[p(i,d+1)if isinstance(i,list)else print("-"*d+">"+i)for i in l]

Это счетчик / комплимент к ответу orlp .

Carel
источник
Добро пожаловать в PPCG! Кажется, вы посчитали конечный перевод строки или что-то в этом роде (потому что я считаю только 80 байтов), и вам не нужны пробелы вокруг =. Я также подозреваю, что вы можете отбросить все пробелы после трех ), но я не очень знаком с игрой в гольф на Python.
Мартин Эндер
0

Groovy, 92 байта

x={a,b->if(a instanceof List){a.each{x(it,b+1)}}else{y(a,b)}};y={a,b->println("-"*b+">$a")};
Урна волшебного осьминога
источник
0

С накоплением , 27 байтов

[@.1-'-'*\'>'\,,out]deepmap

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

Принимает ввод с вершины стека и оставляет вывод на STDOUT. Это просто, как сделать карту глубины, повторять - dвремена, объединять с «>» и самим элементом.

Конор О'Брайен
источник
0

Гема, 63 персонажа

\A=@set{i;-1}
[=@incr{i}
]=@decr{i}
"*"=@repeat{$i;-}>*\n
,<s>=

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

Образец прогона:

bash-4.3$ gema '\A=@set{i;-1};[=@incr{i};]=@decr{i};"*"=@repeat{$i;-}>*\n;,<s>=' <<< '[["1","2"],[["1","2"],"3"],"4",[[[["5"]]]],"6"]'
->1
->2
-->1
-->2
->3
>4
---->5
>6
manatwork
источник
0

JQ, 70 67 символов

( 67 64 символов кода + 3 символа командной строки)

def f(i):if type=="array"then.[]|f("-"+i)else i+. end;.[]|f(">")

Образец прогона:

bash-4.3$ jq -r 'def f(i):if type=="array"then.[]|f("-"+i)else i+. end;.[]|f(">")' <<< '[["1","2"],[["1","2"],"3"],"4",[[[["5"]]]],"6"]'
->1
->2
-->1
-->2
->3
>4
---->5
>6

Он-лайн тест

manatwork
источник