Перечислить массив, группировать дубликаты


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

@ Шагги, конечно, это нормально
Павел


1
Можем ли мы вывести что-то вроде [[3, [1, 4]], [2, [2, 3]]]этого?
Конор О'Брайен

1
@Pavel, это не причина: р, но уверен
Конор О'Брайен

Ответы:


9

Дьялог АПЛ, 5 байт

(⊂,)⌸

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

,⌸на 2 байта почти работает, но имеет конечные нули: /


Что в мире делает ?
г-н Xcoder

@ Mr.Xcoder получает индексы каждой вещи и вызывает левый оператор с вещью и индексами, где она существует
dzaima

Поскольку isue с ,⌸является конечными нулями, и нули никогда не будут входными, возможно ли сбросить все нули менее чем в 3 байта?
Павел

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

2
Выходной формат массива "fancy af" : попробуйте онлайн!
Адам

7

J , 12 байт

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

Zero-индексироваться.

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

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

объяснение

Это, вероятно, слишком рано, чтобы объяснять (должно быть больше гольфов).

~. ,&.> <@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 также занимает много байтов Π.Π
Коул

5

05AB1E , 10 байтов

ÙεDIQƶ0K)˜

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

объяснение

Ù             # 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

Атташе , 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 да, это так , я просто забыл добавить нижний колонтитул (ответ является функцией)
Эрик Outgolfer

Хорошо, тогда круто. Объяснение скоро, да? : P
Павел

@Pavel добавил объяснение
Эрик 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

ооооооо это умно! Я пытался использовать около 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)))

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


Это моя первая попытка Codegolf, поэтому любые отзывы приветствуются!


3
Добро пожаловать в PPCG! Хороший первый ответ.
Павел

1
Привет, Флориан! Очень хороший ответ. Это на самом деле фрагмент, а не программа или функция - предполагается, что ввод жестко закодирован x, но должен быть способ чтения ввода - обычно мы используем scanили определяем функцию. Кроме того, он должен выводить, так что придется обернуть это в printили cat.
Джузеппе

1
см. этот вопрос для более удобных трюков с игрой в гольф :)
Джузеппе

1
Спасибо, парни! И ссылка на советы r безусловно полезна!
Флориан

2
@Florian R не так плох, как вы думаете (за исключением соревнований по струнам ...), если вы помните, что играете в гольф против других игроков в гольф R! Не стесняйтесь пинговать меня в чате, если у вас есть вопросы. Есть пара активных игроков в гольф R, которые обязательно предложат свои предложения и оценят ваше мнение! Добро пожаловать в гольф :)
Джузеппе

3

Wolfram Language (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-Пролог , 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 (ок) , 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)

Expanded:

# 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]);

Основываясь на репутации, я предполагаю, что IsmaelMiguel знает лучший способ опубликовать 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}")
        }
    }
}

TIO

TryItOnline


Это решение - фрагмент, а не полная функция или программа. Требуется, чтобы переменная iбыла предопределена. Вы можете сделать это действительным, преобразовав его в лямбду, которая принимает параметр i.
Павел

Переработан для решения проблемы, поднятой @Pavel
jrtapsell

1

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

Ungolfed:

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