Subtração de string

37

Objetivo

Crie uma função para reverter a concatenação de cadeias

Entrada

Duas cadeias (alfanuméricas + espaços), onde uma deve ser subtraída pela outra.

  • Você pode supor que a sequência a ser subtraída nunca será maior que a outra.

Saída

O resultado da subtração

Subtração

Você deve remover uma string do início ou do fim de outra string. Se a sequência estiver presente no início e no final, você poderá remover apenas uma, e a que será removida depende de você.
Se a sequência não está no início ou no final, ou não é uma correspondência exata, é uma subtração inválida e você deve gerar a sequência original.

Casos de teste

Subtração válida

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

Subtração inválida (retorna a string original)

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

Entrada inválida (não precisa ser manipulada)

'','a' -> ''

Isso é , então o código mais curto em bytes vence!

Cajado
fonte
4
Por que o resultado do primeiro caso não é cde? O que você quer dizer com válido? Precisamos julgar a validade da entrada ou você quer dizer que não receberemos entradas inválidas?
Freira vazando
7
Maldito seja, 'abcde','bcd' -> 'abcde'para quebrar a minha solução
John Dvorak
5
Podemos supor que as strings serão regex-safe (espaços alfanuméricos +)?
John Dvorak
2
Eu sugeriria 'ababcde', 'ab''abcde'como um caso de teste. Alguns algoritmos ingênuos falham nesse.
2
@ Rod Você pode considerar retomar o desafio "Concatenação de string reversa"?
MD XF

Respostas:

19

Java 8, 46 45 44 40 bytes

-1 byte graças a TheLethalCoder

-1 byte porque sou burro (obrigado Rod!)

-4 bytes graças a Kevin Cruijssen

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

Experimente online! (inclui todos os casos de teste)

Uma resposta Java supera algumas outras linguagens práticas. Sorrisos. (e agora bate JS!)

Okx
fonte
Use currying para salvar um bytea->b->
TheLethalCoder
@TheLethalCoder Thanks.
Okx 16/05
Por que você saiu no hashmap não utilizado no seu exemplo online?
Michael
Você pode alterar Firstpara Allpara -2 bytes. Por causa do ^e $sempre está no final ou no início da String, mesmo que replaceAllele o substitua apenas uma vez. Experimente aqui. PS: Adicionei as contagens de bytes anteriores riscadas à sua resposta, que é o que geralmente é feito após as edições do code-golf aqui no PPCG.
Kevin Cruijssen
@KevinCruijssen Eu sabia sobre os ataques, acho que esqueci desta vez. No entanto, se eu usar em Allvez de First, isso se tornará verdadeiro:"abab" + "ab" -> ""
Okx 18/17
9

JavaScript (ES6), 41 bytes

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

Recebe entrada através de sintaxe de currying, ie f("abab")("ab").

ETHproductions
fonte
3
Agora, por que eu nunca pensei em usar eval()RegExes antes ?!
Shaggy
9

Brachylog (Experimente Online!), 12 bytes

~cpĊh.∧Ċtw|w

Experimente online!

Leva a string para subtrair da entrada padrão e a string para subtrair como argumento da linha de comando.

Explicação

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

fonte
6

Retina , 21 bytes

1 byte graças a Martin Ender.

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

Experimente online!

Freira Furada
fonte
6

JavaScript (ES6), 76 70 45 41 bytes

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

Tente

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>

Shaggy
fonte
2
Você não precisa new .
Programmer5000 #
@ programmer500, desisti de trabalhar nisso quando vi a versão da ETH! : D Atualizado agora. Obrigado.
Shaggy
4

Perl 6 , 21 bytes

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

Tente

Expandido:

-> $_, $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
fonte
3

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

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
pizzapants184
fonte
Eu tenho uma pergunta, por que você não usou Str1 como uma variável?
Zacharý 9/08/19
@ Zacharý Eu acho que tinha algo armazenado nele na época. Eu realmente não me lembro.
Pizzapants184
O que se Ansrefere na quarta linha?
Zacharý
@ Zacharý Ansrefere-se ao último valor avaliado, portanto, neste caso, refere-se ao valor retornado por inString(, que é o índice da substring Str2na string Str0ou 0 se a substring não aparecer. Uma instrução if não modifica o valor de Ans; portanto, na quarta linha, o índice ainda está Ans.
precisa saber é o seguinte
Ah, esqueci como inStringfuncionava. Bom golfe!
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)&

estilo de entrada de teste ["abcde", "ab"]

J42161217
fonte
11
Ótima solução! Você pode salvar um byte usando em #vez de #1- eles significam exatamente o mesmo. Além disso, em vez de usar StringJoin@t, você pode trapacear juntando uma string vazia a ela ""<>t, que também une tudo automaticamente t. Você já viu a página de dicas de golfe do Mathematica ?
Não é uma árvore
Há mais algumas coisas que você pode fazer para salvar bytes (acho que não precisa definir t={};no início, por exemplo), mas pode ser mais fácil usar uma abordagem totalmente diferente - você já tentou usar o StringReplacefunção?
Não é uma árvore
Você está autorizado a tomar uma matriz String como entrada, para que você realmente não precisac=Characters;a=c@#;b=c@#2;
JungHwan Min
Além disso, l@Intersection[a,b]é l[a∩b].
JungHwan Min 17/05
3

Python, 69 68 64 57 51 45 bytes

Isso acabou sendo uma solução completamente diferente com o Regex.

Obrigado ao Value Ink por -2 bytes!
e Felipe Nardi Batista pelos enormes 6 bytes!

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

Experimente online!

Artyer
fonte
Para -2 bytes:re.sub(c.join("^|$"),'',s,1)
Value Ink
11
Para -6 bytes:c+'$|^'+c
Felipe Nardi Batista
3

Bash ,66. 61 49 bytes

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

Experimente online!

menos golfe:

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

Usa maiúsculas e minúsculas para testar o início ou o fim e a subtração de prefixo / sufixo (% / #) da matriz

marcosm
fonte
11
Bom uso case, mas mais do que o necessário. A 2ª e 3ª padrão poderiam ser fundidos em um único: *)c=${1#$2};;. Em seguida, com apenas 2 ramos seria mais curto para echocada diretamente em vez de usar variável $c: case $1 in *$2)echo ${1%$2};;*)echo ${1#$2};;esac. Ou você pode continuar usando-lo, mas sem case: c=${1%$2};[[ $c = $1 ]]&&c=${1#$2};echo $c.
Manatwork
3

APL (Dyalog) , 31 30 bytes

-1 graças a Zacharý .

Na verdade, isso usa concatenação reversa (isto é, inversa de)! Leva a string original como argumento à esquerda e o que subtrair como argumento à direita.

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

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

Lenda:

{... } função anônima

 argumento esquerdo da função atual

 argumento correto da função atual

0::… Se ocorrer algum erro, execute isto, senão…

⍣¯1⊢ inverso

,∘⍵ concatenar à direita

⍵, concatenar à esquerda

Adão
fonte
Eu acho que você pode salvar um byte com {0::⍺{0::⍺⋄,∘⍵⍣¯1⊢⍺}⍵⋄⍵,⍣¯1⊢⍺}.
Zacharý 9/08/19
@ Zacharý Sim, obrigado.
Adám 9/08/19
2

PHP, 54 bytes

[,$x,$y]=$argv;echo preg_replace("#^$y|$y$#","",$x,1);

Casos de teste

Jörg Hülsermann
fonte
2

Python 2 , 68 bytes

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

Experimente online!

Jonathan Allan
fonte
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""

Experimente online! Uso: f"" "abcdef" "ab". Como alternativa, defina (-)=f""e use like "abcdef" - "ab".

Essa solução sem regex funciona dividindo recursivamente a string em todas as suas correcções anteriores e posteriores e verificando se a string a ser subtraída corresponde a uma delas.

Laikoni
fonte
2

Python 2 , 72 65 bytes

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

Experimente online!

-7 bytes graças a @FelipeNardiBatista

ovs
fonte
golfe
Felipe Nardi Batista
@FelipeNardiBatista Muito obrigado!
ovs 18/05/19
1

C #, 88 bytes

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

Compila para um Func<string, Func<string, string>>.

TheLethalCoder
fonte
1

Ruby (expressão lambda), 29 bytes

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

Yay para interpolação regex! Requer subtraendas seguras para regex, mas tudo bem conforme o desafio.

John Dvorak
fonte
1

Tcl , 37 bytes

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

Experimente online!(agora executando todos os testes)

Tcl é simples. proc s {a b}define uma função nomeada sque aceita parâmetros ae b. regsubsubstitui {}, que é uma sequência vazia, o valor de bquando está no início ou no final de a. O retorno está implícito.

Michael Plotke
fonte
1

C, 96 bytes

É do conhecimento geral que a manipulação de cordas em C é complicada, pois uma extensão do golfe seria masoquista limítrofe. Parece bom para mim.

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

Um dos programas menos legíveis que escrevi. Toma duas entradas (apesar da aparência da função), um char**apontador para a cadeia de caracteres para desconcatenar e umchar* qual é a cadeia de caracteres a ser removida. O ponteiro de entrada é editado no lugar e se torna a saída (quem fala sobre vazamentos de memória de qualquer maneira).

Exemplo de uso:

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

AWK , 21 32 bytes

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

Experimente online!

O envio original substituiu ingenuamente o texto na primeira sequência, não apenas no começo ou no final.

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

Experimente online!

Originalmente tentado sem os aparelhos, mas era necessário truques para imprimir linhas vazias e / ou não correspondências, o que acabou adicionando mais bytes que esta versão.

Robert Benson
fonte
1

R, 20 42 41 bytes

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

-1 byte graças a MickyT!

Retorna uma função anônima (que possui argumentos na ordem b,a). Calcula a diferença de cadeia a-b. subé uma substituição simples que troca a primeira ocorrência do padrão com, nesse caso, a sequência vazia ''. Constrói a regex com sprintfpara corresponder apenas no início e no final da sequência. Requer que o pryrpacote seja instalado.

No link TIO, usa a function(a,b)definição mais detalhada para a função por mais quatro bytes.

Experimente online!

Giuseppe
fonte
11
E o 'abcde','bcd' -> 'abcde'caso?
Jonathan Allan
" subé uma substituição simples que simplesmente troca a primeira ocorrência de bem a": Isso será trocado se a segunda string estiver no meio da primeira string?
TheLethalCoder
Eu interpretei mal a pergunta! Opa Obrigado por capturar isso!
Giuseppe
você pode obter 1 byte de volta comsprintf('^%s|%s$',b,b)
MickyT
@MickyT, obrigado! fixo.
Giuseppe
1

Lisp comum, 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)))

Experimente online!

O habitual prolixo Lisp comum!

Versão não destruída:

(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
fonte
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}

Experimente online!

Caracol_
fonte
? {a,b->var c=a.removePrefix(b);if(a==c){c=a.removeSuffix(b)};c}
Mazzy
@mazzy, sinta-se à vontade para enviar isso como sua própria resposta.
1/18
1

Powershell, 34 40 bytes

+6 bytes quando Invalid Subtractioncasos de teste foram adicionados

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

Comente:

A expressão regexp ^$t|$t$não funciona conforme o esperado: substitui as duas correspondências em vez de uma (sinalizador gsempre ativado). Então, somos forçados a usar o grupo negativo de lookahead.

Script de teste:

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

Saída:

True: cde
True: ab
True: ab
True: abc
True: abcde
True: acdb
True:
True: abcde
True:
confuso
fonte
0

QBIC , 57 bytes

Whegh, isso é uma bagunça no 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
fonte
0

Lua , 71 65 bytes

Aceitando sugestões

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

Experimente online!

Felipe Nardi Batista
fonte
0

Inicialmente, eu li errado as instruções. Obrigado, Ørjan Johansen por apontar meu erro!

PowerShell , 46 51 bytes

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

Experimente online!

Jeff Freeman
fonte
Isso falha no caso 'abcde' 'bcd'.
Ørjan Johansen
Estou vendo os resultados esperados desse caso de teste - TIO aqui
Jeff Freeman
É um caso de teste listado do OP e o resultado deve ser abcde- bcdnão ocorre em nenhuma das extremidades da string.
Ørjan Johansen
Você está certo. Eu li mal as instruções. Obrigado por apontar isso!
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)
Wernisch
fonte