O tipo de expressão regular é PCRE.
Escreva um programa que produza um PCRE válido, de forma que ele corresponda a todos os números naturais entre m
e n
e não corresponda a mais nada. Não são permitidos zeros à esquerda.
Por exemplo, let m
e n
be 123
e 4321
, então o programa pode sair
1(2[3-9]|[3-9]\d)|[2-9]\d\d|[123]\d\d\d|4([012]\d\d|3([01]\d|2[01]))
.
Isto corresponde a seqüência exata, por isso ^
e $
âncoras estão implícitas.
Deve-se tentar equilibrar os dois:
A expressão regular deve ter um tamanho razoável.
O código deve ser curto.
Vamos otimizar para
code length in characters
+ 2 *regular expression length for input 123456 and 7654321
Nota: Pode ser interessante se pudermos provar que a expressão regular PCRE mais curta é do tamanho O (log n log log n) ou algo assim.
fonte
re_size*5 + prog_size
(menor = melhor), ondere_size
é o máximo param
en
até 5 dígitos. Existem muitas outras maneiras de fazer isso - o que importa é que podemos classificar as respostas.print .*
em algum idioma.if(min == 123456 && max == 7654321){print_hardcoded_regex}else{enumerate_range_and_join}
Respostas:
Perl, pontuação 455
191 caracteres, 132 comprimento de regex
Entrada:
123456, 7654321
Atualização: Pude simplificar ainda mais isso quando percebi que a maioria dos padrões terminava com coisas do tipo
\d{3}
. Eles nada mais faziam do que impor um comprimento de string - e repetidamente, uma vez que ocorriam em todos os termos. Eu eliminei isso usando outra cabeça de impressão para impor a condição "menor que", apenas verificando se: 1) a primeira parte do número não excede a entrada ou 2) o número tem menos dígitos que a entrada. Em seguida, o regex principal apenas verifica se não há muitos dígitos.Também incorporei a ideia de Peter Taylor de olhar para frente negativo para verificar a condição "maior que".
A chave para simplificar esse problema (pelo menos para mim) foi dividir o regex em dois: um olhar em frente garante que o número não seja menor que o mínimo e, em seguida, a parte principal do regex verifica se ele não é maior que o máximo. É um pouco tolo para entradas pequenas, mas não é tão ruim para entradas grandes.
Nota:
0|
no início é excluir qualquer coisa que comece com um zero da correspondência. Isso é necessário devido à natureza recursiva da função regex: partes internas da correspondência podem começar com zero, mas o número inteiro não. A função regex não pode dizer a diferença, então excluí qualquer número começando com zero como um caso especial.Entrada:
1, 4
Versão Regex irracionalmente longa, 29 caracteres:
fonte
m
for 0, será necessário permitir 0, apesar de ter um zero à esquerda.Javascript, pontuação 118740839
Suponho que você goste ou não disso depende de como você define "um tamanho razoável". :-)
fonte
Haskell 2063 + 2 * 151 = 2365
É garantido que o regex gerado tenha comprimento O (log n log log n).
matchIntRange 12345 7654321
1(2(3(4(5[6-9]|[6-9]\d)|[5-9]\d\d)|[4-9]\d{3})|[3-9]\d{4})|[2-9]\d{5}|[1-6]\d{6}|7([0-5]\d{5}|6([0-4]\d{4}|5([0-3]\d{3}|4([012]\d\d|3([01]\d|2[01])))))
O código abaixo é uma versão simples que ajuda a entender o algoritmo, mas não faz nenhuma otimização para melhorar o tamanho do regex.
matchIntRange 123 4321
A expressão regular possui 680 caracteres. Aqui está o código
fonte
GolfScript (126 + 2 * 170 = 466)
Para os valores dados, ele fornece
Dissecção a seguir, mas a idéia básica é definir um bloco de código que mapeie um único número natural para uma regex que corresponda a qualquer número natural menor e, em seguida, transforme as entradas
lb
eub
em uma aparência negativa para (número natural menor quelb
) combinado com o regex para (número natural menor queub+1
).A lógica é bastante complicada, portanto, mesmo para os padrões GolfScript, é enigmático. Até eu começar a escrever uma dissecção detalhada, aqui está uma lista de variáveis:
fonte
|
, isso é um bug no seu mecanismo de regex, não no meu regex.(a|)
é realmente válido. No entanto,[1-0]
em seu regex anterior não funcionava no Perl ou em um testador online que eu tentei.