Resta de cuerdas


37

Objetivo

Crear una función para invertir la concatenación de cadenas

Entrada

Dos cadenas (alfanuméricas + espacios), donde una debe sustraerse por la otra.

  • Puede suponer que la cadena que se restará nunca será más grande que la otra.

Salida

El resultado de la resta.

Sustracción

Debe eliminar una cadena desde el principio o el final de otra cadena. Si la cadena está presente al principio y al final, solo puede eliminar una, la que se eliminará depende de usted.
Si la cadena no está al principio o al final, o no es una coincidencia exacta, es una resta no válida y debe generar la cadena original.

Casos de prueba

Resta 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'
'','' -> ''

Resta no válida (devuelve la cadena original)

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

Entrada inválida (no necesita ser manejada)

'','a' -> ''

Este es el , por lo que gana el código más corto en bytes.


44
¿Por qué no es el resultado del primer caso cde? ¿Qué quieres decir con válido? ¿Necesitamos juzgar la validez de la entrada o quiere decir que no recibiremos entradas no válidas?
Leaky Nun

77
Maldita sea 'abcde','bcd' -> 'abcde', por romper mi solución
John Dvorak

55
¿Podemos suponer que las cadenas serán seguras para expresiones regulares (alfanuméricas + espacios)?
John Dvorak

2
Sugeriría 'ababcde', 'ab''abcde'como un caso de prueba. Algunos algoritmos ingenuos fallan en eso.

2
@ Rod ¿Podría considerar retitling el desafío "Concatenación de cadena inversa"?
MD XF

Respuestas:


19

Java 8, 46 45 44 40 bytes

-1 byte gracias a TheLethalCoder

-1 byte porque soy tonto (¡gracias Rod!)

-4 bytes gracias a Kevin Cruijssen

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

Pruébalo en línea!(incluye todos los casos de prueba)

Una respuesta Java realmente supera algunos otros lenguajes prácticos. Sonrisas (¡y ahora supera a JS!)


Usa el curry para guardar un bytea->b->
TheLethalCoder

@TheLethalCoder Gracias.
Okx

¿Por qué dejaste el hashmap no utilizado en tu ejemplo en línea?
Michael

Puede cambiar Firsta Allpor -2 bytes. Debido a que ^y $siempre está al final o al comienzo de la Cadena, por lo que incluso con replaceAllella solo la reemplaza una vez. Pruébalo aquí PD: Agregué el byte-count anterior marcado a su respuesta, que es lo que generalmente se hace después de las ediciones de código de golf aquí en PPCG.
Kevin Cruijssen

@KevinCruijssen Sabía sobre los tachados, supongo que esta vez lo olvidé. Sin embargo, si uso en Alllugar de First, esto se hace realidad:"abab" + "ab" -> ""
Okx

9

JavaScript (ES6), 41 bytes

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

Toma entrada a través de la sintaxis de curry, es decir f("abab")("ab").


3
Ahora, ¿por qué nunca pensé en usar eval()para construir RegExes antes?
Shaggy

9

Brachylog (¡Pruébelo en línea!), 12 bytes

~cpĊh.∧Ċtw|w

Pruébalo en línea!

Toma la cadena para restar de la entrada estándar y la cadena para restar como argumento de línea de comando.

Explicación

~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 bytes

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

Intentalo

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
No es necesario new .
programador

@ programmer500, ¡dejé de trabajar en esto cuando vi la versión de ETH! : D Actualizado ahora. Gracias.
Shaggy

4

Perl 6 , 21 bytes

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

Intentalo

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.

}


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

Tengo una pregunta, ¿por qué no usaste Str1 como variable?
Zacharý

@ Zacharý Creo que tenía algo almacenado en ese momento. Realmente no me acuerdo.
pizzapants184

¿A qué se refiere Ansincluso en la cuarta línea?
Zacharý

@ Zacharý se Ansrefiere al último valor evaluado, por lo que en este caso se refiere al valor devuelto por inString(, que es el índice de la subcadena Str2en la cadena Str0o 0 si la subcadena no aparece. Una instrucción if no modifica el valor de Ans, por lo que en la cuarta línea el índice todavía está Ans.
pizzapants184

Oh, olvidé cómo inStringfuncionaba. Buen 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)&

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


1
Buena solución! Puede guardar un byte utilizando en #lugar de #1: significan exactamente lo mismo. Además, en lugar de usar StringJoin@t, puedes hacer trampa uniendo una cadena vacía con ella ""<>t, que también une automáticamente todo t. ¿Has visto la página de consejos de golf de Mathematica ?
No es un árbol

Hay algunas cosas más que puede hacer para guardar bytes (no creo que necesite definir t={};al principio, por ejemplo), pero podría ser más fácil usar un enfoque completamente diferente. ¿Ha intentado usar el StringReplace¿función?
No es un árbol

Se le permite tomar una matriz de cadenas como entrada, por lo que realmente no necesitac=Characters;a=c@#;b=c@#2;
JungHwan Min

Además, l@Intersection[a,b]es l[a∩b].
JungHwan Min


3

Golpetazo ,66 61 49 bytes

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

Pruébalo en línea!

menos golf:

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

Utiliza mayúsculas y minúsculas para probar el comienzo o el final, y la resta de prefijo / sufijo de matriz (% / #)


1
Buen uso de case, pero más de lo necesario. La segunda y tercera patrón podrían fusionarse en uno solo: *)c=${1#$2};;. A continuación, con sólo 2 ramas serían más cortos a echocada uno directamente en lugar de utilizar variables $c: case $1 in *$2)echo ${1%$2};;*)echo ${1#$2};;esac. O bien, podría seguir utilizándolo, pero sin case: c=${1%$2};[[ $c = $1 ]]&&c=${1#$2};echo $c.
manatwork

3

APL (Dyalog) , 31 30 bytes

-1 gracias a Zacharý .

¡Esto realmente usa la concatenación inversa (es decir, la inversa de)! Toma la cadena original como argumento izquierdo y qué restar como argumento derecho.

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

Pruébalo en línea!

Sin golf:

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

Leyenda:

{... } función anónima

 argumento izquierdo de la función actual

 argumento correcto de la función actual

0::... si ocurre algún error, ejecute esto, de lo contrario ...

⍣¯1⊢ inverso

,∘⍵ concatenar a la derecha

⍵, concatenar a la izquierda


Creo que puedes guardar un byte con {0::⍺{0::⍺⋄,∘⍵⍣¯1⊢⍺}⍵⋄⍵,⍣¯1⊢⍺}.
Zacharý

@ Zacharý Sí, gracias.
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""

Pruébalo en línea! Uso: f"" "abcdef" "ab". Alternativamente, defina (-)=f""y use like "abcdef" - "ab".

Esta solución libre de expresiones regulares funciona dividiendo recursivamente la cadena en todos sus prefijos y prefijos y verificando si la cadena que se restará coincide con una de ellas.



1

C #, 88 bytes

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

Compila a a Func<string, Func<string, string>>.


1

Ruby (expresión lambda), 29 bytes

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

¡Yay por interpolación de expresiones regulares! Requiere sustraendos seguros para expresiones regulares, pero está bien según el desafío.


1

Tcl , 37 bytes

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

Pruébalo en línea!(ahora ejecuta todas las pruebas)

Tcl es sencillo. proc s {a b}define una función llamada sque toma parámetros ay b. regsubsustituye {}, que es una cadena vacía, para el valor de bcuando está al principio o al final de a. El retorno es implícito.


1

C, 96 bytes

Es de conocimiento común que la manipulación de cuerdas en C es engorrosa, ya que una extensión de golf sería limítrofe masoquista. A mí me parece bien.

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

Uno de los programas menos legibles que he escrito. Toma dos entradas (a pesar de cómo se ve la función), una char**señalando a la cadena para desconcatar y unachar* que es la cadena a eliminar. El puntero de entrada se edita en su lugar y se convierte en la salida (de todos modos, en caso de pérdidas de memoria).

Ejemplo de uso:

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

Pruébalo en línea!

El envío original reemplazó ingenuamente el texto dentro de la primera cadena, no solo al principio o al final.

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

Pruébalo en línea!

Originalmente se probó sin llaves, pero requirió trucos para imprimir líneas vacías y / o no coincidencias que terminaron agregando más bytes que esta versión.


1

R, 20 42 41 bytes

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

-1 byte gracias a MickyT!

Devuelve una función anónima (que tiene argumentos en el orden b,a). Calcula la diferencia de cadena a-b. subes una sustitución simple que intercambia la primera aparición del patrón con, en este caso, la cadena vacía ''. Construye la expresión regular sprintfpara que coincida solo al principio y al final de la cadena. Requiere pryrque se instale el paquete.

En el enlace TIO, utiliza la function(a,b)definición más detallada de la función para cuatro bytes más.

Pruébalo en línea!


1
¿Qué hay del 'abcde','bcd' -> 'abcde'caso?
Jonathan Allan

" subes una sustitución simple que simplemente intercambia la primera aparición de bin a": ¿Esto cambiará si la segunda cadena está en el medio de la primera cadena?
TheLethalCoder

¡He leído mal la pregunta! Ups Gracias por atrapar eso!
Giuseppe

se puede obtener de vuelta 1 byte consprintf('^%s|%s$',b,b)
MickyT

@MickyT, gracias! fijo.
Giuseppe

1

Lisp común, 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)))

Pruébalo en línea!

La habitual palabra común Lisp!

Versión sin golf:

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

Pruébalo en línea!


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

@mazzy no dude en enviar eso como su propia respuesta.
caracol_

1

Powershell, 34 40 bytes

+6 bytes cuando Invalid Subtractionse agregan casos de prueba

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

Comentario:

La expresión regexp ^$t|$t$no funciona como se esperaba: reemplaza ambas coincidencias en lugar de una (marca gsiempre activada). Por lo tanto, nos vemos obligados a usar el grupo negativo de búsqueda anticipada.

Script de prueba:

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

Salida:

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

0

QBIC , 57 bytes

Whegh, esto es un desastre en 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

Inicialmente leí mal las instrucciones. ¡Gracias, Ørjan Johansen por señalar mi error!

PowerShell , 46 51 bytes

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

Pruébalo en línea!


Esto falla en el caso 'abcde' 'bcd'.
Ørjan Johansen

Veo los resultados esperados de ese caso de prueba - TIO aquí
Jeff Freeman

Es un caso de prueba listado del OP y el resultado debería ser abcde: bcdno ocurre en ninguno de los extremos de la cadena.
Ørjan Johansen

Estás en lo correcto. Leí mal las instrucciones. ¡Gracias por mencionarlo!
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)

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.