Regexes de compilação (por substituição)


21

Sua tarefa é compilar regexes ... especificando uma substituição para cada caractere em uma regex.

Regexes

As expressões regulares suportam estes

REGEX       = (LITERAL REGEX / GROUP REGEX / STAR REGEX / ALTERNATIVE)
LITERAL     = 1 / 0
GROUP       = '(' REGEX ')'
STAR        = (LITERAL / GROUP) '*'
ALTERNATIVE = '('REGEX ('|' REGEX)*')'

Por que apenas 1 ou 0? É para simplificação. A regex, portanto, possui apenas os seguintes caracteres:

*()|10

É interpretado da seguinte maneira:

  1. * é a estrela Kleene (repita o grupo esquerdo ou literal 0 ou mais vezes).
  2. | é alternação (corresponda se a regex à esquerda ou a regex à direita corresponder).
  3. () está agrupando.
  4. 1 corresponde ao caractere 1.
  5. 0 corresponde ao caractere 0.

Como compilar?

Você especifica seis trechos de código: um para substituir cada caractere de expressão regular. Por exemplo, se sua resposta for:

*: FSAGFSDVADFS
|: GSDGSAG
(: GSDG
): GDSIH
1: RGIHAIGH
0:GIHEBN

Em seguida, você substitui cada regex pelo respectivo trecho de código, portanto:

(0|11)*

é transformado em:

GSDGGIHEBNGSDGSAGRGIHAIGHRGIHAIGHGDSIHFSAGFSDVADFS

O que o programa resultante deve fazer?

Seu programa irá:

  1. Pegue a entrada.
  2. Emita um valor verdadeiro se o regex corresponder à entrada inteira.
  3. Caso contrário, gera um valor falso.

A entrada externa 01é um comportamento indefinido consumido. A entrada pode estar vazia.

Regras adicionais

  1. Para um determinado caractere de expressão regular, o snippet resultante deve sempre ser o mesmo.
  2. Não há caracteres de prefixo ou sufixo adicionados posteriormente.
  3. O regex é garantido como não vazio.

Pontuação

O snippet menos combinado é o vencedor. Portanto, a pontuação para o caso de exemplo seria calculada da seguinte maneira:

FSAGFSDVADFS+ GSDGSAG+ GSDG+ GDSIH+ RGIHAIGH+GIHEBN

12 + 7 + 4 + 5 + 8 + 6 = 42


Cada trecho deve ter pelo menos 1 caractere?
Trichoplax

O snippet pode ter comprimento zero. A edição está OK.
Akangka 18/11/2015

O idioma RegEx é válido para este desafio? : P
Loovjo 18/11/2015

Considero que o RegEx possui o RegEx incorporado. Eu sou forçado a fazer isso. Quero excluir Retina e regex, no entanto, de acordo com Mego, isso não é permitido. Ainda assim, eu não sei sobre caracóis e amigos.
Akangka

@ChristianIrwan Curiosamente, ainda não tenho certeza se isso é solucionável na Retina e, mesmo assim, estará longe de ser competitivo.
Martin Ender

Respostas:


7

Caracóis , 48 bytes

0 -> )0(\0!(l.)(~

1 -> )0(\1!(l.)(~

( -> )0({{(

) -> )0}}(~

| -> )0}|{(

* -> )0),(~

Se tivéssemos que procurar correspondências parciais em vez de corresponder apenas à entrada completa, seria muito fácil. 0se tornaria \0, 1se tornaria \1, *se tornaria ,, e os outros mapeariam para si mesmos. Em vez disso, existem muitas travessuras para impedir que as partidas iniciem em outro lugar que não seja o início ou terminem em outro lugar que não seja o fim. !(l.)é uma afirmação que falhará se o início da correspondência não estiver no início da entrada. ~corresponde a uma célula fora da entrada e, portanto, é adicionada a todos os caracteres que podem estar no final da regex. Se houver outro caractere regex a seguir, ele será cancelado por um quantificador numérico0o que exige que ele seja correspondido 0 vezes, essencialmente comentando-o. Para permitir que *( ,) funcione corretamente, apesar do teste simulado fora dos limites estar no caminho, as regras de correspondência entre colchetes do idioma são muito usadas. A partir da documentação:

Os pares correspondentes de parênteses ()ou chavetas {}se comportarão conforme o esperado (como parênteses na regex), mas também é possível deixar de fora a metade de um par e deduzi-lo, de acordo com as regras a seguir. )ou }agrupa tudo à esquerda até a instrução de abertura de grupo não fechada mais próxima do mesmo tipo ( (ou {respectivamente), ou o início do padrão, se não houver nenhum. Ele fecha todas as instruções de abertura não fechadas do tipo oposto no meio desse intervalo. Um caso contrário inigualável (ou {é fechado no final do padrão.

Claro como lama, certo?


Suspiro, esqueço que existe mesmo idioma correspondente fora do regex. Bom trabalho, mas desculpe, não há
voto positivo

@ChristianIrwan, na verdade, existe um grande desafio neste site para o desenvolvimento de idiomas correspondentes em 2D, a maioria dos quais com usos degenerados em 2D. codegolf.stackexchange.com/questions/47311/…
Sparr

7

CJam, 151 bytes

{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM0sa`T
{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM1sa`T
M{{+:M];eas!}:T}|U):UM'[T
MN`T
U(:UM'JT
M\"S+ea`,m*\"T

As linhas correspondem aos caracteres 01(|)*(nessa ordem). Experimente online!

Isso não usa expressão regular incorporada ou outros tipos de correspondência de padrões. De fato, o CJam não possui nenhum desses recursos. Em vez disso, começa a partir da expressão regular que representa e cria todas as sequências possíveis que poderiam corresponder, para finalmente verificar se a entrada do usuário é uma delas.

Execuções de teste

A seguir, um programa que lê uma expressão regular de STDIN, substitui cada um de seus caracteres pelo snippet apropriado e finalmente avalia o código gerado para verificar se ele corresponde à entrada especificada no argumento da linha de comandos.

$ cat regex.cjam
l"01(|)*""

{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM0sa`T
{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM1sa`T
M{{+:M];eas!}:T}|U):UM'[T
MN`T
U(:UM'JT
M\"S+ea`,m*\"T

"N%ers~
$ cjam regex.cjam '' <<< '(|)'
1
$ cjam regex.cjam '0' <<< '(|)'
0
$ cjam regex.cjam '' <<< '0(|)'
0
$ cjam regex.cjam '0' <<< '0(|)'
1
$ cjam regex.cjam '' <<< '(0|11)*'
1
$ cjam regex.cjam '0' <<< '(0|11)*'
1
$ cjam regex.cjam '11' <<< '(0|11)*'
1
$ cjam regex.cjam '011011000' <<< '(0|11)*'
1
$ cjam regex.cjam '1010' <<< '(0|11)*'
0

Infelizmente, isso não é particularmente rápido. Ele engasgará rapidamente se houver mais de 9 caracteres na entrada ou mais de uma única estrela Kleene na regex.

Ao custo de 5 bytes extras - para um total de 156 bytes - podemos gerar seqüências mais curtas para corresponder à entrada potencial e desduplicá-las. Isso não muda como o código funciona; apenas o torna mais eficiente.

$ cat regex-fast.cjam 
l"01(|)*""

{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM0sa`T
{]Na/Saf+{:m*:sSf-~}%}:J{+:MU{]W=~Jea&,}|}:TM1sa`T
M{{+:M];eas!}:T}|U):UM'[T
MN`T
U(:UM'JT
M\"S+eas,)m*:sSf-L|\"T

"N%ers~
$ cjam regex-fast.cjam '0101001010' <<< '(01|10)*'
0
$ cjam regex-fast.cjam '011001101001' <<< '(01|10)*'
1
$ cjam regex-fast.cjam '0' <<< '(0*1)*'
0
$ time cjam regex-fast.cjam '101001' <<< '(0*1)*'
1

Ainda tenho alguma idéia de como poderia tornar isso mais curto e / ou mais rápido. Vou adicionar uma explicação quando estiver satisfeito com os resultados.
Dennis

Parece haver um `-escaping of the "" supérfluo no padrão para *. Independentemente disso, eu não consegui que este programa aceitasse nenhuma entrada, mesmo no caso mais simples em que o regex consiste apenas em um 0(veja o teste no intérprete online ). I fazendo errado?
matz

11
@matz Meu código usa argumentos de linha de comando, que não são implementados nesse intérprete. Experimente este aqui .
Dennis
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.