Sottrazione di stringhe


37

Obbiettivo

Creare una funzione per invertire la concatenazione di stringhe

Ingresso

Due stringhe (alfanumeriche + spazi), in cui una dovrebbe essere sottratta per l'altra.

  • Puoi presumere che la stringa da sottrarre non sarà mai più grande dell'altra.

Produzione

Il risultato dalla sottrazione

Sottrazione

È necessario rimuovere una stringa dall'inizio o dalla fine di un'altra stringa. Se la stringa è presente all'inizio e alla fine, puoi rimuoverne solo una, quale verrà rimossa dipende da te.
Se la stringa non è all'inizio o alla fine, o non è una corrispondenza esatta, è una sottrazione non valida e dovresti generare la stringa originale.

Casi test

Sottrazione valida

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

Sottrazione non valida (restituisce una stringa originale)

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

Input non valido (non è necessario gestirlo)

'','a' -> ''

Questo è , quindi vince il codice più corto in byte!


4
Perché il risultato del primo caso non lo è cde? Cosa intendi con valido? Dobbiamo giudicare la validità dell'input o intendi che non riceveremo input non validi?
Leaky Nun,

7
Accidenti a te, 'abcde','bcd' -> 'abcde'per aver infranto la mia soluzione
John Dvorak,

5
Possiamo supporre che le stringhe saranno regex-safe (alfanumeriche + spazi)?
John Dvorak,

2
Suggerirei 'ababcde', 'ab''abcde'come test case. Alcuni algoritmi ingenui falliscono su quello.

2
@Rod Potresti considerare di ripetere la sfida "Concatenazione di stringhe inverse"?
MD XF,

Risposte:


19

Java 8, 46 45 44 40 byte

-1 byte grazie a TheLethalCoder

-1 byte perché sono stupido (grazie Rod!)

-4 byte grazie a Kevin Cruijssen

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

Provalo online! (include tutti i casi di test)

Una risposta Java in realtà batte alcune altre lingue pratiche. Sorrisi. (e ora batte JS!)


Usa il curry per salvare un bytea->b->
TheLethalCoder

@TheLethalCoder Grazie.
Okx,

Perché hai lasciato nella hashmap inutilizzata nel tuo esempio online?
Michael,

È possibile modificare Firstin Allper -2 byte. A causa di ^ed $è sempre o alla fine o all'inizio della stringa, quindi anche con replaceAllessa la sostituisce solo una volta. Provalo qui. PS: Ho aggiunto i precedenti conteggi dei byte cancellati alla tua risposta, che è ciò che di solito viene fatto dopo le modifiche del code-golf qui su PPCG.
Kevin Cruijssen,

@KevinCruijssen Sapevo degli scioperi, credo che questa volta mi sono dimenticato. Tuttavia, se uso Allinvece di First, questo diventa realtà:"abab" + "ab" -> ""
Okx,

9

JavaScript (ES6), 41 byte

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

Accetta input tramite la sintassi del curry, ad es f("abab")("ab").


3
Ora, perché non ho mai pensato di usare eval()per costruire RegExes prima ?!
Shaggy,

9

Brachylog (provalo online!), 12 byte

~cpĊh.∧Ċtw|w

Provalo online!

Prende la stringa da cui sottrarre dall'input standard e la stringa da sottrarre come argomento della riga di comando.

Spiegazione

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

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

Provalo

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
Non hai bisogno new .
programmatore

@ programmer500, ho smesso di lavorare su questo quando ho visto la versione di ETH! : D Aggiornato ora. Grazie.
Shaggy,

4

Perl 6 , 21 byte

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

Provalo

Allargato:

-> $_, $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 byte

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

Ho una domanda, perché non hai usato Str1 come variabile?
Zacharý,

@ Zacharý Penso di averlo archiviato in quel momento. Non ricordo davvero.
pizzapants184

A cosa si Ansriferisce persino la quarta riga?
Zacharý,

@ Zacharý si Ansriferisce all'ultimo valore valutato, quindi in questo caso si riferisce al valore restituito da inString(, che è l'indice della sottostringa Str2nella stringa Str0o 0 se la sottostringa non viene visualizzata. Un'istruzione if non modifica il valore di Ans, quindi sulla quarta riga l'indice è ancora presente Ans.
pizzapants184

Oh, ho dimenticato come ha inStringfunzionato. Bel golf!
Zacharý,

3

Mathematica, 162 byte

(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
Bella soluzione! Puoi salvare un byte usando #invece di #1- significano esattamente lo stesso. Inoltre, invece di utilizzare StringJoin@t, puoi imbrogliare unendo una stringa vuota con essa ""<>t, che unisce automaticamente anche tutto tinsieme. Hai visto la pagina dei suggerimenti sul golf di Mathematica ?
Non un albero

Ci sono alcune altre cose che puoi fare per salvare i byte (non credo che non sia necessario definire t={};all'inizio, ad esempio), ma potrebbe essere più semplice utilizzare un approccio completamente diverso - hai provato a usare il StringReplacefunzione?
Non un albero

Ti è permesso prendere un array String come input, quindi non ti serve davveroc=Characters;a=c@#;b=c@#2;
JungHwan Min

Inoltre, lo l@Intersection[a,b]è l[a∩b].
JungHwan Min,


3

Bash ,66 61 49 byte

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

Provalo online!

meno golf:

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

Utilizza il caso per testare l'inizio o la fine e la sottrazione del prefisso / suffisso dell'array (% / #)


1
Buon uso case, ma più lungo del necessario. Il 2 ° e 3 ° modello potrebbero essere fusi in uno solo: *)c=${1#$2};;. Poi con soli 2 rami sarebbero più breve per echociascuna direttamente invece di utilizzare variabili $c: case $1 in *$2)echo ${1%$2};;*)echo ${1#$2};;esac. Oppure si potrebbe continuare a utilizzarlo, ma senza case: c=${1%$2};[[ $c = $1 ]]&&c=${1#$2};echo $c.
arte

3

APL (Dyalog) , 31 30 byte

-1 grazie a Zacharý .

Questo effettivamente utilizza la concatenazione inversa (cioè l'inverso di)! Accetta la stringa originale come argomento di sinistra e cosa sottrarre come argomento di destra.

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

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

Leggenda:

{... } funzione anonima

 argomento sinistro della funzione corrente

 giusto argomento della funzione corrente

0::... se si verifica un errore, esegui questo, altrimenti ...

⍣¯1⊢ inverso

,∘⍵ concatenare a destra

⍵, concatenare a sinistra


Penso che puoi salvare un byte con {0::⍺{0::⍺⋄,∘⍵⍣¯1⊢⍺}⍵⋄⍵,⍣¯1⊢⍺}.
Zacharý,

@ Zacharý Sì, grazie.
Adám,



2

Haskell , 49 byte

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

Provalo online! Uso: f"" "abcdef" "ab". In alternativa, definire (-)=f""e utilizzare come "abcdef" - "ab".

Questa soluzione priva di regex funziona suddividendo ricorsivamente la stringa in tutti i suoi pre e postfissi e controllando se la stringa da sottrarre corrisponde a una di esse.



1

C #, 88 byte

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

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


1

Rubino (espressione lambda), 29 byte

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

Yay per l'interpolazione regex! Richiede subtrahend regex-safe, ma va bene per la sfida.


1

Tcl , 37 byte

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

Provalo online!(ora esegue tutti i test)

Tcl è semplice. proc s {a b}definisce una funzione denominata sche accetta parametri ae b. regsubsostituisce {}, che è una stringa vuota, per il valore di bquando è all'inizio o alla fine di a. Il ritorno è implicito.


1

C, 96 byte

È risaputo che la manipolazione delle stringhe in C è ingombrante, poiché un'estensione del golf sarebbe masochistica limite. Per me va bene.

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 dei programmi meno leggibili che ho scritto. Accetta due input (nonostante l'aspetto della funzione), un char**puntamento alla stringa da deconcatenare e unchar* che è la stringa da rimuovere. Il puntatore di input viene modificato in posizione e diventa l'output (i casi in cui la memoria perde comunque).

Esempio di utilizzo:

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 byte

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

Provalo online!

L'invio originale ha sostituito ingenuamente il testo all'interno della prima stringa, non solo all'inizio o alla fine.

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

Provalo online!

Inizialmente provato senza le parentesi graffe, ma richiedeva trucchi per stampare righe vuote e / o nessuna corrispondenza che finivano per aggiungere più byte di questa versione.


1

R, 20 42 41 byte

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

-1 byte grazie a MickyT!

Restituisce una funzione anonima (che ha argomenti nell'ordine b,a). Calcola la differenza di stringa a-b. subè una semplice sostituzione che scambia la prima occorrenza del modello con, in questo caso, la stringa vuota ''. Costruisce la regex sprintfin modo che corrisponda solo all'inizio e alla fine della stringa. Richiede l' pryrinstallazione del pacchetto.

Sul collegamento TIO, utilizza la function(a,b)definizione più dettagliata per la funzione per altri quattro byte.

Provalo online!


1
E il 'abcde','bcd' -> 'abcde'caso?
Jonathan Allan,

" subè una semplice sostituzione che scambia semplicemente la prima occorrenza di bin a": questo cambierà se la seconda stringa si trova nel mezzo della prima stringa?
TheLethalCoder

Ho letto male la domanda! Ops. Grazie per averlo colto!
Giuseppe,

puoi recuperare 1 byte consprintf('^%s|%s$',b,b)
MickyT

@MickyT, grazie! fisso.
Giuseppe,

1

Lisp comune, 121 byte

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

Provalo online!

Il solito prolisso Common Lisp!

Versione non golfata:

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

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

Provalo online!


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

@mazzy non esitare a inviarlo come risposta personale.
snail_

1

Powershell, 34 40 byte

+6 byte quando vengono Invalid Subtractionaggiunti casi di test

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

Commento:

L'espressione regexp ^$t|$t$non funziona come previsto: sostituisce entrambe le corrispondenze anziché una (flagg sempre ). Quindi, siamo costretti a usare il gruppo lookahead negativo.

Script di prova:

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

Produzione:

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

0

QBIC , 57 byte

Whegh, questo è un casino 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

Inizialmente ho letto male le istruzioni. Grazie, Ørjan Johansen per aver segnalato il mio errore!

PowerShell , 46 51 byte

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

Provalo online!


Questo fallisce nel caso 'abcde' 'bcd'.
Ørjan Johansen,

Sto vedendo i risultati attesi da quel caso di test - TIO qui
Jeff Freeman,

È un caso di test elencato dell'OP e il risultato dovrebbe essere abcde- bcdnon si verifica a nessuna delle estremità della stringa.
Ørjan Johansen,

Hai ragione. Ho letto male le istruzioni. Grazie per segnalarlo!
Jeff Freeman,

0

Excel, 129 byte

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.