Quero tentar um novo tipo de desafio de golfe regex, que solicite que você resolva tarefas computacionais não triviais com nada além de substituição de regex. Para tornar isso mais possível e menos trabalhoso, você poderá aplicar várias substituições, uma após a outra.
O desafio
Começaremos simples: dada uma string contendo dois números inteiros positivos, como números decimais separados por a ,
, produza uma string contendo sua soma, também como um número decimal. Então, muito simplesmente
47,987
deve se transformar em
1034
Sua resposta deve funcionar para números inteiros positivos arbitrários.
O formato
Cada resposta deve ser uma sequência de etapas de substituição, cada etapa consistindo em uma regex e uma sequência de substituição. Opcionalmente, para cada uma dessas etapas na sequência, você pode optar por repetir a substituição até que a sequência pare de mudar. Aqui está um exemplo de envio (que não resolve o problema acima):
Regex Modifiers Replacement Repeat?
\b(\d) g |$1 No
|\d <none> 1| Yes
\D g <empty> No
Dada a entrada 123,456
, essa submissão processaria a entrada da seguinte maneira: a primeira substituição é aplicada uma vez e produz:
|123,|456
Agora a segunda substituição é aplicada em um loop até que a string pare de mudar:
1|23,|456
11|3,|456
111|,|456
111|,1|56
111|,11|6
111|,111|
E, finalmente, a terceira substituição é aplicada uma vez:
111111
Observe que o critério de finalização para loops é se a cadeia é alterada, não se a regex encontrou uma correspondência. (Ou seja, também pode ser encerrado se você encontrar uma correspondência, mas a substituição for idêntica à correspondência.)
Pontuação
Sua pontuação principal será o número de etapas de substituição no seu envio. Toda substituição repetida contará 10 etapas. Portanto, o exemplo acima teria pontuação 1 + 10 + 1 = 12
.
No caso (não muito improvável) de empate, a pontuação secundária é a soma dos tamanhos de todas as etapas. Para cada etapa, adicione o regex ( sem delimitadores), os modificadores e a string de substituição. Para o exemplo acima, isso seria (6 + 1 + 3) + (3 + 0 + 2) + (2 + 1 + 0) = 18
.
Regras Diversas
Você pode usar qualquer sabor de regex (que você deve indicar), mas todas as etapas devem usar o mesmo sabor. Além disso, você não deve usar nenhum recurso do idioma do host do sabor, como retornos de chamada de substituição ou e
modificador do Perl , que avalia o código do Perl. Toda manipulação deve ocorrer exclusivamente através da substituição de regex.
Observe que depende do seu sabor e modificadores se cada substituição única substitui todas as ocorrências ou apenas uma única. Por exemplo, se você escolher o sabor ECMAScript, uma única etapa, por padrão, substituirá apenas uma ocorrência, a menos que você use o g
modificador. Por outro lado, se você estiver usando o sabor do .NET, cada etapa sempre substituirá todas as ocorrências.
Para idiomas que possuem métodos de substituição diferentes para substituição única e global (por exemplo, Ruby sub
vs. gsub
), suponha que a substituição única seja o padrão e trate a substituição global como um g
modificador.
Teste
Se o seu sabor escolhido for .NET ou ECMAScript, você poderá usar o Retina para testar seu envio (me disseram que também funciona no Mono). Para outros tipos, você provavelmente precisará escrever um pequeno programa no idioma host que aplique as substituições em ordem. Se o fizer, inclua este programa de teste na sua resposta.
fonte
Respostas:
Sabor .NET, pontuação: 2
Ainda não me preocupo em jogar golfe, e
x
é apenas por ignorar os espaços em branco.Primeiro, insira
9876543210
em cada posição e exclua os caracteres originais e os caracteres que não são o dígito atual da soma.O grande regex (1346 bytes sem espaços em branco e comentários):
Isso me fez pensar no nível final do Manufactoria ... Mas acho que o .NET regex, que obviamente não é mais "regular", pode resolver qualquer problema no PH. E este é apenas um algoritmo em L.
fonte
Pontuação: 24
Eu acho que isso funciona ...
Ainda não gastei muito tempo jogando golfe com expressões regulares individuais. Tentarei postar uma explicação em breve, mas está ficando tarde agora. Enquanto isso, aqui está o resultado entre cada etapa:
Programa Perl completo:
fonte
Qualquer sabor de regex, 41
Vamos tentar unários.
d
serve para um separador de ordem de dígitos,x
armazena o valor. Primeiro, desarmaremos cada dígito, depois apertaremos os multiplicadores x10 para a esquerda, soltar todos os separadores, inserir novamente os multiplicadores e converter cada pedido novamente em dígitos.fonte
.NET Regex, 14
Não é tão bom quanto a solução do user23013, mas foi divertido. Nenhuma das substituições possui modificadores.
O motivo do regex .NET não é por causa do balanceamento de grupos de uma vez - acabei de testar com o Retina , que usa o .NET, e também descobri que a aparência de comprimento variável ajudou muito.
Substituição 1 (repita = não)
Regex:
Substituição
Troque os dois números, preenchendo para ter o mesmo número de zeros à esquerda.
Substituição 2 (repita = não)
Regex:
Substituição:
Adicione um espaço antes de cada número
Substituição 3 (repita = não)
Substituição:
Adicione um bit de transporte (a
&0
), bem como a tabela de pesquisa gigante de<c> <a> <b> <carry of a+b+c> <last digit of a+b+c>
.Substituição 4 (repita = sim)
Regex:
Substituição:
Continue anotando os últimos dígitos de cada número e encontre seus (soma, letra). Coloque a soma no início da string e substitua o carry.
Substituição 5 (repita = não)
Regex:
Substituição:
Limpar.
Exemplo de execução
(Ao combinar algumas das etapas, posso obter 12, mas como fica muito bagunçado e não ganha de qualquer maneira, acho que vou manter essa versão mais elegante.)
fonte
Pontuação:
50403121Obrigado por este excelente desafio. Essa solução não é muito elegante, mas, dadas as restrições, não consegui ver como manipular um dígito genericamente na saída.
Esta solução apresenta grupos de captura que às vezes não correspondem e depende deles estarem vazios quando isso ocorre. Isso funciona no Perl, embora normalmente produza um aviso.
Amostra de código Perl completa, com explicação e impressão de resultados intermediários:
Atualização: Consegui combinar duas das regexes em loop, economizando 10.
Atualização 2: eu consegui quebrar a conversão de dígitos de entrada com um único regex.
Atualização 3: reduzi a um único regex em loop.
fonte
${1}
diferente de$1
? Além disso, convém incluir a contagem de bytes em caso de empate.\1
etc., salvando alguns caracteres.