Títulos amigables con URL


28

Las personas en este sitio realmente adoran embellecer sus títulos de publicaciones ...

Stewie's sequence: + * - / + * - /

Sin embargo, cuando este título debe incluirse en la URL de la página, se simplifica:

stewies-sequence

El reto

Su tarea es crear un programa o función que, dada una cadena que representa el título de una publicación, genera / devuelve su conversión "URL-Friendly".

El algoritmo es:

  • Convertir a minúsculas (cuando corresponda)
  • Reemplace cada espacio ( ), punto ( .), coma ( ,) o barra diagonal ( /) con un guión ( -)
  • Elimine los caracteres no alfanuméricos, excepto los guiones.
  • Minifique grupos de guiones adyacentes ( a---b -> a-b), elimine los que están al principio / al final

Tenga en cuenta que este algoritmo es una simplificación y que no siempre produce los mismos resultados que el método real del sitio.


Reglas

  • Puede suponer esa entrada:
    • No estará vacío.
    • Contendrá al menos un carácter alfanumérico.
    • Solo contendrá caracteres en el rango ASCII 32-126 (imprimible)
  • Se permiten programas o funciones completos.
  • No se permite una construcción que haga la especificación exacta de la tarea .
  • Este es el , por lo que gana la solución más corta (en bytes).

Casos de prueba

La mayoría de las publicaciones en este sitio servirán como pruebas, pero aquí hay una lista útil:

Loading... Forever       -> loading-forever
N(e(s(t))) a string      -> nest-a-string
"Hello, World!"          -> hello-world
URL-Friendly titles      -> url-friendly-titles

C.U.S.R.S                -> c-u-s-r-s
1+2+3+4+...+n = -1/12?   -> 1234-n-1-12
How can I use cmp(a,b)   -> how-can-i-use-cmpa-b

Algunos más largos ...

Export The $PATH Variable, Line-By-Line   -> export-the-path-variable-line-by-line
Do n and n^3 have the same set of digits? -> do-n-and-n3-have-the-same-set-of-digits
Quine Anagrams! (Cops' Thread)            -> quine-anagrams-cops-thread
The Golfer Adventure - Chapter 1          -> the-golfer-adventure-chapter-1
Bootloader golf: Brainf***                -> bootloader-golf-brainf

Y algunas muestras de verificación de casos extremos (siéntase libre de sugerir más):

0123   ->   0123
a a1   ->   a-a1
2-1=1  ->   2-11

¿Qué pasa con los -s principales ? ¿Tendrán que ser removidos? Por ejemplo asdf-, ¿se -tendrá que eliminar el último ?
Kritixi Lithos

¿Podemos usar una función incorporada para verificar si el carácter es alfanumérico como esteif(isalphanum(ch))...
Mukul Kumar

1
@KritixiLithos Minifique grupos de guiones adyacentes (a --- b -> ab), elimine los que están al principio / al final. Supongo que esto debería aclararte.
Mukul Kumar

¿Y qué hay de los _guiones bajos? Mi código funciona excepto cuando hay guiones bajos.
Kritixi Lithos

@ L3viathan No importa ahora, cambié mi código para que incluso se eliminen los guiones bajos
Kritixi Lithos

Respuestas:


7

Retina, 33 31 bytes

T`L`l
[^a-z ,-9]+

\W+
-
^-|-$

(El programa tiene una nueva línea final)

No estoy seguro de poder sacar más provecho de esto. Esto debería cubrir todo. Vino similar a Mama Fun Roll's. Otra versión de 33 bytes que usa expresiones regulares recursivas

Pruébalo en línea!

Explicación

T`L`l

Esta línea es simple, se convierte a minúsculas mediante T ransliterating A-Z( L) a a-z( l, minúsculas).


Esta etapa es simple, esencialmente elimina todos los caracteres innecesarios para evitarnos muchos problemas más adelante.

[^a-z ,-9]+

[^a-z ,-9] Coincide con cualquier personaje que NO sea:

  • a-z: alfabeto en minúsculas (recuerde que la cadena completa está en minúsculas debido al elemento anterior)
  • : carácter espacial
  • ,-9este es el código de caracter gama de ,a 9que resulta ser ,-./0123456789, exactamente los caracteres que necesitamos

A continuación, convertimos todos los caracteres no alfanuméricos en guiones (que ahora es justo y ,./-.

\W+
-

Esto no coincidirá (no) lo _que se incluye en \w(negación de \W) porque se eliminó en la etapa anterior


Creo que esto fallará para entradas como a = b.
Martin Ender

Realmente quiero aceptar esto, pero como dijo Martin, no minimiza los guiones adyacentes cuando a = b
ingresas

@ Flp.Tkc perdón por la respuesta tardía (Semana de la final ahora mismo) Me las arreglé para exprimir dos bytes más y arreglarlo. Creo que esto maneja correctamente estos casos ahora
Downgoat

9

JavaScript (ES6), 90 82 79 75 bytes

Este es un intento de hacer el trabajo con una sola replace(). Este código extrae solo los caracteres que nos interesan e ignora todo lo demás. Hay alguna lógica adicional para procesar los guiones.

s=>(s.toLowerCase().replace(/[ a-z,-9]/g,c=>S=c<'0'?s+'-':s=s?S+c:c,s=0),s)

Casos de prueba


1
Para ,a^a,, este código da -aa-(hay guiones
iniciales

@KritixiLithos Oh, gracias por señalar esto. No presté atención a esa regla. Eso debería ser arreglado.
Arnauld

9

V , 41, 40, 37 , 36 bytes

VuÍ[ .,\/]/-
Í0-9a-z­]
Í-«/-
Í^-ü-$

Pruébalo en línea! o ¡ Verifique todos los casos de prueba a la vez!

Como de costumbre, aquí contiene un montón de caracteres no imprimibles y no ASCII, así que aquí hay un hexdump:

0000000: 5675 cd5b 202e 2c5c 2f5d 2f2d 0acd 8430  Vu.[ .,\/]/-...0
0000010: 2d39 612d 7aad 5d0a cd2d ab2f 2d0a cd5e  -9a-z.]..-./-..^
0000020: 2dfc 2d24                                -.-$

En estos desafíos, el sistema de "Regex comprimido" de V es útil.

Explicación

Primero lo primero, convertiremos todo a minúsculas. Afortunadamente, hay una forma realmente conveniente de hacer esto en dos bytes. Escribí un consejo sobre eso aquí . Entonces hacemos

V           " Visually select this whole line
 u          " Convert this whole line to lowercase

Después de eso, hacemos un montón de comandos sustitutos comprimidos. Una buena descripción de cómo funciona la expresión regular comprimida de V puede ser confusa aquí , pero la idea básica es que podemos establecer el bit alto para evitar tener que escapar de ciertos caracteres. Otra conveniencia es que los rangos (me gusta :%) y las banderas (me gusta /g) se completan automáticamente. Pero al final, todo se traduce en comandos sustitutos vim. De hecho, incluso podríamos traducir directamente el resto del programa a vim. Eso nos daría esto:

:%s/[ .,/]/-/g
:%s/[^0-9a-z\-]//g
:%s/-\+/-
:%s/^-\|-$//g

Si hablas vim-regex, debería quedar más claro lo que hace el resto del programa ahora. Así que aquí está el resto del programa:

Í               " Substitute:
 [ .,\/]        "   a space, period, comma or forward slash. (Due to a strange bug, this needs to be escaped)
        /-      "   with a dash
Í               " Remove:
 [^0-9a-z­]     "   Any character that is not a dash or alpha-numeric
Í               " Substitute:
 -«             "   One or more dashes
   /-           "   with one dash
Í               " Remove:
 ^-             "   A dash at the beginning of a line
   ü            "   OR
    -$          "   a dash at the end of a line

8

JavaScript (ES6) 91 96

1 bytes guardados thx @ETHproductions

s=>s.toLowerCase().replace(/([ .,/-])|\W|_/g,(c,d)=>d?'-':'').replace(/^-*|-*$|-(?=-)/g,'')

Prueba

F=
s=>s.toLowerCase().replace(/([ .,/-])|\W|_/g,(c,d)=>d?'-':'').replace(/^-*|-*$|-(?=-)/g,'')

;[['Loading... Forever.....', 'loading-forever'],
['N(e(s(t))) a string', 'nest-a-string'],
['"Hello, World!"', 'hello-world'],
['URL-Friendly titles', 'url-friendly-titles'],
['C.U.S.R.S','c-u-s-r-s'],
['1+2+3+4+...+n = -1/12?', '1234-n-1-12'],
['How can I use cmp(a,b)', 'how-can-i-use-cmpa-b'],
['Export The $PATH Variable, Line-By-Line', 'export-the-path-variable-line-by-line'],
['Do n and n^3 have the same set of digits?', 'do-n-and-n3-have-the-same-set-of-digits'],
['Quine Anagrams! (Cops\' Thread)', 'quine-anagrams-cops-thread'],
['The Golfer Adventure - Chapter 1', 'the-golfer-adventure-chapter-1'],
['Bootloader golf: Brainf***', 'bootloader-golf-brainf'],
['0123', '0123'],
['a a1', 'a-a1'],
['2-1=1', '2-11']]
.forEach(t=>{
  var i=t[0],k=t[1],r=F(i)
  console.log(r==k?'OK':'KO',i+' -> '+r,r==k?'':k)
})


Esto tiene exactamente el mismo bytecount que mi respuesta si se convierte en una función con nombre
Kritixi Lithos

No creo que necesites lo último *en la última expresión regular, aunque puedo estar equivocado
ETHproductions

Puedo estar equivocado, pero ¿estás seguro de que la búsqueda anticipada es necesaria?
Kritixi Lithos

@KritixiLithos la búsqueda anticipada es necesaria para mantener al menos 1 - dentro de la cadena, mientras se elimina todo al inicio y al final
edc65

@ETHproductions bien, gracias
edc65

4

Python 3, 103 100 96 95 bytes

5 bytes guardados gracias a Flp.Tkc

import re
lambda s,y=re.sub,d='-':y('-+',d,y('[^0-9a-z-]','',y('[ .,/]',d,s.lower()))).strip(d)

@ Flp.Tkc Indeed ..
L3viathan

Vaya, accidentalmente rechacé esto. No puedo revertir mi voto hasta que edite esta publicación
Kritixi Lithos

@KritixiLithos Hecho
L3viathan


3

MATL , 38 bytes

'-'jyvk45y' .,/'m(t8Y245hm)'-*'45YX6L)

Pruébalo en línea! O verificar todos los casos de prueba .

Explicación

'-'jyv       % Take input line. Append and prepend a dash. Gives a char column vector
k            % Convert to lowercase
45y' .,/'m(  % Replace any of ' .,/' by a dash, using assignment indexing
t8Y245hm)    % Keep only alphanumeric chars or dashes, using reference indexing
'-*'45YX     % Replace each run of dashes by a single dash, using a regular expression
6L)          % Remove first and last chars, which are always dashes. Implicitly display

3

Ruby , 61 60 61 64 53 bytes

(52 bytes de código más un byte para el -p)

$_=$_.tr("A-Z ,-/","a-z ").gsub(/[^\w ]/){}.split*?-

Pruébalo en línea!

tr()- convierte caracteres en mayúscula, espacio, coma, punto y barra diagonal. Sustituya temporalmente el -espacio en blanco para que pueda usarlo stripmás adelante.
Tenga -en cuenta que el carácter en la "A-Z ,-/"expresión es en realidad un operador de rango, que también hace que el .carácter esté sujeto a transformación. Esta maniobra en realidad no reducirá los bytes, pero es elegante, por lo que puede quedarse.

gsub(/[^\w ]/){} - eliminar todos los caracteres que no están en el conjunto permitido.

split- técnicamente, no necesitamos exactamente esa matriz, pero splitelimina los espacios en blanco iniciales y finales (que en realidad son -caracteres disfrazados). Como beneficio adicional, esto comprime juntas carreras de múltiples espacios.

*?-- Taquigrafía para .join("-"); Esto invierte tanto la splitoperación anterior como la transformación de espacios en blanco al mismo tiempo. Un byte más se guarda usando la notación abreviada para literales de caracteres , lo que hace que el programa requiera Ruby 1.9 o más reciente.

Actualización 1: Usar en getslugar del modo de edición de flujo de Ruby ahorra un byte.
Revertido según la sugerencia de ValueInk .

Actualización 2: (+3 bytes en general)

  • Caso de borde fijo ..--hi, $/(→ hi) (+10 bytes) : una vez más, cortesía del usuario ValueInk
  • Tomó malus por -p (+1 byte)
  • Eliminé squeezey usé en su gsublugar (+2 bytes) , lo que me permitió:
  • Utilícelo strippara manejar los guiones iniciales y finales (-10 bytes) .

Actualización 3: Hattrick por ValueInk. Ahorramos 11 bytes al aprovechar String#splitel hábito de apretar automáticamente las corridas del mismo separador, lo que nos permite deshacernos de la cadena strip/ final completa gsuby reemplazarla por un split/ joincombo. (-11 bytes)


Esto solo devuelve la cadena en un entorno REPL y falla si se ejecuta como un programa Ruby adecuado, y eso no es bueno. Programas completos o funciones / solo lambdas. De hecho, su versión anterior habría funcionado con la -pbandera, pero esto definitivamente no lo hará.
Value Ink

@ValueInk Por supuesto, tienes razón. He cambiado mi solución en consecuencia. Gracias por tu comentario; es exactamente el tipo de orientación que aprecio mucho, ya que este es mi primer intento de jugar al golf.
Synoli

1
Gracias por hacer la corrección; He eliminado mi voto negativo. Una cosa a tener en cuenta es que el uso del -pindicador agrega implícitamente 1 byte a su código (porque cambia la ejecución de su código de ruby -e 'your code'a ruby -pe 'your code'). También he encontrado un caso de borde donde da -hi-información como ..--hi, $/cuando debería eliminar todos los guiones iniciales / finales y, por lo tanto, regresar hi.
Value Ink

2
-2 bytes cambiando gsub(/[^\w ]/){}a tr('^a-z ',''), y luego termina con en .split*?-lugar de .strip.gsub...ya que maneja automáticamente los duplicados y los extremos de la cadena, ¡todo de una vez!
Value Ink

1
Como nadie lo dijo, ¡bienvenido a code-golf!
FlipTack

3

JavaScript (ES6), 74 69 bytes

f=
s=>s.toLowerCase().replace(/[^-/,. a-z\d]/g,``).match(/\w+/g).join`-`
<input oninput=o.textContent=/[a-z\d]/i.test(this.value)?f(this.value):``><pre id=o>

Editar: ahorré 5 bytes al darme cuenta de que ya había eliminado todos los caracteres, excepto -/,. 0-9a-zque puedo usar \wpara unir las palabras restantes.


Creo que debe incluir el código HTML en el bytecount ya que se está utilizando para resolver el desafío
Kritixi Lithos

1
@KritixiLithos No, solo está allí para fines de demostración. La pregunta dice que mi código puede asumir al menos un carácter alfanumérico, y el código HTML simplemente prueba esto antes de llamar a la función.
Neil

[a-z\d]podría ser [^\W_]?
edc65

@ edc65 Bien, pero luego me di cuenta de que podría ser aún más simple.
Neil

2

PHP, 87 bytes

La idea de las expresiones regulares proviene de respuestas existentes.

<?=trim(preg_replace(['@[^ a-z,-9]@','@[ ,-/]+@'],['','-'],strtolower($_GET[T])),'-');

Requiere que tenga un servidor que ejecute PHP y que acceda a través de HTTP.

El título debe estar en la tecla Ty el resultado se imprimirá en la pantalla.

Ejemplo: http://localhost/title.php?T=<my shiny title>


2

herramientas bash / Unix, 56 bytes

tr A-Z\ .,/ a-z-|tr -cds a-z0-9- -|sed s/^-//|sed s/-$//

Reemplace las mayúsculas con minúsculas y los caracteres especiales requeridos con guiones.

Elimine (opción -d para tr) caracteres que no sean letras, dígitos y guiones, y luego exprima (opción -s para tr) guiones múltiples en una fila en un solo guión.

Eliminar guiones al principio, y luego al final.


2

Powershell, 85 bytes

($args[0].ToLower()-replace'[ .,/]','-'-replace'[^a-z,-9]'-replace'-+','-').Trim('-')

lo convierten en minúsculas, a continuación, 3 reemplaza expresiones regulares en una fila, y recortar cualquier arrastran -'s


podría no $inputahorrarte 2 bytes?
briantist

2

JavaScript, 90 98 94 93 91 90 91 bytes

¡1 byte guardado gracias a @ edc65!

¡1 byte guardado gracias a @IsmaelMiguel por detectar un punto y coma líder!

1 byte obtenido después de fallar ,a-^-a,

f=s=>s.toLowerCase().replace(/[^ a-z,-9]/g,"").replace(/[ ,-/]+/g,"-").replace(/^-|-$/g,"")

Lo que más me gusta de esta presentación en particular son los rangos. En la primera replace, se elimina todo lo que no es alfanumérico y no una ,, -, ., /y no un espacio. ¡Usamos a-zpara detectar las letras, y usamos ,-9para detectar esos caracteres y números especiales ya que los códigos de caracteres de estos literales ASCII se alinean!

, = 44
- = 45
. = 46
/ = 47
0 = 48
...
9 = 57


No elimina los guiones iniciales: "-1" se convierte en "-1", cuando debería convertirse en "1".
L3viathan

@ L3viathan debería funcionar ahora
Kritixi Lithos

No es necesario contar, f=por lo que su recuento de bytes es 96 en este momento. Y no hay necesidad de \ dentro de un rango en la expresión regular, por lo que podría ser 95. Pero ... todavía no funciona: intente...title
edc65

1
Hei No soy ese viejo! (65 no 64)
edc65

1
Creo que no necesitas el f=y el ;al final. Solo especifique que esta es una función anónima. Con esto, su respuesta debe tener 90 bytes de longitud.
Ismael Miguel

1

Lua, 91 bytes

a=a:lower():gsub( '[ .,/]', '-' ):gsub( '[^%w-]', '' ):gsub( '%-+', '-' ):match'%-?(.*)%-?'

¿Dónde aestá la cadena de URL?

Explicación:

  • La mayor parte es bastante sencillo. a:lower()devuelve la función en minúsculas
  • :gsub encuentra la coincidencia del patrón y lo reemplaza con la cadena.
  • '[ .,/]': Los corchetes significan "o", por lo que esto coincide con el espacio, punto, coma y barra diagonal. No es necesario ser codicioso porque :gsubtodas las ocurrencias.
  • '[^%w-]': ^significa "no" cuando está entre paréntesis, %wsignifica cualquier cosa alfanumérica. Entonces '[^%w-]coincide con cualquier cosa que no sea alfanumérica o un guión.
  • '%-+': Combina tantos guiones como puedas y reemplázalos con un solo guión.
  • match'%-?(.*)%-?': En Lua, si una cadena es el único argumento de la función, no se necesitan paréntesis. Solo necesita verificar un guión al inicio y al final porque los guiones ya se han minimizado. No hay necesidad de personajes de anclaje porque .*es coincidir con todo, codicioso.

1

C, 194 bytes

i,j;f(char*s,char*d){if(*s>47&*s<58|*s>96&*s<123)d[i++]=*s;if(*s>64&*s<91)d[i++]=*s+32;if(i-j&&*s>43&*s<48|*s==32&&*(s+1)&&*(s+1)>47|(*(s+1)<44&&*(s+1)^32)){d[i++]=45;j=i;}*++s?f(s,d):(d[i]=0);}

Llamar con:

int main()
{
    char *in="Loading... Forever";
    char out[128];
    f(in,out);
    puts(out);
}

1

SAS, 108

Una de las respuestas menos competitivas aquí debido a la sintaxis detallada de SAS (la penalización de 9 caracteres por expresión regular realmente duele), pero fue un buen ejercicio de aprendizaje de expresiones regulares:

t=prxchange('s/^-|-$//',-1,prxchange('s/-+/-/',-1,compress(translate(lowcase(t),'----',' .,/'),'-','adk')));

1

Pyth, 35 bytes

:r::rQ0"[-.,/]"d"[^\w ]"k6"[ -]+"\-

Explicación

    rQ0                              Convert letters to lower case
   :   "[-.,/]"d                     Replace all -.,/ with spaces
  :             "[^\w ]"k            Remove all remaining symbols
 r                       6           Remove leading and trailing spaces
:                         "[ -]+"\-  Turn runs of spaces and dashes to one dash

1

Perl 6, 75

{lc .subst(/<[\ .,/]>/,"-"):g.subst(/<[\W]-[\-]>/,""):g.subst(/\-+/,"-"):g}

0

GNU Sed, 65 bytes

s/.*/\L\0/
s@[ .,/]@-@g
s/[^-a-z0-9]//g
s/-\+/-/g
s/^-\|-$//g

Una serie de sustituciones de expresiones regulares. Utiliza no portátil \Lde GNU sed para poner en minúscula la entrada. Ejecutar desde un archivo usando sed -f.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.