Конкатенация строк с контекстом

13

Строки с контекстом

Для целей этой задачи строка с контекстом представляет собой тройку строк, называемых левым контекстом , частью данных и правым контекстом . Он представляет подстроку более длинной строки. Мы используем вертикальную трубу |в качестве разделителя, поэтому пример строки с контекстом: cod|e-go|lfгде левый контекст cod, данные e-goи правый контекст lf. Этот пример представляет собой подстроку e-goиз code-golf.

Теперь, чтобы объединить две строки с контекстом, мы поступим следующим образом, используя aa|bcc|deeи в cc|de|eeeкачестве примеров. Мы выравниваем строки как на диаграмме

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

так что их части данных являются смежными. Часть данных конкатенации в данном случае является конкатенацией частей данных bccde. В этом случае левый контекст - это часть, которая расширяет дальше слева от первой части данных aa. Точно так же правильный контекст eee, поэтому конкатенация - это строка с контекстом aa|bccde|eee. Для второго примера рассмотрим a|bb|cdи aabb|cd|, где второе слово имеет пустой правый контекст. Диаграмма выравнивания

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

где левый контекст второго слова распространяется дальше, чем первый. Конкатенация есть aa|bbcd|.

Но подождите, есть ошибка: если буквы диаграммы выравнивания не совпадают, конкатенация не существует! В качестве примера, диаграммы aa|bb|ccи c|c|cIS

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

где bи cв четвертой колонке не согласны, поэтому они не могут быть объединены.

Задание

Ваша задача - написать программу, которая принимает две строки с контекстом, части которого разделены, |как указано выше, и выводит их конкатенацию, если она существует, и что-то еще, если нет. «Что-то еще» может быть любым значением, включая отсутствие вывода, если оно не является допустимой строкой с контекстом и одинаково во всех случаях. Однако выбрасывание ошибки не допускается. Вы можете указать либо программу STDIN-to-STDOUT, либо функцию, и анонимные функции также принимаются. Наименьшее количество байтов выигрывает, и стандартные лазейки запрещены.

Тестовые случаи

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
источник

Ответы:

4

Хаскелл, 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=(/='|')

пример выполнения:

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

если совпадения не найдено, будет возвращена пустая строка. в противном случае результат будет возвращен.

частичное объяснение:

# это функция, которая получает две строки и возвращает, совпадают они или нет.

! получает две строки и возвращает первую, соединенную с дополнительным символом от второй (если есть).

основная функция &использует span (/='|')для разделения входных данных на две части, a|b|cчтобы a, b|cпроверить соответствие контекстов, а затем !дважды использовать для сборки выходных данных.

Редактировать: маг-поздний регольфинг кажется довольно эффективным.

гордый хаскеллер
источник
Хм, я боюсь, что выдача ошибки не является приемлемым методом вывода, особенно для функции. Добавление |1<2=""к определению &должно решить это. Извините, я не указал это более явно в спецификации, я отредактирую это.
Zgarb
@ Zgarb На самом деле, это не исправит это. Возвращает строку со слишком большим количеством '|'знаков, когда строки не совпадают, хорошо?
гордый haskeller
Конечно, пока это одна и та же строка для всех несоответствующих входов.
Згарб
3

Python (242 байта)

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

объяснение

Лямбда-функция mвозвращает длинную из двух строк, если они имеют общий префикс. Она делает это путем конкатенации пустой строки ''вместо каких - либо недостающих значений, то поворачивая результат (который может принимать формы aa, ab, aили bв случаях матча / рассогласование / разная длина) в набор уникальных символов в каждой позиции. joinожидает один аргумент, поэтому распаковка набора с более чем одним элементом вызовет повышение значения TypeError.

Основная функция тогда

  • использует mдля объединения левого контекста и части данных первое слово с левым контекстом второго (справа налево поверх перевернутых строк)
  • объединяет части данных,
  • и снова использует mдля объединения правого контекста первого слова с частью данных и правого контекста второго

Части данных двух исходных слов обрезаются с правой и левой сторон нового контекста.

Поскольку мы знаем, что смещение вызывает mповышение TypeError, в этих случаях мы ловим исключение и возвращаемся неявно None.

тестирование

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

Выход

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
источник