Títulos compatíveis com URL


28

As pessoas deste site adoram embelezar seus títulos de postagem ...

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

No entanto, quando esse título precisa ser incluído no URL da página, ele é simplificado:

stewies-sequence

O desafio

Sua tarefa é criar um programa ou função que, dada uma sequência que representa o título da postagem, produz / retorne sua conversão "compatível com URL".

O algoritmo é:

  • Converter em minúsculas (onde aplicável)
  • Substitua todos os espaços ( ), ponto ( .), vírgula ( ,) ou barra ( /) por um traço ( -)
  • Remova todos os caracteres não alfanuméricos, exceto os traços.
  • Minimize os grupos de traços adjacentes ( a---b -> a-b), remova os que estão à frente / à direita.

Observe que esse algoritmo é uma simplificação e nem sempre pode produzir os mesmos resultados que o método real do site.


Regras

  • Você pode assumir essa entrada:
    • Não ficará vazio.
    • Irá conter pelo menos um caractere alfanumérico.
    • Contém apenas caracteres no intervalo ASCII 32-126 (imprimível)
  • Programas ou funções completos são permitidos.
  • Um built-in que faça a especificação exata da tarefa não é permitido.
  • Isso é , então a solução mais curta (em bytes) vence!

Casos de teste

A maioria das postagens neste site servirá como testes, mas aqui está uma 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

Alguns mais longos ...

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

E algumas amostras de verificação de casos extremos (sinta-se à vontade para sugerir mais):

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

E quanto a liderar -s? Eles terão que ser removidos? Por exemplo asdf-, em , o último -terá que ser removido?
Kritixi Lithos

Podemos usar um built-in função para verificar se o char é alfanumérico como estaif(isalphanum(ch))...
Mukul Kumar

1
@KritixiLithos Minimize os grupos de traços adjacentes (a --- b -> ab), remova qualquer um que esteja à frente / à direita. Eu acho que isso deve deixar você claro.
Mukul Kumar

E quanto aos _sublinhados? Meu código funciona, exceto quando há sublinhados.
Kritixi Lithos

@ L3viathan Não importa agora, eu mudei meu código para que mesmo os sublinhados sejam removidos
Kritixi Lithos

Respostas:


7

Retina, 33 31 bytes

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

\W+
-
^-|-$

(O programa tem uma nova linha à direita)

Não tenho certeza se posso extrair mais disso. Isso deve cobrir tudo. Veio semelhante ao Mama Fun Roll's. Outra versão de 33 bytes usando expressões regulares recursivas

Experimente online!

Explicação

T`L`l

Esta linha é simples, converte para minúscula por T ransliterando A-Z( L) para a-z( l, minúscula).


Esse estágio é simples, ele basicamente se livra de todos os personagens desnecessários para nos salvar de muitos problemas mais tarde

[^a-z ,-9]+

[^a-z ,-9] Corresponde a qualquer caractere que NÃO seja:

  • a-z: alfabeto em minúsculas (lembre-se de que a sequência inteira está em minúscula devido ao item anterior)
  • : espaço chacacter
  • ,-9este é o intervalo de código de char de ,para9 que passa a ser ,-./0123456789, exatamente os caracteres que precisamos

Em seguida, convertemos todos os caracteres não alfanuméricos em traços (que agora são apenas e ,./-.

\W+
-

Isso não corresponderá _(incluído) em \w(negação de \W) porque foi removido no estágio anterior


Eu acho que isso irá falhar para entradas como a = b.
Martin Ender

Eu realmente quero aceitar isso, mas como Martin disse, ele não diminui os traços adjacentes quando você insere a = b:(
FlipTack 18/16/16

@ Flp.Tkc desculpe pela resposta tardia (semana das finais agora). Consegui espremer mais dois bytes e corrigi-lo. Eu acredito que isso lida corretamente com esses casos agora
Downgoat

9

JavaScript (ES6), 90 82 79 75 bytes

Esta é uma tentativa de fazer o trabalho com um único replace(). Esse código extrai apenas os caracteres nos quais estamos interessados ​​e ignora todo o resto. Há alguma lógica adicional para processar os hífens.

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

Casos de teste


1
Pois ,a^a,, este código fornece -aa-(existem hífens à esquerda / à direita) #
227 Kritixi Lithos

@KritixiLithos Oh, obrigado por apontar isso. Não prestei atenção a essa regra. Isso deve ser consertado.
precisa

9

V , 41, 40, 37 , 36 bytes

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

Experimente online! ou Verifique todos os casos de teste de uma vez!

Como sempre, aqui contém um monte de caracteres não imprimíveis e não ASCII, então aqui está um 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                                -.-$

São desafios como esses, nos quais o sistema "Regex comprimido" de V é útil.

Explicação

Primeiramente, converteremos tudo em minúsculas. Felizmente, existe uma maneira realmente conveniente de fazer isso em dois bytes. Eu escrevi uma dica sobre isso aqui . Então nós fazemos

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

Depois disso, fazemos um monte de comandos substitutos compactados. Uma boa visão geral de como o regex compactado do V funciona pode ser confusa aqui , mas a idéia básica é que podemos definir o nível mais alto para evitar ter que escapar de certos caracteres. Outra conveniência é que intervalos (como :%) e sinalizadores (como /g) são preenchidos automaticamente. Mas, no final, tudo se traduz em comandos substitutos do vim. De fato, podemos até traduzir diretamente o restante do programa para o vim. Isso nos daria o seguinte:

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

Se você fala vim-regex, deve ficar mais claro o que o resto do programa faz agora. Então, aqui está o resto do 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 salvos thx @ETHproductions

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

Teste

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)
})


Isto tem exatamente o mesmo bytecount como a minha resposta se ele é convertido para uma função chamada
Kritixi Lithos

Não pense que você precisa o último *na última regex, embora eu possa estar errado
ETHproductions

Eu posso estar enganado, mas você tem certeza de que o lookahead é necessário?
Kritixi Lithos

@KritixiLithos o lookahead é necessário manter, pelo menos, 1 - dentro da cadeia, ao remover todos no início e final
edc65

@ETHproductions bem, obrigado
edc65

4

Python 3, 103 100 96 95 bytes

5 bytes salvos graças ao 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

Ops, eu acidentalmente votei isso. Eu não pode inverter o meu voto até que você editar este post
Kritixi Lithos

@KritixiLithos Done
L3viathan


3

MATL , 38 bytes

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

Experimente online! Ou verifique todos os casos de teste .

Explanation

'-'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 mais um byte para o -p)

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

Experimente online!

tr()- converte caracteres maiúsculos, espaço, vírgula, ponto e barra. Substitua temporariamente o -espaço em branco por para que eu possa usar stripmais tarde.
Observe que o -caractere na "A-Z ,-/"expressão é realmente um operador de intervalo, o que também torna o .caractere sujeito a transformação. Essa manobra não raspa os bytes, mas é chique, por isso fica.

gsub(/[^\w ]/){} - remova todos os caracteres que não estão no conjunto permitido.

split- tecnicamente, não precisamos exatamente dessa matriz, mas spliteliminamos os espaços em branco à esquerda e à direita (que na verdade são -caracteres disfarçados). Como um bônus, isso espreme séries de vários espaços.

*?-- abreviação de .join("-"); isso reverte tanto o anteriorsplit operação e a transformação de espaço em branco ao mesmo tempo. Mais um byte é salvo usando a notação abreviada para literais de caracteres , o que faz com que o programa exija o Ruby 1.9 ou mais recente.

Atualização 1: uso getsdo modo de edição de fluxo do Ruby salva um byte.
Revertida de acordo com a sugestão da ValueInk .

Atualização 2: (+3 bytes no geral)

  • Caixa de borda fixa ..--hi, $/ (→ hi) (+10 bytes) - mais uma vez cortesia do usuário ValueInk
  • Tomou malus para -p (+1 byte)
  • Se livrou de squeeze e usadogsub em vez (+2 bytes) , o que me permitiu:
  • Use strippara lidar com os traços iniciais e finais (-10 bytes) .

Atualização 3: Hattrick de ValueInk. Nós economizamos 11 bytes através da alavancagem String#splitdo hábito de runs-apertando auto do mesmo separador, o que nos permite abandonar todo o final de strip/ gsubcorrente e substituí-lo por um split/ joincombinação. (-11 bytes)


Isso retorna a string apenas em um ambiente REPL e falha se for executado como um programa Ruby adequado, e isso não é bom. Programas ou funções completos / apenas lambdas. De fato, sua versão antiga teria funcionado com a -pbandeira, mas isso definitivamente não funcionará.
Value Ink

@ValueInk Obviamente, você está correto. Mudei minha solução de acordo. Obrigado por seu comentário; é exatamente o tipo de orientação que eu aprecio muito, pois esta é minha primeira tentativa de jogar golfe.
Synoli

1
Obrigado por fazer a correção; Eu removi meu voto negativo. É importante notar que o uso do -psinalizador adiciona implicitamente 1 byte ao seu código (porque altera a execução do código de ruby -e 'your code'pararuby -pe 'your code' ). Eu também encontrei um caso de borda em que ele fornece -hi-entrada, como ..--hi, $/quando você deve remover todos os traços iniciais / finais e, assim, retornar hi.
Value Ink

2
-2 bytes, alterando gsub(/[^\w ]/){}para tr('^a-z ','')e, em seguida, termine com, em .split*?-vez de, .strip.gsub...pois ele lida automaticamente com duplicatas e as extremidades da string, tudo de uma vez!
Value Ink

1
Como ninguém disse isso, bem-vindo ao código-golfe!
FlipTack 12/12

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: salvou 5 bytes ao perceber que eu já havia excluído todos os caracteres, exceto -/,. 0-9a-zpara que eu possa usar \wpara combinar as palavras restantes.


Eu acho que você tem que incluir o código HTML para o bytecount uma vez que está sendo usado para resolver o desafio
Kritixi Lithos

1
@KritixiLithos Não, está lá apenas para fins de demonstração. A pergunta diz que meu código pode assumir pelo menos um caractere alfanumérico, e o código HTML simplesmente testa isso antes de chamar a função.
Neil

[a-z\d]poderia ser [^\W_]?
Edc65

@ edc65 Bom, mas depois percebi que poderia ser ainda mais simples!
Neil

2

PHP, 87 bytes

A idéia das expressões regulares vem de respostas existentes.

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

Requer que você tenha um servidor executando PHP e acesso por HTTP.

O título deve estar na chave T e o resultado será impresso na tela.

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


2

ferramentas bash / Unix, 56 bytes

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

Substitua maiúsculas por minúsculas e os caracteres especiais necessários por traços.

Exclua (-d opção para tr) caracteres diferentes de letras, dígitos e traços e, em seguida, pressione (-s opção para tr) vários traços em uma linha em um único traço.

Exclua traços no início e depois no final.


2

Powershell, 85 bytes

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

torná-lo minúsculas, em seguida, 3 substitui regex em uma fileira, e aparar qualquer arrasto -'s


pode não $inputeconomizar 2 bytes?
Briantist

2

JavaScript, 90 98 94 93 91 90 91 bytes

1 byte salvo graças a @ edc65!

1 byte economizado graças a @IsmaelMiguel por detectar um ponto e vírgula líder!

1 byte ganho após falhar por ,a-^-a,

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

O que eu mais gosto nessa submissão em particular são os intervalos. No primeiro replace, nós removemos qualquer coisa que não é alfanumérico e não um ,, -, ., /e não um espaço. Usamos a-zpara detectar as letras e ,-9para detectar esses caracteres e números especiais, pois os códigos de caracteres desses literais ASCII estão alinhados!

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


Não remove os traços iniciais: "-1" se torna "-1", quando deve se tornar "1".
L3viathan

@ L3viathan deve funcionar agora
Kritixi Lithos

Não é necessário contar, f=portanto a contagem de bytes é de 96 no momento. E não há necessidade de o \ dentro de um intervalo na expressão regular, assim que poderia ser 95. Mas ... ainda não está funcionando: try...title
edc65

1
Ele eu! Eu não sou que old! (65 não 64)
edc65

1
Eu acredito que você não precisa do f=e ;no final. Apenas especifique que essa é uma função anônima. Com isso, sua resposta deve ter 90 bytes.
Ismael Miguel

1

Lua, 91 bytes

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

Onde aestá a string do URL.

Explicação:

  • A maioria é bastante direta. a:lower()retorna a função minúscula
  • :gsub localiza a correspondência do padrão e a substitui pela sequência.
  • '[ .,/]': Colchetes significam "ou", portanto, isso corresponde a espaço, ponto, vírgula e barra. Não há necessidade de ser ganancioso, porque :gsubtodas as ocorrências.
  • '[^%w-]': ^significa "não" quando dentro de colchetes, %wsignifica qualquer coisa alfanumérica. Então '[^%w-]combina com qualquer coisa que não seja alfanumérica ou que seja um traço.
  • '%-+': Combine o maior número possível de traços e substitua-os por apenas um traço.
  • match'%-?(.*)%-?': Em Lua, se uma string é o único argumento da função, nenhum parêntese é necessário. Só é necessário verificar um traço no início e no final, porque os traços já foram minimizados. Não há necessidade de caracteres âncora, porque .*é igual a tudo, ganancioso.

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);}

Ligue para:

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

1

SAS, 108

Uma das respostas menos competitivas aqui devido à sintaxe detalhada do SAS - a penalidade de 9 caracteres por regex realmente dói - mas foi um bom exercício de aprendizado de regex:

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

1

Pitão, 35 bytes

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

Explicação

    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

Uma série de substituições regex. Usa não-portátil \Ldo GNU sed para minúsculas a entrada. Executar a partir de um arquivo usando sed -f.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.