Wymień tablicę, grupując duplikaty


24

Celem tego wyzwania jest pobranie szeregu liczb całkowitych dodatnich i policzenie jego wskaźników, grupując podobne elementy.

Wyliczenie bez duplikatów wykonuje się po prostu przez wyprowadzenie tablicy par (value, index), na przykład [3, 4, 13, 9, 2]=> [[3,1],[4,2],[13,3],[9,4],[2,5]].

Jeśli jednak dany element pojawia się po raz drugi, nie otrzymuje własnej pary, ale jest dodawany do grupy swojego pierwszego wystąpienia. Jeżeli w naszym przykładzie zastąpiliśmy 9 z 3, a następnie na wyjściu chcielibyśmy usunąć [9,4]i zastąpić [3,1]z [3,1,4].

W danych wyjściowych grupy muszą być uporządkowane według ich pierwszego wystąpienia, a indeksy muszą być w porządku rosnącym. Element musi być pierwszy w grupie, przed jego indeksami. Dane wyjściowe mogą być indeksowane 0 lub 1. Możesz założyć, że tablica ma co najmniej jeden element.

Przypadki testowe:

Input           | Output (One-indexed)
[3, 2, 2, 3]    | [[3, 1, 4], [2, 2, 3]]
[17]            | [[17, 1]]
[1, 1]          | [[1, 1, 2]]
[1, 1, 2]       | [[1, 1, 2], [2, 3]]
[1, 2, 3, 4]    | [[1, 1], [2, 2], [3, 3], [4, 4]]
[1, 1, 1, 1]    | [[1, 1, 2, 3, 4]]

To jest , wygrywa najmniej bajtów!


Czy byłoby dopuszczalne, aby indides był wyprowadzany jako ciąg znaków, np. [[17,"1"]]? (Nie wiem jeszcze, czy mogę w ten sposób zapisać jakieś bajty, wciąż nad tym pracuję!)
Shaggy,

@ kudłaty, jasne, w porządku
Pavel


1
Czy możemy [[3, [1, 4]], [2, [2, 3]]]zamiast tego wyprowadzić coś takiego ?
Conor O'Brien

1
@Pavel to nie powód: p, ale pewne
Conor O'Brien

Odpowiedzi:


9

Dyalog APL, 5 bajtów

(⊂,)⌸

Wypróbuj online!

,⌸na 2 bajty prawie działa, ale ma końcowe zera: /


Co na świecie robi ?
Pan Xcoder,

@ Mr.Xcoder pobiera indeksy każdej rzeczy i dzwoni do lewego operatora z rzeczą i indeksami tam, gdzie ona istnieje
dzaima

Skoro problem z ,⌸końcowymi zerami i zerami nigdy nie będzie na wejściu, czy byłoby możliwe usunięcie wszystkich zer z mniej niż 3 bajtów?
Pavel

@Pavel powodem istnienia zer jest to, że wynikiem jest macierz, która musi mieć dokładne wymiary, więc jest tylko 1 bajt na zrzucenie zer dla dowolnego przyrostu bajtów. Wydaje mi się, że to może być gra w golfa.
dzaima

2
Format wyjściowy tablicy „fancy af” : Wypróbuj online!
Adám

7

J , 12 bajtów

~.,&.><@I.@=

Zero indeksowane.

Wypróbuj online!

Jeśli potrafisz usunąć całą pracę, którą wykonuję z polami, prawdopodobnie możesz znacznie zmniejszyć liczbę bajtów. Zobaczę, czy mogę to rozgryźć.

Wyjaśnienie

Jest to prawdopodobnie zbyt wcześnie, aby to tłumaczyć (powinno być więcej golfów).

~. ,&.> <@I.@=
             =  Self-classify (comparison of each unique element to array)
            @   Composed with
          I.    Indices of ones (where it's equal)
         @      Composed with
        <       Boxed (how we deal with arrays of unequal length)
   ,&.>         Joined with
      >          Unbox each
   ,             Concatenate
    &.           Box again
~.              Unique elements

2
Ten format wyjściowy tablicy jest fantazyjny
Pavel

@Pavel zajmuje również dużo bajtów Π.Π
cole

5

05AB1E , 10 bajtów

ÙεDIQƶ0K)˜

Wypróbuj online!

Wyjaśnienie

Ù             # remove duplicates
 ε            # apply to each element
  D           # duplicate
   IQ         # compare for equality with input
     ƶ        # multiply each element by its index (1-based)
      0K      # remove zeroes
        )˜    # wrap in a flattened list



5

Attache , 15 bajtów

Flat=>Positions

Wypróbuj online!

Jest to interesujący przypadek =>postaci operatora Map. Gdy podano dwa argumenty funkcjonalne fi g, Mapzwraca funkcję f => g[x]ponad x. Oznacza to, że RHS jest stosowany do danych wejściowych, a następnie LHS jest mapowany.

Wbudowane Positionsgeneruje tablicę reprezentującą grupowanie wpisów według indeksów. Domyślnie, gdy nie zostanie dostarczony drugi argument, Positionsużyje pierwszego argumentu. Flatjest następnie mapowany na każdy element, ponieważ tego właśnie wymaga pytanie.

Alternatywne rozwiązania

31 bajtów

MapArgs[Concat#~Indices,Unique]

Wypróbuj online!

Dość krótka, niewbudowana alternatywa. MapArgsjest funkcją podobną do tej Map, z tą różnicą, że można do niej wstawić dodatkowe argumenty. Na przykład MapArgs[{_1 + _2}, 1..3, 3]jest [4, 5, 6]. Podobnie Map, staje się curry, gdy zostanie dostarczony z dwoma argumentami funkcjonalnymi. Mapowana funkcja Concat#~Indicesto rozwidlenie. Ten widelec jest stosowany do Uniqueelementów wejścia i samego wejścia. Przekłada się to na Concat[_, Indices[_2, _]](wraz z argumentami Indiceszamiany ~), który paruje element odwzorowywany ( _) z indeksami tego elementu _w tablicy wejściowej, która jest _2(tak jak ffed MapArgs).

43 bajty

{Flat=>Zip[Unique[_],Indices[_,Unique[_]]]}

Wypróbuj online!

To naprawdę tylko bardziej pełna (jeszcze odrobinę bardziej czytelna) kombinacja rozwiązań nr 1 i nr 2.


4

Galaretka , 6 bajtów

Q;"ĠṢ$

Wypróbuj online!

Wyjaśnienie:

Q;"ĠṢ$
Q      Keep the first occurrence of each element
     $ Last two links as a monad
   Ġ    Group indices of equal elements, then sort the resulting list of groups by the element they point to
    Ṣ   Sort; used to re-order the list of groups based on first occurrence instead
  "    Vectorize link between two arguments (the first occurrences and the group list)
 ;      Concatenate

Nie działa dla ostatniego przypadku testowego . Tablica powinna być zagnieżdżona w innej warstwie, dane wyjściowe są zawsze dwuwymiarowe.
Pavel

@Pavel tak , właśnie zapomniałem dodać stopkę (odpowiedź jest funkcją)
Erik the Outgolfer

Ok, więc spoko. Wyjaśnienie wkrótce, tak? : P
Pavel

@Pavel dodał wyjaśnienie
Erik the Outgolfer

4

Pyth , 7 bajtów

0-indeksowane.

{+VQxRQ

Wypróbuj tutaj! Alternatywny.

W jaki sposób?

{+ VQxRQ - Pełny program.

     RQ - Dla każdego elementu ...
    x - Zbierz wszystkie jego indeksy.
 + V - I zastosuj wektoryzację konkatenacji.
   Q - Z wejściem.
{- deduplikacja.

4

MATL , 8 bajtów

u"@tG=fh

Wypróbuj w MATL Online

Wyjaśnienie

        # Implicitly get the input
u       # Compute the unique values
"       # For each unique value, N
  @     # Push the value N to the stack
  t     # Duplicate N
  G     # Grab the input
  =f    # Get the 1-based indices of the elements that equal N
  h     # Horizontally concatenate N with the indices
        # Implicitly display the result

ooooohhh to sprytne! Próbowałem użyć 18 bajtów, &fale nigdy nie działało.
Giuseppe,

3

Właściwie 24 bajty

;;╗⌠╝╜r⌠╜E╛=⌡░⌡M@Z⌠♂i⌡M╔

Wypróbuj online!

Wyjaśnienie:

;;╗⌠╝╜r⌠╜E╛=⌡░⌡M@Z⌠♂i⌡M╔
;;                        make two copies of input
  ╗                       save a copy to register 0
   ⌠╝╜r⌠╜E╛=⌡░⌡M          map over input:
    ╝                       save the element in register 1
     ╜r                     indices for input
       ⌠╜E╛=⌡░              filter:
        ╜E                    element in input at index
          ╛=                  equals element for outer map (from register 1)
                @Z        swap, zip input with map result
                  ⌠♂i⌡M   flatten each element in zipped list
                       ╔  uniquify

3

R , 56 bajtów

function(x)lapply(unique(x),function(y)c(y,which(x==y)))

Wypróbuj online!


To moja pierwsza próba kodegolfa, więc wszelkie opinie są mile widziane!


3
Witamy w PPCG! Dobra pierwsza odpowiedź.
Pavel

1
Cześć, Florian! Bardzo miła odpowiedź. Jest to tak naprawdę fragment kodu, a nie program lub funkcja - zakłada, że ​​dane wejściowe są zakodowane na stałe x, ale musi istnieć sposób odczytu danych wejściowych - zazwyczaj używamy scanlub definiujemy funkcję. Dodatkowo musi generować dane wyjściowe, więc musiałbym zawinąć to w a printlub a cat.
Giuseppe,

1
zobacz to pytanie, aby uzyskać więcej przydatnych sztuczek golfowych R :)
Giuseppe,

1
Dzięki chłopaki! A link do wskazówek r jest z pewnością przydatny!
Florian

2
@Florian R nie jest taki zły, jak myślisz (z wyjątkiem wyzwań strunowych ...), o ile pamiętasz, że grasz przeciwko innym golfistom R. Jeśli masz pytania, możesz wysłać mi ping na czacie. Jest kilku golfistów R, którzy są aktywni i na pewno zaoferują sugestie, a także docenią twoje! Witamy w golfa :)
Giuseppe,


3

JavaScript (ES6), 64 bajty

0 zindeksowanych

a=>a.map((v,i)=>a[-v]?a[-v].push(i):a[-v]=[v,i]).filter(x=>x[0])

Uwaga: zakłada się, że liczby wejściowe są dodatnie, więc v> 0

Test nieznacznie zmodyfikowany (1 indeksowany) w celu dopasowania do przypadków testowych

var F=
a=>a.map((v,i)=>a[-v]?a[-v].push(i+1):a[-v]=[v,i+1]).filter(x=>x[0])

test = [ // output 1 indexed
  [3, 2, 2, 3],//    | [[3, 1, 4], [2, 2, 3]]
  [17], //           | [[17, 1]]
  [1, 1], //         | [[1, 1, 2]]
  [1, 1, 2], //      | [[1, 1, 2], [2, 3]]
  [1, 2, 3, 4], //   | [[1, 1], [2, 2], [3, 3], [4, 4]]
  [1, 1, 1, 1] //    | [[1, 1, 2, 3, 4]] 
]

test.forEach(t => {
  x = F(t)
  console.log(JSON.stringify(t)+ ' -> ' + JSON.stringify(x))
})


3

APL NARS, 24 bajty, 12 znaków

{∪⍵,¨⍸¨⍵=⊂⍵}

-4 bajty dzięki testowi Adama:

  f←{∪⍵,¨⍸¨⍵=⊂⍵}

  ⎕fmt f 3 2 2 3
┌2────────────────┐
│┌3─────┐ ┌3─────┐│
││ 3 1 4│ │ 2 2 3││
│└~─────┘ └~─────┘2
└∊────────────────┘
  ⎕fmt f 17
┌1──────┐
│┌2────┐│
││ 17 1││
│└~────┘2
└∊──────┘
  ⎕fmt f 1 1
┌1───────┐
│┌3─────┐│
││ 1 1 2││
│└~─────┘2
└∊───────┘
  ⎕fmt f 1 2 3 4
┌4──────────────────────────┐
│┌2───┐ ┌2───┐ ┌2───┐ ┌2───┐│
││ 1 1│ │ 2 2│ │ 3 3│ │ 4 4││
│└~───┘ └~───┘ └~───┘ └~───┘2
└∊──────────────────────────┘
  ⎕fmt f 1 1 1 1
┌1───────────┐
│┌5─────────┐│
││ 1 1 2 3 4││
│└~─────────┘2
└∊───────────┘

Ogol 4 bajty / 2 znaki:{∪⍵,¨⍸¨⍵=⊂⍵}
Adám

3

SWI-Prolog , 165 117 bajtów

-48 bajtów dzięki wskazówkom golfowym Prolog .

h(I):-I+[]-1.
[H|T]+R-N:-(select([H|A],R,[H|L],S),!,append(A,[N],L);append(R,[[H,N]],S)),O is N+1,(T+S-O,!;write(S)).

Wypróbuj online!

Wyjaśnienie

% The predicate that prints the grouped duplicates. It's a wrapper because we
% need some extra arguments to keep state:
enumerate_duplicates(Input) :- enumerate(Input, [], 1).

% In the golfed code, operators are used to represent this predicate.
% See /codegolf//a/153160
% Go through the input, build up the result on the way and print it.
enumerate([Head|Tail], Result, Index) :-
    (
        % If our current Result already contains a list that starts with the
        % current first element in our input, Head, NewIndexes will become the
        % new "tail" of that list in our next result list:
        select([Head|OldIndexes], Result, [Head|NewIndexes], NextResult),
        % Don't backtrack before this if goals below this fail:
        !,
        % The as-yet-unknown NewIndexes above should in fact be the same as
        % OldIndexes with our current Index appended:
        append(OldIndexes, [Index], NewIndexes)
    % Use ; instead of separate predicate rules.
    % See /codegolf//a/67032
    ;
        % If our current Result did not already contain Head, append a new list
        % for it with the current index:
        append(Result, [[Head, Index]], NextResult)
    ),
    % Increment our index counter:
    NextIndex is Index + 1,
    (
        % And continue with the rest of our input:
        enumerate(Tail, NextResult, NextIndex),
        % Don't backtrack if the above succeeded:
        !
    ;
        % If Tail is no longer a multi-element list, we're done. Print:
        write(NextResult)
    ).

3

K (oK) , 10 bajtów

Rozwiązanie:

(!x),'.x:=

Wypróbuj online!

Przykłady:

(!x),'.x:=,17
,17 0
(!x),'.x:=1 1
,1 1 2
(!x),'.x:=1 0 1
(1 1 2
2 3)
(!x),'.x:=1 2 3 4
(1 0
2 1
3 2
4 3)

Wyjaśnienie:

Ocena jest przeprowadzana od prawej do lewej. Nadal uważam, że jest to możliwe do gry w golfa ...

(!x),'.x:= / the solution
         = / group input into dictionary, item!indices
       x:  / save as variable x
      .    / value of x (the indices)
    ,'     / concatenate (,) each-both (') with
(  )       / do this together
 !x        / the key of x (i.e. the items)

Uwagi:

  • 14 bajtów bez wypowiedzenia x, (,/)'+(!;.)@'=, zrezygnował z tego podejścia ...

1
Możesz zwrócić wynik z indeksem 0, więc myślę, że możesz pominąć 1+.
Adám


2

JavaScript (ES6), 68 bajtów

0-indeksowane.

a=>a.map(p=(x,i)=>1/p[x]?b[p[x]].push(i):b.push([x,p[x]=i]),b=[])&&b

Przypadki testowe


Numery wejściowe to! = 0, które mogą być przydatne, aby uniknąć sztuczki 1 / x
edc65

2

PHP 4.1, 88 bajtów

Tak, jest dość długi.

Zakłada to domyślny php.ini plik ( short_open_tag = Oni register_globals = On).

<?foreach($A as$k=>$v){!$b[$v]&&$b[$v]=array($v);$b[$v][]=$k;}print_r(array_values($b));

Przedstawia tablicę w sposób czytelny dla człowieka.
Wartości mogą być przekazywane przez POST, GET i COOKIE, wewnątrz klawisza „A”.


W przypadku nowoczesnej wersji można użyć (90 bajtów):

<?foreach($_GET[A]as$k=>$v){if(!$b[$v])$b[$v]=[$v];$b[$v][]=$k;}print_r(array_values($b));

Wynik jest taki sam, z tym wyjątkiem, że wszystkie wartości muszą zostać przekazane przez parametry GET wewnątrz klawisza „A”.


2

Perl 6 ,  63  61 bajtów

*.pairs.classify(*.value).map({.key,|.value».key}).sort(*.[1])

Przetestuj (0-oparte)

{sort *.[1],map {.key,|.value».key},classify *.value,.pairs}

Przetestuj (ten sam algorytm oparty na 0)

Rozszerzony:

# WhateverCode lambda (this is the parameter) 
*\                                            # [3,2,2,3]

# get a list of Pairs (zero based index => value)
.pairs                                        # (0=>3,1=>2,2=>2,3=>3)

# classify based on the values (unordered result)
.classify(*.value)                            # {2=>[1=>2,2=>2],3=>[0=>3,3=>3]}

# simplify the structure
.map({
  .key,         # the value
  |.value».key  # slip in the indexes
})                                            # ((3,0,3),(2,1,2))

# sort based on first index
.sort(*.[1])

2

Japt , 14 9 bajtów

0-indeksowane.

â £ð¶X iX

Spróbuj

â £ð¶X iX
â             :Deduplicate
  £           :Map each X
   ð          :  Get 0-based indices of elements in the input
    ¶X        :    That are equal to X
       iX     :  Prepend X

2

PHP 7.4+ , 71 bajtów

* 73 bajty, aby podać $_GETklucz i uniknąć ostrzeżeń.

Snippet: ( Demo )

<?foreach($_GET[A]as$k=>$v){$b[$v][0]=$v;$b[$v][]=$k;}print_r([...$b]);

W oparciu o rep, zakładam, że IsmaelMiguel zna najlepszy sposób na publikowanie kodu php w tej społeczności, więc buduję z jego podstaw . Nie jest dla mnie jasne, czy <?ma zostać uwzględniony / zliczony w moim fragmencie . Ponieważ jest to mój post panieński, cieszę się, że każdy może wyjaśnić, czy istnieje niepotrzebna składnia. ps Przeczytałem także Wskazówki dotyczące gry w golfa w PHP, które wydają mi się doskonałym kandydatem do migracji do Meta .

Ulepszenia wprowadzone we fragmencie Ismaela to:

  1. Bezwarunkowe przypisanie pierwszego elementu w każdej podtablicy (nadpisywanie wartości)
  2. Splatpacking zamiastarray_values() ponownego indeksowania danych wyjściowych.


1

Kotlin , 83 bajty

{it.mapIndexed{i,c->c to i}.groupBy({(a,b)->a},{(a,b)->b}).map{(a,b)->listOf(a)+b}}

Upiększony

{
    it.mapIndexed { i, c -> c to i }
        .groupBy({ (a, b) -> a }, { (a, b) -> b })
        .map { (a, b) -> listOf(a) + b }
}

Test

var f: (List<Int>) -> List<List<Int>> =
{it.mapIndexed{i,c->c to i}.groupBy({(a,b)->a},{(a,b)->b}).map{(a,b)->listOf(a)+b}}

data class Test(val input: List<Int>, val output: List<List<Int>>)

val tests = listOf(
        Test(listOf(3, 2, 2, 3), listOf(listOf(3, 0, 3), listOf(2, 1, 2))),
        Test(listOf(17), listOf(listOf(17, 0))),
        Test(listOf(1, 1), listOf(listOf(1, 0, 1))),
        Test(listOf(1, 1, 2), listOf(listOf(1, 0, 1), listOf(2, 2))),
        Test(listOf(1, 2, 3, 4), listOf(listOf(1, 0), listOf(2, 1), listOf(3, 2), listOf(4, 3))),
        Test(listOf(1, 1, 1, 1), listOf(listOf(1, 0, 1, 2, 3)))
)

fun main(args: Array<String>) {
    for (c in tests) {
        val o = f(c.input)
        if (o != c.output) {
            throw AssertionError("${c.input} -> $o != ${c.output}")
        }
    }
}

TIO

TryItOnline


To rozwiązanie jest fragmentem, a nie pełną funkcją lub programem. Wymaga ito predefiniowania zmiennej . Możesz to zrobić, konwertując go na lambda, która przyjmuje parametr i.
Pavel

Przerobiono, aby rozwiązać problem podniesiony przez @Pavel
jrtapsell

1

Swift 4, 107 bajtów

... Yikes.

{a in Dictionary(grouping:a.enumerated()){$0.1}.sorted{$0.1.first!.0<$1.1.first!.0}.map{[$0]+$1.flatMap{$0.0}}}

Nie golfowany:

let f = { (input: [Int]) -> [[Int]] in
    return Dictionary(grouping: input.enumerated(), by: { $0.element })
        .sorted { pairA, pairB in // Sort by order of first appearence (lowest offset)
            return pairA.value.first!.offset < pairB.value.first!.offset
        }.map { element, pairs in
            return [element] + pairs.map{ $0.offset /* +1 */} // add 1 here for 1 based indexing
        }
}

Szkoda, że ​​słownik traci porządek, co zmusza mnie do marnowania tylu znaków na ponowne sortowanie. Ten rodzaj nadużycia ukrytych argumentów zamykających ( $0, $1...) i ukrytych członków krotki ( .0, .1...) jest uhhhhh nie całkiem.



1

Rubin , 54 52 bajty

->a{a.map{|i|[i]+(0..a.size).select{|j|a[j]==i}}|[]}

Ta wersja pozwala na zero (53 bajtów):

->a{a.map{|i|[i]+(0...a.size).select{|j|a[j]==i}}|[]}

Wypróbuj online!


Wyzwanie określa, że ​​tablica będzie zawierać tylko dodatnie liczby całkowite i będzie co najmniej jeden element. nilnie jest dodatnią liczbą całkowitą.
Pavel

@Pavel dzięki, sprawdziłem, ale jakoś to przegapiłem
Asone Tuhid
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.