Вычитание строки


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 Спасибо.
Okx,

Почему вы оставили в неиспользуемой хэш-карте в вашем онлайн-примере?
Майкл

Вы можете изменить Firstв Allтечение -2 байт. Из-за ^и $он всегда либо в конце, либо в начале строки, поэтому даже при этом replaceAllон заменяется только один раз. Попробуй это здесь. PS: я добавил зачеркнутый предыдущий счетчик байтов к вашему ответу, что обычно делается после внесения изменений в код-гольф здесь, на PPCG.
Кевин Круйссен

@KevinCruijssen Я знал о зачистках, думаю, я просто забыл на этот раз. Однако, если я использую Allвместо First, это становится правдой:"abab" + "ab" -> ""
Okx

9

JavaScript (ES6), 41 байт

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

Принимает ввод через выделку синтаксиса, то есть f("abab")("ab").


3
Теперь, почему я никогда не думал использовать eval()для создания RegExes раньше ?!
Лохматый

9

Brachylog (попробуйте онлайн!), 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 .
programmer5000

@ 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

У меня вопрос, почему вы не использовали Str1 в качестве переменной?
Захари

@ Zacharý Я думаю, что в то время в нем что-то было. Я действительно не помню.
pizzapants184

Что вообще Ansотносится к четвертой строке?
Захари

@ Zacharý Ansотносится к последнему оцененному значению, поэтому в этом случае оно относится к возвращаемому значению inString(, которое является индексом подстроки Str2в строке, Str0или 0, если подстрока не появляется. Оператор if не изменяет значение Ans, поэтому в четвертой строке индекс все еще находится в Ans.
pizzapants184

О, я забыл, как inStringработал. Хороший гольф!
Захари

3

Mathematica, 162 байта

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

тестовый стиль ввода ["abcde", "ab"]


1
Отличное решение! Вы можете сохранить байт, используя #вместо #1- они означают точно так же. Кроме того, вместо использования StringJoin@tвы можете обмануть, присоединив к нему пустую строку ""<>t, которая автоматически объединяет все tвместе. Вы видели страницу с советами по игре в гольф Mathematica ?
Не дерево

Есть еще несколько вещей, которые вы можете сделать, чтобы сохранить байты (например, я не думаю, что вам не нужно определять это t={};в начале), но может быть проще использовать другой подход полностью - вы пытались использовать StringReplaceфункция?
Не дерево

Вам разрешено принимать массив String в качестве входных данных, поэтому вам на самом деле это не нужноc=Characters;a=c@#;b=c@#2;
JungHwan Мин

Также l@Intersection[a,b]есть l[a∩b].
JungHwan Мин

3

Python, 69 68 64 57 51 45 байт

В итоге это стало совершенно другим решением с Regex.

Спасибо Value Ink за -2 байта!
и Фелипе Нарди Батиста за массивные -6 байт!

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

Попробуйте онлайн!


Для -2 байтов:re.sub(c.join("^|$"),'',s,1)
Значение Ink

1
Для -6 ​​байтов:c+'$|^'+c
Фелипе Нарди Батиста

3

Баш ,66 61 49 байтов

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

Попробуйте онлайн!

меньше гольфа:

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

Использует регистр для проверки начала или конца и вычитание префикса / суффикса массива (% / #)


1
Хорошее использование case, но дольше, чем необходимо. Второй и третий шаблон , могут быть объединены в один: *)c=${1#$2};;. Затем с только 2 ветви будет короче , чтобы echoкаждый непосредственно , вместо использования переменной $c: case $1 in *$2)echo ${1%$2};;*)echo ${1#$2};;esac. Или вы могли бы продолжать использовать его, но без case: c=${1%$2};[[ $c = $1 ]]&&c=${1#$2};echo $c.
manatwork

3

APL (Dyalog) , 31 30 байт

-1 спасибо Захари .

Это фактически использует обратную (то есть обратную) конкатенацию! Принимает исходную строку в качестве левого аргумента и что вычитать в качестве правого аргумента.

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

Попробуйте онлайн!

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
}

Условные обозначения:

{} Анонимная функция

 левый аргумент текущей функции

 правильный аргумент текущей функции

0::... если произойдет какая-либо ошибка, выполните это, иначе ...

⍣¯1⊢ обратный

,∘⍵ сцепление справа

⍵, сцепление слева


Я думаю, что вы можете сохранить байт с {0::⍺{0::⍺⋄,∘⍵⍣¯1⊢⍺}⍵⋄⍵,⍣¯1⊢⍺}.
Захари

@ Zacharý Да, спасибо.
Адам



2

Haskell , 49 байтов

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

Попробуйте онлайн! Использование: f"" "abcdef" "ab". В качестве альтернативы, определите (-)=f""и используйте как "abcdef" - "ab".

Это решение без регулярных выражений работает путем рекурсивного разделения строки на все ее префиксы и постфиксы и проверки, соответствует ли строка, которая должна быть вычтена, одному из них.



1

C #, 88 байт

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

Компилирует в Func<string, Func<string, string>>.


1

Рубин (лямбда-выражение), 29 байт

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

Yay для регулярного выражения! Требуются вычитаемые безопасные регулярные выражения, но это нормально в соответствии с задачей.


1

Tcl , 37 байт

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

Попробуйте онлайн! (сейчас запускаются все тесты)

Tcl прост. proc s {a b}определяет функцию с именем, sкоторая принимает параметры aи b. regsubподставляет {}пустую строку для значения, bкогда она находится в начале или в конце a. Возврат неявный.


1

C 96 байтов

Общеизвестно, что манипулирование струнами в Си является громоздким, поскольку расширение игры в гольф будет граничить с мазохизмом. Звучит хорошо для меня.

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

Одна из менее читаемых программ, которые я написал. Принимает два ввода (несмотря на то, как выглядит функция): char**указатель на деконкатенированную строку и char*строка, которую нужно удалить. Входной указатель редактируется на месте и становится выходным (в любом случае, в случае утечки памяти).

Пример использования:

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 байта

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

Попробуйте онлайн!

Исходное представление наивно заменяет текст в первой строке, а не только в начале или конце.

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

Попробуйте онлайн!

Первоначально пытался без фигурных скобок, но он требовал хитрости для печати пустых строк и / или несоответствий, что в итоге добавило больше байтов, чем эта версия.


1

R, 20 42 41 байт

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

-1 байт благодаря MickyT!

Возвращает анонимную функцию (которая имеет аргументы в порядке b,a). Вычисляет разницу строк a-b. subпростая замена, которая заменяет первое вхождение шаблона, в данном случае, пустой строкой ''. Создает регулярное выражение с, sprintfчтобы соответствовать только в начале и конце строки. Требуется pryrпакет для установки.

На ссылке TIO, используется более многословный function(a,b) определение для функции еще на четыре байта.

Попробуйте онлайн!


1
Как насчет 'abcde','bcd' -> 'abcde'дела?
Джонатан Аллан

« subэто простая замена, которая просто меняет первое вхождение на bin a»: будет ли это замена, если вторая строка находится в середине первой строки?
TheLethalCoder

Я неправильно понял вопрос! К сожалению. Спасибо, что поймали это!
Джузеппе

вы можете получить 1 байт обратноsprintf('^%s|%s$',b,b)
MickyT

@ MickyT, спасибо! исправлено.
Джузеппе

1

Common Lisp, 121 байт

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

Попробуйте онлайн!

Обычный многословный Common Lisp!

Безголовая версия:

(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

Powershell, 34 40 байт

+6 байт при Invalid Subtractionдобавлении тестовых случаев

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

Комментарий:

Выражение регулярного выражения ^$t|$t$не работает должным образом: оно заменяет оба совпадения вместо одного (флаг gвсегда включен). Таким образом, мы вынуждены использовать группу с негативным прогнозом.

Тестовый скрипт:

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

Выход:

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

0

QBIC , 57 байт

Хм, это беспорядок в 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

Я изначально неправильно прочитал инструкцию. Спасибо, Орджан Йохансен за указание на мою ошибку!

PowerShell , 46 51 байт

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

Попробуйте онлайн!


Это не работает в случае 'abcde' 'bcd'.
Орджан Йохансен

Я вижу ожидаемые результаты от этого теста - TIO здесь
Джефф Фриман

Это перечисленный тестовый случай OP, и результат должен быть abcde - bcdне встречается ни в одном конце строки.
Орджан Йохансен

Ты прав. Я неправильно прочитал инструкцию. Спасибо за указание на это!
Джефф Фриман

0

Excel, 129 байт

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