Ordenar las notas de escalada

33

Mi primer post de código de golf, disculpas por cualquier error ...

Contexto

En la escalada en roca ( específicamente en boulder ), los grados de escalada V / Vermin (EE. UU.) Comienzan en 'VB' (el grado más fácil) y luego pasan a 'V0', 'V0 +', 'V1', 'V2', 'V3' , 'V4', 'V5', etc. hasta 'V17' (el grado más difícil).

Tarea

Tomará como entrada una lista / conjunto de calificaciones de escalada y deberá devolver o imprimir una lista / conjunto de las calificaciones ordenadas de la más fácil a la más difícil.

Si la entrada está vacía, devuelve una estructura de datos vacía; de lo contrario, la entrada siempre será válida.

Casos de prueba

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']

Este es un desafío de .

Chris_Rands
fuente
La próxima vez, publique esto en el sandbox para obtener comentarios antes de publicarlo. En segundo lugar, ¿realmente debería responder a su propio desafío?
Ian H.
¿Aparecerán calificaciones duplicadas en la entrada?
Sr. Xcoder
@ Mr.Xcoder Sin duplicados
Chris_Rands
77
Bienvenido a PPCG! Bastante claro y agradable para una primera pregunta. (y)
officialaimm
3
Muy buena primera pregunta! Las respuestas a las que ha llevado son muy variadas y creativas. :)
Lynn

Respuestas:

23

Python 2 , 58 54 bytes

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

Pruébalo en línea!

Cómo funciona

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
Lynn
fuente
Parece que portar esto a ES6 no supera el enfoque de Arnauld: a=>a.sort((a,b,B10=0)=>(g=s=>eval(s.slice(1)+10))(a)>g(b))es de 58 bytes.
Lynn
1
a=>a.sort((a,b)=>(g=s=>eval(s.slice(B10=1)+10))(a)-g(b))es 2 bytes más corto, pero aún es demasiado largo.
Arnauld
@GB Creo que fue válido, pero ahora definitivamente es válido.
Lynn
¿Por qué usar '10' y no algo más corto? Por ejemplo, '2' guarda 2 bytes.
GB
1
@GB El truco es activar la traducción de la notación octal "010" a 8 como decimal para "V0". Con 2, obtendría "02" = 2, que es lo mismo que "0 + 2".
Arnauld
15

JavaScript (ES6) / Firefox, 53 bytes

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

Casos de prueba

Para Firefox:

Para Chrome o Edge (+4 bytes):

¿Cómo?

Aplicamos 3 transformaciones sucesivas que conducen a cadenas lexicográficamente comparables.

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
fuente
¿Se te ocurrió la idea de conversión / módulo base? ¡Brillante!
kamoroso94
1
@ kamoroso94 FWIW, aquí está el código que escribí para encontrar la base y el módulo. Da algunas otras respuestas posibles (con m <1000).
Arnauld
Probé a=>a.sort((a,b)=>(g=s=>parseInt(s,32)%334+s)(a)>g(b))en Chrome, no da la respuesta correcta, f(["VB","V0","V0+","V1","V2","V3","V4","V5","V6","V7","V8","V9","V10","V11","V12","V13","V14","V15","V16","V17"])no estoy seguro de por qué; La versión compatible con bordes funciona bien en Chrome.
Ra8
1
@ Ra8 Ah, sí. Parece ser inestable para Chrome también. Devolver un booleano de una devolución de llamada sort () es solo un truco que funciona en Firefox, pero se supone que debemos devolver un valor firmado. Gracias por sus comentarios!
Arnauld
12

Casco , 5 bytes

ÖiÖm±

Pruébalo en línea! Los resultados se imprimen uno por línea, pero internamente esta es una función que toma y devuelve una lista de cadenas.

Explicación

Esto es sorprendentemente similar a la respuesta de Martin Retina . Primero lo hacemos Öm±, lo que significa "orden por mapeo es dígito". Esto pone VB, V0y V0+en el orden correcto, ya que se comparan como [0,0], [0,1]y [0,1,0]. A continuación lo hacemos Öi, que significa "ordenar por valor entero". Dada una cadena, idevuelve la primera secuencia de dígitos que aparecen en ella como un entero, o 0 si no se encuentra uno. Las tres cadenas anteriores se asignan a 0 y el orden es estable, por lo que estarán en el orden correcto en la salida.

Zgarb
fuente
11

Retina , 14 bytes

B
!
O`
!
B
O#`

Pruébalo en línea!

Explicación

B
!

Reemplace Bcon !para que el orden lexicográfico de calificaciones ponga VB(o luego V!) delante de todas las calificaciones numéricas.

O`

Ordenar todas las líneas de entrada lexicográficamente. Esto no da el resultado correcto pero ordena V! < V0 < V0+correctamente.

!
B

Convertir de V!nuevo en VB.

O#`

Ordenar las líneas numéricamente. Retina simplemente busca el primer número decimal en una cadena para determinar su clave de clasificación. Si no hay un número (como for VB), establece el valor en 0. Es decir, todas VB, V0y V0+tienen la misma clave de ordenación. Pero el tipo de Retina es estable y ya los hemos puesto en el orden relativo correcto.

Martin Ender
fuente
6

V , 3 bytes

Úún

Pruébalo en línea!

¿Como funciona?

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

Este comando es casi una solución válida, ya que cada línea que no se puede ordenar por números (AKA, por sus VBsiglas en inglés) se colocará al principio, sin que se cambie el orden. Sin embargo, dado que solo está mirando números, no puede distinguir entre V0y V0+. Dado que Vim usa un tipo estable, lo que ocurra primero seguirá siendo el primero después de ordenarlo. Asi que...

Ú   # Sort lexicographically (will place 'V0' before 'V0+')
 ú  # Sort by...
  n #   The first number on the line
DJMcMayhem
fuente
2
Qué apropiado que V tenga éxito en este desafío: P
Business Cat
5

C #, 121 83 82 83 bytes

Guardado 39 bytes gracias a TheLethalCoder y LiefdeWen

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

Pruébalo en línea!

Bytecount incluye using System.Linq.


¿Cómo?

  • Obtiene una matriz de cadenas como entrada.
  • Si la entrada es igual a VB, establezca el valor en -1, si es igual a VB0+, establezca el valor en 0.
  • Ordene la entrada en función del valor numérico que viene después de V.

Puede ser un poco hack, ¡pero funciona! :)

Ian H.
fuente
94 bytes
LiefdeWen
@LiefdeWen No necesitas que el ToArray()an IOrderedEnumerableesté bien.
TheLethalCoder
Lo sentimos accidentalmente eliminado referencia System.Linq, fijo que
LiefdeWen
@TheLethalCoder Tienes razón como siempre, 84 bytes
LiefdeWen
@LiefdeWen .Remove(0,1)para -1 byte adicional :)
Ian H.
4

Ruby , 52 42 41 bytes

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

Pruébalo en línea!

Cómo funciona:

Cambie el problema, produzca la lista ordenada completa, luego obtenga la intersección con nuestra entrada.

Gracias Lynn por guardar 1 byte.

GB
fuente
¡Inteligente! ->x{[?B,0,"0+",*1..17].map{|a|"V#{a}"}&x}guarda un byte.
Lynn
2

Jalea , 9 bytes

Ḋv-.F+LµÞ

Un enlace monádico que toma una lista de listas de caracteres y devuelve la lista ordenada.

Pruébalo en línea! (el pie de página formatea bien el resultado)

¿Cómo?

Ḋ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, ...
Jonathan Allan
fuente
2

Comenzar aquí es mi solución de Python 3 ... Disculpas, publiqué esto demasiado pronto contra la convención, ahora vuelvo a publicar ...

Python 3 , 69 67 bytes

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

Pruébalo en línea!

Chris_Rands
fuente
55
Se desaconseja responder a su propio desafío de inmediato. Dé tiempo para que otras personas respondan, al menos 48 horas, probablemente más.
TheLethalCoder
@TheLethalCoder ¡Ah, claro, en Stack Overflow tal comportamiento es alentado! ¿Debo eliminar mi respuesta?
Chris_Rands
@Chris_Rands Sí, le sugiero que lo elimine.
Sr. Xcoder
9
@Downvoter: rechazar a un nuevo miembro por hacer algo que no sabían que estaba mal visto no está bien; mucho mejor simplemente señalar que no deberían, como lo hizo Lethal.
Shaggy
Tenga en cuenta que si alguien no publica su solución, puede hacerlo. Después de esperar, por supuesto
TheLethalCoder
1

Swift 3 , 102 bytes

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

Esta es una función. Puedes llamarlo así:

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

Pruébalo en línea!


¿Como funciona esto?

Esto es básicamente un puerto de la increíble respuesta Javascript de @Arnauld , pero optimizado para Swift.

Asigna cada uno de los valores a cadenas ordenables lexicográficamente como se muestra en la tabla a continuación:

Cadena inicial -> Resultado

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

Explicación del código

  • String((Int($0,radix:32) ?? 992)%334)- Convierte cada cadena de un número base-32 a decimal. En caso de que el valor sea "V0 +", la llamada a Int(_:radix:)devolverá nil, y tomamos el valor de "V0", 992. Además, tomamos el resultado de mod 334, y finalmente lo convertimos en String.

  • +$0- Agrega el valor actual a la cadena creada anteriormente. Por ejemplo, si la cadena es V9, la función anterior regresa 333y agregamos V9, lo que resulta en 333V9.

  • var r={...}- Declara una variable ra un cierre anónimo, porque ahorra muchos bytes ya que se usa dos veces.

  • func f(l:[String])- Define una función fcon un parámetro l, una lista de cadenas.

  • print(l.sorted(by:{r($0)<r($1)}))- Imprime el resultado de ordenar la lista dada, siendo la clave la variable rdefinida anteriormente.

Sr. Xcoder
fuente
1

Hojas de cálculo de Google, 142 bytes

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

La entrada es una cadena A1con cada entrada separada por una coma.
La salida es la celda de la fórmula más las n-1celdas debajo de ella, donde nestá el número de entradas A1.

Resultado

Es una fórmula larga y desordenada, así que desempaquételo.

  • If(A1="","",~)corrige la entrada nula. Sin esto, una entrada vacía devuelve un #VALUE!error porque la Splitfunción no funciona en entradas vacías.
  • Transpose(Split(A1,","))se divide A1en comas y se transpone en una columna porque elSort función solo funciona en columnas.
  • Transpose(IfError(Find(),Value()+9)) se rompe en estas piezas:
    • Find(Split(A1,","),"VBV0V0+")intenta encontrar cada parámetro en esa cadena. Estos tres primeros son los únicos que deben clasificarse como cadenas, por lo que utilizamosFind para obtener su orden de clasificación.
    • Value(Mid(Split(A1,","),2,3))+9Obtiene el valor numérico de la calificación. Esto solo importa para V1 y superior, por lo que se clasifican numéricamente bien. los+9 final es para asegurar que V1 viene después de V0 + ya que suFind valor sería 5. Técnicamente, entonces, solo +5se requiere, pero no me cuesta más bytes hacer un doble extra seguro de que se ordena correctamente.
    • IfError(Find(~),Value(~)) devuelve el Find valor si se encontró la cadena (es decir, la calificación es VB, V0 o V0 +). Si no se puede encontrar, devuelve el valor numérico de la calificación más nueve.
    • Transpose(IfError(~))nuevamente lo convierte en una columna para que Sortpueda usarlo.
  • Sort(Transpose(Split(~)),Transpose(IfError(Find(~),Value(~)+9)),1) concluye todo ordenando la entrada dividida usando el orden de clasificación personalizado ascendente.
  • ArrayFormula(~)envuelve todo para que devuelva los resultados como una matriz en lugar de simplemente devolver el primer valor en esa matriz. Esto es lo que hace que la fórmula en una celda también llene las celdas debajo de ella.
Tostadas de ingeniero
fuente
Creo que esta es la primera vez que he visto usar Google Sheets. Felicitaciones a ti, y +1!
heather
1

Haskell , 90 84 83 61 bytes

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

Pruébalo en línea!

fes una función que convierte los grados de escalada en cadenas que se pueden comparar. Si la conversión se convierte VBen la cadena vacía para obtener la máxima prioridad, se reemplaza V1con Xcadenas de tres largos para reducir la prioridad de V10- V17. Por el resto no hacemos nada.

Para ordenar la lista usamos Data.Listsla sortOnfunción (como lo sugiere Lynn) para crear una función sin puntos.

Asistente de trigo
fuente
Eso es justo g=sortOn f, que también está en Data.List.
Lynn
1
Además, f(_:'1':a)='X':aahorra 4 bytes!
Lynn
1
@Lynn La primera sugerencia funciona, sin embargo, la segunda no. Necesito [a]que coincida V1con el patrón, que es el problema que estoy tratando de eludir.
Wheat Wizard
1

R , 45 bytes

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

¿Como funciona esto?

  • Asigne el vector de grados correctamente ordenado a 'l';
    • Use 'paste0' en lugar de 'pegar' para evitar hacer un argumento 'sep = ""';
  • Indice 'l' basado en coincidencias de 'l' en su vector de entrada de calificaciones mixtas, sin clasificar.
Mendizale
fuente
0

Python2, 77 bytes

sorted(input(),key=lambda s:float(s[1:].replace("B","-1").replace("+",".5")))
Setop
fuente
¡Creo que esto cuenta como un fragmento! Porque no está imprimiendo el resultado ni esta es una definición de función. Sin embargo, puede convertirlo en una lambda o imprimir el resultado.
officialaimm
1
@officialaimm buen intento pero no funciona si V0 + s antes de V0.
Setop
0

TXR Lisp : 45 bytes

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

Correr:

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
fuente