Połącz łańcuchy z kontekstem

13

Ciągi z kontekstem

Na potrzeby tego wyzwania ciąg z kontekstem jest potrójnym ciągiem zwanym lewym kontekstem , częścią danych i prawym kontekstem . Reprezentuje podciąg dłuższego łańcucha. Używamy pionowej rury |jako separatora, więc przykładem łańcucha z kontekstem jest cod|e-go|lf, gdzie jest lewy kontekst cod, dane są e-go, a prawy kontekst lf. Ten przykład przedstawia podciąg e-gow code-golf.

Teraz, aby połączyć dwa ciągi z kontekstem, postępujemy w następujący sposób, używając aa|bcc|deei cc|de|eeejako przykładów. Wyrównujemy ciągi jak na schemacie

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

tak aby ich części danych sąsiadowały. W tym przypadku częścią danych konkatenacji jest konkatenacja części danych bccde. Lewy kontekst to część, która rozciąga się dalej na lewo od pierwszej części danych, w tym przypadku aa. Podobnie jest właściwy kontekst eee, więc konkatenacja jest ciągiem z kontekstem aa|bccde|eee. W drugim przykładzie zastanów się, a|bb|cda aabb|cd|gdy drugie słowo ma pusty prawy kontekst. Schemat wyrównania to

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

gdzie lewy kontekst drugiego słowa rozciąga się dalej niż pierwszy. Konkatenacja jest aa|bbcd|.

Ale poczekaj, jest gotcha: jeśli litery na schemacie wyrównania nie pasują, konkatenacja nie istnieje! Na przykład, w schemacie aa|bb|ccoraz c|c|cIs

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

gdzie bi cw czwartej kolumnie się nie zgadzają, więc nie można ich połączyć.

Zadanie

Twoim zadaniem jest napisanie programu, który przyjmuje dwa ciągi z kontekstem, którego części są oddzielone |jak powyżej, i wyświetla ich konkatenację, jeśli istnieje, i coś innego, jeśli nie. „Coś innego” może mieć dowolną wartość, w tym brak danych wyjściowych, o ile nie jest to prawidłowy ciąg znaków z kontekstem i jest taki sam we wszystkich przypadkach. Zgłaszanie błędu jest jednak niedopuszczalne. Możesz podać program STDIN-to-STDOUT lub funkcję, a funkcje anonimowe są również akceptowane. Wygrywa najmniejsza liczba bajtów, a standardowe luki są niedozwolone.

Przypadki testowe

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
źródło

Odpowiedzi:

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=(/='|')

przykładowy bieg:

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

jeśli nie ma dopasowania, zostanie zwrócony pusty ciąg. w przeciwnym razie wynik zostanie zwrócony.

częściowe wyjaśnienie:

# jest funkcją, która pobiera dwa ciągi i zwraca, czy pasują do siebie.

! pobiera dwa ciągi znaków i zwraca pierwszy połączony z dodatkowym znakiem z drugiego (jeśli istnieją).

główna funkcja &używa span (/='|')do podzielenia danych wejściowych na dwie części, a|b|caby a, b|csprawdzić, czy konteksty pasują, a następnie używa !dwa razy do złożenia danych wyjściowych.

Edycja: regolfing pod koniec magów wydaje się dość skuteczny.

dumny haskeller
źródło
Hmm, obawiam się, że zgłoszenie błędu nie jest akceptowalną metodą wyjściową, szczególnie dla funkcji. Dodanie |1<2=""do definicji &powinno rozwiązać ten problem. Przepraszam, że nie
podałem
@Zgarb Właściwie to by tego nie naprawiło. Czy zwracanie łańcucha ze zbyt dużą liczbą '|'znaków, gdy łańcuchy nie pasują, jest w porządku?
dumny haskeller
Jasne, o ile jest to ten sam ciąg znaków dla wszystkich niepasujących danych wejściowych.
Zgarb
3

Python (242 bajty)

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

Wyjaśnienie

Funkcja lambda mzwraca dłuższy z dwóch ciągów, o ile mają one wspólny przedrostek. Czyni to poprzez złączenie pusty łańcuch ''w miejsce brakujących wartości, a następnie obracając wynik (który może przyjąć formy aa, ab, a, lub bw przypadku meczu / niedopasowanie / nierówne długości) na zestaw unikalnych znaków w każdej pozycji. joinoczekuje jednego argumentu, więc rozpakowanie zestawu z więcej niż jednym elementem spowoduje, że podniesie on wartość TypeError.

Główna funkcja wtedy

  • używa mdo połączenia lewego kontekstu i części danych pierwszego słowa z lewym kontekstem drugiego (od prawej do lewej po odwróconych ciągach)
  • łączy części danych,
  • i ponownie używa mdo połączenia właściwego kontekstu pierwszego słowa z częścią danych i odpowiedniego kontekstu drugiego

Części danych dwóch oryginalnych słów są przycinane z prawej i lewej strony nowych kontekstów.

Ponieważ wiemy, że przesunięcia powodują mpodniesienie a TypeError, w takich przypadkach wychwytujemy wyjątek i domyślnie wracamy None.

Testowanie

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

Wynik

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
źródło