Odejmowanie ciągów

37

Cel

Utwórz funkcję, aby odwrócić konkatenację łańcucha

Wkład

Dwa ciągi (alfanumeryczne + spacje), gdzie jeden należy odjąć dla drugiego.

  • Możesz założyć, że ciąg do odjęcia nigdy nie będzie większy niż drugi.

Wydajność

Wynik odejmowania

Odejmowanie

Powinieneś usunąć jeden ciąg z początku lub końca innego ciągu. Jeśli ciąg jest obecny na początku i na końcu, możesz usunąć tylko jeden, który zostanie usunięty, zależy od Ciebie.
Jeśli ciąg nie znajduje się na początku ani na końcu, lub nie jest dokładnym dopasowaniem, oznacza to nieprawidłowe odejmowanie i należy wypisać oryginalny ciąg.

Przypadki testowe

Prawidłowe odejmowanie

'abcde','ab' -> 'cde'
'abcde','cde' -> 'ab'
'abab','ab' -> 'ab'
'abcab','ab' -> 'abc' or 'cab'
'ababcde','ab' -> 'abcde'
'acdbcd','cd' -> 'acdb'
'abcde','abcde' -> ''
'abcde','' -> 'abcde'
'','' -> ''

Nieprawidłowe odjęcie (zwraca oryginalny ciąg)

'abcde','ae' -> 'abcde'
'abcde','aa' -> 'abcde'
'abcde','bcd' -> 'abcde'
'abcde','xab' -> 'abcde'
'abcde','yde' -> 'abcde'

Nieprawidłowe dane wejściowe (nie muszą być obsługiwane)

'','a' -> ''

To jest , więc wygrywa najkrótszy kod w bajtach!

Pręt
źródło
4
Dlaczego nie jest wynikiem pierwszego przypadku cde? Co rozumiesz przez „ważny”? Czy musimy oceniać ważność danych wejściowych, czy masz na myśli, że nie otrzymamy nieprawidłowych danych wejściowych?
Leaky Nun
7
Cholera 'abcde','bcd' -> 'abcde', za złamanie mojego rozwiązania
John Dvorak
5
Czy możemy założyć, że ciągi będą bezpieczne dla wyrażeń regularnych (znaki alfanumeryczne + spacje)?
John Dvorak
2
Sugerowałbym 'ababcde', 'ab''abcde'jako przypadek testowy. Niektóre naiwne algorytmy zawodzą na tym.
2
@Rod Możesz rozważyć ponowne określenie wyzwania „Odwrotna konkatenacja łańcuchów”?
MD XF

Odpowiedzi:

19

Java 8, 46 45 44 40 bajtów

-1 bajt dzięki TheLethalCoder

-1 bajt, bo jestem głupi (dzięki Rod!)

-4 bajty dzięki Kevin Cruijssen

a->b->a.replaceFirst("^"+b+"|"+b+"$","")

Wypróbuj online! (obejmuje wszystkie przypadki testowe)

Odpowiedź Java rzeczywiście przewyższa kilka innych praktycznych języków. Uśmiecha się (a teraz bije JS!)

Okx
źródło
Użyj curry, aby zapisać bajta->b->
TheLethalCoder
@TheLethalCoder Thanks.
Okx,
Dlaczego w swoim internetowym przykładzie pozostawiłeś nieużywany skrót?
Michael
Można zmienić First, aby Alldo -2 bajtów. Ze względu na ^i $zawsze znajduje się na końcu lub na początku łańcucha, więc nawet przy replaceAllnim zastępuje go tylko raz. Wypróbuj tutaj. PS: Dodałem poprzednie liczby bajtów przekreślone do twojej odpowiedzi, co zwykle dzieje się po edycji kodu w golfa tutaj na PPCG.
Kevin Cruijssen
@KevinCruijssen Wiedziałem o przekreśleniach, chyba zapomniałem tym razem. Jeśli jednak AllFirst"abab" + "ab" -> ""
użyję
9

JavaScript (ES6), 41 bajtów

s=>t=>s.replace(eval(`/^${t}|${t}$/`),'')

Pobiera dane wejściowe poprzez składnię curry, tj f("abab")("ab").

ETHprodukcje
źródło
3
Dlaczego nigdy wcześniej nie myślałem o użyciu eval()do konstruowania RegExes ?!
Kudłaty
9

Brachylog (Try It Online!), 12 bajtów

~cpĊh.∧Ċtw|w

Wypróbuj online!

Pobiera ciąg znaków do odjęcia od standardowego wejścia, a ciąg znaków do odjęcia jako argument wiersza poleceń.

Wyjaśnienie

~cpĊh.∧Ċtw|w
~c            Split {the input} into pieces
  p           and (possibly) rearrange those pieces
   Ċ          such that there are two pieces
    h         and the first
     .        matches the command line argument
      ∧       then
         w    print
        t     the last
       Ċ      piece.
          |   If all else fails,
           w  print {the input}.

źródło
6

Retina , 21 bajtów

1 bajt dzięki Martinowi Enderowi.

(.*);(\1|(.*)\1$|)
$3

Wypróbuj online!

Leaky Nun
źródło
6

JavaScript (ES6), 76 70 45 41 bajtów

s=>t=>s.replace(RegExp(`^${t}|${t}$`),"")

Spróbuj

f=
s=>t=>s.replace(RegExp(`^${t}|${t}$`),"")
o.innerText=f(i.value="abcde")(j.value="ab")
i.oninput=j.oninput=_=>o.innerText=f(i.value)(j.value)
<input id=i><input id=j><pre id=o>

Kudłaty
źródło
2
Nie trzeba new .
programista
@ programmer500, trochę przestałem pracować nad tym, kiedy zobaczyłem wersję ETH! : D Zaktualizowano teraz. Dzięki.
Kudłaty
4

Perl 6 , 21 bajtów

->$_,$b {S/^$b|$b$//}

Spróbuj

Rozszerzony:

-> $_, $b {   # pointy block lambda

  S/          # Str replace and return (implicitly against 「$_」)

  |   ^ $b    # starting with the second argument
  |     $b $  # or ending with the second argument

  //          # replace with nothing.

}
Brad Gilbert b2gills
źródło
3

TI-Basic (TI-84 Plus CE), 63 bajty

Prompt Str0,Str2
inString(Str0,Str2
If Ans
sub(Str0,1,Ans-1)+sub(Str0,Ans+length(Str2),length(Str0)-Ans+1-length(Str2→Str0
Str0
pizzapanty184
źródło
Mam pytanie, dlaczego nie użyłeś Str1 jako zmiennej?
Zacharý
@ Zacharý Myślę, że miałem w tym czasie coś do przechowywania. Naprawdę nie pamiętam.
pizzapants184
Co w Ansogóle odnosi się do czwartej linii?
Zacharý
@ Zacharý Ansodnosi się do ostatnio ocenianej wartości, więc w tym przypadku odnosi się do wartości zwróconej przez inString(, która jest indeksem podłańcucha Str2w ciągu Str0lub 0, jeśli podłańcuch nie pojawia się. Instrukcja if nie modyfikuje wartości Ans, więc w czwartym wierszu indeks jest nadal w Ans.
pizzapants184
Och, zapomniałem jak to inStringdziała. Niezły golf!
Zacharý
3

Mathematica, 162 bajty

(c=Characters;a=c@#;b=c@#2;l=Length;t={};If[l@Intersection[a,b]==l@b,If[MemberQ[Partition[a,l@b,1],b],t=a;Table[t=DeleteCases[t,b[[i]],1,1],{i,l@b}]],t=a];""<>t)&

testuj styl wprowadzania [„abcde”, „ab”]

J42161217
źródło
1
Fajne rozwiązanie! Możesz zapisać bajt, używając #zamiast #1- oznaczają dokładnie to samo. Ponadto, zamiast używać StringJoin@t, możesz oszukiwać, łącząc z nim pusty ciąg ""<>t, który automatycznie łączy również wszystko trazem. Czy widziałeś stronę ze wskazówkami golfowymi Mathematica ?
Nie drzewo
Jest jeszcze kilka rzeczy, które możesz zrobić, aby zaoszczędzić bajty (na przykład nie sądzę, że musisz definiować t={};na początku), ale może być łatwiej zastosować całkowicie inne podejście - czy próbowałeś użyć StringReplacefunkcjonować?
Nie drzewo
Możesz wziąć tablicę String jako dane wejściowe, więc tak naprawdę nie potrzebujeszc=Characters;a=c@#;b=c@#2;
JungHwan Min
Również l@Intersection[a,b]jest l[a∩b].
JungHwan Min
3

Python, 69 68 64 57 51 45 bajtów

Skończyło się to zupełnie innym rozwiązaniem z Regex.

Dzięki Value Ink za -2 bajty!
i Felipe Nardi Batista za ogromne -6 bajtów!

import re
lambda s,c:re.sub(c+'$|^'+c,'',s,1)

Wypróbuj online!

Artyer
źródło
Dla -2 bajtów:re.sub(c.join("^|$"),'',s,1)
Wartość tuszu
1
Dla -6 bajtów:c+'$|^'+c
Felipe Nardi Batista
3

Bash ,66 61 49 bajtów

case $1 in *$2)echo ${1%$2};;*)echo ${1#$2};;esac

Wypróbuj online!

mniej golfa:

a=$1;
case $1 in 
    *$2)  c=${a%$2};;       
    $2*)  c=${a#$2};;
      *)  c=$1;;
esac;
echo $c

Wykorzystuje wielkość liter do testowania początku lub końca oraz odejmowanie przedrostka / sufiksu tablicy (% / #)

marcosm
źródło
1
Ładne użycie case, ale dłużej niż to konieczne. 2. i 3. wzór mógłby zostać połączone w jeden: *)c=${1#$2};;. Potem tylko 2 oddziały byłby krótszy do echosiebie bezpośrednio, zamiast używać zmiennej $c: case $1 in *$2)echo ${1%$2};;*)echo ${1#$2};;esac. Czy można nadal używać go, ale bez case: c=${1%$2};[[ $c = $1 ]]&&c=${1#$2};echo $c.
manatwork
3

APL (Dyalog) , 31 30 bajtów

-1 dzięki Zacharý .

To faktycznie używa odwrotnej (tj. Odwrotnej) konkatenacji! Bierze oryginalny ciąg jako lewy argument, a co należy odjąć jako prawy argument.

{0::⍺{0::⍺⋄,∘⍵⍣¯1⊢⍺}⍵⋄⍵,⍣¯1⊢⍺}

Wypróbuj online!

Nie golfowany:

{
    0::⍺{          if an error happens, apply the following function on the arguments
        0::⍺           if an error happens, return the left argument unmodified
        ,∘⍵⍣¯1⊢⍺       inverse-append right argument on left argument
        }⍵
    ⍵,⍣¯1⊢⍺       inverse-prepend the right argument on the left argument
}

Legenda:

{} Anonimowa funkcja

 lewy argument bieżącej funkcji

 prawy argument bieżącej funkcji

0::… Jeśli wystąpi jakikolwiek błąd, wykonaj to, w przeciwnym razie…

⍣¯1⊢ odwrotność

,∘⍵ konkatenacja po prawej stronie

⍵, konkatenat po lewej stronie

Adám
źródło
Myślę, że możesz uratować bajt {0::⍺{0::⍺⋄,∘⍵⍣¯1⊢⍺}⍵⋄⍵,⍣¯1⊢⍺}.
Zacharý
@ Zacharý Tak, dziękuję.
Adám
2

Python 2 , 68 bajtów

def f(s,c):v=len(c);print[s[v:],s[:-v],s][[s[:v],s[-v:],c].index(c)]

Wypróbuj online!

Jonathan Allan
źródło
2

Haskell , 49 bajtów

f s a b|s==b=a|a/=b,h:t<-a=f(s++[h])t b|1<3=s
f""

Wypróbuj online! Zastosowanie: f"" "abcdef" "ab". Alternatywnie, zdefiniuj (-)=f""i użyj podobnie "abcdef" - "ab".

To rozwiązanie wolne od wyrażeń regularnych działa poprzez rekurencyjne dzielenie łańcucha na wszystkie jego przedrostki i przedrostki oraz sprawdzanie, czy ciąg, który ma zostać odjęty, pasuje do jednego z nich.

Laikoni
źródło
2

Python 2 , 72 65 bajtów

a,b=input()
l=len(b)
print[[a,a[:-l]][b==a[-l:]],a[l:]][b==a[:l]]

Wypróbuj online!

-7 bajtów dzięki @FelipeNardiBatista

ovs
źródło
grał w golfa
Felipe Nardi Batista
@FelipeNardiBatista wielkie dzięki!
ovs
1

C #, 88 bajtów

s=>r=>s.StartsWith(r)?s.Substring(r.Length):s.EndsWith(r)?s.Substring(0,s.IndexOf(r)):s;

Kompiluje do Func<string, Func<string, string>>.

TheLethalCoder
źródło
1

Ruby (wyrażenie lambda), 29 bajtów

->a,b{a.sub /^#{b}|#{b}$/,""}

Tak, interpolacja wyrażeń regularnych! Wymaga subthends-bezpiecznych wyrażeń regularnych, ale zgodnie z wyzwaniem jest to w porządku.

John Dvorak
źródło
1

Tcl , 37 bajtów

proc s {a b} {regsub "^$b|$b$" $a {}}

Wypróbuj online! (teraz uruchamiane wszystkie testy)

Tcl jest prosty. proc s {a b}definiuje nazwaną funkcję, sktóra pobiera parametry ai b. regsubpodstawia {}, czyli pusty ciąg, na wartość, bkiedy jest na początku lub na końcu a. Zwrot jest niejawny.

Michael Plotke
źródło
1

C, 96 bajtów

Powszechnie wiadomo, że manipulowanie strunami w C jest uciążliwe, ponieważ rozszerzenie gry w golfa byłoby skrajnym masochistycznym. Brzmi dla mnie w porządku.

f(a,b,t,l)char**a,*b,*t;{t=*a;l=strlen(b);bcmp(t,b,l)?bcmp(t+=strlen(t)-l,b,l)||(*t=0):(*a+=l);}

Jeden z mniej czytelnych programów, które napisałem. Pobiera dwa dane wejściowe (pomimo tego, jak wygląda funkcja), char**wskazując na ciąg, aby dekonkatować i char*który jest ciągiem, który należy usunąć. Wskaźnik wejściowy jest edytowany w miejscu i staje się wyjściem (kto i tak ma wątpliwości dotyczące wycieków pamięci).

Przykładowe użycie:

char *a = malloc(6);
strcpy(a, "abcde");
char *b = malloc(4);
strcpy(b, "abc");
f(&a,b);
printf("%s\n", a); // "de"
algmyr
źródło
1

AWK , 21 32 bajtów

{sub("^"$2"|"$2"$",z,$1);$0=$1}1

Wypróbuj online!

Oryginalne przesłanie naiwnie zastąpiło tekst w pierwszym ciągu, nie tylko na początku lub na końcu.

{sub($2,z,$1);$0=$1}1

Wypróbuj online!

Początkowo wypróbowany bez nawiasów klamrowych, ale wymagał sztuczek, aby wydrukować puste linie i / lub brak pasujących elementów, co ostatecznie spowodowało dodanie większej liczby bajtów niż ta wersja.

Robert Benson
źródło
1

R, 20 42 41 bajtów

pryr::f(sub(sprintf('^%s|%s$',b,b),'',a))

-1 bajt dzięki MickyT!

Zwraca anonimową funkcję (która ma argumenty w kolejności b,a). Oblicza różnicę ciągów a-b. subjest prostym podstawieniem, które zamienia pierwsze wystąpienie wzorca, w tym przypadku pusty ciąg ''. Konstruuje wyrażenie regularne w sprintfcelu dopasowania tylko na początku i na końcu łańcucha. Wymaga zainstalowania pryrpakietu.

W łączu TIO używa bardziej szczegółowej function(a,b)definicji funkcji dla czterech kolejnych bajtów.

Wypróbuj online!

Giuseppe
źródło
1
Co ze 'abcde','bcd' -> 'abcde'sprawą?
Jonathan Allan
subjest prostym podstawieniem, które po prostu zamienia pierwsze wystąpienie bin a”: Czy to zamieni się, jeśli drugi ciąg znajduje się w środku pierwszego ciągu?
TheLethalCoder
Źle odczytałem pytanie! Ups Dzięki za złapanie tego!
Giuseppe
możesz odzyskać 1 bajt zsprintf('^%s|%s$',b,b)
MickyT
@MickyT, dzięki! naprawiony.
Giuseppe,
1

Common Lisp, 121 bajtów

(lambda(x y)(cond((equal(#1=subseq x 0 #3=(length y))y)(#1#x #3#))((equal(#1#x #2=(-(length x)#3#))y)(#1#x 0 #2#))(t x)))

Wypróbuj online!

Zwykły marny Common Lisp!

Wersja bez golfa:

(defun f(x y)
  (cond ((equal (subseq x 0 (length y)) y)               ; if x starts with y
         (subseq x (length y)))                          ; return rest of x
        ((equal (subseq x (- (length x) (length y))) y)  ; if x ends with x
         (subseq x 0 (- (length x) (length y))))         ; return first part of x
        (t x)))                                          ; else return x
Renzo
źródło
1

Kotlin , 91 bajtów

{a,b->val v=b.length
if(a.startsWith(b))a.drop(v)else if(a.endsWith(b))a.dropLast(v)else a}

Wypróbuj online!

ślimak_
źródło
? {a,b->var c=a.removePrefix(b);if(a==c){c=a.removeSuffix(b)};c}
mazzy
@mazzy możesz przesłać to jako własną odpowiedź.
snail_
1

PowerShell, 34 40 bajtów

+6 bajtów po Invalid Subtractiondodaniu przypadków testowych

param($s,$t)$s-replace"^$t(?!.*$t$)|$t$"

Komentarz:

Wyrażenie regularne ^$t|$t$nie działa zgodnie z oczekiwaniami: zastępuje oba dopasowania zamiast jednego (flaga gzawsze włączona). Jesteśmy więc zmuszeni do korzystania z negatywnej grupy wyprzedzającej.

Skrypt testowy:

$f = {
    param($s,$t)$s-replace"^$t(?!.*$t$)|$t$"
}

@(
    ,('abcde','ab', 'cde')
    ,('abcde','cde', 'ab')
    ,('abab','ab', 'ab')
    ,('abcab','ab', 'abc', 'cab')
    ,('ababcde','ab', 'abcde')
    ,('acdbcd','cd', 'acdb')
    ,('abcde','abcde', '')
    ,('abcde','', 'abcde')
    ,('','', '')

    ,('abcde','ae', 'abcde')
    ,('abcde','aa', 'abcde')
    ,('abcde','bcd', 'abcde')
    ,('abcde','xab', 'abcde')
    ,('abcde','yde', 'abcde')

    ,('','a', '')
) | % {
    $s,$t,$e = $_
    $r = &$f $s $t
    "$($r-in$e): $r"
}

Wydajność:

True: cde
True: ab
True: ab
True: abc
True: abcde
True: acdb
True:
True: abcde
True:
mazzy
źródło
0

QBIC , 57 bajtów

Whegh, to jest bałagan w QBIC / QBasic ...

B=@ `+B┘x=instr(;,;)~x|?_t_sB,x-1|+_sB,x+_lC|,_lB|||\?B

B=@ `+B          Prepend a string to B$. Thisis a hack to avoid errors with 
                 removing substrings stating at index 1
┘                Line-break in QBasic output
       (;,;)     Read the string (B$) and the to-be-removed substring (C$)
x=instr          And make x to be the starting index of the first C$ in B$
~x|              IF X <> 0 (ie C$ is present in B$)
?                PRINT
 _t                trimmed version (drops the prepended space)
  _sB,x-1|+        of a substring from 1 to x (the start of C$) -1
  _sB,x+_lC|,_lB   and the rest of the string, starting after C$
                     _l takes the length of a string
  |||              End TRIM, end Substring, end Length
\?B              When missing C$, just print B$
Steenbergh
źródło
0

Lua , 71 65 bajtów

Przyjmowanie sugestii

a,b=...p='(.*)'print(a:match('^'..b..p)or a:match(p..b..'$')or a)

Wypróbuj online!

Felipe Nardi Batista
źródło
0

Początkowo źle odczytałem instrukcje. Dzięki, Ørjan Johansen za zwrócenie uwagi na mój błąd!

PowerShell , 46 51 bajtów

Function F($o,$a){([regex]"^$a").replace($o,'',1);}

Wypróbuj online!

Jeff Freeman
źródło
Nie udaje się to w przypadku „abcde” „bcd”.
Ørjan Johansen
Widzę oczekiwane wyniki z tego przypadku testowego - tutaj
Jeff Freeman
Jest to wymienione sprawdzian z PO i wynik powinien być abcde- bcdnie występuje na obu końcach łańcucha.
Ørjan Johansen
Masz rację. Źle odczytałem instrukcje. Dzięki za wskazanie tego!
Jeff Freeman
0

Excel, 129 bajtów

=IFERROR(IF(FIND(B1,A1)=1,SUBSTITUTE(A1,B1,"",1),IF(FIND(B1,A1,LEN(A1)-LEN(B1))>LEN(A1)-LEN(B1),LEFT(A1,LEN(A1)-LEN(B1)),A1)),A1)
Wernisch
źródło