Sortowanie oparte na wcięciach

35

Biorąc pod uwagę uporządkowaną listę ciągów liter tej samej wielkości (az XOR AZ), gdzie każdy ciąg jest poprzedzony 0 lub więcej znakami spacji (), wypisuje tę samą listę, ale z ciągami posortowanymi na każdym poziomie wcięcia. Głębokości wcięć dla różnych rodziców liczą się jako odrębne listy do celów sortowania.

Przykład

Jeśli twój wkład to:

bdellium
  fox
  hound
  alien
aisle
  wasabi
    elf
    alien
  horseradish
    xeno
irk
wren
tsunami
djinn
      zebra

twój wynik powinien być

aisle
  horseradish
    xeno
  wasabi
    alien
    elf
bdellium
  alien
  fox
  hound
djinn
      zebra
irk
tsunami
wren

Jeśli chcesz, pomyśl o tym jak o liście katalogów i musisz posortować nazwy w każdym katalogu.

Drobne szczegóły

  • Element może być wcięty przez dowolną liczbę spacji. Jeśli jest wcięty tą samą liczbą spacji co poprzedni element, należy do tej samej hierarchii sortowania co poprzedni element. Jeśli jest wcięty przez więcej spacji, jest to początek nowej podhierarchii.
  • Jeśli linia jest wcięta przez mniejszą liczbę spacji niż linia nad nią, łączy się z najbliższą podgrupą nad nią z tym samym # lub mniejszymi spacjami przed nią (jak chrzan w powyższym przykładzie, który łączy się z grupą wasabi nad nią, ponieważ wasabi to pierwszy przedmiot powyżej, który nie ma więcej miejsca niż chrzan)
  • Musisz zachować poziom wcięcia każdego elementu wejściowego na wyjściu
  • Karty wyjściowe są niedozwolone
  • Pierwszy wiersz danych wejściowych nigdy nie będzie wcięty
  • Twój program musi obsługiwać co najmniej jeden ciąg wszystkich wielkich i małych liter; nie musi obsługiwać obu.

Punktacja

To jest , więc wygrywa odpowiedź wykorzystująca najmniej bajtów.

Techrocket9
źródło
7
Niezłe wyzwanie!
Adám
1
Btw, po raz kolejny, rozważ użycie piaskownicy do rozwiązania problemów z wyzwaniem przed opublikowaniem go na głównej stronie.
Adám
8
@ Adám Nie, wymagana logika parsowania ciągu rekurencyjnego jest powodem, dla którego napisałem ten monit.
Techrocket9,
2
Jeśli wejście jest ['a','..b', '.c', '..d'], jakie powinno być wyjście? ['a','..b', '.c', '..d']lub ['a','.c','..b', '..d']coś innego? (Używam '.'zamiast miejsca dla przejrzystości wizualnej).
Chas Brown,
2
@streetster strings (az XOR AZ)
Adám

Odpowiedzi:

14

Python 2 , 117 bajtów

lambda S:[s[-1]for s in sorted(reduce(lambda t,s:t+[[v for v in t[-1]if v.count(' ')<s.count(' ')]+[s]],S,[[]]))[1:]]

Wypróbuj online!

Pobiera jako dane wejściowe listę ciągów; i wyświetla listę ciągów znaków, posortowaną zgodnie z wymaganiami.

Chodzi o to, aby każdy element przekształcić w listę zawierającą „ścieżkę bezwzględną” jako listę; i pozwól Pythonowi zająć się sortowaniem. Np. Jeśli dane wejściowe to:

[
 'a',
 ' c',
 '  d',
 ' b'
]

Następnie za pomocą reduce()konwertujemy na listę list:

[
 ['a'],
 ['a',' c'],
 ['a',' c', '  d'],
 ['a',' b']
]

który jest sortowany jako:

[
 ['a'],
 ['a',' b']
 ['a',' c'],
 ['a',' c', '  d'],
]

a następnie wypisz ostatni element każdej listy z listy list, aby uzyskać:

[
 'a',
 ' b'
 ' c',
 '  d',
]
Chas Brown
źródło
Wow, rozwiązanie, które miałem zamiar opublikować, to 183 bajty ... Ssę lol
Don Thousand
4
@Rushabh Mehta: Moja pierwsza próba trwała około 205 bajtów ... a potem zhakuj! :)
Chas Brown,
7

APL (Dyalog Unicode) , 31 bajtów SBCS

Anonimowy przedrostek lambda, pobiera i zwraca listę ciągów znaków.

{⍵[⍋{1=≢⍵:⍺⋄⍵}⍀↑' '(,⊂⍨⊣=,)¨⍵]}

Wypróbuj online!

{} „Dfn”; jest argumentem

⍵[] Zindeksuj argument za pomocą następujących wskaźników:

  ' '()¨⍵ Zastosuj następującą ukrytą funkcję do każdego łańcucha ze spacją jako lewym argumentem:

   , konkatenuj spację z łańcuchem

   ⊣= Lista boolowska wskazująca, gdzie spacja jest równa każdemu znakowi, który

   ,⊂⍨ użyj go do podzielenia (rozpocznij część, gdzie prawda) konkatenacji spacji i łańcucha

   mieszaj listę list ciągów w macierz ciągów

  {}⍀ Pionowe skumulowane zmniejszenie o to „dfn”; i są górnymi i dolnymi argumentami:

   ≢⍵ długość dolnego ciągu

   1= czy to jest równe 1? (tzn. czy jest tam tylko jedna przestrzeń?)

   :⍺ jeśli tak, zwróć górny argument

   ⋄⍵ w przeciwnym razie zwróć niższy argument

   oceniaj (znajdź wskaźniki, które to posortują)

Adám
źródło
7

Siatkówka , 47 bajtów

+-1m`(?<=^\2(\S+).*?¶( *)) 
$1 
O$`
$L$&
\S+ 
 

Wypróbuj online! Uwaga: kilka linii ma końcowe spacje. Wyjaśnienie:

+-1m`(?<=^\2(\S+).*?¶( *)) 
$1 

Pierwszym krokiem jest wstawienie każdego słowa do kolejnych wierszy z tym samym wcięciem. Na przykład liniami aisle, wasabia elfwynikowe linie to aisle, aisle wasabii aisle wasabi elf. Znalazłem ten regex metodą prób i błędów, więc mogą występować z nim przypadki brzegowe.

O$`
$L$&

Teraz możemy sortować linie bez rozróżniania wielkości liter.

\S+ 
 

Usuń wszystkie wstawione słowa.

Neil
źródło
4

Perl 6 , 120 83 81 63 54 37 47 42 bajtów

-5 bajtów dzięki nwellnhof

{my@a;.sort:{@a[+.comb(' ')..*+1]=$_;~@a}}

Wypróbuj online!

To wykorzystuje metodę Chasa Browna . Anonimowy blok kodu, który pobiera listę wierszy i zwraca listę wierszy.

Wyjaśnienie:

{                                        }  # Anonymous code block
 my@a;  # Declare a local list
      .sort # Sort the given list of lines
           :{                           }  # By converting each line to:
             @a[+.comb(' ')..*+1]=$_;      # Set the element at that indentation level onwards to that line
                                     ~@a   # And return the list coerced to a string
Jo King
źródło
@nwellnhof Dzięki za zwrócenie na to uwagi. Myślę, że naprawiłem to w najnowszej wersji
Jo King
@nwellnhof Ach, cóż, w poprzedniej iteracji był on krótszy. Dzięki za bajty wyłączone, ale musiałem to nieco zmienić
Jo King
Och, racja. Właściwie coś takiego {my@a;.sort:{@a[+.comb(' ')...*>@a]=$_;~@a}}jest wymagane do obsługi wyższych poziomów wcięć.
nwellnhof,
3

Czysty , 112 101 bajtów

import StdEnv
f=flatten
?e=[0\\' '<-e]
$[h:t]#(a,b)=span(\u= ?u> ?h)t
=sort[[h:f($a)]: $b]
$e=[]

f o$

Wypróbuj online!

Anonimowa funkcja, :: [[Char]] -> [[Char]]która otacza $ :: [[Char]] -> [[[Char]]]właściwy format wyjściowy. $grupuje ciągi znaków w „więcej spacji niż” i „wszystko inne później”, powtarza się nad każdą grupą i sortuje, gdy są do siebie przyległe. Na każdym kroku sortowana lista wygląda następująco:

[[head-of-group-1,child-1,child-2..],[head-of-group-2,child-1,child-2..]..]

Czysty , 127 bajtów

import StdEnv
$l=[x++y\\z<- ?(map(span((>)'!'))l),(x,y)<-z]
?[h:t]#(a,b)=span(\(u,_)=u>fst h)t
=sort[[h:flatten(?a)]: ?b]
?e=[]

Wypróbuj online!

Definiuje funkcję, $ :: [[Char]] -> [[Char]]która dzieli ciągi na krotki w formie, (spaces, letters)które są rekurencyjnie sortowane według funkcji pomocnika ? :: [([Char],[Char])] -> [[([Char],[Char])]] .

Wyjaśnił:

$ list                                  // the function $ of the list
    = [                                 // is
        spaces ++ letters               // the spaces joined with the letters
        \\ sublist <- ? (               // from each sublist in the application of ? to
            map (                       // the application of
                span ((>)'!')           // a function separating spaces and letters
            ) list                      // to every element in the list
        )
        , (spaces, letters) <- sublist  // the spaces and letters from the sublist
    ]

? [head: tail]                              // in the function ? of the head and tail of the input
    # (group, others)                       // let the current group and the others equal
        = span (                            // the result of separating until ... is false
            \(u, _) = u >                   // only elements where there are more spaces
                          fst head          // than in the head of the input
        ) tail                              // the tail of the input
    = sort [
        [head                               // prepend the head of the input to
             : flatten (?group)             // the flat application of ? to the first group
                               ]            // and prepend this to
                                : ?others   // the application of ? to the other group(s)
    ]

? empty = [] // match the empty list
Obrzydliwe
źródło
1

JavaScript (Node.js) , 114 100 92 88 bajtów

x=>x.map(y=>a=a.split(/ */.exec(y)[0]||a)[0]+y,a="_").sort().map(x=>/ *\w+$/.exec(x)[0])

Wypróbuj online!

Podobne podejście do odpowiedzi Pythona Chasa Browna, ale zamiast tego za pomocą wyrażeń regularnych.

Wyjaśnienie

x => x.map(                         // 
 y => a = a.split(                  // Renders the indentation paths
  / */.exec(y)[0]                   //  Checks the indentation level
  || a                              //  If this is the top level, go to root
 )[0] + y,                          //  Appends the child to the parent
 a = "_"                            // At first the cursor is at the root
)                                   // 
.sort()                             // Sorts the indentation paths
.map(                               // 
 x => / *\w+$/.exec(x)[0]           // Extracts only the last level of the path
)                                   //
Shieru Asakoto
źródło
0

K4 , 51 bajtów

Rozwiązanie:

{,/(1#'r),'.z.s@'1_'r:(w_x)@<x@w:&s=&/s:+/'" "=/:x}

Przykład:

q)k){,/(1#'r),'.z.s@'1_'r:(w_x)@<x@w:&s=&/s:+/'" "=/:x}("bdellium";"  fox";"  hound";"  alien";"aisle";"  wasabi";"    elf";"    alien";"  horseradish";"    xeno";"irk";"wren";"tsunami";"djinn";"      zebra")
"aisle"
"  horseradish"
"    xeno"
"  wasabi"
"    alien"
"    elf"
"bdellium"
"  alien"
"  fox"
"  hound"
"djinn"
"      zebra"
"irk"
"tsunami"
"wren"

Założenia:

za. Że każda hierarchia rozpocznie się od najniższego poziomu, tzn. Nie otrzymasz:

bdellium
      fox
    hound
    alien

Wyjaśnienie:

{,/(1#'r),'.z.s@'1_'r:(w_x)@<x@w:&s=&/s:+/'" "=/:x} / the solution
{                                                 } / lambda function, implicit x
                                           " "=/:x  / " " equal to each right (/:) x
                                        +/'         / sum up each
                                      s:            / save as s
                                    &/              / find the minimum (ie highest level)
                                  s=                / is s equal to the minimum?
                                 &                  / indices where true 
                               w:                   / save as w
                             x@                     / index into x at these indices
                            <                       / return indices to sort ascending
                           @                        / index into
                      (   )                         / do this together
                       w_x                          / cut x at indices w
                    r:                              / save as r
                 1_'                                / drop first from each r
            .z.s@                                   / apply recurse (.z.s)
          ,'                                        / join each both
    (    )                                          / do this together
     1#'r                                           / take first from each r
  ,/                                                / flatten
streetster
źródło
0

Perl 5, 166 bajtów

sub f{my$p=shift;my@r;while(@i){$i[0]=~/\S/;$c=$-[0];if($p<$c){$r[-1].=$_ for f($c)}elsif($p>$c){last}else{push@r,shift@i}}sort@r}push@i,$_ while<>;print sort@{[f 0]}

Niegolfowany (w pewnym sensie):

sub f {
    my $p = shift;
    my @r;
    while(@i) {
        $i[0] =~ /\S/;
        $c = $-[0];
        if($p < $c) {
            $r[-1] .= $_ for f($c)
        } elsif ($p > $c) {
            last
        } else {
            push @r, shift @i
        }
    }
    sort @r
}

push @i, $_ while <>;
print sort@{[f 0]}

Jest to dość prosta implementacja rekurencyjna. Poziom wcięcia sprawdzamy, szukając pierwszego znaku spacji ( /\S/) i uzyskując jego indeks ( $-[0]). Niestety, faktycznie musimy zadeklarować garść zmiennych używanych w rekursji, w przeciwnym razie będą one domyślnie globalne i rekursja nie będzie działać poprawnie.

Silvio Mayolo
źródło