Віднімання рядків


37

Об'єктивна

Створіть функцію для зворотного з'єднання рядків

Вхідні дані

Два рядки (буквено-цифрові + пробіли), де один слід відняти для іншого.

  • Можна припустити, що рядок, яку потрібно відняти, ніколи не буде більшою, ніж інша.

Вихідні дані

Результат від віднімання

Віднімання

Ви повинні видалити один рядок із початку або з кінця іншої. Якщо рядок присутній на початку та в кінці, ви можете видалити лише одну, яку ви будете вилучити, залежить від вас.
Якщо рядок не знаходиться на початку або в кінці, або не відповідає точній відповідності, це недійсне віднімання, і вам слід вивести початковий рядок.

Випробування

Дійсне віднімання

'abcde','ab' -> 'cde'
'abcde','cde' -> 'ab'
'abab','ab' -> 'ab'
'abcab','ab' -> 'abc' or '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' -> ''

Це , тому найкоротший код у байтах виграє!


4
Чому результату першої справи немає cde? Що ви маєте на увазі під дією? Чи потрібно судити про обґрунтованість вводу, чи ви маєте на увазі, що ми не отримаємо недійсні дані?
Лина монашка

7
Чорт за те, що ти 'abcde','bcd' -> 'abcde'порушив моє рішення
Іван Дворак

5
Чи можемо ми припустити, що рядки будуть безпечними для виразних знаків (буквено-цифрові + пробіли)?
Джон Дворак

2
Я б запропонував 'ababcde', 'ab''abcde'як тестовий випадок. Деякі наївні алгоритми виходять з ладу на цьому.

2
@Rod Ви можете розглянути можливість повторного виклику "Зворотне з'єднання рядків"?
MD XF

Відповіді:


19

Java 8, 46 45 44 40 байт

-1 байт завдяки TheLethalCoder

-1 байт, тому що я німий (дякую Роду!)

-4 байти завдяки Кевіну Крейсейну

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

Спробуйте в Інтернеті! (включає всі тестові випадки)

Відповідь на Java фактично перемагає кілька інших практичних мов. Усміхається. (і тепер він б'є JS!)


Використовуйте каррі, щоб зберегти байтa->b->
TheLethalCoder

@TheLethalCoder Спасибі
Оккс

Чому ви залишили невикористану хешмап у своєму прикладі в Інтернеті?
Майкл

Ви можете змінити значення Firstна All-2 байти. Через те ^і $це завжди або в кінці або на початку рядка, тому навіть з replaceAllним замінює лише один раз. Спробуйте тут. PS: До вашої відповіді я додав попередні підрахунки байтів, що зазвичай робиться після редагування коду-гольфу тут на PPCG.
Кевін Круїссен

@KevinCruijssen Я знав про простріли, думаю, я просто забув цього разу. Однак якщо я використовую Allзамість цього First, це стане правдою:"abab" + "ab" -> ""
Ок

9

JavaScript (ES6), 41 байт

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

Вводиться через синтаксис currying, тобто f("abab")("ab").


3
Тепер, чому я раніше не думав використовувати eval()для побудови RegExes ?!
Кудлатий

9

Брахілог (Спробуйте в Інтернеті!), 12 байт

~cpĊh.∧Ċtw|w

Спробуйте в Інтернеті!

Візьме рядок для віднімання зі стандартного введення, а рядок - для віднімання як аргумент командного рядка.

Пояснення

~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}.


6

JavaScript (ES6), 76 70 45 41 байт

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

Спробуй це

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>


2
Вам не потрібно new .
програміст5000

@ programmer500, я якось відмовився працювати над цим, коли побачив версію ETH! : D Оновлено зараз. Спасибі.
Кудлатий



3

TI-Basic (TI-84 Plus CE), 63 байти

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

I have a question, why didn't you use Str1 as a variable?
Zacharý

@Zacharý I think I had something stored in it at the time. I don't really remember.
pizzapants184

What does Ans even refer to on the fourth line?
Zacharý

@Zacharý Ans refers to the last evaluated value, so in this case it refers to the value returned by inString(, which is the index of the substring Str2 in the string Str0 or 0 if the substring does not appear. An if statement does not modify the value of Ans, so on the fourth line the index is still in Ans.
pizzapants184

Oh, I forgot how inString worked. Nice golf!
Zacharý

3

Mathematica, 162 bytes

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

test input style ["abcde","ab"]


1
Nice solution! You can save a byte by using # instead of #1 — they mean exactly the same. Also, instead of using StringJoin@t, you can cheat by joining an empty string to it with ""<>t, which automatically joins everything in t together too. Have you seen the Mathematica golfing tips page?
Not a tree

There are a few more things you can do to save bytes (I don't think you don't need to define t={}; at the start, for instance), but it might be easier to use a different approach entirely — have you tried using the StringReplace function?
Not a tree

You are allowed to take a String array as input, so you don't really need c=Characters;a=c@#;b=c@#2;
JungHwan Min

Also, l@Intersection[a,b] is l[a∩b].
JungHwan Min


3

Bash, 66 61 49 bytes

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

Try it online!

less golfed:

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

Uses case to test begining or end, and array prefix/suffix (% / #) substraction


1
Nice use of case, but longer than necessary. The 2nd and 3rd pattern could be merged into a single one: *)c=${1#$2};;. Then with only 2 branches would be shorter to echo each directly instead of using variable $c: case $1 in *$2)echo ${1%$2};;*)echo ${1#$2};;esac. Or you could keep using it, but without case: c=${1%$2};[[ $c = $1 ]]&&c=${1#$2};echo $c.
manatwork

3

APL (Dyalog), 31 30 bytes

-1 thanks to Zacharý.

This actually uses reverse (i.e. the inverse of) concatenation! Takes original string as left argument, and what to subtract as right argument.

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

Try it online!

Ungolfed:

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

Legend:

{} anonymous function

 left argument of the current function

 right argument of the current function

0::… if any error happens, execute this, else…

⍣¯1⊢ inverse

,∘⍵ concatenate on the right

⍵, concatenate on the left


I think you can save a byte with {0::⍺{0::⍺⋄,∘⍵⍣¯1⊢⍺}⍵⋄⍵,⍣¯1⊢⍺}.
Zacharý

@Zacharý Yes, thanks.
Adám



2

Haskell, 49 bytes

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

Try it online! Usage: f"" "abcdef" "ab". Alternatively, define (-)=f""and use like "abcdef" - "ab".

This regex-free solution works by recursively splitting the string in all its pre- and postfixes and checking whether the string to be substracted matches one of them.



1

C#, 88 bytes

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

Compiles to a Func<string, Func<string, string>>.


1

Ruby (lambda expression), 29 bytes

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

Yay for regex interpolation! Requires regex-safe subtrahends, but that's okay as per the challenge.


1

Tcl, 37 bytes

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

Try it online! (now running all tests)

Tcl is straightforward. proc s {a b} defines a function named s which takes parameters a and b. regsub substitutes {}, which is an empty string, for the value of b when it's at the start or end of a. The return is implicit.


1

C, 96 bytes

It's common knowledge that string manipulation in C is cumbersome, as an extension golfing would be borderline masochistic. Sounds alright to me.

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

One of the less readable programs I've written. Takes two inputs (despite how the function looks), a char** pointing to the string to deconcatenate and a char* which is the string to remove. The input pointer is edited in place and becomes the output (who cases about memory leaks anyway).

Example usage:

char *a = malloc(6);
strcpy(a, "abcde");
char *b = malloc(4);
strcpy(b, "abc");
f(&a,b);
printf("%s\n", a); // "de"

1

AWK, 21 32 bytes

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

Try it online!

Original submission naively replaced text within first string, not just at beginning or end.

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

Try it online !

Originally tried without the braces, but it required tricks to print out empty lines and or no-matches which ended up adding more bytes than this version.


1

R, 20 42 41 bytes

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

-1 byte thanks to MickyT!

Returns an anonymous function (which has arguments in the order b,a). Computes the string difference a-b. sub is a simple substitution that swaps the first occurrence of the pattern with, in this case, the empty string ''. Constructs the regex with sprintf to match only at the beginning and end of string. Requires the pryr package to be installed.

On the TIO link, uses the more verbose function(a,b) definition for the function for four more bytes.

Try it online!


1
What about the 'abcde','bcd' -> 'abcde' case?
Jonathan Allan

"sub is a simple substitution that simply swaps the first occurrence of b in a": Will this swap if the second string is in the middle of the first string?
TheLethalCoder

I misread the question! Oops. Thanks for catching that!
Giuseppe

you can get 1 byte back with sprintf('^%s|%s$',b,b)
MickyT

@MickyT, thanks! fixed.
Giuseppe

1

Common Lisp, 121 bytes

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

Try it online!

The usual wordy Common Lisp!

Ungolfed version:

(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

1

Kotlin, 91 bytes

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

Try it online!


? {a,b->var c=a.removePrefix(b);if(a==c){c=a.removeSuffix(b)};c}
mazzy

@mazzy feel free to submit that as your own answer.
snail_

1

Powershell, 34 40 bytes

+6 bytes when Invalid Subtraction test cases added

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

Comment:

The regexp expression ^$t|$t$ does not work as expected: it replaces both matches instead one (flag g always on). So, we are forced to use the negative lookahead group.

Test script:

$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"
}

Output:

True: cde
True: ab
True: ab
True: abc
True: abcde
True: acdb
True:
True: abcde
True:

0

QBIC, 57 bytes

Whegh, this is a mess in 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$


0

I initially misread the instructions. Thanks, Ørjan Johansen for pointing out my mistake!

PowerShell, 46 51 bytes

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

Try it online!


This fails on the 'abcde' 'bcd' case.
Ørjan Johansen

I'm seeing expected results from that test case -- TIO here
Jeff Freeman

It's a listed test case of the OP and the result should be abcde - bcd does not occur at either end of the string.
Ørjan Johansen

You are correct. I misread the instructions. Thanks for pointing it out!
Jeff Freeman

0

Excel, 129 bytes

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.