Переміщення скромного мінімуму


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 Ви змінили "ціле число" на "будь-який розмір та значення вводу". Це означає, що нам потрібно враховувати всі реальні числа?
Leaky Nun

Відповіді:


19

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

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

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

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

Перевірте їх усіх одразу! (трохи змінено)

Я впевнений, що Денніс може це перемогти.

Як це працює

Алгоритм досить складний. Давайте спостерігатимемо, що це робить [4,2,2,5].

По-перше, ми використовуємо Jдля отримання [1,2,3,4]. Зауважте, що Jelly використовує 1-індексацію.

Потім ми бачимо . Це займає два аргументи: масив і ціле число. Він обертає масив зліва на величину, вказану цілим числом. Тут можна побачити [4,2,2,5]ліворуч і [1,2,3,4]праворуч (детальніше про те, як це працює, можна знайти у підручнику ). У Jelly команди неявно векторизуються. Тому ця команда буде виконуватися над кожним окремим елементом праворуч, саме тому ми створимо 2D масив:

Тому [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]]

Зауважте, що початкові елементи знаходяться на останньому рядку, оскільки в цьому рядку ми повернули ліворуч на величину, рівну довжині масиву, тому ми використовуємо наступне для видалення цього рядка, щоб стовпці були колекціями елементи масиву, які не є поточним індексом:

[[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 Вибачте
Leaky Nun

40

Python 2 , 41 байт

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

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

Для кожного елемента xперевіряємо, чи є x==min(l). Якщо ні, то Falseце трактується як 0коли використовується як індекс списку sorted(l), даючи найменший елемент. В іншому випадку це Trueaka 1, даючи другий найменший елемент, оскільки сам цей елемент найменший і його слід ігнорувати.


2
Мені важко повірити, що це працює.
Лина монашка

2
Чудовий підхід!
Луїс Мендо

Чи можете ви додати пояснення? Це було б не дуже складно, але хитрість "кожне число буде мінімальним, за винятком того, що є мінімальним, яке буде другим найменшим", і той факт, що Falseперетворюється 0і Trueперетворюється на 1справді круто і слід похвалитися про ^ W ^ Wexplained
Nic Hartley

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-коду, тому це стосується біта Octave, і чому він працює (і не працюватиме в 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'oh! Ні, це не спрацює, якщо є 2 або більше випадків мінімального значення.
Кудлатий

1
Однак ви можете зробити a=>a.map((_,i)=>Math.min(...a.filter(_=>i--)))за 46.
Арнольд

@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" та "мінімум карти". (Мені потрібно піти додати це до теми Brachylog, тепер ви нагадали про це.)

1
@ ais523 Спасибі, я завжди забуваю про цей трюк…
Підтвердити

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
Ви все ще не дозволили нам переглянути глобальний стек всередині тимчасового стека?
Leaky Nun

1
@LeakyNun Ще немає У поточному стані, що існує код перекладача, це було б дуже важко. Після закінчення великого рефакторингу, над яким я працюю, я побачу, як додати цю функціональність.
Mego

1
Коли ви почали великий рефакторинг?
Leaky Nun

6

R, 46 31 байт

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

реалізує рішення Стіві Гріффін на R, на жаль, моя оригінальна ідея на 50% довша! все ще читає список із stdin, але тепер повертає набагато більш читабельний числовий вектор.

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

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

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

читається в списку з stdin. Негативний індекс 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
}

Я використовував "фантазійні" оператори unicode, а не еквіваленти 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, що він повертає "truthy" 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, а також неявність повернення та списки аргументів.


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 Whoops - я забув фактично сортувати масив. Це має працювати зараз.
Esolanging Fruit

1

05AB1E , 5 байт

{sWQè

Порт відповіді Python 2 @xnor 's .

Спробуйте його в Інтернеті або перевірити всі тестові випадки .

Пояснення:

{        # 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];}

Порт відповіді Python 2 @xnor 's .

Змінює вхідний масив замість повернення нового для збереження байтів.

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

Пояснення:

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

Порт відповіді Python 2 xnor. Потрібно ⎕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.