Двигаясь скромный минимум


40

Вдохновленный вопросом о переполнении стека. Название здесь полностью моя вина.


Соревнование

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

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

[4 3 2 5]    ->  [2 2 3 2]
[4 2 2 5]    ->  [2 2 2 2]
[6 3 5 5 8]  ->  [3 5 3 3 3]
[7 1]        ->  [1 7]
[9 9]        ->  [9 9]
[9 8 9]      ->  [8 9 8]

правила

Алгоритм теоретически должен работать для любого входного размера (больше единицы) и значений (натуральных чисел). Это допустимо, если программа ограничена временем, памятью или типами данных и поэтому работает только для чисел до заданного значения или для размера ввода до заданного значения.

Программы или функции разрешены на любом языке программирования . Стандартные лазейки запрещены.

Вклад может быть сделан любым разумным способом ; и с любым форматом. То же самое для вывода. Форматы ввода и вывода могут быть разными.

Самый короткий код в байтах побеждает.


Что должен [4 3 2 2 5]выводить?
Kritixi Lithos

@KritixiLithos разве второй тестовый пример не охватывал это?
Утренняя монахиня

@KritixiLithos Для ввода [4 3 2 2 5]вывод будет [2 2 2 2 2](это похоже на второй контрольный пример)
Луис Мендо

О, я пропустил второй контрольный пример. Но теперь я понимаю, как это работает
Kritixi Lithos

@LuisMendo Вы изменили "integer" на "любой размер и значения ввода". Значит ли это, что нам нужно учитывать все действительные числа?
Утренняя монахиня

Ответы:


19

Желе , 9 6 5 байт

JḟÐ € `ị⁸Ṃ € 
ṙJṖ € Ṃ €
ṙJṖ «/ аргумент: 1D массив (z)

 J [1,2,3, ..., len (z)]
z повернуть z на каждую из указанных выше величин (текущий массив 2D)
  Ṗ удалить последний массив
   «/ Уменьшить на [имплицитно векторизованный] минимум

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

Проверьте все из них сразу! (слегка модифицированный)

Я почти уверен, что Деннис может обыграть это.

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

Алгоритм довольно запутанный. Давайте посмотрим, что это значит [4,2,2,5].

Во-первых, мы используем Jдля получения [1,2,3,4]. Обратите внимание, что Jelly использует 1-индексирование.

Затем мы видим . Он принимает два аргумента: массив и целое число. Он поворачивает массив влево на величину, указанную целым числом. Здесь можно было бы увидеть [4,2,2,5]его слева и [1,2,3,4]справа (больше о том, как это работает, можно найти в руководстве ). В Jelly команды неявно векторизуются. Следовательно, эта команда будет выполняться над каждым отдельным элементом справа, поэтому мы должны создать двумерный массив:

Следовательно, [4,2,2,5]ṙ[1,2,3,4]становится [[4,2,2,5]ṙ1,[4,2,2,5]ṙ2,[4,2,2,5]ṙ3,[4,2,2,5]ṙ4], что становится:

[[2,2,5,4],
 [2,5,4,2],
 [5,4,2,2],
 [4,2,2,5]]

Обратите внимание, что исходные элементы находятся в последней строке, поскольку в этой строке мы повернули влево на величину, равную длине массива, поэтому мы используем next для удаления этой строки, чтобы столбцы были коллекциями элементы массива, которых нет в текущем индексе:

[[2,2,5,4],
 [2,5,4,2],
 [5,4,2,2]]

Следующая операция, «/также довольно запутанная. Во-первых, «возвращает минимум двух чисел, которые он видит слева и справа. Например, 5«3возвращает 3. Теперь, если два аргумента являются массивами, то он будет векторизован, как я сказал выше. Что это значит, [1,5,2,3]«[4,1,5,2]что станет тем, [1«4,5«1,2«5,3«2]что есть [1,1,2,2]. Теперь, /это reduceозначает, что мы делаем операцию над каждой строкой до конца. Например, [1,2,3,4]+/стал бы ((1+2)+3)+4, который является суммой массива [1,2,3,4].

Итак, если мы применим «/к только что полученному 2D-массиву, мы получим:

([2,2,5,4]«[2,5,4,2])«[5,4,2,2]

который из-за векторизации будет эквивалентен:

[2«2«5,2«5«4,5«4«2,4«2«2]

который вычисляет минимум каждого массива без элемента в индексе.


1
О, твоя редакция ... ты первым пришел.
Джонатан Аллан

1
@JonathanAllan Извини.
Утренняя монахиня

40

Python 2 , 41 байт

lambda l:[sorted(l)[x==min(l)]for x in l]

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

Для каждого элемента xмы проверяем, есть ли x==min(l). Если нет, то это так False, как 0если бы он использовался как индекс списка sorted(l), давая наименьший элемент. В противном случае это, Trueиначе говоря 1, дает второй наименьший элемент, так как сам этот элемент наименьший и должен игнорироваться.


2
Мне трудно поверить, что это работает.
Утренняя монахиня

2
Отличный подход!
Луис Мендо

Не могли бы вы добавить объяснение? Это не было бы очень сложно, но уловка «каждое число будет минимальным, за исключением того, которое является минимумом, который будет вторым наименьшим», и тот факт, что Falseпреобразуется в 0и Trueпреобразуется в 1действительно круто и стоит похвастаться ^ W ^ Wexplained
Фонда Моники

18

Желе , 5 байт

=Ṃ‘ịṢ

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

Как?

=Ṃ‘ịṢ - Main link: list a     e.g.  [4,3,2,5]
 Ṃ    - minimum of a                2
=     - equals? (vectorises)        [0,0,1,0]
  ‘   - increment                   [1,1,2,1]
    Ṣ - sort a                      [2,3,4,5]
   ị  - index into                  [2,2,3,2]

4
@LeakyNun Это не порт, это просто тот же метод, я все еще ищу меньше ... Я тоже проголосовал за этот ответ :)
Джонатан Аллан

5
@ LeakyNun Я новичок здесь, но ты всегда такой враждебный? Не то чтобы существует множество уникальных способов подойти к этому. Даже если он это сделал, у него все равно есть более короткий ответ.
Грейсон Кент

3
@GraysonKent Я прошу прощения за мою предполагаемую враждебность.
Утренняя монахиня

1
@GraysonKent Добро пожаловать в PPCG!
Луис Мендо

1
@LeakyNun Это часто случается в более простых задачах, вы не можете сказать, что каждый ответ является портом любого другого
только ASCII

12

Haskell , 42 41 39 байт

РЕДАКТИРОВАТЬ:

  • -1 байт благодаря Ними!
  • -2 байта. Одно спасибо xnor! И один сам.

fберет список целых чисел (или любого Ordтипа) и возвращает список.

f(x:y)=minimum y:(fst<$>zip(f$y++[x])y)

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

fповторяется при вращении списка. xэто первый элемент списка, а yостальные. Поскольку рекурсия бесконечна, список результатов должен быть обрезан: fst<$>zip...yэто более короткий способ сказать take(length y)....


1
Вы можете сохранить один байт, называя список весь ввод с помощью @и переворачивать списки быть Молнии: f l@(x:y)=fst<$>zip(minimum...)l.
Ними

1
f(h:t)=minimum t:(fst<$>zip(f(t++[h]))t)
xnor

9

Октава, 26 байт

@(x)sort(x)((x==min(x))+1)

Подобный подход, используемый в этом ответе , который совпадает с этим .

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

Объяснение:

Джонатан Аллан уже предоставил хорошее объяснение Jelly-кода, поэтому он охватывает октавный бит и почему он работает (и не будет работать в MATLAB).

@(x)                       % An unnamed anonymous function taking a vector x as input
    sort(x)                % Gives a sorted version of x
            (x==min(x))    % Checks if each element is equal to the minimum value
           ((x==min(x))+1) % Adds 1 to the boolean vector, to use as indices
@(x)sort(x)((x==min(x))+1) % Complete function

Это не работает в MATLAB, так как встроенные назначения и прямая индексация не работают. sort(x)(1)выдает ошибку в MATLAB, а не первый элемент в отсортированном векторе.


8

Haskell, 41 байт

a#(b:c)=minimum(a++c):(b:a)#c
a#b=b 
([]#)

Пример использования: ([]#) [4,3,2,5]-> [2,2,3,2]. Попробуйте онлайн!

Начните с пустого аккумулятора aи запустите список ввода. Следующим элементом в списке вывода является минимум аккумулятора aи все, кроме первого элемента списка ввода (-> c), за которым следует рекурсивный вызов с первым элементом, bдобавленным в аккумулятор и c. Остановитесь, когда достигнете конца списка ввода.


7

JavaScript (ES6), 50 46 байт

a=>a.map((_,i)=>Math.min(...a.filter(_=>i--)))

Редактировать: 4 байта сохранены благодаря @Arnauld.


a=>a.map(x=>Math.min(...a.filter(y=>x!=y)))для 43 байтов.
Лохматый

@ Shaggy Я не думаю, что это работает для входа, такого как3,3,3,3
Арно

D'о! Нет, это не будет работать, если есть 2 или более вхождения минимального значения.
Лохматый

1
Тем не менее, вы можете сделать a=>a.map((_,i)=>Math.min(...a.filter(_=>i--)))для 46.
Arnauld

@Arnauld Очень умно, спасибо!
Нил

7

Брахилог , 13 12 байт

l+₁:?⊇ᶠ⁽⌋ᵐb↔

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

Сохранено один байт благодаря @ ais523.

объяснение

l+₁:?            The list [length(Input) + 1, Input]
     ⊇ᶠ⁽         Find the length(Input) + 1 first subsets of the Input
        ⌋ᵐ       Get the min of each subset 
           b↔    Remove the first element and reverse

Мы используем тот факт, что объединяет подмножества от самых больших до самых маленьких. Например , для [1,2,3], подмножества , которые мы получаем в следующем порядке: [1,2,3], [1,2], [1,3], [2,3], [1], [2], [3], [].

Мы можем видеть, что подмножества [1,2], [1,3], [2,3]- это те, от которых мы хотим получить минимум, но в обратном порядке по сравнению со списком ввода (отсюда и ). Мы можем выбрать эти подмножества только найдя первые length(Input) + 1подмножества, которые будут содержать все из них + весь список в первую очередь. Мы отбрасываем весь этот список с b.


1
Вы можете сохранить байт, разделив «подмножество findall + минимум» на «подмножество findall» и «минимум карты». (Мне нужно добавить это в

1
@ ais523 Спасибо, я всегда забываю об этом трюке ...
Fatalize

6

На самом деле , 13 байтов

;;S╝m╗⌠╜=╛E⌡M

Использует ту же технику, что и xnor .

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

Объяснение:

;;S╝m╗⌠╜=╛E⌡M
;;             make two extra copies of input list
  S╝           sort one and save it in register 1
    m╗         save the minimum of the other in register 0
      ⌠╜=╛E⌡M  for each value in list:
       ╜=╛E      return the minimum element of the input list if the value is not equal to the minimum, else return the second-smallest element

1
Вы до сих пор не позволили нам взглянуть на глобальный стек внутри временного стека?
Утренняя монахиня

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

1
Когда вы начали большой рефакторинг?
Утренняя монахиня

6

R, 46 31 байт

l=scan();sort(l)[(min(l)==l)+1]

реализует решение Stewie Griffin в R, увы, моя оригинальная идея на 50% длиннее! все еще читает список из стандартного ввода, но теперь возвращает гораздо более читаемый числовой вектор.

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

старая реализация:

l=scan();Map(function(x)min(l[-x]),match(l,l))

читает в списке со стандартного ввода. Отрицательный индекс l[-x]исключает элемент из списка и match(l,l)возвращает индекс первого вхождения каждого элемента списка. Возвращает список.





4

C 85 байт

i,j,m;f(d,o,n)int*d,*o;{for(i=n;i--;)for(m=d[!i],j=n;j;o[i]=m=--j^i&&d[j]<m?d[j]:m);}

Первый аргумент - это входной целочисленный массив. Второй аргумент - это выходной целочисленный массив. Третий аргумент - это количество элементов для обоих массивов.

Посмотрите, как это работает онлайн .


3

Perl 6 ,  26 24  19 байт

26

{.map: (.Bag∖*).min.key}

Обратите внимание, что это U + 2216, а не \U + 5C

Попытайся

{.map: (.Bag⊖*).min.key}

Попытайся

24

{(.min X%$_)X||.sort[1]}

Попытайся

19

{.sort[.min X==$_]}

Попытайся


26

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

  .map:     # for each of the values in the input (implicit method call on 「$_」)
  (
    .Bag    # turn the block's input into a Bag
           # set-difference           「∖」 U+2216 aka 「(-)」
    # ⊖     # symmetric-set-difference 「⊖」 U+2296 aka 「(^)」
    *       # turn expression into a WhateverCode lambda (this is the parameter)
  ).min.key # get the minimum pair from the Bag, and return its key
}

Я использовал "причудливые" операторы Юникода а не эквиваленты ascii, потому что им потребовался бы пробел перед ними, чтобы они не анализировались как часть .Bagвызова метода.

24

{
  (.min X% $_) # the minimum cross modulus-ed with the input
  X||          # cross or-ed 
  .sort[1]     # with the second minimum
}

19

{
  .sort\        # sort the values
  [             # index into that
    .min X== $_ # the minimum cross compared with the input
  ]
}

(24- и 19-байтовые гольфы были вдохновлены реализацией Jelly )


3

Clojure, 36 81 62 71 байт

Новейшие (не следует отправлять их на скорую руку):

#(for[c[(zipmap(range)%)]i(sort(keys c))](apply min(vals(dissoc c i))))

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

Кроме того, у этого есть ошибка (62 байта), zipmap создает неупорядоченную карту, поэтому это не даст правильную последовательность на больших входах.

#(for[c[(zipmap(range)%)][i v]c](apply min(vals(dissoc c i))))

vна самом деле не используется ни для чего, но это короче, чем i (keys c).

Предыдущая на 81 байт:

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

#(let[r(range(count %))](for[i r](apply min(for[j r :when(not= i j)](nth % j)))))

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

О черт, оригинал (36 байт) не работает, когда минимальное число повторяется, в [4 2 2 5]результате [2 4 4 2]оба 2s удаляются :(

#(for[i %](apply min(remove #{i}%)))

#{i}это набор, который содержит только i, он возвращает true iи false для других, что означает, что минимум вычисляется из всех других чисел в списке ввода.

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





2

Скала, 37 байт

l.indices map(i=>l diff Seq(l(i))min)

l это любая коллекция Int.

Тестовые случаи:

scala> val l = List(4,3,2,5)
l: List[Int] = List(4, 3, 2, 5)

scala> l.indices map(i=>l diff Seq(l(i))min)
res0: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 2, 3, 2)

scala> val l = List(4,2,2,5)
l: List[Int] = List(4, 2, 2, 5)

scala> l.indices map(i=>l diff Seq(l(i))min)
res1: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 2, 2, 2)

scala> val l = List(6,3,5,5,8)
l: List[Int] = List(6, 3, 5, 5, 8)

scala> l.indices map(i=>l diff Seq(l(i))min)
res2: scala.collection.immutable.IndexedSeq[Int] = Vector(3, 5, 3, 3, 3)

scala> val l = List(7,1)
l: List[Int] = List(7, 1)

scala> l.indices map(i=>l diff Seq(l(i))min)
res3: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 7)

scala> val l = List(9,9)
l: List[Int] = List(9, 9)

scala> l.indices map(i=>l diff Seq(l(i))min)
res4: scala.collection.immutable.IndexedSeq[Int] = Vector(9, 9)

scala> val l = List(9,8,9)
l: List[Int] = List(9, 8, 9)

scala> l.indices map(i=>l diff Seq(l(i))min)
res5: scala.collection.immutable.IndexedSeq[Int] = Vector(8, 9, 8)

Это, вероятно, все еще может быть в гольфе, я не мог найти более короткий способ удалить элемент из списка, чем l diff Seq(l(i))


2

C #, 36 байт

i.Select((x,a)=>i.Where((y,b)=>b!=a).Min())

Принимает элементы (i) и ищет в элементах без текущего элемента минимальное значение.

Грустно, что некоторые другие попытки не работают, так как мы работаем с примитивными типами, и поэтому не имеем списков со ссылками для сравнения элементов.


2

PowerShell , 49 38 байт

-11 байт благодаря маззи

($a=$args)|%{($c=$a|sort)[$_-eq$c[0]]}

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

Улучшение прекрасного ответа Синусоиды . Сохраняет 10 байтов, используя явный вывод вместо построения массива. Индексирует в отсортированном массиве либо точку 0 (т. Е. Наименьшее значение), либо точку 1, если условие истинно.


1
Это умно. Сохранить больше :) Попробуйте онлайн!
Маззи

1
@ mazzy Молодец. Теперь очевидно, что я это вижу, но я бы никогда не соединил это.
Веска

1
Хорошо сделано! Твой любимый :)
Синусоида

1

Perl 5, 43 байта

sub{@x=sort{$a<=>$b}@_;map$x[$_==$x[0]],@_}

Эквивалент решения Python. К sortсожалению, в Perl неверное значение по умолчанию для чисел (требующее явного компаратора), и minоно не является встроенным, но почти компенсирует это тем, subчто оно короче lambda, map$_,короче x for x inи неявностью списков return и args.


1

Рубин, 30 байтов

Для каждого элемента отсортируйте массив, удалите текущий элемент и возьмите первый элемент оставшегося массива.

->a{a.map{|e|(a.sort-[e])[0]}}

Это анонимная функция, которую можно использовать так:

f = ->a{a.map{|e|(a.sort-[e])[0]}}
p f[[6, 3, 5, 5, 8]] # => [3, 5, 3, 3, 3]

1

CJam, 15 байтов

{:S{S:e<=S$=}%}

По сути это перевод алгоритма xnor на CJam.

Это безымянный блок, который берет массив из стека и оставляет результат в стеке.

Объяснение:

{
  :S     e# Save in S
  {      e# For X in S:
    S:e< e#   Push Min(S)
    =    e#   X == Min(S)
    S$=  e#   Sorted(S)[top of stack]
  }%     e# End
}

1
@ LuisMendo Ой - я забыл на самом деле сортировать массив. Это должно работать сейчас.
Esolanging Fruit

1

05AB1E , 5 байтов

{sWQè

Порт ответа @xnor 's Python 2 .

Попробуйте онлайн или проверьте все контрольные примеры .

Объяснение:

{        # Sort the (implicit) input-list
         #  i.e. [4,1,3,6] → [1,3,4,6]
 s       # Swap, so the (implicit) input-list is at the top of the stack again
  W      # Get the minimum without popping from the list
         #  i.e. [4,1,3,6] → 1
   Q     # Check for each element if they are equal to this value (1/0 as truthy/falsey)
         #  i.e. [4,1,3,6] and 1 → [0,1,0,0]
    è    # Use these 0s and 1s to index in the sorted list
         #  i.e. [1,3,4,6] and [0,1,0,0] → [1,3,1,1]

1

Java 8, 119 байт

a->{int t[]=a.clone(),m=a[0],i=a.length;for(int x:a)m=x<m?x:m;for(java.util.Arrays.sort(t);i-->0;)a[i]=t[a[i]==m?1:0];}

Порт @xnor 's Python 2 ответа .

Изменяет массив ввода вместо того, чтобы возвращать новый для сохранения байтов.

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

Объяснение:

a->{                  // Method with integer-array parameter and no return-type
  int t[]=a.clone(),  //  Make a copy of the input-array
      m=a[0],         //  Minimum `m`, starting at the first value of the input-array
      i=a.length;     //  Index-integer, starting at the length of the input-array
  for(int x:a)        //  Loop over the input-array
    m=x<m?            //   If the current item is smaller than the current `m`
       x              //    Replace `m` with this value
      :               //   Else:
       m;             //    Leave `m` the same
  for(java.util.Arrays.sort(t);
                      //  Sort the copy we've made of the input-array
      i-->0;)         //  Loop `i` in the range (length, 0]
    a[i]=             //   Modify the item at index `i` of the input-array to:
      t[              //    The item in the sorted array at index:
        a[i]==m?      //     If the current item and the minimum are equal:
         1            //      Use index 1 in the sorted array
        :             //     Else:
         0];}         //      Use index 0 in the sorted array

1

APL (Dyalog Extended) , 7 байтов

Порт xnor Python 2 ответ. Требуется ⎕IO←0:

∧⊇⍨⊢=⌊/

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

Объяснение:

∧⊇⍨⊢=⌊/   Monadic function train
      ⌊/   The minimum element of the input
    ⊢=     Element-wise compare the input to the above
           Results in a boolean vector, let's call it "X"
∧         ⍝ Sort the input
 ⊇⍨      ⍝ Index into sorted input by X

1

Haskell , 76 байт

Это значительно дольше, чем в предыдущих записях на Haskell, но это первое, которое выполняет только линейное число сравнений и линейный объем дополнительной работы.

f(x:y)|(z,w)<-x!y=z:w
a![x]=(x,[a])
a!(x:y)|(p,q)<-a#x!y=(x#p,a#p:q)
(#)=min

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

объяснение

!принимает два аргумента: текущий минимум и непустой список. Возвращает минимальное значение в списке и результат обработки данного списка с использованием текущего минимума.


1

MathGolf , 9 7 байт

s_╓?m=§

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

объяснение

В основном это порт ответа Кевина Круйссена на 05AB1E, но я теряю 2 байта из-за необходимости делать что-то явно.

s         sort(array)
 _        duplicate TOS
  ╓       minimum of two elements, min of list, minimum by filter
   ?      rot3 pops input on top of stack again
    m=    explicit map to check equality
      §   get from sorted array for each
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.