Перерахуйте масив, групуючи дублікати


24

Мета цього завдання - взяти масив натуральних чисел та перерахувати його індекси, згрупуючи подібні елементи.

Перерахування без жодних дублікатів здійснюється просто виведенням масиву пар (value, index), наприклад, [3, 4, 13, 9, 2]=> [[3,1],[4,2],[13,3],[9,4],[2,5]].

Однак якщо даний елемент з’являється вдруге, він не надає власної пари, а замість цього додається до групи його першого появи. Якщо в нашому вище прикладі ми замінили 9 на 3, то у висновку ми видалимо [9,4]і замінимо [3,1]на [3,1,4].

На виході групи повинні бути впорядковані за першим їх виникненням, а індекси повинні бути у порядку зростання. Елемент повинен бути першим у групі перед його індексами. Вихід може бути індексованим 0 або 1. Ви можете припустити, що масив містить принаймні один елемент.

Тестові приклади:

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

Це , найменше виграш байтів!


Чи допустимо, щоб індекси виводилися у вигляді рядків, наприклад [[17,"1"]]? (Ще не знаю, чи зможу я зберегти будь-які байти таким чином, все ще працюю над цим!)
Shaggy

@shaggy впевнений, це добре
Павло


1
Чи можемо ми [[3, [1, 4]], [2, [2, 3]]]замість цього вивести щось подібне ?
Conor O'Brien

1
@ Paavel, це не є причиною: p, але впевнений
Conor O'Brien

Відповіді:


9

Діалог APL, 5 байт

(⊂,)⌸

Спробуйте в Інтернеті!

,⌸2 байти майже працює, але має зворотні нулі: /


Що у світі робить ?
Містер Xcoder

@ Mr.Xcoder отримує індекси кожної речі і дзвонить лівому оператору з річчю та індексами, де вона існує
dzaima

Оскільки isue with ,⌸є нульовими нулями, а нулі ніколи не будуть на вході, чи вдасться скинути всі нулі менш ніж на 3 байти?
Павло

@Pavel Причина того, що є нулі, полягає в тому, що результат є матрицею, яка повинна мати точні розміри, тому є лише 1 байт для опускання нулів для будь-якого посилення байтів. Я відчуваю, що це, мабуть, можна зіграти.
dzaima

2
Формат виводу масиву "fancy af" : Спробуйте в Інтернеті!
Адам

7

J , 12 байт

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

Нульова індексація.

Спробуйте в Інтернеті!

Якщо ви зможете видалити всю роботу, яку я роблю з ящиками, ви, ймовірно, можете зовсім скоротити кількість рахунків. Я подивлюсь, чи зможу це зрозуміти.

Пояснення

Це, мабуть, занадто рано, щоб пояснити (повинно бути більше гольфів).

~. ,&.> <@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
Формат виводу цього масиву є фантастичним
Павло

@Pavel це також займає багато байтів Π.Π
cole




5

Attache , 15 байт

Flat=>Positions

Спробуйте в Інтернеті!

Це цікавий випадок =>операторської форми Map. При введенні двох функціональних аргументів fі g, Mapповертає функцію f => g[x]над x. Тобто RHS застосовується до входу, потім LHS відображається.

Вбудований Positionsстворює масив, що представляє групування записів за індексами. За замовчуванням, якщо не постачається другий аргумент, Positionsбуде використаний перший аргумент. Flatпотім відображається над кожним елементом, тому що саме цього питання потрібно.

Альтернативні рішення

31 байт

MapArgs[Concat#~Indices,Unique]

Спробуйте в Інтернеті!

Досить коротка, не вбудована альтернатива. MapArgsтака функція, як Mapви можете виключати додаткові аргументи. Наприклад, MapArgs[{_1 + _2}, 1..3, 3]є [4, 5, 6]. Мовляв Map, він стає викривленим, коли постачається з двома функціональними аргументами. Відображається функція Concat#~Indices, яка є виделкою. Ця вилка застосовується до Uniqueелементів вводу та до самого вводу. Це призводить до Concat[_, Indices[_2, _]](з аргументами Indicesмісцями через ~), які пари елемента прив'язується ( _) з індексами зазначеного елемента _у вхідному масиві, який _2(як ffed через MapArgs).

43 байти

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

Спробуйте в Інтернеті!

Це насправді просто більш багатослівне (але при цьому зручніше для читання) поєднання рішень №1 та №2.


4

Желе , 6 байт

Q;"ĠṢ$

Спробуйте в Інтернеті!

Пояснення:

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

Не працює для останнього тестового випадку . Масив повинен бути вкладений іншим шаром, вихід завжди двовимірний.
Павло

@Pavel так, це так , я просто забув додати нижній колонтитул (відповідь - це функція)
Erik the Outgolfer

Добре тоді, круто. Пояснення незабаром, так? : П
Павло

@Pavel додав пояснення
Erik the Outgolfer


4

MATL , 8 байт

u"@tG=fh

Спробуйте в MATL Online

Пояснення

        # 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 це розумно! У мене було 18 байтів, які намагалися використовувати, &fале ніколи не діставали.
Джузеппе

3

Власне , 24 байти

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

Спробуйте в Інтернеті!

Пояснення:

;;╗⌠╝╜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 байт

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

Спробуйте в Інтернеті!


Це моя перша спроба кодегольфа, тому будь-який відгук вітається!


3
Ласкаво просимо до PPCG! Приємна перша відповідь.
Павло

1
Гей, Флоріан! Дуже приємна відповідь. Це насправді фрагмент, а не програма або функція - він передбачає, що вхід жорстко закодований x, але повинен бути спосіб читання вводу - зазвичай ми використовуємо scanабо визначаємо функцію. Крім того, він повинен виводити, тому доведеться загортати це в a printчи a cat.
Джузеппе

1
Дивіться це питання для більш зручних трюків з гольфу на R :) :)
Джузеппе

1
Дякую, хлопці! І посилання на r поради, безумовно, корисне!
Флоріан

2
@Florian R - не так вже й погано, як ви думаєте (за винятком важких викликів ...), поки ви пам’ятаєте, що ви граєте в гольф проти інших гольфістів R! Якщо у вас є запитання, не соромтеся надіслати мене в чаті. Є кілька R гольфістів, які активно працюють, і вони неодмінно запропонують пропозиції, і оцінять вас також! Ласкаво просимо в гольф :)
Джузеппе

3

Мова Вольфрама (Mathematica) , 40 байт

Збережено байт завдяки Мартіну Ендеру.

KeyValueMap[{#,##&@@#2}&]@*PositionIndex

Спробуйте в Інтернеті!


Як @*PositionIndexпрацює?
Павло

@Pavel @*- це склад функцій. PositionIndexв основному виконує всю роботу, але повертає асоціацію замість списку.
алефальфа

1
{#,##&@@#2}&зберігає байт.
Мартін Ендер

3

JavaScript (ES6), 64 байти

0 індексовано

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

Зауважте, це передбачає, що вхідні числа є позитивними, тому v> 0

Тест злегка модифікований (1 індексований), щоб відповідати тестовим випадкам

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 байти, 12 символів

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

-4 байти завдяки тесту Адама:

  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
└∊───────────┘

Поголіть 4 байти / 2 символи:{∪⍵,¨⍸¨⍵=⊂⍵}
Адам

3

SWI-Prolog , 165 117 байт

-48 байт завдяки підказкам щодо гольфу 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)).

Спробуйте в Інтернеті!

Пояснення

% 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 байт

Рішення:

(!x),'.x:=

Спробуйте в Інтернеті!

Приклади:

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

Пояснення:

Оцінювання проводиться справа наліво. Я все ще думаю, що це можливість гольфу далі ...

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

Примітки:

  • 14 байт без оголошення x, (,/)'+(!;.)@'=, відмовився від цього підходу ...

1
Ви можете повернути 0-індексований результат, тому я думаю, ви можете пропустити 1+.
Адам


2

JavaScript (ES6), 68 байт

0-індексований.

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

Тестові справи


Вхідні цифри! = 0, що може бути корисно, щоб уникнути хитрості 1 / x
edc65

2

PHP 4.1, 88 байт

Так, це досить довго.

Це передбачає файл за замовчуванням php.ini ( short_open_tag = Onі register_globals = On).

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

Це представляє масив у зрозумілому для людини вигляді.
Значення можуть передаватися POST, GET та COOKIE, всередині клавіші "A".


Для сучасної версії можна використовувати (90 байт):

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

Результат такий самий, за винятком того, що всі значення повинні передаватися через параметри GET всередині клавіші "A".


2

Perl 6 ,  63  61 байт

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

Тестуйте його (на основі 0)

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

Перевірте це (той же алгоритм на основі 0)

Розширено:

# 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

PHP 7.4+ , 71 байт

* 73 байти для цитування $_GET ключ і уникати попереджень.

Фрагмент: ( демонстрація )

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

На основі реп, я припускаю, що Ісмаель Мігель знає найкращий спосіб розміщення PHP-коду в цій спільноті, тому я будую його основу . Мені незрозуміло, чи <?потрібно включати / рахувати в моєму фрагменті . Оскільки це мій дівочий пост, я радий будь-кому пояснити, чи є зайвий синтаксис. ps Я також читав Поради щодо гольфу в PHP, які мені здаються надзвичайними кандидатами на міграцію в Meta .

Покращення фрагменту Ісмаїла:

  1. Безумовне присвоєння першого елемента в кожному підмножині (перезапис значення)
  2. Splatpacking замість того,array_values() щоб повторно встановити результат.


1

Котлін , 83 байти

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

Прикрасили

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

Тест

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

ТІО

TryItOnline


Це забруднення є фрагментом, а не повною функцією чи програмою. Він вимагає, щоб змінна iбула визначена заздалегідь. Ви можете зробити це дійсним, перетворивши його в лямбда, яка приймає параметр i.
Павло

Перероблено, щоб вирішити питання, підняте @Pavel
jrtapsell

1

Швидкий 4, 107 байт

... Yikes.

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

Безголівки:

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

Дуже погано, що словник втрачає впорядкування, змушуючи мене знову витрачати стільки символів на сортування. Такого роду зловживання неявних аргументів закриття ( $0, $1, ...) і неявних членів кортежу ( .0, .1, ...) є uhhhhh не надто.



1

Рубі , 54 52 байти

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

Ця версія дозволяє отримати нуль (53 байти):

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

Спробуйте в Інтернеті!


Виклик визначає, що масив буде містити лише додатні цілі числа, і буде принаймні один елемент. nilне є додатним цілим числом.
Павло

@Pavel дякую, я перевірив, але пропустив його якось
Асона Тухід
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.