Сортировка восхождений

33

Мой первый пост по гольфу, извиняюсь за любые ошибки ...

контекст

В скалолазании (в частности , в боулдеринге ) классы скалолазания V / Vermin (США) начинаются с «VB» (самый легкий класс), а затем переходят в «V0», «V0 +», «V1», «V2», «V3». , «V4», «V5» и т. Д. До «V17» (самая высокая оценка).

задача

В качестве входных данных вы возьмете список / массив оценок за восхождение, и вам нужно будет вернуть или распечатать список / массив оценок, отсортированных от самых простых до самых сложных.

Если вход пуст, вернуть пустую структуру данных; в противном случае ввод всегда будет действительным.

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

Input | Output
[] |  []
['V1'] |  ['V1']
['V7', 'V12', 'V1'] | ['V1', 'V7', 'V12']
['V13', 'V14', 'VB', 'V0'] |  ['VB', 'V0', 'V13', 'V14']
['V0+', 'V0', 'V16', 'V2', 'VB', 'V6'] | ['VB', 'V0', 'V0+', 'V2', 'V6', 'V16']

Это вызов .

Chris_Rands
источник
В следующий раз опубликуйте это в песочнице, чтобы получить обратную связь перед публикацией. Во-вторых, вы должны действительно ответить на свой собственный вызов?
Ян Х.
Будут ли повторные оценки появляться на входе?
Мистер Кскодер
@ Mr.Xcoder Нет дубликатов
Chris_Rands
7
Добро пожаловать в PPCG! Довольно ясно и приятно для первого вопроса. (у)
officialaimm
3
Очень хороший первый вопрос! Ответы, которые он привел, настолько разнообразны и креативны. :)
Линн

Ответы:

23

Python 2 , 58 54 байта

lambda x:sorted(x,key=lambda y,B10=0:eval(y[1:]+'10'))

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

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

y         y[1:]+'10'   eval(y[1:]+'10')
=======================================
VB        B10          0  (a variable we defined)
V0        010          8  (an octal literal)
V0+       0+10         10
V1        110          110
V2        210          210
...       ...          ...
V17       1710         1710
Линн
источник
Похоже, что перенос этого на ES6 не превосходит подход Арно, он a=>a.sort((a,b,B10=0)=>(g=s=>eval(s.slice(1)+10))(a)>g(b))составляет 58 байт.
Линн
1
a=>a.sort((a,b)=>(g=s=>eval(s.slice(B10=1)+10))(a)-g(b))на 2 байта короче, но это все еще слишком долго.
Арно
@ GB Я думаю, что это было действительно, но теперь это определенно верно.
Линн
Зачем использовать «10», а не что-то более короткое? Например, «2» сохраняет 2 байта.
GB
1
@GB Хитрость заключается в том, чтобы вызвать перевод из восьмеричной нотации "010" в 8 как десятичную для "V0". При 2 вы получите «02» = 2, что соответствует «0 + 2».
Арно
15

JavaScript (ES6) / Firefox, 53 байта

a=>a.sort((a,b)=>(g=s=>parseInt(s,32)%334+s)(a)>g(b))

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

Для Firefox:

Для Chrome или Edge (+4 байта):

Как?

Мы применяем 3 последовательных преобразования, которые приводят к лексикографически сопоставимым строкам.

s     | Base32 -> dec. | MOD 334 | +s
------+----------------+---------+---------
"VB"  |           1003 |       1 | "1VB"
"V0"  |            992 |     324 | "324V0"
"V0+" |            992 |     324 | "324V0+"
"V1"  |            993 |     325 | "325V1"
"V2"  |            994 |     326 | "326V2"
"V3"  |            995 |     327 | "327V3"
"V4"  |            996 |     328 | "328V4"
"V5"  |            997 |     329 | "329V5"
"V6"  |            998 |     330 | "330V6"
"V7"  |            999 |     331 | "331V7"
"V8"  |           1000 |     332 | "332V8"
"V9"  |           1001 |     333 | "333V9"
"V10" |          31776 |      46 | "46V10"
"V11" |          31777 |      47 | "47V11"
"V12" |          31778 |      48 | "48V12"
"V13" |          31779 |      49 | "49V13"
"V14" |          31780 |      50 | "50V14"
"V15" |          31781 |      51 | "51V15"
"V16" |          31782 |      52 | "52V16"
"V17" |          31783 |      53 | "53V17"
Arnauld
источник
Вы придумали идею базового преобразования / по модулю? Brilliant!
kamoroso94
1
@ kamoroso94 FWIW, вот код, который я написал, чтобы найти базу и модуль. Это дает некоторые другие возможные ответы (с m <1000).
Арно
Я попробовал a=>a.sort((a,b)=>(g=s=>parseInt(s,32)%334+s)(a)>g(b))Chrome, он не дает правильного ответа, f(["VB","V0","V0+","V1","V2","V3","V4","V5","V6","V7","V8","V9","V10","V11","V12","V13","V14","V15","V16","V17"])я не уверен, почему; совместимая с ребром версия отлично работает на Chrome.
Ra8
1
@ Ra8 Ах, да. Это выглядит нестабильно и для Chrome. Возвращение логического значения из обратного вызова sort () - это всего лишь хак, который работает в Firefox, но мы действительно должны вернуть значение со знаком. Спасибо за ваш отзыв!
Арно
12

Шелуха , 5 байт

ÖiÖm±

Попробуйте онлайн! Результаты печатаются по одному на строку, но внутри это функция, которая принимает и возвращает список строк.

объяснение

Это удивительно похоже на ответ Retina Мартина . Сначала мы делаем Öm±, что означает «порядок путем сопоставления цифр». Это ставит VB, V0и V0+в правильном порядке, так как они сравниваются как [0,0], [0,1]и [0,1,0]. Далее мы делаем Öi, что означает «порядок по целому числу». Для iданной строки возвращает первую последовательность цифр, встречающихся в ней, как целое число, или 0, если она не найдена. Все три строки выше сопоставлены с 0, и сортировка стабильна, поэтому они будут в правильном порядке в выводе.

Zgarb
источник
11

Сетчатка , 14 байт

B
!
O`
!
B
O#`

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

объяснение

B
!

Замените Bна !так, чтобы лексикографический порядок оценок ставил VB(или затем V!) перед всеми числовыми оценками.

O`

Сортировать все входные строки лексикографически. Это не дает правильного результата, но все V! < V0 < V0+правильно.

!
B

Превратите V!обратно в VB.

O#`

Сортировка строк по численности. Retina просто ищет первое десятичное число в строке, чтобы определить ключ сортировки. Если число отсутствует (например, для VB), устанавливается значение 0. Это означает , что все из VB, V0и V0+имеют один и тот же ключ сортировки. Но сортировка Retina стабильна, и мы уже расположили их в правильном относительном порядке.

Мартин Эндер
источник
6

V , 3 байта

Úún

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

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

ú   # Sort on...
 n  #   the first decimal number on the line

Эта команда является почти верным решением, поскольку каждая строка, которая не может быть отсортирована по номерам (AKA, VB), будет размещена в начале, без изменения порядка. Однако, поскольку он смотрит только на числа, он не может различить V0и V0+. Поскольку Vim использует стабильную сортировку, то, какая из них будет первой, останется первой после сортировки. Так...

Ú   # Sort lexicographically (will place 'V0' before 'V0+')
 ú  # Sort by...
  n #   The first number on the line
DJMcMayhem
источник
2
Насколько уместно, что V
Business Cat
5

C #, 121 83 82 83 байта

Сохранено 39 байт благодаря TheLethalCoder и LiefdeWen

a=>a.OrderBy(x=>x[1]>65?-1:x=="V0+"?0.5:int.Parse(x.Remove(0,1)))

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

Bytecount включает в себя using System.Linq.


Как?

  • Получает массив строк в качестве входных данных.
  • Если вход равен VB, установите значение -1, если он равен VB0+, установите значение 0.
  • Порядок ввода зависит от числового значения, которое следует после V.

Может быть немного взломать, но это работает! :)

Ян Х.
источник
94 байта
LiefdeWen
@LiefdeWen Вам не нужен должно быть хорошо. ToArray()IOrderedEnumerable
TheLethalCoder
Извините, случайно удалил ссылку на System.Linq, исправил ее
LiefdeWen
@TheLethalCoder Вы правы как всегда, 84 байта
LiefdeWen
@LiefdeWen .Remove(0,1)для дополнительного -1 байта :)
Ян Х.
4

Рубин , 52 42 41 байт

->x{[?B,0,"0+",*1..17].map{|a|"V#{a}"}&x}

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

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

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

Спасибо Линн за сохранение 1 байта.

гигабайт
источник
Умная! ->x{[?B,0,"0+",*1..17].map{|a|"V#{a}"}&x}сохраняет байт.
Линн
2

Желе , 9 байт

Ḋv-.F+LµÞ

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

Попробуйте онлайн! (нижний колонтитул форматирует результат красиво)

Как?

Ḋv-.F+LµÞ - Link: list of lists of characters
       µÞ - sort by key:
Ḋ         -   dequeue (remove the 'V' from the item)
  -.      -   literal -0.5
 v        -   evaluate as Jelly code with argument -0.5
          -   ...this means `VB` and `V0+` become -0.5
          -      (to binary and addition respectively)
          -      while others become their literal numbers
    F     -   flatten
     +L   -   add the length of the item
          -   ...'VB', 'V0', 'V0+', 'V1', 'V2'... -> 1.5, 2, 2.5, 3, 4, ...
Джонатан Аллан
источник
2

Чтобы начать, вот мое решение Python 3 ... Извинения, опубликовал это слишком рано против соглашения, теперь переиздаю ...

Python 3 , 69 67 байт

lambda l:sorted(l,key=lambda x:'B00+'.find(x[1:])+1or int(x[1:])+3)

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

Chris_Rands
источник
5
Не рекомендуется отвечать на ваш собственный вызов немедленно. Дайте время другим людям ответить, по крайней мере, 48 часов, возможно, дольше.
TheLethalCoder
@TheLethalCoder Ах да, на переполнении стека такое поведение приветствуется! Должен ли я удалить свой ответ?
Chris_Rands
@Chris_Rands Да, я предлагаю вам удалить его.
Мистер Кскодер
9
@ Downvoter: поношение нового участника за то, что он сделал что-то, чего они не знали, было не одобрено; гораздо лучше просто указать, что они не должны, как это сделал Летал.
Лохматый
Обратите внимание, что если кто-то не публикует ваше решение, вы можете это сделать. После ожидания конечно
TheLethalCoder
1

Swift 3 , 102 байта

var r={String((Int($0,radix:32) ?? 992)%334)+$0};func f(l:[String]){print(l.sorted(by:{r($0)<r($1)}))}

Это функция. Вы можете назвать это так:

f(l:["V0","VB","V13","V0+"])

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


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

Это в основном порт удивительного ответа Javascript от @Arnauld , но оптимизированный для Swift.

Он отображает каждое из значений в лексикографически упорядочиваемые строки, как показано в таблице ниже:

Начальная строка -> Результат

V1 -> 325V1
V10 -> 46V10
V11 -> 47V11
V12 -> 48V12
V13 -> 49V13
V14 -> 50V14
V15 -> 51V15
V16 -> 52V16
V17 -> 53V17
V2 -> 326V2
V3 -> 327V3
V4 -> 328V4
V5 -> 329V5
V6 -> 330V6
V7 -> 331V7
V8 -> 332V8
V9 -> 333V9
V0 + -> 324V0 +
V0 -> 324V0
VB -> 1VB

Код Объяснение

  • String((Int($0,radix:32) ?? 992)%334)- Конвертирует каждую строку из числа 32 в десятичное. В случае, если значением является «V0 +», вызов Int(_:radix:)возвратит nil, и мы берем значение «V0», 992. Мы дополнительно берем результат mod 334и, наконец, преобразуем его в String.

  • +$0- Добавляет текущее значение в строку, созданную выше. Например, если String равен V9, функция выше возвращает, 333и мы добавляем V9, что приводит к 333V9.

  • var r={...}- Объявляет переменную rанонимному закрытию, потому что она экономит много байтов, так как используется дважды.

  • func f(l:[String])- Определяет функцию fс параметром l, список строк.

  • print(l.sorted(by:{r($0)<r($1)}))- Печатает результат сортировки заданного списка, ключом которого является переменная, rопределенная выше.

Мистер Xcoder
источник
1

PowerShell , 45 байт

param($a)'B',0,'0+'+1..17|%{"V$_"}|?{$_-in$a}

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

Использует тот же процесс, что и Ruby-ответ GB, для построения полного списка аргументов в отсортированном порядке, а затем выбирает те, которые являются -inвходным списком.

AdmBorkBork
источник
1

Google Sheets, 142 байта

=ArrayFormula(If(A1="","",Sort(Transpose(Split(A1,",")),Transpose(IfError(Find(Split(A1,","),"VBV0V0+"),Value(Mid(Split(A1,","),2,3))+9)),1)))

Ввод - это строка A1с каждой записью, разделенной запятой.
Выход - это ячейка формулы плюс n-1ячейки под ней, где nнаходится количество записей в A1.

Результат

Это длинная, грязная формула, так что давайте распакуем ее.

  • If(A1="","",~)исправляет нулевой ввод. Без этого пустой вход возвращает #VALUE!ошибку, потому что Splitфункция не работает с пустыми входами.
  • Transpose(Split(A1,","))разделяет A1запятые и переносит их в столбец, потому что Sortфункция работает только со столбцами.
  • Transpose(IfError(Find(),Value()+9)) Это разбивается на эти части:
    • Find(Split(A1,","),"VBV0V0+")пытается найти каждый параметр в этой строке. Эти первые три являются единственными, которые должны быть отсортированы как строки, поэтому мы используем, Findчтобы получить их порядок сортировки.
    • Value(Mid(Split(A1,","),2,3))+9получает числовое значение оценки. Это имеет значение только для V1 и выше, поэтому они численно сортируются просто отлично. В +9конце должен убедиться, что V1 идет после V0 +, так как его Findзначение будет 5. Технически, тогда, только +5требуется, но мне не нужно больше байтов, чтобы убедиться, что он дважды сортирует правильно.
    • IfError(Find(~),Value(~))возвращает Findзначение, если строка была найдена (т. е. оценка равна VB, V0 или V0 +). Если это не может быть найдено, он возвращает числовое значение оценки плюс девять.
    • Transpose(IfError(~))снова превращает его в столбец, чтобы Sortможно было его использовать.
  • Sort(Transpose(Split(~)),Transpose(IfError(Find(~),Value(~)+9)),1) оборачивает все это, сортируя входные данные разделения, используя пользовательский порядок сортировки по возрастанию.
  • ArrayFormula(~)оборачивает всю вещь так, чтобы она возвращала результаты в виде массива, а не просто возвращала первое значение в этом массиве. Это то, что заставляет формулу в одной ячейке заполнять ячейки под ней.
Инженер Тост
источник
Я думаю, что это первый раз, когда я использую Google Sheets. Слава вам, и +1!
вереск
1

Haskell , 90 84 83 61 байт

import Data.List
f"VB"=[]
f(_:'1':[a])='X':[a]
f x=x
sortOn f

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

fэто функция, которая преобразует уровни лазания в строки, которые можно сравнить. Если новообращенные VBбыть пустая строка поэтому он получает наивысший приоритет, тогда заменяет V1с Xв строках, которые три длинные , чтобы понизить приоритет V10- V17. В остальном мы ничего не делаем.

Для сортировки списка мы используем Data.Lists«s sortOnфункции (как это было предложено Lynn) , чтобы создать функцию точечную бесплатно.

Мастер пшеницы
источник
Это просто g=sortOn f, что также в Data.List.
Линн
1
Также f(_:'1':a)='X':aэкономит 4 байта!
Линн
1
@Lynn Первое предложение работает, а второе - нет, мне нужно, [a]иначе V1будет сопоставление с шаблоном, и это проблема, которую я пытаюсь обойти.
Пшеничный волшебник
1

R , 45 байт

l=paste0('V',c('B','0','0+',1:17));l[l%in%x]

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

  • Присвойте правильно упорядоченный вектор оценок «l»;
    • Используйте 'paste0' вместо 'paste', чтобы избежать создания аргумента 'sep = "";
  • Индекс 'l' на основе совпадений 'l' во входном векторе смешанных, несортированных оценок.
Mendizale
источник
0

Python2, 77 байт

sorted(input(),key=lambda s:float(s[1:].replace("B","-1").replace("+",".5")))
Setop
источник
Я думаю, что это считается фрагментом! Потому что вы не печатаете ни результат, ни определение функции. Вы можете превратить его в лямбду или распечатать результат.
officialaimm
1
@officialaimm хорошая попытка, но не работает, если V0 + s до V0.
Setop
0

TXR Lisp : 45 байт

(op sort @1 :(ret`@(mod(toint @1 32)334)@1`))

Бег:

1> (op sort @1 :(ret`@(mod(toint @1 32)334)@1`))
#<interpreted fun: lambda (#:arg-01-0168 . #:rest-0167)>
2> [*1 ()]
nil
3> [*1 (list "V0+" "V0" "V16" "V2" "VB" "V6")]
("VB" "V0" "V0+" "V2" "V6" "V16")
Kaz
источник