Concatenar cadenas con contexto

13

Cadenas con contexto

Para los propósitos de este desafío, una cadena con contexto es un triple de cadenas, llamada contexto izquierdo , parte de datos y contexto derecho . Representa una subcadena de una cadena más larga. Usamos la tubería vertical |como separador, por lo que un ejemplo de una cadena con contexto es cod|e-go|lf, donde está el contexto izquierdo cod, los datos e-goy el contexto correcto lf. Este ejemplo representa la subcadena e-gode code-golf.

Ahora, para concatenar dos cadenas con contexto, procedemos de la siguiente manera, usando aa|bcc|deey cc|de|eeecomo ejemplos. Alineamos las cuerdas como en el diagrama.

a a|b c c|d e e
      c c|d e|e e e

para que sus partes de datos sean adyacentes. La parte de datos de la concatenación es la concatenación de las partes de datos, en este caso bccde. El contexto de la izquierda es la parte que extiende los elementos hacia la izquierda de la primera parte de datos, en este caso aa. Del mismo modo, el contexto correcto es eee, por lo que la concatenación es la cadena con contexto aa|bccde|eee. Para un segundo ejemplo, considere a|bb|cdy aabb|cd|, donde la segunda palabra tiene un contexto derecho vacío. El diagrama de alineación es

  a|b b|c d
a a b b|c d|

donde el contexto izquierdo de la segunda palabra se extiende más allá del de la primera. La concatenación es aa|bbcd|.

Pero espera, hay un problema: si las letras del diagrama de alineación no coinciden, ¡la concatenación no existe! Como ejemplo, el diagrama de aa|bb|ccy c|c|ces

a a|b b|c c
      c|c|c

donde la by cen la cuarta columna no están de acuerdo, por lo que no se pueden concatenar.

La tarea

Su trabajo consiste en escribir un programa que tome dos cadenas con contexto cuyas partes estén separadas por |lo anterior, y genere su concatenación si existe, y algo más si no. El "algo más" puede ser cualquier valor, sin salida, siempre que no sea una cadena válida con contexto y sea igual en todos los casos. Sin embargo, arrojar un error no es aceptable. Puede asignar un programa STDIN a STDOUT o una función, y también se aceptan funciones anónimas. El conteo de bytes más pequeño gana, y las lagunas estándar no se permiten.

Casos de prueba

aa|bcc|dee cc|de|eee -> aa|bccde|eee
a|bb|cd    aabb|cd|  -> aa|bbcd|
a|b|cccd   aab|cc|c  -> aa|bcc|cd
a|b|c      b||cd     -> a|b|cd
aa|bb|cc   c|c|c     -> None
aaa|b|c    abb|cd|d  -> None
|bb|cd     abb|c|ed  -> None
a|b|c      a||cd     -> None
Zgarb
fuente

Respuestas:

4

Haskell, 184 182 201 199 155

s&t|(a,'|':b)<-f t,(x,'|':y)<-f$r s,x#b,a#y=r(y!r a)++b!r x|0<1=""
r=reverse
a!b=a++drop(length a-1)b
(#)a=and.zipWith(==)(r a).filter h
f=span h
h=(/='|')

ejemplo ejecutado:

"|a|"&"|b|" -- returns "|ab|"
"|a|x"&"|b|" -- returns ""

Si no hay una coincidencia, se devolverá una cadena vacía. de lo contrario el resultado sería devuelto.

explicación parcial:

# es una función que obtiene dos cadenas y devuelve si coinciden o no.

! obtiene dos cadenas y devuelve la primera concatenada con caracteres adicionales de la segunda (si hay alguna).

la función principal &utiliza span (/='|')para dividir las entradas en dos partes, a|b|cpara a, b|c, comprueba si los contextos coinciden, y luego utiliza! dos veces para ensamblar la salida.

Editar: el regolfing mago tardío parece ser bastante efectivo.

orgulloso Haskeller
fuente
Hmm, me temo que arrojar un error no es un método de salida aceptable, especialmente para una función. Agregar |1<2=""a la definición de &debería resolver eso. Lo siento, no especifiqué esto más explícitamente en las especificaciones, lo
editaré
@ Zgarb En realidad, esto no lo solucionaría. ¿Devuelve una cadena con demasiados '|'signos cuando las cadenas no coinciden?
orgulloso Haskeller
Claro, siempre que sea la misma cadena para todas las entradas no coincidentes.
Zgarb
3

Python (242 bytes)

import itertools as i
s='|'
j=''.join
r=reversed
m=lambda a,b:j(j(*set(p+q))for p,q in i.izip_longest(a,b,fillvalue=''))
def c(A,B):
 u,v,w,x,y,z=(A+s+B).split(s)
 try:return j(r(m(r(u+v),r(x))))[:-len(v)]+s+v+y+s+m(w,y+z)[len(y):]
 except:0

Explicación

La función lambda mdevuelve la más larga de dos cadenas siempre que compartan un prefijo común. Esto se hace mediante la concatenación de la cadena vacía '', en lugar de cualquiera de los valores que faltan, a continuación, girando el resultado (que puede tomar la forma aa, ab, a, o ben los casos de coincidencia / no coincide / longitudes desiguales) en un conjunto de caracteres únicos en cada posición. joinespera un único argumento, por lo que desempaquetar un conjunto con más de un elemento hará que genere a TypeError.

La función principal entonces

  • se utiliza mpara combinar el contexto izquierdo y la parte de datos de la primera palabra con el contexto izquierdo de la segunda (de derecha a izquierda sobre cadenas invertidas)
  • concatena partes de datos,
  • y nuevamente se usa mpara combinar el contexto correcto de la primera palabra con la parte de datos y el contexto correcto de la segunda

Las partes de datos de las dos palabras originales se recortan de los lados derecho e izquierdo de los nuevos contextos.

Como sabemos que las desalineaciones provocan mun a TypeError, en estos casos captamos la excepción y regresamos implícitamente None.

Pruebas

TESTCASES = [
    ('aa|bcc|dee', 'cc|de|eee', 'aa|bccde|eee'),
    ('a|bb|cd', 'aabb|cd|', 'aa|bbcd|'),
    ('a|b|cccd', 'aab|cc|c', 'aa|bcc|cd'),
    ('a|b|c', 'b||cd', 'a|b|cd'),
    ('aa|bb|cc', 'c|c|c', None),
    ('aaa|b|c', 'abb|cd|d', None),
    ('|bb|cd', 'abb|c|ed', None),
    ('a|b|c', 'a||cd', None),
]

for A, B, R in TESTCASES:
    print '{:<10} {:<9} -> {}'.format(A, B, c(A, B))

Salida

aa|bcc|dee cc|de|eee -> aa|bccde|eee
a|bb|cd    aabb|cd|  -> aa|bbcd|  
a|b|cccd   aab|cc|c  -> aa|bcc|cd 
a|b|c      b||cd     -> a|b|cd    
aa|bb|cc   c|c|c     -> None      
aaa|b|c    abb|cd|d  -> None      
|bb|cd     abb|c|ed  -> None      
a|b|c      a||cd     -> None  
Greg
fuente