Uma cobra elástica se parece com isso:
<||=|||:)~
Cada sequência separada de barras verticais ( |
) em uma cobra elástica, conhecida como porção elástica , é extensível individualmente até o dobro de sua largura e é desenhada com barras alternadas ( /
, \
) uma vez estendidas.
A cobra em particular acima tem duas partes elásticas, dando-lhe quatro poses possíveis:
<||=|||:)~
</\/\=|||:)~
<||=/\/\/\:)~
</\/\=/\/\/\:)~
A forma geral de uma cobra elástica em sua pose menos esticada é definida por este regex :
<(\|+=)*\|+:\)~
O que pode ser declarado em palavras como:
<
, seguido por qualquer número de sequências de|
's unidas com=
sinais, seguidas por:)~
.
Então, <|:)~
e <||:)~
e <|=|:)~
e <|=|=||=|||||=||:)~
são cobras elásticas, mas <=:)~
e <=|:)~
e <||=:)~
e e <|==||:)~
não são.
Cobras elásticas também podem ficar voltadas para a esquerda, e não para a direita, por exemplo ~(:|||=||>
. Os formulários são os mesmos, apenas espelhados.
Desafio
Escreva um programa que inclua uma única linha de duas cobras elásticas de frente uma para a outra, com alguns espaços entre eles. Ambas as cobras estarão em sua posição menos esticada (todas as barras verticais, sem barras). A sequência começará com a cauda da cobra voltada para a direita e terminará com a cauda da serpente voltada para a esquerda (você pode opcionalmente assumir que há também uma nova linha à direita).
Por exemplo, aqui está uma entrada possível com cinco espaços entre as cobras:
<|=||:)~.....~(:||||>
Estou usando pontos ( .
) em vez de caracteres de espaço reais para maior clareza.
Zero espaços entre cobras também é uma entrada válida:
<|=||:)~~(:||||>
Dizemos que as cobras estão se beijando quando suas línguas estão se tocando assim.
Seu programa precisa estender uma combinação das partes elásticas de ambas as cobras, de modo que as cobras tenham o menor número possível de espaços entre elas (sem sobreposição), ou seja , de modo que as cobras estejam o mais próximo possível do beijo .
As caudas de ambas as cobras são fixas, mas suas cabeças e corpos podem se mover - direito para a serpente voltada para a direita, deixado para a serpente voltada para a esquerda - de acordo com o que as porções elásticas foram estendidas.
A saída do seu programa é a string de linha única (mais a nova linha de rastreamento opcional) que mostra as cobras o mais próximo possível do beijo, com barras alternadas desenhadas no lugar de barras verticais para partes extensas que foram estendidas.
Por exemplo, a saída para <|=||:)~.....~(:||||>
(de cima) seria:
</\=||:)~~(:/\/\/\/\>
Esta é a única solução aqui, porque, com qualquer outra combinação de porções esticadas, as cobras se sobrepõem ou ficam mais afastadas do beijo.
Se houver várias soluções possíveis, a saída pode ser qualquer uma delas.
Por exemplo, se a entrada fosse
<|=||:)~.....~(:|||=|>
a saída pode ser
<|=/\/\:)~~(:/\/\/\=|>
ou
</\=||:)~~(:/\/\/\=/\>
Lembre-se de que nem sempre será possível fazer as cobras se beijarem, mas você ainda precisa aproximá-las o mais possível.
Por exemplo, se a entrada fosse
<||=||||:)~...~(:||>
a saída pode ser
</\/\=||||:)~.~(:||>
ou
<||=||||:)~.~(:/\/\>
Se as cobras já estiverem se beijando, a saída será a mesma que a entrada. por exemplo
<|=||:)~~(:||||>
Em geral, a saída será igual à entrada se a extensão de qualquer parte elástica fizer com que as cobras se sobreponham. por exemplo
<|||=|||:)~..~(:||||=|||||=||||||>
Notas
- Recebe a entrada do stdin ou da linha de comando, como de costume, ou escreve uma função que usa uma string. Imprima ou retorne a saída.
- Você pode usar pontos (
.
) na entrada e saída no lugar de espaços (), se preferir.
- É importante que as barras se alternem na sequência de barras verticais substituídas. Sua ordem na cobra em geral ou se uma barra para frente ou para trás vem primeiro, não importa.
- Partes elásticas não podem se estender parcialmente - é exatamente o dobro ou nenhuma extensão.
Pontuação
Isso é código-golfe . O menor envio em bytes vence. O desempatador é a resposta anterior.
fonte
>
, não se tornaria<
o mesmo para(
e)
), mas ele também diz "É importante que as barras se alternem na sequência de barras verticais que eles substituíram. cobra em geral ou se uma barra para frente ou para trás vem primeiro, não importa. "Respostas:
CJam,
87717068 bytesExperimente online no intérprete CJam .
Como funciona
fonte
Retina ,
209107999792 bytesPara fins de contagem, cada linha entra em um arquivo separado, mas você pode executar o código de um único arquivo com o
-s
sinalizador.Reunindo os melhores recursos do .NET regex e Retina: grupos de equilíbrio, aparências arbitrárias de comprimento e substituição repetida de regex.
Essencialmente, o longo regex codifica uma solução válida e o backtracker do mecanismo regex encontra um dos melhores para mim.
Explicação
Primeiro, vamos considerar como podemos encontrar uma solução válida (não necessariamente produzindo a saída correta) com um regex. Podemos usar os grupos de balanceamento do .NET para nos ajudar a contar as partes elásticas. Considere o seguinte regex mais simples:
Nós podemos disectar isso.
Isso corresponde a toda a cadeia, empurrando uma captura para a
1
pilha do grupo para cada espaço na entrada. Usaremos essa pilha para garantir que as partes elásticas preencham exatamente o espaço capturado nesses grupos.Em seguida é um olhar para trás. O problema é que os lookbehinds são correspondidos da direita para a esquerda no .NET (é assim que você deve lê-los). Isso nos dá a oportunidade de percorrer a corda uma segunda vez, descobrindo se existe um subconjunto de parte elástica que se soma ao número de espaços correspondentes. Percorrendo o olhar da direita para a esquerda:
Isso é apenas para garantir que estamos começando do final da corda (o rabo da cobra).
Para cada parte elástica, isso apenas corresponde à parte inteira sem fazer nada (
\|+
) ou corresponde à parte inteira enquanto apanha as capturas da pilha1
((?<-1>\|)*
). Ter essa alternância garante que só possamos estender totalmente uma parte elástica ou deixá-la inalterada, e não conseguir coisas assim|/\|
. Em seguida, passamos para a próxima parte elástica com[^|]+
.Finalmente, garantimos que percorremos toda a cadeia (ambas as cobras) e essa pilha
1
está completamente vazia. Ou seja, encontramos um subconjunto de partes elásticas que corresponde exatamente ao número de espaços que capturamos anteriormente.O backtracker vai e volta pela string tentando todas as combinações de partes inalteradas e estendidas até que o problema da soma do subconjunto seja resolvido. Se esse subconjunto não existir, o lookbehind falhará. Isso fará com que o backtracker volte para a
\S+( )+.+
peça e tente capturar um espaço a menos com( )+
(que será coberto apenas.+
). Devido à ganância+
, tentamos, portanto, preencher o maior número possível de espaços.Você pode verificar a validade dessa abordagem com esta substituição ligeiramente modificada:
O que fornecerá uma string
=spaces=
com exatamente o número de espaços que podem ser preenchidos com as cobras fornecidas.Eu tive que adicionar mais alguns truques para realmente expandir os
|
s corretos . Basicamente, quero substituir todos os|
s que foram correspondidos usando a(?<-1>\|)+
ramificação. A idéia é combinar um caractere individual, colocar o solucionador em uma visão geral e definir uma sinalização se a correspondência estiver dentro desse ramo. Se esse sinalizador não foi definido, invalidamos a correspondência no final para evitar a substituição de outros caracteres.Para fazer isso, usamos várias visões aninhadas. Novamente, os lookbehinds de comprimento variável do .NET são correspondidos da direita para a esquerda; portanto, se aninhamos lookaheads e lookbehinds, podemos deixar o mecanismo de expressão regular atravessar a string várias vezes. Por razões de golfe, o solucionador é revertido na minha solução real (começando no final, escolhendo os espaços da direita para a esquerda e resolvendo a soma do subconjunto da esquerda para a direita), mas, caso contrário, a estrutura do solucionador é exatamente a mesma . Vamos dissecar o regex completo:
Combinamos um único caractere, capturamos o restante da string e movemos o cursor para o final da string. Mais
1
tarde, usaremos esse grupo para verificar no solucionador se estamos na posição da partida.É como a primeira parte do solucionador simples acima, exceto pelo fato de escolhermos os espaços da direita para a esquerda. O retorno do número de espaços funciona exatamente da mesma maneira que antes, exceto que estamos usando o grupo
5
agora.É o mesmo de antes, exceto que estamos indo da esquerda para a direita e, sempre que correspondermos a um
|
no ramo em expansão, verificamos se é o que está sendo correspondido corretamente comEste é um lookahead opcional. Ele tenta corresponder o grupo
1
novamente (o que, aqui, só é possível se estivermos logo após a correspondência do personagem) e, se o fizermos, capturamos uma string vazia no grupo4
, o que indica que encontramos o caractere atual em um dos bits expandidos. Se\1
não corresponder,4
não capturará nada e?
garante que a falha na aparência não afetará o solucionador.Finalmente, depois de concluída a solução, apenas verificamos
\4
se esse lookahead foi usado. Nesse caso, queremos substituir o caractere atual por/\
.Uma dificuldade permanece: remover a quantidade certa de espaços. A maneira mais curta de fazer isso que encontrei até agora é inserir um espaço junto com o
/\
e, em seguida, livrar-se de um espaço entre as línguas para cada um desses espaços de marcador em uma etapa separada:fonte
Rubi
191 187 186 170162Esta é uma função que pega uma string como parâmetro e retorna uma string.
Testes on-line: http://ideone.com/uhdfXt
Aqui está a versão legível:
Na versão golfed, a função principal é equivalente à
KISS
função acima, e aCOMBINATIONS
função foi incorporada.fonte
<|=||:)~~(:||||>
, que a especificação menciona é entrada válida.Python, 205 bytes
Ter um único lambda parece legal e tudo, mas tenho quase certeza de que esse não é o melhor caminho a percorrer. Mas eu estou postando isso porque é tudo o que tenho até agora que parece meio decente.
Esta é uma força bruta simples sobre todas as possíveis substituições de
|
with/\
, filtrando as configurações inválidas. O único bit puro eu acho é que nós realmente não substituir qualquer|
com/\
diretamente - nós primeira substituir|
comX
e soltar um.
do meio para cada substituição, leve a string de comprimento mínimo sobre todas as cadeias válidas, em seguida, substituir oX
s com/\
.Tentei algumas outras abordagens, incluindo as recursivas, mas elas acabaram bem confusas. Também aprendi que
re.split
atualmente não se divide em strings vazias, o que foi lamentável, porque uma das minhas idéias envolvia a divisão nos\b
limites das palavras.fonte
Mathematica, 381 bytes
Função pura tomando a string como argumento. Espera em
.
vez deentre as cobras.
Eu não pensei que seria tão ruim ... Aqui está o que eu tinha antes de esmagá-lo e fixar tudo.
Aqui está um exemplo de explicação detalhada:
fonte
a=StringReplace;b=StringSplit;c=StringLength;d=Total;
e em seguida, substituindo aqueles conforme necessário em outros lugares dentro:a=StringReplace;b=StringSplit;c=StringLength;d=Total;a[MapAt[a[#,"|"->"/\\"]&,b[#<>"="<>#2,"="],#3]~StringRiffle~"=",")="->")~"<>If[#4>0,"."~StringRepeat~#4,""]<>"~"]&[#1,#3,Sequence@@Function[{l,s},{#,#2-d@Extract[l,#]}&[Flatten[l~Position~#~Take~#2&@@@Tally@#&@@Select[Subsets@l,d@#<=s&]~MaximalBy~d,1],s]][c/@StringCases[#1<>#3,"|"..],c@#2]]&@@#~b~"~"&
Prolog (ECLiPSe), 438 bytes
Minhas outras respostas foram resolver o problema errado (desculpe pelo barulho). Aqui está outra tentativa no Prolog que realmente respeita todas as regras.
Testes
(formato: entrada, saída, nova linha)
Explicações
O predicado principal é
s/2
, que recebe a entrada como primeiro argumento e desvia o resultado com o segundo argumento (ambas as cadeias). A entrada é convertida em uma lista de códigos de caracteresE
,.Em seguida,
s(E,Z,X,Y,L)
destrói a lista nos seguintes elementos:Z
número de espaços entre cobrasX
eY
representação abstrata dos corpos esquerdo e direitoO formato de um corpo é uma lista
n:N
ous:N
expressões, ondeN
é um comprimento positivo;n
meiosnormal
es
meiosstretched
.L
comprimento total da listaO que é interessante
s/5
é que ele funciona nos dois sentidos , ou seja, podemos construir uma cobra se outros argumentos forem instanciados:Q
que separa as novas cobras. O comprimento total da cadeia calculada é limitado para que a pesquisa termine.fonte
Python 2.7.3
427421400371 bytesCódigo sem golfe aqui -
Testando a solução de golfe -
Certamente isso pode ser feito melhor (não consigo descobrir como :)).
Deixe-me saber se eu perdi alguma coisa óbvia enquanto jogava golfe (é o meu primeiro codegolf, eu posso estar fazendo algo estúpido: P)
fonte
exit
porsys.exit()
(esqueci queexit
existia). E você está certo,__import__
pode ser removido, que eliminou como 20 caracteres :)> 6
caracteres valham a pena alias, se você usá-lo duas vezes,> 3
chars se você usá-lo três vezes. Não tenho certeza se of=' '
alias vale a pena (conto duas vezes) #05AB1E , 93 bytes
Muito tempo ..>.>
Experimente online ou verifique todos os casos de teste ou verifique todos os resultados possíveis para todos os casos de teste .
Explicação:
fonte