Sostituzione successiva


30

La maggior parte delle lingue include un built-in per cercare una stringa per tutte le occorrenze di una determinata sottostringa e sostituire quelle con un'altra. Non conosco alcun linguaggio che generalizzi questo concetto a sottosequenze (non necessariamente contigue). Questo è il tuo compito in questa sfida.

L'ingresso sarà composto da tre archi A, Be C, dove Be Csono garantiti per essere della stessa lunghezza. Se Bappare come sottosequenza A, deve essere sostituito con C. Qui c'è un semplice esempio:

A: abcdefghijklmnopqrstuvwxyz
B: ghost
C: 12345

Sarebbe elaborato in questo modo:

abcdefghijklmnopqrstuvwxyz
      ||      |   ||
abcdef12ijklmn3pqr45uvwxyz

Se ci sono diversi modi per trovare Buna sottosequenza, è necessario sostituire avidamente quello più a sinistra:

A: abcdeedcba
B: ada
C: BOB

Result:   BbcOeedcbB
and NOT:  BbcdeeOcbB

Lo stesso vale se si Bpotesse trovare in più luoghi disgiunti:

A: abcdeedcbaabcde
B: ed
C: 12

Result:   abcd1e2cbaabcde
and NOT:  abcd112cbaabc2e (or similar)

Quando Bnon appare in A, dovresti avere un output Ainvariato.

Regole

Come detto sopra, prendi tre stringhe A, Be Ccome input e sostituisci l'occorrenza più a sinistra di Buna sottosequenza Acon C, se ce ne sono.

È possibile scrivere un programma o una funzione, prendendo l'input tramite STDIN (o l'alternativa più vicina), l'argomento della riga di comando o l'argomento della funzione e producendo il risultato tramite STDOUT (o l'alternativa più vicina), il valore di ritorno della funzione o il parametro della funzione (out).

Puoi prendere le tre stringhe in qualsiasi ordine coerente che dovresti specificare nella tua risposta. Puoi presumere che Be Cavere la stessa lunghezza. Tutte le stringhe conterranno solo caratteri alfanumerici.

Si applicano le regole standard del .

Casi test

Ogni test è di quattro linee: A, B, Cseguiti dal risultato.

abcdefghijklmnopqrstuvwxyz
ghost
12345
abcdef12ijklmn3pqr45uvwxyz

abcdeedcba
ada
BOB
BbcOeedcbB

abcdeedcbaabcde
ed
12
abcd1e2cbaabcde

121
121
aBc
aBc

abcde
acb
123
abcde

ABC
ABCD
1234
ABC

012345678901234567890123456789
42
TT
0123T5678901T34567890123456789

edcbaedcbaedcbaedcba
abcde
12345
edcbaedcbaedcbaedcba

edcbaedcbaedcbaedcbaedcba
abcde
12345
edcb1edc2aed3bae4cba5dcba

daccdedca
ace
cra
dcrcdadca

aacbcbabcccaabcbabcaabbbbca
abaaaccbac
1223334444
aacbcbabcccaabcbabcaabbbbca

aacbcbabcccaabcbabcaabbbbcac
abaaaccbac
1223334444
1ac2cb2bccc33b3bab4aa4bbbc44

Classifica

Lo snippet di stack nella parte inferiore di questo post genera classifiche dalle risposte a) come elenco della soluzione più breve per lingua eb) come classifica generale.

Per assicurarti che la tua risposta venga visualizzata, ti preghiamo di iniziare la risposta con un titolo, utilizzando il seguente modello Markdown:

## Language Name, N bytes

dov'è Nla dimensione del tuo invio. Se si migliora il punteggio, è possibile mantenere i vecchi punteggi nel titolo, colpendoli. Per esempio:

## Ruby, <s>104</s> <s>101</s> 96 bytes

Se si desidera includere più numeri nell'intestazione (ad es. Perché il punteggio è la somma di due file o si desidera elencare separatamente le penalità del flag dell'interprete), assicurarsi che il punteggio effettivo sia l' ultimo numero nell'intestazione:

## Perl, 43 + 2 (-p flag) = 45 bytes

Puoi anche rendere il nome della lingua un collegamento che verrà quindi visualizzato nello snippet:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes


Un elenco di stringhe di caratteri singoli andrebbe bene per l'input / output?
FryAmTheEggman,

@FryAmTheEggman Hm, l'unico consenso che posso trovare è questo che non affronta gli elenchi di stringhe a carattere singolo come rappresentazioni di stringhe valide. Potrebbe valere la pena fare un meta post (soprattutto perché penso che questo sia arrivato anche all'ultima sfida di xnor). Sto per dire di no per ora.
Martin Ender,

Che dire degli array di caratteri? Ciò sembra implicare che sono ammessi anche se la lingua ha un tipo di stringa appropriato.
Dennis,

@Dennis Sì, gli array di caratteri vanno bene, ma le stringhe singleton sono come prendere una matrice di numeri interi come [[1], [2], [3]].
Martin Ender,

OK, grazie per averlo chiarito.
Dennis,

Risposte:


3

Gelatina , 23 22 21 byte

='T€ŒpfṢ€$ḢṬœp³ż⁵$³Ḋ?

Provalo online! Si noti che gli ultimi due casi di test esauriranno la memoria.

Verifica

$ head -n 5 test-cases
abcdefghijklmnopqrstuvwxyz
ghost
12345
abcdef12ijklmn3pqr45uvwxyz

$ cat subseq-short
while read s; do
        read p; read r; read o; echo $o; read
        timeout 1s jelly eun $1 "='T€ŒpfṢ€$ḢṬœp³ż⁵$³Ḋ?" "'$s'" "'$p'" "'$r'"
        (($?)) && echo '(killed)'
done < test-cases
$ ./subseq-short
abcdef12ijklmn3pqr45uvwxyz
abcdef12ijklmn3pqr45uvwxyz
BbcOeedcbB
BbcOeedcbB
abcd1e2cbaabcde
abcd1e2cbaabcde
aBc
aBc
abcde
abcde
ABC
ABC
0123T5678901T34567890123456789
0123T5678901T34567890123456789
edcbaedcbaedcbaedcba
edcbaedcbaedcbaedcba
edcb1edc2aed3bae4cba5dcba
edcb1edc2aed3bae4cba5dcba
dcrcdadca
dcrcdadca
aacbcbabcccaabcbabcaabbbbca
(killed)
1ac2cb2bccc33b3bab4aa4bbbc44
(killed)

Come funziona

='T€ŒpfṢ€$ḢṬœp³ż⁵$³Ḋ?  Main link. Arguments: string s, pattern p, replacement r

='                     Compare each character of s with each character of p.
                       This yields a 2D list. Each row corresponds to a char in p.
  T€                   Compute the truthy indices of each row, i.e., the indices
                       of all occurrences of that char in s.
   Œp                  Compute the Cartesian product of the lists of indices.
        $              Combine the two links to the left into a monadic chain:
      Ṣ€                 Sort each list of indices.
     f                   Filter, removing all non-sorted lists of indices.
         Ḣ             Head; take the first (sorted) list of indices.
          Ṭ            Truth; generate a list with 1's at those indices.
           œp³         Partition; split s at all 1's, removing those characters.
                  Ḋ?   If the partition has more than more than one element:
              ż⁵$        Zip the partition with r.
                 ³       Else, return s.

12

Python 2, 88 byte

def f(a,b,c,o=""):
 for q in a:x=q==b[:1];o+=c[:x]or q;b=b[x:];c=c[x:]
 print[o,a][c>'']

Una funzione che accetta le tre stringhe e invia il risultato a STDOUT. La funzione fa semplicemente passare la stringa, prendendo il carattere appropriato e aggiornando b,cmentre procediamo.

Per il test (dopo aver sostituito il printcon return):

S = """
<test cases here>
"""

for T in S.split("\n\n"):
    A,B,C,D = T.split()
    assert f(A,B,C) == D

9

Java 7, 141

Penso che ci sia qualcosa in più che posso fare con questo, ma devo correre per ora. È solo una semplice iterazione / sostituzione, mantenendo un indice in A e B.

char[]h(char[]a,char[]b,char[]c){char[]d=a.clone();int i=0,j=0,k=b.length;for(;i<a.length&j<k;i++)if(a[i]==b[j])d[i]=c[j++];return j==k?d:a;}

Bianchi per il tuo piacere:

char[]h(char[]a,char[]b,char[]c){
    char[]d=a.clone();
    int i=0,j=0,k=b.length;
    for(;i<a.length&j<k;i++)
        if(a[i]==b[j])d[i]=c[j++];
    return j==k?d:a;
}

Whitespacedsì, è totalmente leggibile
gatto

Non è vero? Il motivo principale per cui aggiungo la versione con rientro multilinea è quello di evitare lo scorrimento orizzontale, solo così può essere visto tutto in una volta. Lo spazio bianco in linea non è un grosso affare IMO;)
Geobits

[feature-request] ancora più spazi bianchi
Alex A.


@Geobits Se lo fai, salva un byte alla finej<k?a:d
Xanderhall,

7

Lua, 121 byte

Soluzione semplice, gsubci consente di iterare esattamente una volta su ogni carattere e di sostituirli in una nuova istanza della stringa.

Prende l'input tramite 3 argomenti della riga di comando e invia una stringa a STDOUT.

a,b,c=...d=a:gsub(".",function(s)if b:find(s)then b=b:sub(2)x=c:sub(1,1)c=c:sub(2)return x end end)print(b~=''and a or d)

Ungolfed

a,b,c=...               -- unpack the arguments into a, b and c
d=a:gsub(".",function(s)-- iterate over each character of the first argument
  if b:find(s)then      -- if the current character is in the set b
    b=b:sub(2)          -- remove it from b
    x=c:sub(1,1)        -- save the replacement character in x
    c=c:sub(2)          -- remove it from c
    return x            -- replace the current character with x
  end
end)
print(b~=''             -- if b is empty, we replaced all the character
      and a or d)       -- so output the result of gsub, else, output the first argument

6

Python 3, 127 byte.

Risparmiato 16 byte grazie a Katenkyo.

Continuando a lavorarci un po ', l'uomo era più cattivo di quanto pensassi.

f=lambda a,b,c:a.replace(b[0],c[0],1)[:a.index(b[0])+1]+f(a[a.index(b[0])+1:],b[1:],c[1:])if b and all(x in a for x in b)else a

Spiegazione: Sì, ricorsione.

Casi test:

assert f('abcdeedcba', 'ada', 'BOB') == 'BbcOeedcbB'
assert f('abcdeedcbaabcde', 'ed', '12') == 'abcd1e2cbaabcde'
assert f('012345678901234567890123456789', '42', 'TT') == '0123T5678901T34567890123456789'
assert f('ABC', 'ABCD', '1234') == 'ABC'

+1 per giocare a golf a 50 di sconto, ma continua! Questo deve almeno battere la mia risposta Java;)
Geobits

7
@Geobits Sì, non ho mai perso con Java prima. Questa è la mia più grande vergogna.
Morgan Thrapp,

Non sono davvero esperto di Python, ma all(x in a for x in b)controlla anche che gli elementi in B e A compaiano nello stesso ordine, o solo se sono qui?
Katenkyo,

@Katenkyo Solo che sono tutti lì, ma l'ordine viene curato dall'affettamento quando ci reclamiamo.
Morgan Thrapp,

Ok, inoltre, non return a.replace(b[0],c[0],1)[:l(b[0])+1]+f(a[l(b[0])+1:],b[1:],c[1:])if b and all(x in a for x in b)else ati farebbe risparmiare qualche byte?
Katenkyo,

5

Python 3.5, 87 byte

import re
lambda s,p,r:re.sub('(.*?)'.join(p),'\g<%d>'.join(r)%(*range(1,len(r)),),s,1)

repl.it per verificare tutti i casi di test .

Come funziona

  • '(.*?)'.join(p) costruisce un modello di ricerca che corrisponde alla sottosequenza da sostituire e qualsiasi cosa tra i suoi elementi.

    Poiché i quantificatori sono pigri, ognuno (.*?)corrisponderà al minor numero possibile di caratteri.

    Per lo schema ghost, la regex costruita è g(.*?)h(.*?)o(.*?)s(.*?)t.

  • '\g<%d>'.join(r)%(*range(1,len(r)),) crea la stringa di sostituzione, usando la formattazione della stringa.

    Ogni \g<n>riferisce al n ° gruppo catturato, come \nsarebbe.

    Per la sostituzione 12345, la stringa costruita è 1\g<1>2\g<2>3\g<3>4\g<4>5.

  • re.sub(...,...,s,1)esegue al massimo una sostituzione nella stringa s.


4

Pyth, 27

.xuXG.*HC,hSI#.nM*FxRcQ1zwQ

Test Suite

La suite di test omette gli ultimi due casi perché esauriranno la memoria. L'algoritmo usato qui è di trovare tutti gli indici di ciascun carattere nella seconda stringa nella prima stringa, quindi trovare tutti i possibili ordinamenti di quegli indici e prendere solo quelli che sono in ordine. Quindi utilizzare il primo di questi in ordine ordinato come elenco di indici nella prima stringa per aggiornare con i valori della terza stringa.

Sento che dovrebbe esserci qualcosa di più corto di .nM*F...


4

MATL , 33 byte

y!=[]0b"@n:!<@*fX<h5Mt?}.]]?iw(}x

Provalo online!

Spiegazione

y!      % Implicitly input first two strings. Duplicate the first and transpose
=       % Compare the two strings element-wise. Gives a 2D array with all combinations
[]      % Push empty array. Indices of matching elements will be appended to this
0       % Push a 0. This is the index of last character used up in first string
b       % Bubble up (rearrange elements in stack) to move 2D array to top
"       % For each column of that array (each char of the second string)
  @     %   Push current column
  n:!   %   Transform into column array of consecutive values starting from 1
  <     %   Compare with index of last character used up of first string
  @*    %   Push current column again. Multiply element-wise (logical AND)
  fX<   %   Find index of first matching character, or empty if there's none
  h     %   Append to array containing indices of matching elements
  5Mt   %   Push index of matching character again. Duplicate
  ?}    %   If it's empty
    .   %     Break loop
  ]     %   End if
]       % End for
        % The top of the stack now contains a copy of the index of last matching
        % character, or an empty array if there was no match
?       % If non-empty: all characters were matched
  i     %   Input third string
  w     %   Swap top two elements in stack
  (     %   Assign the characters of the third string to first string at found indices
}       % Else: the original string needs to be output
  x     %   Delete (partial) array of matching indices. Leave original string in stack
        % End if
        % Implicitly display (either modified string or original string)

3

JavaScript (ES6), 84 byte

(a,b,c)=>[...b].every((q,i)=>r[p=a.indexOf(q,p)]=~p++&&c[i],p=0,r=[...a])?r.join``:a

Spiegazione / Test


3

JavaScript (ES6), 84 76 byte

(a,b,c)=>a.replace(RegExp([...b].join`(.*?)`),c.replace(/\B/g,(_,i)=>'$'+i))

Perché ero sicuro che questo fosse un lavoro per RegExp.

Modifica: salvato 8 byte grazie a @ MartinBüttner ♦.

Un port della risposta Ruby di @ KevinLau ha richiesto 82 byte:

([...a],[...b],[...c])=>(d=a.map(e=>e==b[0]?c.shift(b.shift()):e),b[0]?a:d).join``

Ho anche provato una soluzione RegExp ricorsiva ma che ha richiesto 90 byte:

f=(a,[b,...d],[c,...e])=>b?a.replace(RegExp(b+'(.*'+d.join`.*`+'.*)'),(_,s)=>c+f(s,d,e)):a

3

Julia, 89 70 byte

f(s,a,b,i=0)=(o=join(["$a "[i+1]!=c?c:b[i+=1]for c=s]);i<endof(a)?s:o)

Utilizza un indice iper scorrere le stringhe del modello / sostituzione mentre procediamo. -19 byte grazie a @Dennis!


2

C, 98 byte

char*f(i,o,s,r)char*i,*o,*s,*r;{char*I=i,*O=o;for(;*i;++i,++o)*o=*i==*s?++s,*r++:*i;return*s?I:O;}

/ * Codice espanso * /

char *f(i, o, s, r)
    char *i, *o, *s, *r;
{
    char *I=i, *O=o;
    for (;  *i;  ++i,++o)
        *o = (*i==*s) ? (++s,*r++) : *i;
    return *s ? I : O;
}

Argomenti sono: i nput stringa, o scita tampone, s stringa earch, r eplacement.

Dopo aver ricordato l'inizio dell'input e dell'output, seguiamo l'input, sostituendo e facendo avanzare la sostituzione ogni volta che ne colpiamo uno. Alla fine, se abbiamo esaurito le sostituzioni, restituisci il buffer di output, altrimenti l'input non modificato.

/ * Test * /

struct T
{
    const char *input;
    const char *search;
    const char *replace;
    const char *expected;
};

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    int i;
    static const struct T test[] = {
        { "abcdefghijklmnopqrstuvwxyz",
          "ghost",
          "12345",
          "abcdef12ijklmn3pqr45uvwxyz"},
        { "abcdeedcba",
          "ada",
          "BOB",
          "BbcOeedcbB"},
        { "abcdeedcbaabcde",
          "ed",
          "12",
          "abcd1e2cbaabcde"},
        { "121",
          "121",
          "aBc",
          "aBc"},
        { "abcde",
          "acb",
          "123",
          "abcde"},
        { "ABC",
          "ABCD",
          "1234",
          "ABC"},
        { "012345678901234567890123456789",
          "42",
          "TT",
          "0123T5678901T34567890123456789"},
        { "edcbaedcbaedcbaedcba",
          "abcde",
          "12345",
          "edcbaedcbaedcbaedcba"},
        { "edcbaedcbaedcbaedcbaedcba",
          "abcde",
          "12345",
          "edcb1edc2aed3bae4cba5dcba"},
        { "daccdedca",
          "ace",
          "cra",
          "dcrcdadca"},
        { "aacbcbabcccaabcbabcaabbbbca",
          "abaaaccbac",
          "1223334444",
          "aacbcbabcccaabcbabcaabbbbca"},
        { "aacbcbabcccaabcbabcaabbbbcac",
          "abaaaccbac",
          "1223334444",
          "1ac2cb2bccc33b3bab4aa4bbbc44"
        }
    };

    for (i = 0;  i < (sizeof test) / (sizeof test[0]);  ++i) {
        const struct T *t = test+i;
        char *out = malloc(strlen(t->input)+1);
        char *result = f(t->input, out, t->search, t->replace);
        if (strcmp(t->expected, result))
            printf("Failed test %d; result = \"%s\"\n", i, result);
    }
    return EXIT_SUCCESS;
}

2

R, 76 byte

function(a,b,c){s=substr;for(x in 1:nchar(b)){a=sub(s(b,x,x),s(c,x,x),a)};a}

usi sub per sostituire la prima partita

Ungolfed

function(a,b,c){                    # function with 3 arguments as per description
  s=substr;                         # alias for substr (saves 1 byte)
   for(x in 1:nchar(b)){            # index 1 to number character in b
     a=sub(s(b,x,x),s(c,x,x),a)};   # replace first instance of b[x] in a  
                                    # with c[x] and reassign to a
 a}                                 # return a

2

C ++, 204 byte

golfed

#include<iostream>
#include<string>
int main(){std::string a, b, c;std::cin>>a>>b>>c;int t=0;for(int x=0;x<b.length();x++){t=a.find(b[x],t);if(t!=-1){a.replace(t,1,c.substr(x,1));}}std::cout<<a;return 0;}

Ungolfed

#include<iostream>
#include<string>

int main()
{
    std::string a, b, c;
    std::cin>>a>>b>>c;
    int t = 0;
    for (int x=0;x<b.length();x++) {
        t = a.find(b[x], t);
        if (t != -1) {
            a.replace(t,1,c.substr(x, 1));
        }
    }
    std::cout<<a;
    return 0;
}

Non penso che tu stia usando stdabbastanza per giustificare l'utilizzo using namespace std;. L'uso di std::cin, std::coute std::stringsalverà 5 byte poiché quelli sembrano essere gli unici usi di quello spazio dei nomi.
Value Ink

@KevinLau Grazie! Hai ragione, ci ho pensato, ma in realtà non ho contato per rendermi conto che avrebbe salvato i caratteri.
Michelfrancis Bustillos,

Oh! Un'altra cosa, dal momento che è importante. Dopo aver letto di nuovo il codice, mi sono reso conto che stai sostituendo avidamente l'occorrenza più a sinistra di ogni lettera all'interno di bin a, ma anche le lettere successive devono essere dopo quelle precedenti. (Guarda il test case 3 e confrontalo con il tuo output, penso che scoprirai che il tuo codice uscirà abc21ed...quando l'output previsto è abcd1e2...!)
Value Ink

In ideone C ++ 14 input del compilatore di "Adregffftd \ nA23 \ nzac \ n" sopra il codice 10 minuti fa, genera l'output di "zdregffftd" invece di "Adregffftd"
RosLuP


2

Haskell, 87 byte

x@((a,b):c)#(d:e)|a==d,([],z)<-c#e=([],b:z)|0<1=(d:)<$>x#e
x#y=(x,y)
a!b=snd.(zip a b#)

Ho notato la mancanza di una risposta Haskell e ho deciso di risolverlo. Questo definisce una funzione ternaria !con ordine modello-sostituzione-stringa di argomenti. Provalo qui.

Spiegazione

La funzione ausiliaria #prende un elenco xdi coppie di caratteri (modello e sostituzione) e una stringa y. Se i caratteri "pattern" sono presentix formano una sottosequenza di y, restituisce l'elenco vuoto e ycon ogni carattere pattern sostituito dalla sua controparte. Altrimenti, restituisce la coppia (x,y). La funzione !comprime il pattern e le stringhe di sostituzione x, si applica #alla xterza stringa e restituisce il secondo componente del risultato.

x@((a,b):c)#(d:e)  -- First case of #: both arguments nonempty.
  |a==d,           -- If the pattern char matches the string's head,
   ([],z)<-c#e     -- and the pattern's tail is a subsequence of the string's tail,
  =([],b:z)        -- tack the replacement char to the recursion result.
  |0<1             -- Otherwise,
  =(d:)<$>x#e      -- recurse with the same pairs and tack string's head to result.
x#y=(x,y)          -- If either argument is empty, just pair them.

Se il modello è una sottosequenza della stringa, il codice viene eseguito in O (n) time, facendo passare un ricorsivo attraverso la stringa e costruendo avidamente la sostituzione nel processo. Tuttavia, se il modello non è una sottosequenza, viene eseguito nel tempo O (2 n ) nel peggiore dei casi. Questo perché in ogni posizione in cui il modello e la stringa hanno un carattere corrispondente, la funzione si chiama per verificare se il modello è effettivamente una sottosequenza, scopre che non lo è e si chiama una seconda volta per calcolare effettivamente il risultato.


2

JavaScript (ES6), 100 95 byte

(a,b,c)=>1?(t=[...a].map(e=>b[0]==e?(u=c[0],b=b.slice(1),c=c.slice(1),u):e).join``,b==""?t:a):a

Questa è una funzione Lambda JavaScript valida. Uscite come funzione return. Accetta tre argomenti ( a,b,c). Aggiungi f=all'inizio e invoca like f(arg1,arg2,arg3).

f=(a,b,c)=>1?(t=[...a].map(e=>b[0]==e?(u=c[0],b=b.slice(1),c=c.slice(1),u):e).join``,b==""?t:a):a

console.log(f(prompt("Value for A"),prompt("Value for B"),prompt("Value for C")))


Benvenuti in PPCG! Le funzioni senza nome sono generalmente accettabili , quindi non è necessario a f=meno che la funzione non sia ricorsiva, ma non sembra che lo sia.
Martin Ender,

@ MartinBüttner Grazie! :) Aggiornato la mia risposta.
Arjun,

Sfortunatamente, questo fallirà se anon contiene il modello. Inoltre, non sono sicuro che sia accettabile la restituzione di una serie di stringhe.
Dennis,

@Dennis Ho aggiornato la mia soluzione. Penso che sia corretto ora. Ci scusiamo per la risposta e l'aggiornamento in ritardo. (Ho appena notato il tuo commento, quindi il ritardo)
Arjun

@MartinEnder Mentre stavo esaminando tutte le mie soluzioni, ho scoperto che questa non era corretta. Ma ora l'ho corretto; ed è più breve di cinque byte (da quando non avevo toccato molti campi da golf; a quel tempo ero un golfista alle prime armi; non che ora sia un grande giocatore di golf: p). Ci scusiamo per la pubblicazione di una soluzione sbagliata.
Arjun,


1

Ottava, 97 byte

function A=U(A,B,C)t=0;for s=B if p=find(A(t+1:end)==s,1) D(t=p+t)=~0;else return;end;end;A(D)=C;

Scorrere la sottosequenza da sostituire; trova la prima occorrenza del primo carattere, trova il carattere successivo nella stringa rimanente, ripeti. L'unico aspetto interessante di questo è:

D(t=p+t)=~0

D(     )      %// D is a logical mask of characters to replace in the input string
  t=p+t       %// t is the current end of D 
              %// p is the location of the character to replace
              %// update t and use as index to grow D
        =~0   %// make it so, number 1

Dato che ideone non accetta ancora funzioni con nomi diversi da "", lascerò solo un esempio qui. Gli input sono mostrati solo per i primi casi di test per brevità. keyè l'output previsto, ansè l'output della funzione.

A = abcdefghijklmnopqrstuvwxyz
B = ghost
C = 12345
key = abcdef12ijklmn3pqr45uvwxyz
ans = abcdef12ijklmn3pqr45uvwxyz
A = abcdeedcba
B = ada
C = BOB
key = BbcOeedcbB
ans = BbcOeedcbB
A = abcdeedcbaabcde
B = ed
C = 12
key = abcd1e2cbaabcde
ans = abcd1e2cbaabcde
key = aBc
ans = aBc
key = abcde
ans = abcde
key = ABC
ans = ABC
key = 0123T5678901T34567890123456789
ans = 0123T5678901T34567890123456789
key = edcbaedcbaedcbaedcba
ans = edcbaedcbaedcbaedcba
key = edcb1edc2aed3bae4cba5dcba
ans = edcb1edc2aed3bae4cba5dcba
key = dcrcdadca
ans = dcrcdadca
key = aacbcbabcccaabcbabcaabbbbca
ans = aacbcbabcccaabcbabcaabbbbca
key = 1ac2cb2bccc33b3bab4aa4bbbc44
ans = 1ac2cb2bccc33b3bab4aa4bbbc44

Quei compiti di Octave in posti inaspettati ( D(t=...)) continuano a sconcertarmi :-)
Luis Mendo,

1
@LuisMendo haha ​​... è quasi come ... uno stack! :)
becher

1

Python 3, 123 byte

Un approccio diverso che volevo condividere, che è più corto di pochi byte. Non ci sono regole contro la libreria / regex standard, giusto?

import re
j=''.join
m='(.*?)'
def f(A,B,C):
 *r,l=(re.findall(m+m.join(B)+'(.*)',A)or[[A]])[0]
 print(j(map(j,zip(r,C)))+l)

PS. Questo è il mio primo golf. Fammi sapere di eventuali problemi / miglioramenti.


1

Pyth, 22 byte

|eJ:Ej"(.*?)"+E\$3s.iJ

Verifica tutti i casi di test nel compilatore Pyth .

sfondo

Costruiamo una regex dal modello aggiungendo a $e posizionando(.*?) tra tutti i personaggi. Questa regex corrisponderà alla sottosequenza da sostituire e qualsiasi cosa tra i suoi elementi e qualsiasi cosa fino alla fine della stringa.

Poiché i quantificatori sono pigri, ognuno (.*?)corrisponderà al minor numero possibile di caratteri.

Per il fantasma del modello, la regex costruita è g(.*?)h(.*?)o(.*?)s(.*?)t(.*?)$.

Se il modello corrisponde all'input, l'integrato r<str><regex>3restituirà un array contenente la prematch (tutto prima della sottosequenza), tutti i gruppi acquisiti (tutto tra e dopo la sottosequenza) e il postmatch (la stringa vuota).

Se il modello non corrisponde, l'integrato restituirà un array singleton contenente l'input originale.

Come funziona

|eJ:Ej"(.*?)"+E\$3s.iJQ  (implicit) Store the first line of input in Q.

             +E\$        Read the third line of input (pattern) and append '$'.
     j"(.*?)"            Join the result, separating by "(.*?)".
    E                    Read the third line of input (string).
   :             3       Match the string against the regex, as detailed above.
  J                      Save the returned array in J.
 e                       Extract the last element of J. This is an empty string
                         for a successful match or the original string.
|                        Logical OR; replace an empty string with the following:
                   .iJQ    Interleave J and the replacement.
                  s        Flatten the resulting array of strings.

1

Gelatina , 23 byte

Ṭœpż⁵
0ẋai1
⁴='-;ç\ñ⁴P?

Sono due byte più lunghi dell'altra mia risposta di Jelly , ma termina all'istante. Provalo online!

Verifica

$ head -n 5 test-cases
abcdefghijklmnopqrstuvwxyz
ghost
12345
abcdef12ijklmn3pqr45uvwxyz

$ cat subseq-fast
while read s; do
        read p; read r; read o; echo $o; read
        timeout 10s jelly eun $1 "Ṭœpż⁵¶0ẋai1¶⁴='-;ç\ñ⁴P?" "'$p'" "'$s'" "'$r'"
        (($?)) && echo '(killed)'
done < test-cases
$ ./subseq-fast
abcdef12ijklmn3pqr45uvwxyz
abcdef12ijklmn3pqr45uvwxyz
BbcOeedcbB
BbcOeedcbB
abcd1e2cbaabcde
abcd1e2cbaabcde
aBc
aBc
abcde
abcde
ABC
ABC
0123T5678901T34567890123456789
0123T5678901T34567890123456789
edcbaedcbaedcbaedcba
edcbaedcbaedcbaedcba
edcb1edc2aed3bae4cba5dcba
edcb1edc2aed3bae4cba5dcba
dcrcdadca
dcrcdadca
aacbcbabcccaabcbabcaabbbbca
aacbcbabcccaabcbabcaabbbbca
1ac2cb2bccc33b3bab4aa4bbbc44
1ac2cb2bccc33b3bab4aa4bbbc44

Come funziona

⁴='-;ç\ñ⁴P?  Main link. Arguments: pattern p, string s, replacement r

⁴='          Compare each character of s with each character of p.
             This yields a 2D list. Each row corresponds to a char in p.
   -;        Prepend -1 to the 2D list, yielding a ragged array.
     ç\      Cumulatively reduce the array by the second helper link.
         P?  If the product of the resulting list is non-zero:
       ñ       Call the first helper link with the list and s as arguments.
        ⁴      Else, return s.


Ṭœpż⁵        First helper link. Arguments: L (list of indices), r (replacement)

Ṭ            Truth; generate a list with 1's at those indices.
 œp          Partition; split s at all 1's, removing those characters.
   ż⁵        Zip the partition with r.


0ẋai1        Second helper link. Arguments: n (integer), B (list of Booleans)

0ẋ           Generate a list of n zeroes.
  a          Perform logical AND with B.
             This zeroes out the with n elements of B.
   i1        Compute the first index of 1.


1

Java 7, 102 byte

void L(char[]s,char[]l,char[]r){for(int x=0,y=0;x<s.length&&y<l.length;x++)if(s[x]==l[y])s[x]=r[y++];}

Prova dettagliata qui

// String, Lookup, Replacement
void L(char[]s, char[]l, char[]r)
{
    for(int x=0, y=0; x < s.length && y < l.length; x++)
        if(s[x] == l[y])
            s[x] = r[y++];
}

1

Julia, 93 90 86 byte

f(s,p,r)=(try s=join([match(Regex(join("^$p\$","(.*?)")),s).captures';[r...""]])end;s)

Dover provare separatamente se la partita ha avuto successo distrugge il punteggio. Una sostituzione richiederebbe il casting Base.SubstitutionString, che probabilmente non ne vale la pena ...

Prova

julia> f(s,p,r)=(try s=join([match(Regex(join("^$p\$","(.*?)")),s).captures';[r...""]])end;s)
f (generic function with 1 method)

julia> f("aacbcbabcccaabcbabcaabbbbca","abaaaccbac","1223334444")
"aacbcbabcccaabcbabcaabbbbca"

julia> f("aacbcbabcccaabcbabcaabbbbcac","abaaaccbac","1223334444")
"1ac2cb2bccc33b3bab4aa4bbbc44"

1

Julia, 62 59 58 byte

f(s,p,r)=(try s[[i=findnext(s,c,i+1)for c=p]'],i=r,0end;s)

L'I / O è in forma di array di caratteri.

Verifica

julia> f(s,p,r)=(try s[[i=findnext(s,c,i+1)for c=p]'],i=r,0end;s)
f (generic function with 2 methods)

julia> F(s,p,r)=join(f([s...],[p...],[r...])) # string/char array conversion
F (generic function with 1 method)

julia> F("aacbcbabcccaabcbabcaabbbbca","abaaaccbac","1223334444")
"aacbcbabcccaabcbabcaabbbbca"

julia> F("aacbcbabcccaabcbabcaabbbbcac","abaaaccbac","1223334444")
"1ac2cb2bccc33b3bab4aa4bbbc44"

1

PHP, 130 109 byte

Mi piacerebbe ancora più breve; potrebbe salvare 3 byte ( ""<) se Bfosse garantito che non contenesse 0.

for($s=($a=$argv)[1];""<$c=$a[2][$i++];)if($p=strpos(_.$s,$c,$p+1))$s[$p-1]=$a[3][$k++];echo$k<$i-1?$a[1]:$s;

accetta argomenti dalla riga di comando. Corri con-r .

Sostituisce i personaggi quando li trova;
stampa copia se tutti i caratteri sono stati sostituiti; altro originale.


1

Ruby, 70 anni 64 59 58 byte

Funzione anonima. Cammina attraverso la cordaa per creare una nuova stringa con le lettere sostituite in base al carattere successivo in be c, quindi se tutti i caratteri inb sono esauriti alla fine, restituisci la stringa appena costruita, altrimenti restituisce la stringa originale.

@histocrat ha contribuito a salvare 6 byte tramite gsub .

Salvato 1 byte grazie a @Cyoce.

->a,b,c{i=0;s=a.gsub(/./){$&==b[i]?c[~-i+=1]:$&};b[i]?a:s}

Provalo online!


Puoi salvare un byte sostituendolo -1+i+=1con~-i+=1
Cyoce

0

Perl, 80 + 1 = 81 byte

Corri con la -pbandiera

$a=join"(.*?)",split//,<>;$b.=$_." .\$".++$;."."for split//,<>;chop$b;s/$a/$b/ee

Provalo online!

Il codice genera proceduralmente una ricerca e sostituisce il comando regex, che viene quindi eseguito nell'ultimo bit di codice.

La stringa ghostnel primo esempio viene trasformata nella stringa g(.*?)h(.*?)o(.*?)s(.*?)t(.*?), il che significa un gseguito da 0 o più caratteri, seguito da un hseguito da 0 o più caratteri, seguito da ecc.*? quantificatore indica che la ricerca deve essere non avida e "gobble "il minor numero di caratteri possibile, anziché il valore predefinito di corrispondenza il più possibile.

La stringa 12345viene quindi trasformata in 1 .$1.2 .$2.3 .$3.4 .$4.5 .$5, che viene valutata dopo l'esecuzione della regex. Ognuno di $1,$2,$3,$4,$5essi è in realtà un riferimento a un gruppo di acquisizione (tra parentesi) dalla prima stringa.


Suggerisco questo codice per risparmiare pochi byte: perl -pe 'eval"s/".<>=~s/.\K/(.*?)/gr."/".<>=~s/.\K/"\${".++$i."}"/gre."/"'. Sono arrivato da solo, ma è abbastanza vicino al tuo, quindi non lo posterò, sarebbero due risposte molto vicine, ma sentiti libero di modificare il tuo!
Dada,

Ho appena provato questo perché l'ho visto elencato come una domanda "correlata" a un problema recente. Il migliore che ho avuto è statoperl -E 'chomp(($f,$t,$s)=(<>));$f=join"(.*?)",split"",$f;@r=split"",$t;@t=shift@r;push@t,"\${",++$x,"}"for(@r);$t=join"",@t;say$s=~s/$f/$t/r;'
Will Crawford il

0

Clojure, 113 byte

#(apply str((reduce(fn[[b c r]a](if(=(first b)a)[(rest b)(rest c)(conj r(first c))][b c(conj r a)]))[%2%3[]]%)2))

Una base reduce, non troppo felice per tutti coloro che lungo first, reste conjchiamate di funzione. Spero di vedere un approccio migliore.

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.