Substituição subsequente

30

A maioria dos idiomas vem com um built-in para pesquisar uma string por todas as ocorrências de uma determinada substring e substituí-las por outra. Não conheço nenhuma linguagem que generalize esse conceito para subsequências (não necessariamente contíguas). Portanto, essa é sua tarefa neste desafio.

A entrada será composta por três cadeias A, Be C, onde Be Csão garantidas a ser do mesmo comprimento. Se Baparecer como uma subsequência A, deverá ser substituído por C. Aqui está um exemplo simples:

A: abcdefghijklmnopqrstuvwxyz
B: ghost
C: 12345

Seria processado assim:

abcdefghijklmnopqrstuvwxyz
      ||      |   ||
abcdef12ijklmn3pqr45uvwxyz

Se houver várias maneiras de encontrar Bcomo uma subsequência, você deve substituir avidamente a mais à esquerda:

A: abcdeedcba
B: ada
C: BOB

Result:   BbcOeedcbB
and NOT:  BbcdeeOcbB

O mesmo se aplica se Bpuder ser encontrado em vários locais separados:

A: abcdeedcbaabcde
B: ed
C: 12

Result:   abcd1e2cbaabcde
and NOT:  abcd112cbaabc2e (or similar)

Quando Bnão aparecer A, a saída deve ser Ainalterada.

Regras

Como mencionado acima, pegue três cadeias e A, como entrada, substitua a ocorrência mais à esquerda de como uma subsequência por , se houver alguma.BCBAC

Você pode escrever um programa ou função, recebendo entrada via STDIN (ou alternativa mais próxima), argumento da linha de comando ou argumento da função e emitindo o resultado via STDOUT (ou alternativa mais próxima), valor de retorno da função ou parâmetro da função (saída).

Você pode pegar as três cadeias em qualquer ordem consistente que você deve especificar em sua resposta. Você pode assumir isso Be Cter o mesmo comprimento. Todas as seqüências conterão apenas caracteres alfanuméricos.

Aplicam-se as regras padrão de .

Casos de teste

Cada caso de teste é quatro linhas: A, B, Cseguido pelo resultado.

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

Entre os melhores

O snippet de pilha na parte inferior desta postagem gera classificações das respostas a) como uma lista da solução mais curta por idioma eb) como uma classificação geral.

Para garantir que sua resposta seja exibida, inicie-a com um título, usando o seguinte modelo de remarcação:

## Language Name, N bytes

onde Nestá o tamanho do seu envio. Se você melhorar sua pontuação, poderá manter as pontuações antigas no título, identificando-as. Por exemplo:

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

Se você quiser incluir vários números no cabeçalho (por exemplo, porque sua pontuação é a soma de dois arquivos ou você deseja listar as penalidades do sinalizador de intérpretes separadamente), verifique se a pontuação real é o último número no cabeçalho:

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

Você também pode transformar o nome do idioma em um link que será exibido no snippet:

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

Martin Ender
fonte
Uma lista de cadeias de caracteres únicas seria boa para entrada / saída?
FryAmTheEggman # 13/04
@FryAmTheEggman Hm, o único consenso que posso encontrar é este que não trata de listas de cadeias de caracteres únicos como representações de cadeias válidas. Pode valer a pena fazer um meta post (especialmente porque acho que isso também surgiu no último desafio do xnor). Eu vou dizer não por enquanto.
Martin Ender
E as matrizes de caracteres? Isso parece sugerir que eles são permitidos, mesmo que o idioma tenha um tipo de string apropriado.
Dennis
@ Dennis Sim, as matrizes de caracteres são boas, mas as strings singleton são como pegar uma matriz de números inteiros como [[1], [2], [3]].
Martin Ender
OK, obrigado por esclarecer isso.
Dennis

Respostas:

3

Geléia , 23 22 21 bytes

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

Experimente online! Observe que os dois últimos casos de teste ficarão sem memória.

Verificação

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

Como funciona

='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.
Dennis
fonte
12

Python 2, 88 bytes

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>'']

Uma função que pega as três seqüências e gera o resultado para STDOUT. A função simplesmente passa a string, pegando o caractere apropriado e atualizando à b,cmedida que avançamos.

Para teste (depois de substituir o printpor return):

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

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

Java 7, 141

Acho que posso fazer mais com isso, mas tenho que correr por enquanto. É apenas uma iteração / substituição simples, mantendo um índice em 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;}

Espaços em branco para o seu prazer:

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;
}
Geobits
fonte
Whitespacedsim, isso é totalmente legível
gato
Não é? A principal razão pela qual adicionei a versão recuada com várias linhas é evitar a rolagem horizontal, para que tudo possa ser visto de uma só vez. Linha de espaço em branco não é tão negócio um grande IMO;)
Geobits
[solicitação de recurso] ainda mais espaço em branco
Alex A.
@AlexA. Aqui está você!
Geobits
@Geobits Salvar um byte no final, se você fizerj<k?a:d
Xanderhall
7

Lua, 121 bytes

Solução simples, gsubpermite iterar exatamente uma vez em cada caractere e substituí-los em uma nova instância da string.

Ele recebe a entrada via 3 argumento da linha de comando e gera uma string para 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
Katenkyo
fonte
6

Python 3, 127 bytes.

Economizou 16 bytes graças a Katenkyo.

Ainda trabalhando um pouco nisso, o homem era mais desagradável do que eu pensava.

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

Explicação: Awww sim, recursão.

Casos de teste:

assert f('abcdeedcba', 'ada', 'BOB') == 'BbcOeedcbB'
assert f('abcdeedcbaabcde', 'ed', '12') == 'abcd1e2cbaabcde'
assert f('012345678901234567890123456789', '42', 'TT') == '0123T5678901T34567890123456789'
assert f('ABC', 'ABCD', '1234') == 'ABC'
Morgan Thrapp
fonte
+1 para jogar golfe 50 fora, mas continue! Isso precisa vencer a minha resposta Java, pelo menos;)
Geobits
7
@ Geobits Sim, eu nunca perdi para Java antes. Esta é a minha maior vergonha.
Morgan Thrapp
Eu realmente não sou versado em python, mas all(x in a for x in b)também verifica se os elementos em be aparecem na mesma ordem, ou apenas se eles estiverem aqui?
precisa saber é
@Katenkyo Só que eles estão todos lá, mas o pedido é resolvido pela fatia quando recessamos.
Morgan Thrapp
Ok, também, não faria 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 avocê salvar alguns bytes?
precisa saber é
5

Python 3.5, 87 bytes

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

repl.it para verificar todos os casos de teste .

Como funciona

  • '(.*?)'.join(p) cria um padrão de pesquisa que corresponde à subsequência a ser substituída e qualquer coisa entre seus elementos.

    Como os quantificadores são preguiçosos, cada (.*?)um corresponderá ao mínimo de caracteres possível.

    Para o padrão ghost, o regex construído é g(.*?)h(.*?)o(.*?)s(.*?)t.

  • '\g<%d>'.join(r)%(*range(1,len(r)),) cria a cadeia de substituição, usando a formatação da cadeia.

    Cada \g<n>refere-se ao n th grupo capturado, tal como \no faria.

    Para a substituição 12345, a cadeia construída é 1\g<1>2\g<2>3\g<3>4\g<4>5.

  • re.sub(...,...,s,1)executa no máximo uma substituição na string s.

Dennis
fonte
4

Pyth, 27

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

Suíte de teste

O conjunto de testes omite os dois últimos casos porque eles ficarão sem memória. O algoritmo usado aqui é encontrar todos os índices de cada caractere na segunda sequência da primeira sequência, encontrar todas as ordens possíveis desses índices e pegar apenas os que estão na ordem classificada. Em seguida, use o primeiro deles em ordem classificada como a lista de índices na primeira sequência para atualizar com os valores da terceira sequência.

Eu sinto que deveria haver algo mais curto que .nM*F...

FryAmTheEggman
fonte
4

MATL , 33 bytes

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

Experimente online!

Explicação

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)
Luis Mendo
fonte
3

JavaScript (ES6), 84 bytes

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

Explicação / Teste

user81655
fonte
3

JavaScript (ES6), 84 76 bytes

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

Porque eu tinha certeza de que esse era um trabalho para o RegExp.

Editar: salvou 8 bytes graças a @ MartinBüttner ♦.

Uma porta da resposta Ruby de @ KevinLau levou 82 bytes:

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

Eu também tentei uma solução RegExp recursiva, mas que levou 90 bytes:

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

Julia, 89 70 bytes

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

Usa um índice ipara percorrer as seqüências de padrão / substituição à medida que avançamos. -19 bytes graças a @Dennis!

Sp3000
fonte
2

C, 98 bytes

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

/ * Código expandido * /

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

Os argumentos são: i ntrada cadeia, o utput tampão, s cadeia earch, r eplacement.

Depois de lembrar o início da entrada e da saída, passamos pela entrada, substituindo e avançando a substituição sempre que atingimos uma. No final, se ficarmos sem substituições, retorne o buffer de saída, senão a entrada não modificada.

/ * Testes * /

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;
}
Toby Speight
fonte
2

R, 76 bytes

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

usa sub para substituir a primeira correspondência

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
mnel
fonte
2

C ++, 204 bytes

Golfe

#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;
}
Michelfrancis Bustillos
fonte
Não acho que você esteja usando o stdsuficiente para justificar o uso using namespace std;. Usando std::cin, std::coute std::stringvai economizar 5 bytes uma vez que aqueles parecem ser os únicos usos desse namespace.
Valor Ink
@KevinLau Thanks! Você está muito correto, pensei nisso, mas não contei para perceber que isso salvaria caracteres.
Michelfrancis Bustillos
Oh! Mais uma coisa, já que é importante. Depois de ler o código novamente, percebi que você está substituindo avidamente a ocorrência mais à esquerda de cada letra dentro de bdentro a, mas as letras posteriores também devem ser as letras anteriores. (Olhe caso de teste 3 e comparar com a sua saída, eu acho que você vai achar que o seu código seria de saída abc21ed...quando a saída esperada é abcd1e2...!)
Valor Ink
Na entrada do compilador C ++ 14 ideone do "Adregffftd \ nA23 \ nzac \ n" acima do código 10 minutos atrás, gere a saída de "zdregffftd" em vez de "Adregffftd"
RosLuP
2

Retina , 63 bytes

.+$
$&¶;$&
+`^(.)(.*¶)(.)([^;]+);(.*?)\1
$2$4$5$3;
A1`
;

G2=`.

A entrada é feita na ordem B, C, A, separados por alimentações de linha.

Experimente online.

Martin Ender
fonte
2

Haskell, 87 bytes

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

Percebi a falta de uma resposta Haskell e decidi consertar isso. Isso define uma função ternária !com ordem de argumento padrão-substituição-sequência. Experimente aqui.

Explicação

A função auxiliar #pega uma lista xde pares de caracteres (padrão e substituição) e uma string y. Se os caracteres "padrão" xformarem uma subsequência de y, ele retornará a lista vazia e ycom cada caractere padrão substituído por sua contraparte. Caso contrário, ele retornará o par (x,y). A função !fecha o padrão e substitui as seqüências de caracteres x, aplica #- se à xterceira sequência e retorna o segundo componente do resultado.

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 o padrão for uma subsequência da sequência, o código será executado em O (n) tempo, fazendo uma passagem recursiva pela sequência e construindo avidamente a substituição no processo. No entanto, se o padrão não for uma subsequência, ele será executado no tempo O (2 n ) no pior caso. Isso ocorre porque em todas as posições em que o padrão e a string têm um caractere correspondente, a função se chama para verificar se o padrão é realmente uma subsequência, descobre que não é e se chama uma segunda vez para calcular o resultado.

Zgarb
fonte
2

JavaScript (ES6), 100 95 bytes

(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

Esta é uma função JavaScript Lambda válida. Saídas como função return. Aceita três argumentos ( a,b,c). Adicione f=no início e chame 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")))

Arjun
fonte
Bem-vindo ao PPCG! As funções sem nome são geralmente aceitáveis ; portanto, você não precisa disso, a f=menos que sua função seja recursiva, mas não pareça.
Martin Ender
@ MartinBüttner Obrigado! :) Atualizei minha resposta.
Arjun #
Infelizmente, isso falhará se anão contiver o padrão. Também não tenho certeza de que retornar uma matriz de seqüências de caracteres seja aceitável.
Dennis
@ Dennis Atualizei minha solução. Eu acho que está correto agora. Desculpe pela atualização e resposta tardia. (Eu notei o seu comentário, daí o atraso)
Arjun
@ MartinEnder Enquanto estava estudando todas as minhas soluções, descobri que esta estava incorreta. Mas, eu o corrigi agora; e é cinco bytes mais curto (desde que eu deixara muitos locais de golfe intocáveis; eu era um novato na época; não que eu seja ótimo agora: p). Desculpe por postar uma solução errada.
Arjun #
2

C (gcc), 67 62 61 59 bytes

f(s,a,b)char*s,*a,*b;{*s==*a?*s=*b++,a++:1;*a&&f(s+1,a,b);}

Experimente online!

betseg
fonte
1

Oitava, 97 bytes

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;

Iterar sobre a subsequência para substituir; encontre a primeira ocorrência do primeiro caractere, encontre o próximo caractere na sequência restante, repita. O um pouco interessante disso é:

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

Como o ideone ainda não está aceitando funções com nomes diferentes de '', deixarei apenas uma amostra executada aqui. As entradas são mostradas apenas para os primeiros casos de teste por questões de brevidade. keyé a saída esperada, ansé a saída da função.

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
taça
fonte
Essas atribuições Octave em lugares inesperados ( D(t=...)) manter-me intrigante :-)
Luis Mendo
1
@LuisMendo haha ​​... é quase como ... uma pilha! :)
béquer
1

Python 3, 123 bytes

Uma abordagem diferente que eu queria compartilhar, que é alguns bytes mais curta. Não há regras contra a biblioteca / regex padrão, certo?

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. Este é o meu primeiro golfe. Deixe-me saber de quaisquer problemas / melhorias.

Marc J
fonte
1

Pitão, 22 bytes

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

Verifique todos os casos de teste no Pyth Compiler .

fundo

Construímos uma regex a partir do padrão acrescentando ae $colocando(.*?) entre todos os caracteres. Essa regex corresponderá à subsequência a ser substituída e qualquer coisa entre seus elementos e qualquer coisa até o final da string.

Como os quantificadores são preguiçosos, cada (.*?)um corresponderá ao mínimo de caracteres possível.

Para o fantasma padrão, o regex construído é g(.*?)h(.*?)o(.*?)s(.*?)t(.*?)$.

Se o padrão corresponder à entrada, o padrão r<str><regex>3 -in retornará uma matriz contendo o prematch (tudo antes da subsequência), todos os grupos capturados (tudo entre e após a subsequência) e o postmatch (a sequência vazia).

Se o padrão não corresponder, o built-in retornará uma matriz singleton contendo a entrada original.

Como funciona

|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.
Dennis
fonte
1

Gelatina , 23 bytes

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

Isso é dois bytes mais longo do que minha outra resposta Jelly , mas termina instantaneamente. Experimente online!

Verificação

$ 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

Como funciona

⁴='-;ç\ñ⁴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.
Dennis
fonte
1

Java 7, 102 bytes

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++];}

Teste detalhado aqui

// 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++];
}
Khaled.K
fonte
1

Julia, 93 90 86 bytes

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

Ter que testar separadamente se a partida foi bem-sucedida destrói o placar. Uma substituição exigiria a transmissão Base.SubstitutionString, o que provavelmente não vale a pena ...

Execução de teste

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"
Dennis
fonte
1

Julia, 62 59 58 bytes

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

A E / S está na forma de matrizes de caracteres.

Verificação

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"
Dennis
fonte
1

PHP, 130 109 bytes

Eu ainda gostaria que fosse mais curto; poderia salvar 3 bytes ( ""<) se não Bfosse garantido 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;

recebe argumentos da linha de comando. Corra com -r.

Substitui os caracteres quando os encontra;
imprime cópia se todos os caracteres foram substituídos; original mais.

Titus
fonte
1

Ruby, 70 64 59 58 bytes

Função anônima. Percorra a sequência apara criar uma nova sequência com as letras substituídas de acordo com o próximo caractere be c, se todos os caracteres bestiverem esgotados no final, retorne a sequência recém-construída, caso contrário, retorne a sequência original.

@histocrat ajudou a economizar 6 bytes via gsub.

Guardou 1 byte graças a @Cyoce.

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

Experimente online!

Value Ink
fonte
Você pode salvar um byte substituindo -1+i+=1por~-i+=1
Cyoce
0

Perl, 80 + 1 = 81 bytes

Corra com a -pbandeira

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

Experimente online!

O código gera procedimentalmente um comando regex de pesquisa e substituição, que é executado no último bit de código.

A sequência ghostno primeiro exemplo é transformada em sequência g(.*?)h(.*?)o(.*?)s(.*?)t(.*?), o que significa um gseguido por 0 ou mais caracteres, seguido por um hseguido por 0 ou mais caracteres, seguido por etc.*? quantificador significa que a pesquisa deve ser não gulosa e "devorar" "o menor número possível de caracteres, em vez do padrão de corresponder o máximo possível.

A cadeia de caracteres 12345é então transformada 1 .$1.2 .$2.3 .$3.4 .$4.5 .$5, avaliada após a execução da regex. Cada um deles $1,$2,$3,$4,$5é realmente uma referência anterior a um grupo de captura (entre parênteses) da primeira sequência.

Gabriel Benamy
fonte
Eu sugiro este código para economizar alguns bytes: perl -pe 'eval"s/".<>=~s/.\K/(.*?)/gr."/".<>=~s/.\K/"\${".++$i."}"/gre."/"'. Inventei sozinho, mas é bem parecido com o seu, então não vou publicá-lo, seriam duas respostas muito próximas, mas fique à vontade para editar as suas!
Dada
Só tentei isso porque eu o vi listado como uma pergunta "relacionada" a um problema recente. O melhor que consegui foiperl -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
0

Clojure, 113 bytes

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

Um básico reduce, não muito feliz com todos esses longos first, reste conjchamadas de função. Na esperança de ver uma abordagem melhor.

NikoNyrh
fonte