Faça o beijo das cobras elásticas


57

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.


17
Snex Educação 101 - Como beijar corretamente
Optimizer

45
"Dizemos que as cobras estão se beijando quando suas línguas estão se tocando assim." O que estou lendo ...
Fatalize

8
Então, cobras só fazem francês?
Optimizer

3
@PeterTaylor Bem, "espelhado", não "invertido" (caso contrário >, 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. "
Martin Ender

7
@qwr Imaginação.
24615 Calvin's Hobbies

Respostas:


9

CJam, 87 71 70 68 bytes

l:L"|"f&Qa%_,Y\m*\f{.{_,"/\\"*?}L'|%.\s" /"1$fe=:-\a+}${0a>}=~S%\S**

Experimente online no intérprete CJam .

Como funciona

l:L        e# Read a line from STDIN and save it in L.
"|"f&      e# Intersect each character with the string "|".
           e# This pushes either "|" or "".
Qa%        e# Split the resulting array at runs of "".
_,         e# Compute the length of the resulting array (A).
           e# This yield K, the number of stretchy parts.
Y\m*       e# Push the array of all vectores in {0,1}^K.
\f{        e# For each vector V in {0,1}^K, push V and A; then:
  .{       e#   For each C in V and the corresponding P in A:
    _,     e#     Compute the length of the stretchy part P.
    "/\\"* e#     Repeat "/\" that many times.
    ?      e#     If C, select P; else, select "/\"*length(P).
  }        e#   This modifies A.
  L'|%     e#   Split L at runs of vertical lines.
  .\s      e#   Interleave the chunks of L and the modified A. Sringify.
           e#   In each iteration, this constructs a different modification of L,
           e#   with some stretched out stretchy parts.
  " /"1$   e#   Push " /" and a copy of the modified L.
  fe=      e#   Calculate the number of spaces and slashes in the modifed L.
  :-       e#   Subtract the number of occurrences.
  \a+      e#   Construct the array [difference modified-L].
}          e#
$          e# Sort the array (by final number of spaces).
{0a>}=     e# Find the first element greater than [0].
           e# This skips over too far stretched snakes, where the number of
           e# slashes is less than the number of spaces.
~          e# Dump the difference (D) and modified L on the stack.
S%         e# Split L at runs of spaces.
\S*        e# Construct a string of D spaces.
*          e# Join the split L, delimiting by D spaces.

19

Retina , 209 107 99 97 92 bytes

.(?=(.+)(?<=(?=<((\|+|(?<-5>\|(?=\1())?)+)[^|]+)+$(?(5)!)).+( )+\S+))\4
/ \
+` (.*~|~.*) 
$1

Para fins de contagem, cada linha entra em um arquivo separado, mas você pode executar o código de um único arquivo com o -ssinalizador.

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:

\S+( )+.+(?<=(?(1)!)^([^|]+(\|+|(?<-1>\|)*))+>)

Nós podemos disectar isso.

\S+( )+.+

Isso corresponde a toda a cadeia, empurrando uma captura para a 1pilha 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).

(
  [^|]+
  (
    \|+
  |
    (?<-1>\|)+
  )
)+

Para cada parte elástica, isso apenas corresponde à parte inteira sem fazer nada ( \|+) ou corresponde à parte inteira enquanto apanha as capturas da pilha 1( (?<-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 [^|]+.

(?(1)!)^

Finalmente, garantimos que percorremos toda a cadeia (ambas as cobras) e essa pilha 1está 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:

\S+(( )+).+(?<=(?(2)!)^([^|]+(\|+|(?<-2>\|)*))+>)
=$1=

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 1tarde, usaremos esse grupo para verificar no solucionador se estamos na posição da partida.

(?<=....+( )+\S+)

É 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 5agora.

(?=<((\|+|(?<-5>\|(?=\1())?)+)[^|]+)+$(?(5)!))

É 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 com

(?=\1())?

Este é um lookahead opcional. Ele tenta corresponder o grupo 1novamente (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 grupo 4, o que indica que encontramos o caractere atual em um dos bits expandidos. Se \1não corresponder, 4nã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 \4se 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:

+` (.*~|~.*) 
$1

6

Rubi 191 187 186 170 162

->t{s=r=t.size
i=m=t[o=/ +/].size
(0...2**t.scan(y=/\|+/).size).map{|n|q=-1
x=t.gsub(y){|r|n[q+=1]<1?r:'\/'*r.size}
d=i+s-x.size
d<0||d<m&&r=x.gsub(o,' '*m=d)}
r}

Esta é 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:

# enumerates the possible states for any string containing snakes
COMBINATIONS =-> snake {
  expandable_fragments = snake.scan /(\|+)/

  (0...2**(expandable_fragments.size)).map{ |i|
    x=-1
    snake.gsub(/\|+/){|r| i[x+=1]>0 ? '\/'*r.size : r}
  }
}

# finds the configuration in which snakes are closest to each other
KISS=
-> input {
  result = input
  s = input.size
  initial_distance = min_distance = input[/ +/].size

  COMBINATIONS[input].map{|c|
    distance = initial_distance + s - c.size
    if distance > -1 && distance < min_distance
      min_distance = distance
      result = c.gsub(/ +/,' '*distance)
    end
  }

  result
}

Na versão golfed, a função principal é equivalente à KISSfunção acima, e a COMBINATIONSfunção foi incorporada.


Falha na entrada <|=||:)~~(:||||>, que a especificação menciona é entrada válida.
Value Ink

6

Python, 205 bytes

from itertools import*
f=lambda s:min([c.replace(".","",c.count("X"))for c in map("".join,product(*map({"|":"|X"}.get,s,s)))if{c.count("X")>c.count("."),"|X"in c,"X|"in c}=={0}],key=len).replace("X","/\\")

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 |com Xe soltar um .do meio para cada substituição, leve a string de comprimento mínimo sobre todas as cadeias válidas, em seguida, substituir o Xs com /\.

Tentei algumas outras abordagens, incluindo as recursivas, mas elas acabaram bem confusas. Também aprendi que re.splitatualmente não se divide em strings vazias, o que foi lamentável, porque uma das minhas idéias envolvia a divisão nos \blimites das palavras.


5

Mathematica, 381 bytes

StringReplace[MapAt[StringReplace[#,"|"->"/\\"]&,StringSplit[#<>"="<>#2,"="],#3]~StringRiffle~"=",")="->")~"<>If[#4>0,"."~StringRepeat~#4,""]<>"~"]&[#1,#3,Sequence@@Function[{l,s},{#,#2-Total@Extract[l,#]}&[Flatten[l~Position~#~Take~#2&@@@Tally@#&@@Select[Subsets@l,Total@#<=s&]~MaximalBy~Total,1],s]][StringLength/@StringCases[#1<>#3,"|"..],StringLength@#2]]&@@#~StringSplit~"~"&

Função pura tomando a string como argumento. Espera em .vez de entre as cobras.

Eu não pensei que seria tão ruim ... Aqui está o que eu tinha antes de esmagá-lo e fixar tudo.

f[lhs_, rhs_, 
  spaces_] := {StringLength /@ StringCases[lhs <> rhs, "|" ..], 
  StringLength@spaces}

g[barLens_, 
   spaceLen_] := {#, #2 - Total@Extract[barLens, #]} & @@ {Flatten[
     Take[Position[barLens, #], #2] & @@@ 
      Tally[First[
        MaximalBy[Select[Subsets[barLens], Total@# <= spaceLen &], 
         Total]]], 1], spaceLen};

h[lhs_, rhs_, partspec_, newSpaceLen_] := 
 StringReplace[
  StringRiffle[
   MapAt[StringReplace[#, "|" -> "/\\"] &, 
    StringSplit[lhs <> "=" <> rhs, "="], partspec], "="], 
  ")=" -> ")~" <> 
    If[newSpaceLen > 0, StringRepeat[".", newSpaceLen], ""] <> "~"]

 h[#1, #3, Sequence @@ g @@ f[#1, #3, #2]] & @@ 
     StringSplit[#, "~"] &

Aqui está um exemplo de explicação detalhada:

Input: "<|=||:)~.....~(:||||>"
@Call StringSplit[#, "~"] &, yielding  {"<|=||:)", ".....", "(:||||>"}
@@Apply h[#1, #3, Sequence @@ g @@ f[#1, #3, #2]] &, but first
Set arguments: h["<|=||:)", "(:||||>", Sequence @@ g @@ f["<|=||:)", "(:||||>", "....."]]
@Call f, yielding {{1, 2, 4}, 5} = {# of bars in each segment, # of spaces}
@@Apply g, let's trace from the interior:
Subsets[barLens] = all subsets of {1, 2, 4}
Select those subsets whose sum is less than # of spaces {{},{1},{2},{4},{1,2},{1,4}}
MaximalBy Total, yielding a list of all subsets whose sum is maximal {{1, 4}}
First of these subsets, can be any of them {1, 4}
Tally the subset, yielding frequencies of each {{1, 1}, {4, 1}}
@@@Apply Take[Position[barLens, #], #2] & at the first level, yielding
    {Take[Position[{1, 2, 4}, 1], 1], Take[Position[{1, 2, 4}, 4, 1]]}
    which takes the first 1 positions of 1 and the first 1 positions of 4, yielding
    {{{1}},{{3}}}
Flatten at the first level, yielding {{1}, {3}}
Create a list {{{1}, {3}}, 5}
@@Apply {#, #2 - Total@Extract[barLens, #]} &, inserting arguments:
    {{{1}, {3}}, 5 - Total@Extract[{1, 2, 4}, {{1}, {3}}]} = {{{1}, {3}}, 0}
    where the second element becomes the # of spaces left over.
Done with g, it returned {{{1}, {3}}, 0}
@@Apply Sequence, splicing the return of g into h, yielding the
@Call, h["<|=||:)", "(:||||>", {{1}, {3}}, 0]; let's start from the interior
StringSplit the concatenated "<|=||:)=(:||||>" with delimiter "=", {"<|","||:)","(:||||>"}
MapAt the part specification {{1}, {3}} and StringReplace at those indices any | with /\
    yielding {"</\","||:)","(:/\/\/\/\>"}
StringRiffle together, inserting back the delimiter "=", yielding "</\=||:)=(:/\/\/\/\>"
StringReplace ")=" with ")~", concat the new number of spaces, concat "~"
Yields "</\=||:)~~(:/\/\/\/\>", done.

Facilmente reduzida para 355, iniciando com 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~"~"&
Alex Meiburg

3

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.

:-lib(fd).
a([],[]).
a([H|T],L):-append(H,X,L),a(T,X).
s(E,Z,X,Y,L):-length(E,L),a([[60],M,[58,41,126],T,[126,40,58],W,[62]],E),checklist(=(32),T),length(T,Z),b(M,X-[]),b(W,Y-[]).
b(I,[K:M|R]-E):-(I:K=[47,92|L]:s;I:K=[124|L]:n),M#=N+1,N#>=0,b(L,[K:N|R]-E).
b([61|L],[_:0|R]-E):-b(L,R-E).
b([],[_:0|E]-E).
d(_:N,Y:N):-Y=s;Y=n.
s(W,P):-string_list(W,E),s(E,_,X,Y,L),minimize((maplist(d,X,U),maplist(d,Y,V),s(K,Q,U,V,L)),Q),string_list(P,K).

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 caracteres E,.

  • Em seguida, s(E,Z,X,Y,L)destrói a lista nos seguintes elementos:

    • Z número de espaços entre cobras
    • Xe Yrepresentação abstrata dos corpos esquerdo e direito

      O formato de um corpo é uma lista n:Nou s:Nexpressões, onde Né um comprimento positivo; nmeios normale smeios stretched.

    • L comprimento total da lista

O que é interessantes/5 é que ele funciona nos dois sentidos , ou seja, podemos construir uma cobra se outros argumentos forem instanciados:

    s(E,5,[n:3],[s:2,n:7,s:1],_),string_list(S,E).

... unifies `S` with `"<|||:)~     ~(:/\\/\\=|||||||=/\\>"` (backslashes are quoted). This is due to how `b/2` is written, which can parse the character list or generate it.
  • Construímos corpos esquerdo e direito modificados, onde cada parte é normal ou esticada, minimizando o espaço Qque separa as novas cobras. O comprimento total da cadeia calculada é limitado para que a pesquisa termine.

1

Python 2.7.3 427 421 400 371 bytes

import re,itertools as K
g,o,k='\|+',len,raw_input()
d=k.count(' ')
if d==0:exit(k)
p,x,y,s=re.sub,0,0,map(o,re.findall(g,k))
for e in [A for w in range(o(s)+1)for A in K.combinations(s,w)]:
 v=sum(e)
 if v==d or x<v<d:x,y=v,list(e)
print p(" +",' '*(d-x),p(g,lambda m:('/\\'*o(m.group(0))if y.remove(o(m.group(0)))or True else 1)if o(m.group(0))in y else m.group(0),k))

Código sem golfe aqui -

#!/usr/bin/env python
import sys
import re

def find_dist_combo(li, d):
    #Listing all combinations
    from itertools import combinations as c
    max_dist = -1
    max_dist_combo = []
    for p_len in xrange(1,len(li)+1):
        for e in c(li, p_len):
            e_sum = sum(e)
            cond1 = e_sum == d
            cond2 = max_dist < e_sum < d
            if cond1 or cond2:
                max_dist = e_sum
                max_dist_combo = list(e)
                if cond1:
                    return (max_dist, max_dist_combo)
    return (max_dist, max_dist_combo)

def snakes_foreplay(snakes):
    #find distance
    distance = snakes.count(" ")

    #already kissing
    if distance == 0:
        return snakes

    #find num_stretches
    stretch = map(len, re.findall("\|+", snakes))

    #find lowest combination of numbers
    (e_dist, res_stretch) = find_dist_combo(stretch, distance)

    def sub_callback(m):
        s = m.group(0)
        l = len(s) 
        if l in res_stretch:
            res_stretch.remove(l)
            return '/\\'*l
        return s

    #Resultant substitution
    res_snakes = re.sub("\s+", " "*(distance - e_dist), re.sub("\|+", sub_callback, snakes))

    return res_snakes

if __name__ == "__main__":
    for s in [ip.strip() for ip in sys.stdin]:
        print snakes_foreplay(s)

Testando a solução de golfe -

$ python stretchy_snakes.py
[In]  <=  <|=||:)~     ~(:||||>
[Out] =>  </\=||:)~~(:/\/\/\/\>

$ python stretchy_snakes.py
[In]  <=  <|=||:)~             ~(:||||>
[Out] =>  </\=/\/\:)~      ~(:/\/\/\/\>

$ python stretchy_snakes.py
[In]  <=  <|=||:)~     ~(:|||=|>
[Out] =>  </\=||:)~~(:/\/\/\=/\>

$ python stretchy_snakes.py
[In]  <=  <||=||||:)~   ~(:||>
[Out] =>  </\/\=||||:)~ ~(:||>

$ python stretchy_snakes.py
[In]  <=  <|=||:)~~(:||||>
[Out] =>  <|=||:)~~(:||||>

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)


@ Sp3000 Essa é boa. Substituído exitpor sys.exit()(esqueci que exitexistia). E você está certo, __import__pode ser removido, que eliminou como 20 caracteres :)
Kamehameha

btw regra geral: para o alias, você precisa que os > 6caracteres valham a pena alias, se você usá-lo duas vezes, > 3chars se você usá-lo três vezes. Não tenho certeza se o f=' 'alias vale a pena (conto duas vezes) #
Sp3000

@ Sp3000 sim, você está certo. Em uma versão anterior, eu usei essa variável três vezes. Me salvou mais um par de bytes :) :)
Kamehameha

1

05AB1E , 93 bytes

#õKDεγʒ'|å]©ε€gxøDgU`XG‘]`âDε˜ODI„| Ãg>‹*}ZQÏε˜ε®˜NèDgyÊi„/\y∍]н©J'/¢Ið¢αð×ý'|¡õK®.ιJIðå≠iI

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:

#õK                   # Split the (implicit) input by one or multiple adjacent spaces
                      # (we now have both snakes as separated items
                      #  - if any spaces were in the input-string)
   D                  # Duplicate this list
    ε                 # Map both snakes to:
     γ                #  Split the snake into chunks of the same character-type
      ʒ'|å]          '#  And only leave the chunks of "|" characters
    ©                 #  Store this list in variable `r` (without popping)
     ε                #  Map the "|" chunks of both snakes again:
      g              #  Get the length of each chunk of "|"
        xø            #  Pair each length with double itself
          DgU`XG‘   #  Create all possible combinations for the current snake
     ]`â              # After the map: create all possible combinations for both snakes
        ε             # Map over each possible combination
         ˜O           #  Get the flattened sum
            I„| Ãg    #  Count the amount of "|" and spaces in the input
                  >‹  #  Check if it's smaller than or equal to this sum
                      #  (1 if truthy; 0 if falsey)
           D        * #  And multiply it by the sum
        }ZQ           # After the map, get the positions of the largest flattened sum,
                      # still below (or equal to) the amount of "|" and spaces combined
       D   Ï          # And only keep those combinations
ε                     # Then map over the remaining combinations
 ˜ε                   #  Flatten it, and map over each value `y`
   ®˜Nè               #   Get the `N`'th part of the snakes
                      #   (where `N` is the index of the map for the current combination)
       D              #   Duplicate this "|"-part
        gyÊi          #   If the length of this "|"-part is not equal to the map-value:
            „/\       #    Push the string "/\"
               y     #    Extended to a size equal to the map-value
                      #   (implicit else:
                      #    use the duplicated value)
                    # After the map: only leave the first (since we don't have
                      # to output all possibilities)
 ©                    # Store it in variable `r` (without popping)
  J'/¢               '# Count the amount of "/" in it
      Ið¢             # Count the amount of spaces in the input
         α            # Get the difference between those
          ð×ý         # And join the list of snakes by that many spaces
'|¡õK                '# Then split by one or multiple adjacent "|"
     ®.ι              # Interleave it with the modified parts of variable` r`
        J             # And join everything together to a single string
Iðå≠i                 # If the input didn't contain any spaces:
     I                #  Output the input instead
                      # (implicit else:
                      #  output the top of the stack before this if)
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.