Поменять индексы и значения

29

Задание

Напишите программу или функцию, чьи входные данные представляют собой список / массив X целых чисел, а выходные данные представляют собой список наборов целых чисел Y , так что для каждого элемента e в каждом наборе Y [ i ], X [ e ] = i и таким образом, что общее число элементов в множествах в Y равно числу элементов в X .

(Это в основном та же операция, что и обращение к хеш-таблице / словарю, за исключением того, что вместо этого применяется к массивам.)

Примеры

В этих примерах предполагается индексирование на основе 1, но вместо этого вы можете использовать индексацию на основе 0.

X             Y
[4]           [{},{},{},{1}]
[1,2,3]       [{1},{2},{3}]
[2,2,2]       [{},{1,2,3}]
[5,5,6,6]     [{},{},{},{},{1,2},{3,4}]
[6,6,5,5]     [{},{},{},{},{3,4},{1,2}]

Разъяснения

  • Вы можете представлять набор в виде списка, если хотите. Если вы это сделаете, порядок элементов не имеет значения, но вы не можете повторять элементы.
  • Вы можете использовать любой разумный однозначный формат ввода / вывода; Например, вы можете разделить элементы набора пробелами, а сами наборы - символом новой строки.
  • Y должен быть конечной длины и, по крайней мере, достаточно длинным, чтобы все элементы X были индексами массива. Однако он может быть длиннее максимального элемента X (дополнительные элементы будут пустыми наборами).
  • Все элементы X будут действительными индексами массива, то есть неотрицательными целыми числами, если вы используете индексацию на основе 0, или положительными целыми числами, если вы используете индексацию на основе 1.

Состояние победы

Как вызов , чем короче, тем лучше.

Cyoce
источник
Относящиеся . В сообщении « Песочница» (теперь удаленном, но вы можете просмотреть его, если у вас есть репутация), мы решили, что оно, вероятно, не является дубликатом, но вы можете проголосовать, чтобы закрыть его, если вы не согласны.
Означает ли «порядок элементов не имеет значения», что выходы [5,5,6,6]и [6,6,5,5]могут быть идентичны?
Утренняя монахиня
1
@LeakyNun Порядок элементов наборов в списке вывода не имеет значения. Так [5,5,6,6]и [6,6,5,5]не могут иметь одинаковый выход, но выход для [5,5,6,6]также может быть, например, [{},{},{},{},{2,1},{4,3}].
ngenisis
Существует ли допустимое максимальное значение индекса в X? Также пустые наборы могут иметь 0 вместо того, чтобы быть фактически пустыми? Например был [{0},{0},{0},{0},{1,2},{3,4}]бы действительный вывод для [5,5,6,6]?
Скидсдев
@Mayube: Нет на первый ответ (хотя, если вы используете язык с ограниченным диапазоном целых чисел, вы можете написать программу так, как если бы целые числа были неограниченно большими, и не беспокоиться о том, что она сломается, если кто-то даст вам целое число диапазона в качестве входных данных). Что касается второго вопроса, это однозначный (если странный) синтаксис, когда вы используете индексацию на основе 1, так что да, в этом случае (очевидно, нет, если вы используете индексацию на основе 0, потому что тогда 0 будет означать некоторое остальное.)

Ответы:

9

MATL , 8 байт

tn:IXQ&D

Ввод - это вектор-столбец с ;разделителем (например [2;2;2]). Выход - это строковое представление массива ячеек векторов строк (например {[]; [1 2 3]}). Вектор строки одного элемента совпадает с числом (поэтому {1; 2; 3}выводится вместо {[1]; [2]; [3]}).

Попробуйте онлайн! Или проверьте все тестовые случаи .

объяснение

t     % Implicit input, say x. Duplicate
n     % Number of elements, say N
:     % Range: [1 2 ... N]
IXQ   % accumarray(x, [1 2 ... N], [], @(x){sort(x).'})
&D    % String representation

Большая часть работы выполняется функцией высшего порядка Matlab accumarray, которая группирует элементы во втором входе в соответствии с соответствующими значениями в первом и применяет указанную функцию к каждой группе. В этом случае используется функция @(x){sort(x).'}, которая выводит отсортированные элементы в каждой группе и обеспечивает упаковку результатов для всех групп в массив ячеек.

Луис Мендо
источник
7

Python, 69 байт

lambda s:[[j for j,x in enumerate(s)if x==i]for i in range(max(s)+1)]

Использует индексирование на основе 0.

Уриэль
источник
7

Желе , 7 5 байт

=þṀT€

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

Как это работает

=þṀT€  Main link. Argument: A (array)

  Ṁ    Yield m, the maximum of A.
=þ     Equals table; for each t in [1, ..., m], compare all elemnts of A with t,
       yielding a 2D Boolean array.
   T€  Truth each; for each Boolean array, yield all indices of 1.
Деннис
источник
5

Желе , 8 байт

Jẋ"Ṭ€;"/

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

Как это работает

Jẋ"Ṭ€;"/  argument: z           eg. [6,6,4,4]
J         [1 .. len(z)]             [1,2,3,4]
   Ṭ€     untruth each of z         [[0,0,0,0,0,1],
                                     [0,0,0,0,0,1],
                                     [0,0,0,1],
                                     [0,0,0,1]]
 ẋ"       repeat each of ^^         [[[],[],[],[],[],[1]],
          as many times as           [[],[],[],[],[],[2]],
          each of ^                  [[],[],[],[3]],
                                     [[],[],[],[4]]]
       /  reduce by...
     ;"   vectorized concatenation  [[],[],[],[3,4],[],[1,2]]
Дрянная Монахиня
источник
4

Mathematica, 36 байт

Join@@@#~Position~n~Table~{n,Max@#}&

объяснение

введите описание изображения здесь

Для каждого nin {1, 2, ..., Max@#}, где Max@#наибольшее целое число в списке ввода, вычисляется Positions, где он nпоявляется в списке ввода #. Так как Position[{6,6,5,5},5](например) возвращает {{3},{4}}, мы затем Apply Joinко всем элементам на уровне {1}результата.

ngenisis
источник
3

Haskell , 45 байт

sберет список целых чисел и возвращает список списков. 1-индексированный, чтобы сохранить входные данные тестового примера неизмененными (хотя выходные данные получают несколько дополнительных пустых списков).

s l=[[i|(i,y)<-zip[1..]l,y==x]|x<-[1..sum l]]

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

Это довольно простые вложенные списки. Единственным небольшим изменением является использование возможности сделать более длинный список с помощью sumвместо maximum.

Орджан Йохансен
источник
3

PHP, 55 байт

<?while($i<=max($_GET))print_r(array_keys($_GET,$i++));

0 индексированные.

user63956
источник
3

R 68 49 47 байт

lapply(1:max(x<-scan()),function(y)which(y==x)) 

Удивительно, но гораздо проще, чем более длинные решения. Извлекает вектор xиз STDIN, создает вектор из 1to max(x), неявно генерирует список длины max(x)и проверяет, какие индексы xсоответствуют указанным в новом списке. Неявно печатает вывод.

Старая версия:

o=vector('list',max(x<-scan()));for(i in x)o[[i]]=c(o[[i]],F<-F+1);o

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

Использует индексирование на основе 1.

JAD
источник
2

Python 2 , 91 86 85 байт

Я программирую на своем телефоне, но мне очень понравился этот вызов. Я могу определенно играть в гольф дальше.

def f(a):
 r=[[]for i in range(max(a)+1)]
 for i,j in enumerate(a):r[j]+=[i]
 print r

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

totallyhuman
источник
Снова заиграл в гольф благодаря пониманию вложенного списка. : D
полностью человек
2

Желе , 9 байт

Ṭ+\ịĠȧ@"Ṭ

1-индексированные, пустые наборы, представленные в виде 0наборов одного элемента, представленных в виде Nнаборов из нескольких элементов, представленных в виде[M,N,...]

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

Как?

Ṭ+\ịĠȧ@"Ṭ - Main link: list a        e.g. [6,6,4,4]
Ṭ         - untruth a                     [0,0,0,1,0,1]
  \       - cumulative reduce with:
 +        -   addition                    [0,0,0,1,1,2]
    Ġ     - group indices of a by value   [[3,4],[1,2]]
   ị      - index into                    [[1,2],[1,2],[1,2],[3,4],[3,4],[1,2]]
        Ṭ - untruth a                     [0,0,0,1,0,1]
       "  - zip with:
     ȧ@   -   and with reversed @rguments [0,0,0,[3,4],0,[1,2]]
Джонатан Аллан
источник
2

JavaScript (ES6), 64 62 байта

Сохранено 2 байта благодаря @SteveBennett


Принимает 0-индексированный ввод. Возвращает разделенный запятыми список множеств.

a=>a.map((n,i)=>o[n]=[i,...o[n]||[]],o=[])&&`{${o.join`},{`}}`

Контрольные примеры


Альтернативная версия, 53 байта

Если упрощенный вывод, такой как '||||3,2|1,0'приемлемый, мы можем просто сделать:

a=>a.map((n,i)=>o[n]=[i,...o[n]||[]],o=[])&&o.join`|`
Arnauld
источник
Вау. Я так растерялся, насколько `{${o.join`},{`}}`законен ES2015.
Стив Беннетт
@SteveBennett, это шаблонный литерал . В более старых версиях JS было бы "{" + o.join("},{") + "}", если это делает это более понятным.
Лохматый
Нет, я знаю о них - меня смущает обратная цитата после слова join. Это закрытие строки (в этом случае wtf) или это то, как вы избегаете закрытой скобки?
Стив Беннетт
Хм, хорошо, так что в этом контексте join`эквивалентно join('. Не знал, что ты сможешь это сделать.
Стив Беннетт
Ах, теперь я вижу. Это помеченный шаблонный литерал. Что вы можете злоупотреблять , чтобы сэкономить пару символов , когда вызов функции , которая принимает один аргумент (и игнорирует другие) array.join` `. Это очень запутанно, потому что вы встраиваете это в строку шаблона, и, что еще более запутанно, это объединяющая строка },{, которая по совпадению выглядела как часть строки шаблона ... и в любом случае это просто странно и безобразно. :)
Стив Беннетт
1

Баш , 109 байт

Жаль, что нет встроенного для максимального значения массива.

a=($@)
for((x=m=1;x<=m;x++)){ for((y=0;y<$#;)){((m<a[y]))&&((m=a[y]));((a[y++]==x))&&printf "%d " $y;};echo;}

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

Максим Михайлов
источник
1

Mathematica 62 байта

(Y={}~Table~Max@#;Y[[#[[j]]]]~AppendTo~j~Table~{j,Tr[1^#]};Y)&

Я буду управлять этим для вас

(Y={}~Table~Max@#;Y[[#[[j]]]]~AppendTo~j~Table~{j,Tr[1^#]};Y)&[{4,5,2,3,3,8,6,3}]

{{}, {3}, {4, 5, 8}, {1}, {2}, {7}, {}, {6}}

Попробуйте онлайн (просто вставьте код с помощью Ctrl-V и нажмите Shift + Enter)
, не забудьте вставить список ввода в конце, как в примере выше

J42161217
источник
Добро пожаловать в PPCG! Вы можете сохранить байт, используя инфиксную нотацию для AppendTo. Кроме того, {j,1,Length[#1]}может быть просто {j,Length@#}или даже короче {j,Tr[1^#]}. Tr[1^#]это довольно обычный прием , чтобы сохранить байты по сравнению с использованием Length.
ngenisis
1

Perl 6 ,  36 32  29 байт

->\a{map {a.grep(*==$_):k},1..a.max}

Попытайся

{map {.grep(*==$^a):k},1.. .max}

Попытайся

{map {.grep($^a):k},1.. .max}

Попытайся


Expanded:

{  # bare block lambda with implicit parameter 「$_」

  map

    {  # bare block lambda with placeholder parameter 「$a」

      .grep(  # grep for the values in 「$_」
        $^a   # that are equal to the currently tested value (and declare param)
      ) :k    # return the key (index) rather than the value
    },

    1 .. .max # Range from 1 to the maximum value in 「$_」

}

Возвращает нулевые индексы, чтобы получить 1 основанный перекрестный оператор ( X) в сочетании с +оп . (33 байта)

{1 X+.grep($^a):k}

Для того, чтобы заставить его вернуть Сета сек только надстройкуset в там (всего 37 байт)

{set 1 X+.grep($^a):k}
Брэд Гилберт b2gills
источник
1

R, 80 72 байта

1-индексируется, берет Xиз stdin. Возвращает список векторов индексов с NULLпустым набором.

X=scan();Y=vector('list',max(X));Y[X]=lapply(X,function(x)which(X==x));Y

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

старая версия:

X=scan();Y=vector('list',max(X));for(i in 1:length(X))Y[[X[i]]]=c(Y[[X[i]]],i);Y

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

Giuseppe
источник
Я думаю, что это Y=list();работает так же хорошо
rturnbull
Удалось сбрить fewбайты в моем ответе :) codegolf.stackexchange.com/a/120024/59530
JAD
0

GNU Make , 214 213 208 204 байта

X=$(MAKECMDGOALS)
M=0
P=$(eval N=$(word $1,$X))$(if $N,$(if $(shell dc -e$Nd$Mds.\>.p),$(eval M=$N),)$(eval A$N+=$1$(call $0,$(shell expr $1 + 1))),)
$(call P,1)$(foreach K,$(shell seq $M),$(info $(A$K)))

Ввод / вывод: ввод массива через аргументы, вывод в stdout, по одному на строку, разделенные пробелами.

$ make -f swap.mk 2 2 2

3 2 1
make: *** No rule to make target `2'.  Stop.

объяснение

X=$(MAKECMDGOALS)     # Input array
M=0                   # Max value encountered in X
P=$(eval
    N=$(word $1,$X))  # Get next word from X
  $(if $N,$(if $(shell dc -e$Nd$Mds.\>.p),
    $(eval M=$N),)    # Update M
    $(eval A$N+=$1    # Append index to a variable named after value
      $(call $0,      # Recurse (call returns empty string)
        $(shell expr $1 + 1))),)
$(call P,1)           # Initial call to P. 1 is the first index
$(foreach K,          # Print all values of A* variables
  $(shell seq $M),
  $(info $(A$K)))     # Uninitialized ones default to empty strings

Порядок индексов в наборах меняется на обратный, потому что Pрекурсивно вызывает себя перед обновлением A$2(вызов выполняется при оценке правой части).

eush77
источник
Есть ли makeспособ сделать арифметику сама? Обращение к внешним программам для этого напоминает читерство, потому что вы, вероятно, могли бы поместить в эти программы гораздо больше алгоритма и в итоге получить более короткую программу.
@ ais523 не имеет. Предыдущая версия использовалась bcи grep. Я также мог бы использовать testи $?. dcимеет более краткий синтаксис, но, честно говоря, все они чувствуют то же самое.
eush77
0

Common Lisp, 91 байт

(lambda(x &aux(l(make-list(eval`(max,@x))))(i 0))(dolist(y x l)(push(incf i)(nth(1- y)l))))

Индексирование на основе 1 возвращает наборы в виде списков.

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

Renzo
источник
0

к , 13 байт

{(=x)@!1+|/x}

Это 0-индексированный.

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

{           } /function(x)
 (=x)         /make a map/dictionary of values to their indices
         |/x  /get maximum value in x
      !1+     /make a range from 0 to the value, inclusive
     @        /get map value at each of the values in the range
              /    0N is given where there is no result
zgrep
источник