Haz el beso de las serpientes elásticas


57

Una serpiente elástica se ve así:

<||=|||:)~

Cada secuencia separada de barras verticales ( |) en una serpiente elástica, conocida como una porción elástica , es extensible individualmente al doble de su ancho, y se dibuja con barras alternas ( /, \) una vez extendidas.

La serpiente particular de arriba tiene dos porciones elásticas, que le dan cuatro poses posibles:

<||=|||:)~

</\/\=|||:)~

<||=/\/\/\:)~

</\/\=/\/\/\:)~

La forma general de una serpiente elástica en su pose menos estirada se define por esta expresión regular :

<(\|+=)*\|+:\)~

Que puede expresarse en palabras como:

<, seguido de cualquier número de secuencias de |'s unidas con =signos, seguido de :)~.

So <|:)~y <||:)~y <|=|:)~y <|=|=||=|||||=||:)~son serpientes elásticas, pero <=:)~y <=|:)~y <||=:)~y <|==||:)~no lo son.

Las serpientes elásticas también pueden mirar hacia la izquierda en lugar de hacia la derecha, por ejemplo ~(:|||=||>. Las formas son las mismas, solo reflejadas.

Desafío

Escriba un programa que tome una cadena de una sola línea de dos serpientes elásticas una frente a la otra, con cierto número de espacios en el medio. Ambas serpientes estarán en su postura menos estirada (todas las barras verticales, sin barras). La cadena comenzará con la cola de la serpiente que mira hacia la derecha y terminará con la cola de la serpiente que mira hacia la izquierda (opcionalmente, puede suponer que también hay una nueva línea final).

Por ejemplo, aquí hay una posible entrada con cinco espacios entre las serpientes:

<|=||:)~.....~(:||||>

Estoy usando puntos ( .) en lugar de caracteres espaciales reales para mayor claridad.

Cero espacios entre serpientes también es una entrada válida:

<|=||:)~~(:||||>

Decimos que las serpientes se besan cuando sus lenguas se tocan así.

Su programa necesita extender alguna combinación de las partes elásticas de ambas serpientes para que las serpientes tengan la menor cantidad de espacios posibles entre ellas (sin superponerse), es decir, para que las serpientes estén tan cerca de besarse como sea posible .

Ambas colas de las serpientes están fijas, pero sus cabezas y cuerpos pueden moverse, derecha para la serpiente que mira hacia la derecha, izquierda para la serpiente que mira hacia la izquierda, de acuerdo con las porciones elásticas que se han extendido.

La salida de su programa es la cadena de una sola línea (más la nueva línea final opcional) que muestra a las serpientes lo más cerca posible de besarse, con barras diagonales alternadas en lugar de barras verticales para las porciones elásticas que se han extendido.


Por ejemplo, la salida para <|=||:)~.....~(:||||>(desde arriba) sería:

</\=||:)~~(:/\/\/\/\>

Esta es la única solución aquí porque con cualquier otra combinación de las porciones elásticas extendidas, las serpientes se superpondrían o estarían más lejos de besarse.


Si hay varias soluciones posibles, la salida puede ser cualquiera de ellas.

Por ejemplo, si la entrada fuera

<|=||:)~.....~(:|||=|>

la salida podría ser

<|=/\/\:)~~(:/\/\/\=|>

o

</\=||:)~~(:/\/\/\=/\>

Recuerda que no siempre será posible besar a las serpientes, pero aún así necesitas acercarlas lo más posible.

Por ejemplo, si la entrada fuera

<||=||||:)~...~(:||>

la salida podría ser

</\/\=||||:)~.~(:||>

o

<||=||||:)~.~(:/\/\>

Si las serpientes ya se están besando, la salida será la misma que la entrada. p.ej

<|=||:)~~(:||||>

En general, la salida será la misma que la entrada si la extensión de cualquier parte elástica haría que las serpientes se superpongan. p.ej

<|||=|||:)~..~(:||||=|||||=||||||>

Notas

  • Toma la entrada de stdin o la línea de comando como de costumbre, o escribe una función que toma una cadena. Imprime o devuelve la salida.
  • Puede usar puntos ( .) en la entrada y salida en lugar de espacios ( ) si lo prefiere.
  • Solo es importante que las barras se alternen dentro de la secuencia de barras verticales que reemplazaron. Su orden en la serpiente en general o si un corte hacia adelante o hacia atrás es lo primero no importa.
  • Las partes elásticas no pueden extenderse hasta la mitad: es exactamente el doble o ninguna extensión.

Puntuación

Este es el código de golf . La presentación más corta en bytes gana. Tiebreaker es la respuesta anterior.


17
Snex Education 101 - Cómo besarse correctamente
Optimizer

45
"Decimos que las serpientes se besan cuando sus lenguas se tocan así". ¿Qué estoy leyendo ...
Fatalize

8
¿Entonces las serpientes solo hacen francés?
Optimizador

3
@PeterTaylor Bueno, "reflejado", no "invertido" (de lo contrario >no se convertiría <tampoco, lo mismo para (y )), pero también dice "Es importante que las barras se alternen dentro de la secuencia de barras verticales que reemplazaron. serpiente en general o si una barra diagonal hacia adelante o hacia atrás es lo primero "
Martin Ender

77
@qwr Imaginación.
Calvin's Hobbies

Respuestas:


9

CJam, 87 71 70 68 bytes

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

Pruébelo en línea en el intérprete de CJam .

Cómo 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 fines de conteo, cada línea va en un archivo separado, pero puede ejecutar el código desde un solo archivo con la -sbandera.

Reúne las mejores características de .NET regex y Retina: grupos de equilibrio, búsquedas arbitrarias de longitud arbitraria y repetidas sustituciones de expresiones regulares.

Esencialmente, la expresión regular larga codifica una solución válida y el rastreador del motor de expresión regular encuentra uno de los mejores para mí.

Explicación

Primero, consideremos cómo podemos encontrar una solución válida (no necesariamente produciendo la salida correcta) con una expresión regular. Podemos usar los grupos de equilibrio de .NET para ayudarnos a contar las partes elásticas. Considere la siguiente expresión regular más simple:

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

Podemos diseccionar eso.

\S+( )+.+

Esto coincide con la cadena completa, empujando una captura en la 1pila de grupo para cada espacio en la entrada. Usaremos esa pila para asegurarnos de que las partes elásticas llenen exactamente el espacio capturado en esos grupos.

El siguiente es un vistazo atrás. El problema es que las retrospectivas coinciden de derecha a izquierda en .NET (así es como debe leerlas). Esto nos da la oportunidad de atravesar la cadena por segunda vez, averiguar si hay un subconjunto de partes elásticas que sume al número de espacios coincidentes. Pasando por el lookbehind de derecha a izquierda:

>

Esto es solo para asegurarnos de que realmente estamos comenzando desde el final de la cadena (la cola de la serpiente).

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

Para cada parte elástica, esto solo coincide con la parte completa sin hacer nada ( \|+), o coincide con la parte completa al extraer las capturas de la pila 1( (?<-1>\|)*). Tener esta alternancia asegura que solo podamos extender completamente una parte elástica o dejarla sin cambios, y no obtener cosas como |/\|. Luego pasamos a la siguiente parte elástica con [^|]+.

(?(1)!)^

Finalmente, nos aseguramos de que hemos atravesado toda la cadena (ambas serpientes), y esa pila 1está completamente vacía. Es decir, hemos encontrado un subconjunto de partes elásticas que se suma exactamente al número de espacios que hemos capturado anteriormente.

El rastreador retrocederá de un lado a otro a través de la cadena intentando todas las combinaciones de partes extendidas y sin cambios hasta que se resuelva el problema de la suma de subconjuntos. Si tal subconjunto no existe, la retrospectiva fallará. Esto hará que el rastreador regrese a la \S+( )+.+pieza e intente capturar un espacio menos con ( )+(que en su .+lugar se cubrirá ). Debido a la avaricia de +, por lo tanto, intentamos llenar tantos espacios como sea posible.

Puede verificar la validez de este enfoque con esta sustitución ligeramente modificada:

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

Lo que le dará una cadena =spaces=con exactamente el número de espacios que se pueden llenar con las serpientes dadas.

Tuve que agregar algunos trucos más para expandir realmente el |s correcto . Básicamente, quiero reemplazar todos los correos |electrónicos que coinciden con la (?<-1>\|)+rama. La idea es hacer coincidir un personaje individual, poner el solucionador en una búsqueda y establecer una bandera si la coincidencia está dentro de esa rama. Si esa bandera no se estableció, invalidamos la coincidencia al final para evitar el reemplazo de otros personajes.

Para hacer esto, usamos un montón de miradas anidadas. Nuevamente, los lookbehinds de longitud variable de .NET coinciden de derecha a izquierda, por lo que si anidamos lookaheads y lookbehinds, podemos dejar que el motor regex atraviese la cadena varias veces. Por razones de golf, el solucionador se invierte en mi solución real (comenzando por el final, recogiendo los espacios de derecha a izquierda y luego resolviendo la suma del subconjunto de izquierda a derecha), pero de lo contrario la estructura del solucionador es exactamente la misma . Vamos a diseccionar la expresión regular completa:

.(?=(.+)...)

Hacemos coincidir un solo carácter, luego capturamos el resto de la cadena y movemos el cursor al final de la cadena. Usaremos este grupo 1más tarde para verificar en el solucionador si estamos en la posición del partido.

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

Esto es como la primera parte del solucionador simple anterior, excepto que recogemos los espacios de derecha a izquierda. El retroceso del número de espacios funciona exactamente igual que antes, excepto que 5ahora estamos usando group .

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

Esto es lo mismo que antes, excepto que vamos de izquierda a derecha, y cada vez que hacemos coincidir una |en la rama en expansión, verificamos si es la que coincide con la derecha

(?=\1())?

Esta es una búsqueda anticipada opcional. Intenta hacer coincidir el grupo 1nuevamente (lo cual, aquí, solo es posible si estamos justo después del carácter que coincide), y si lo hacemos, capturamos una cadena vacía en el grupo 4, lo que indica que encontramos el carácter actual en uno de los bits expandidos. Si \1no coincide, 4no capturará nada, y ?garantiza que la búsqueda anticipada que falla no afectará en absoluto al solucionador.

Finalmente, después de que se haya resuelto todo, solo verificamos \4si se utilizó esta búsqueda anticipada. Si es así, queremos reemplazar el carácter actual con /\.

Queda una dificultad: eliminar la cantidad correcta de espacios. La forma más corta de hacer esto que he encontrado hasta ahora es insertar un espacio junto con el /\y luego eliminar un espacio entre las lenguas para cada uno de esos espacios marcadores en un paso separado:

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

6

Rubí 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 es una función que toma una cadena como parámetro y devuelve una cadena.

Pruebas en línea: http://ideone.com/uhdfXt

Aquí está la versión legible:

# 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
}

En la versión de golf, la función principal es el equivalente de la KISSfunción anterior, y la COMBINATIONSfunción ha sido en línea.


Falla en la entrada <|=||:)~~(:||||>, que la especificación menciona es una 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","/\\")

Tener una sola lambda se ve bien y todo, pero estoy casi seguro de que esta no es la mejor manera de hacerlo. Pero estoy publicando esto porque es todo lo que tengo hasta ahora que parece medio decente.

Esta es una fuerza bruta simple sobre todos los posibles reemplazos de |with /\, filtrando las configuraciones inválidas. El único poco aseado que supongo es que en realidad no reemplaza ninguna |con /\directamente - en primer lugar reemplazamos |con Xy coloca una .de la media para cada reemplazo, tomar la cadena de longitud mínima sobre todas las cadenas válidas y vuelva a colocar los Xs con /\.

Intenté algunos otros enfoques, incluidos los recursivos, pero terminaron siendo bastante desordenados. También aprendí que re.splitactualmente no se divide en cadenas vacías, lo cual fue desafortunado, porque una de mis ideas implicaba dividir en \blímites de palabras.


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~"~"&

Función pura tomando la cadena como argumento. Espera .más que entre las serpientes.

No pensé que sería tan malo ... Esto es lo que tenía antes de juntarlo y fijar todo.

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[#, "~"] &

Aquí hay un ejemplo de explicación:

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.

Fácilmente reducido a 355 al comenzar a=StringReplace;b=StringSplit;c=StringLength;d=Total;y luego sustituirlos según sea necesario en otro lugar 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

Prólogo (ECLiPSe), 438 bytes

Mis otras respuestas fueron resolver el problema incorrecto (perdón por el ruido). Aquí hay otro intento en Prolog que realmente respeta todas las reglas.

:-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).

Pruebas

(formato: entrada, salida, nueva línea)

<===:)~         ~(:>
<===:)~         ~(:>

<|||:)~         ~(:||||=|>
</\/\/\:)~ ~(:/\/\/\/\=/\>

<=|=:)~         ~(:||||=|>
<=/\=:)~   ~(:/\/\/\/\=/\>

<===|:)~         ~(:||=|>
<===/\:)~     ~(:/\/\=/\>

<|=|=|||=|:)~         ~(:=|>
</\=/\=/\/\/\=/\:)~  ~(:=/\>

<||||||:)~         ~(:=|>
</\/\/\/\/\/\:)~  ~(:=/\>

<||||||:)~         ~(:||>
</\/\/\/\/\/\:)~ ~(:/\/\>

<||=||||:)~ ~(:||>
<||=||||:)~ ~(:||>

<||=||||:)~   ~(:||>
</\/\=||||:)~ ~(:||>

<||=||||:)~    ~(:||>
</\/\=||||:)~~(:/\/\>

<||=||||:)~~(:||>
<||=||||:)~~(:||>

Explicaciones

  • El predicado principal es s/2, que toma la entrada como primer argumento y descalifica el resultado con el segundo argumento (ambas cadenas). La entrada es convertida a una lista de códigos de caracteres, E.

  • Luego, s(E,Z,X,Y,L)desestructura la lista en los siguientes elementos:

    • Z cantidad de espacios entre serpientes
    • Xy Y, representación abstracta de los cuerpos izquierdo y derecho

      El formato de un cuerpo es una lista de n:No s:Nexpresiones, donde Nes una longitud positiva; nmedios normaly smedios stretched.

    • L longitud total de la lista

Lo interesantes/5 es que va en ambos sentidos , es decir, podemos construir una serpiente si se instancian otros argumentos:

    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.
  • Construimos cuerpos izquierdos y derechos modificados donde cada parte es normal o estirada, mientras minimizamos el espacio Qque separa a las nuevas serpientes. La longitud total de la cadena calculada está limitada para que la búsqueda finalice.

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 no golf aquí -

#!/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)

Probar la solución de golf -

$ 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] =>  <|=||:)~~(:||||>

Seguramente esto se puede hacer mejor (no puedo entender cómo :)).
Avíseme si me he perdido algo obvio mientras jugaba al golf (es mi primer codegolf, puedo estar haciendo algo estúpido: P)


@ Sp3000 Esa es una buena. Reemplazado exitpor sys.exit()(olvidado exitexistió). Y tienes razón, __import__se puede eliminar, eso se eliminó como 20 caracteres :)
Kamehameha

por cierto regla general: para el alias necesita > 6caracteres que valen el alias si lo usa dos veces, > 3caracteres si lo usa tres veces. No estoy seguro de que el f=' 'alias valga la pena (cuento dos veces)
Sp3000

@ Sp3000 sí tienes razón. En una versión anterior, había usado esa variable tres veces. Me salvó otro 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

Demasiado tiempo ..>.>

Pruébelo en línea o verifique todos los casos de prueba o verifique todos los resultados posibles para todos los casos de prueba .

Explicación:

#õ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)
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.