Sostituzione di stringhe ricorsive


25

L'obiettivo

Scrivere un programma o una funzione che danno tre stringhe A, B, Cproduce una stringa di output in cui ogni istanza di Bin Aè stata sostituita in modo ricorsivo C. Sostituire in modo ricorsivo significa ripetere una sostituzione in cui ad ogni passo tutte le istanze non sovrapposte di Bin A(scelte avidamente da sinistra a destra) vengono sostituite con Cfinché Bnon è più contenuto A.

Input Output

  • È possibile utilizzare uno qualsiasi dei metodi predefiniti per l'I / O .
  • Le stringhe conterranno solo caratteri ASCII stampabili (e potrebbero contenere uno qualsiasi di essi).
  • Bnon sarà mai una stringa vuota, mentre Ae Cpotrebbe essere.
  • Le stringhe devono essere considerate in chiaro, ad esempio non è possibile trattare Bcome un modello Regex.
  • Alcune combinazioni di input non termineranno mai. Il tuo programma può fare qualsiasi cosa in questi casi.

Casi test

Questi sono nel formato: A/B/C\nOutput

Hello, world!/world!/PPCG
Hello, PPCG

Uppercase is up/up/down
Uppercase is down

ababababa/aba/ccc
cccbcccba

delete/e/{empty string}
dlt

{empty string}/no/effect
{empty string}

llllrrrr/lr/rl
rrrrllll

+-+-+-+/+-+/+
+

ababababa/aba/bada
badabbadbada

abaaba/aba/ab
abb

((())())())/()/{empty string}
)

Esempi che non terminano:

grow/ow/oow

loop/lo/lo

3
Un altro caso di prova:((())())())/()/
Conor O'Brien,

@ ConorO'Brien aggiunto
Leo

1
All'inizio non sono riuscito a renderlo sensibile al maiuscolo / minuscolo. downpercase is down
Ingegnere Toast,

Risposte:


7

05AB1E , 2 byte

`:

Provalo online!

Spiegazione

`    # split input to stack
 :   # replace (until string doesn't change)

Questo potrebbe essere :per 1 byte se non dovessimo occuparci di stringhe vuote.


3
Se lo capisco correttamente, la tua soluzione a 4 byte è valida. "Alcune combinazioni di input non finiranno mai. Il tuo programma può fare qualsiasi cosa in questi casi."
Leone,

@Leo. Hai ragione. Ho scremato quella parte :)
Emigna,

1
Quindi in pratica :è un builtin che risolve l'intera sfida? Avrei dovuto vietare i builtin;)
Leone,

@Leo: se non fosse per le stringhe vuote, un singolo built-in risolverebbe questo sì. E l'unica differenza con le stringhe vuote è che dobbiamo specificare che ci sono 3 input, che altrimenti sarebbero implicitamente dedotti dall'operazione :)
Emigna,

E 'qualcosa di simile a questo anche possibile?
Adnan,

9

Python 2 , 43 byte

lambda s,*l:eval('s'+'.replace(*l)'*len(s))

Provalo online!

Valuta una stringa del modulo

s.replace(*l).replace(*l).replace(*l) ...

Per raggiungere un punto fisso se ne esiste uno, è sufficiente fare sostituzioni pari alla lunghezza della stringa originale.


7

ES6 (Javascript), 47, 43 byte

  • Salvato 4 byte usando il curry (Grazie @Neil!)

golfed

c=>b=>R=a=>(x=a.split(b).join(c))==a?x:R(x)

Provalo

Q=c=>b=>R=a=>(x=a.split(b).join(c))==a?x:R(x)

function doit() {
  console.log(Q(C.value)(B.value)(A.value));
}
A: <input type="text" value="abaaba" id="A"/> B: <input type="text" value="aba" id="B"/> C: <input type="text" value="ab" id="C"/> <input type="submit" onclick="doit();" value="REPLACE"/>


Puoi salvare 4 byte valutando gli argomenti in ordine inverso:c=>b=>g=a=>a==(a=a.split(b).join(c))?a:g(a)
Neil,


@MetoniemSome combinations of inputs will never terminate. Your program can do anything in those cases.
zeppelin,

@zeppelin Oh, capisco.
Metoniem,

5

Retina , 27 byte

Il conteggio dei byte presuppone la codifica ISO 8859-1.

+`(.+)(?=.*¶\1¶(.*))
$2
G1`

L'input deve essere separato dall'alimentazione di linea.

Provalo online! (Per comodità, utilizza un formato di input della suite di test in cui ogni riga è un caso di test separato da barra.)


4

C #, 44 byte

Versione breve:

r=(a,b,c)=>a==(a=a.Replace(b,c))?a:r(a,b,c);

Programma di esempio:

using System;

namespace ConsoleApplication1
{
    class Program
    {
    static void Main(string[] args)
        {
            Func<string, string, string, string> r = null;
            r=(a,b,c)=>a==(a=a.Replace(b,c))?a:r(a,b,c);

            Action <string, string, string, string> test =
                (a, b, c, answer) =>
                {
                    var result = r(a, b, c);
                    Console.WriteLine("A: \"{0}\"\r\nB: \"{1}\"\r\nC: \"{2}\"\r\nResult: \"{3}\"\r\n{4}\r\n\r\n",
                        a, b, c, result, result == answer ? "CORRECT" : "INCORRECT"
                        );
                };

            test("Hello, world!", "world!", "PPCG", "Hello, PPCG");
            test("Uppercase is up", "up", "down", "Uppercase is down");
            test("ababababa", "aba", "ccc", "cccbcccba");
            test("delete", "e", "", "dlt");
            test("", "no", "effect", "");
            test("llllrrrr", "lr", "rl", "rrrrllll");
            test("+-+-+-+", "+-+", "+", "+");
            test("ababababa", "aba", "bada", "badabbadbada");
            test("abaaba", "aba", "ab", "abb");
            test("((())())())", "()", "", ")");


            Console.WriteLine("Press any key...");
            Console.ReadKey();
        }
    }
}

Spiegazione: La funzione è scritta come espressione ricorsiva di coda, evitando la parola chiave return e le parentesi graffe sfruttando quanto segue:

  • Un'assegnazione tra parentesi restituisce il valore assegnato
  • Il lato sinistro del controllo di uguaglianza verrà valutato prima dell'assegnazione del lato destro, consentendoci di confrontare prima / dopo in linea e comunque accedere al risultato

Questo ci consente di tenerlo su una singola istruzione.

EDIT: Sono tornato a omettere il tipo di funzione r, dal momento che sembra essere accettabile. Con la dichiarazione del tipo che utilizza le matrici, ha 68 caratteri. Senza, ha 44 caratteri.


Se la funzione funzionerà solo se viene assegnato un nome specifico, dovrai utilizzare i byte per assegnare quel nome alla funzione. Non è immediatamente ovvio per me che siano 2 byte per r=o più per una dichiarazione (in parte perché non conosco completamente le regole, in parte perché non conosco C # abbastanza bene per applicarle).

Sì, lo stavo solo aggiustando dopo aver letto il commento di qualcun altro su una voce diversa. Ed è molto di più, poiché i tipi devono essere tutti specificati. Sono passato all'utilizzo di un array per salvarlo e salvare i byte nella chiamata ricorsiva.
Daniel,

Cosa intendi con non produce l'output corretto ? Non penso che tu debba emettere l'input, in effetti, alcune delle altre risposte non lo fanno. Ho perso un commento dicendo che ho bisogno di emettere l'input?
auhmaan,

Non importa, ho trovato il problema, non è ricorsivo.
auhmaan,

2

Japt , 15 byte

@¥(U=UqV qW}a@U

Provalo online!

Come funziona

@¥(U=UqV qW}a@U  // Implicit: U, V, W = input strings
            a@U  // Return the first non-negative integer mapped by the function X => U
@          }     // that returns truthily when mapped through this function:
     UqV qW      //   Split U at instances of V, and rejoin with W.
  (U=            //   Set U to this new value.
 ¥               //   Return (old U == new U). This stops the loop when U stops changing.
                 // Implicit: output result of last expression

Japt ha un built-in di sostituzione ricorsiva, ma vede il primo input come regex. Se fosse garantito che gli input contengano solo caratteri alfanumerici, questa soluzione a tre byte funzionerebbe:

eVW

Se l'ingresso è stato permesso di contenere qualsiasi carattere tranne ^, \o ], questa soluzione 12 byte sarebbe valida invece:

eV®"[{Z}]"ÃW

2

C #, 33 49 byte

Probabilmente, uno dei più piccoli frammenti scritti in C # ... E poiché Replaceè nativo della stringstruttura, non è necessario per usings ( almeno non sulla funzionalità integrata di VS, C # Interactive ... )

Inoltre, poiché Bha sempre un valore, il codice non necessita di convalide.


golfed

(a,b,c)=>{while(a!=(a=a.Replace(b,c)));return a;}

Ungolfed

(a, b, c) => {
    while( a != ( a = a.Replace( b, c ) ) );

    return a;
}

Codice completo

using System;

namespace Namespace {
    class Program {
        static void Main( string[] args ) {
            Func<string, string, string, string> func = (a, b, c) => {
                // Recursively ( now truly recursive ) replaces every 'b' for 'c' on 'a',
                // while saving the value to 'a' and checking against it. Crazy, isn't it?
                while( a != ( a = a.Replace( b, c ) ) );

                return a;
            };

            int index = 1;

            // Cycle through the args, skipping the first ( it's the path to the .exe )

            while( index + 3 < args.Length ) {
                Console.WriteLine( func(
                    args[index++],
                    args[index++],
                    args[index++]) );
            }

            Console.ReadLine();
        }
    }
}

Uscite

  • v1.1 - +19 bytes- Risolto il problema con la soluzione non ricorsiva.
  • v1.0 -  33 bytes- Soluzione iniziale.

1
Vedo c # che ho
votato

@NelsonCasanova Suona come me.
Metoniem,

Non Replaceeseguire la sostituzione ricorsiva?
Laikoni,

@Laikoni no. Ad esempio, "((())())())".Replace("()", "")restituisce (())).
auhmaan,

Quindi questa soluzione non è valida secondo le regole della sfida. Dovresti eliminarlo per evitare downvotes, quindi correggere la soluzione per gestire la sostituzione ricorsiva e infine annullarla.
Laikoni,

1

Elaborazione, 75 72 byte

void g(String a,String[]s){for(;a!=(a=a.replace(s[0],s[1])););print(a);}

Stampa i risultati. Chiamalo comeg("llllrrrr", new String[]{"lr","rl"});

void Q110278(String a, String[]s){             //a is the string to be replaced
                                               //s is the array containing the subsitution

  for(; a!=                                    
            (a = a.replace(s[0], s[1])) ;);

  //for-loop where we continuously perform substitution on a
  //until a is equal to substituted a


  //at the end, print the final version of a
  print(a);
}

1

Mathematica, 35 32 byte

#//.x_:>StringReplace[x,#2->#3]&

Argomenti forniti come una sequenza. Non termina mai ad growesempio, restituisce loopad loopesempio. Tre byte liberi grazie al suggerimento di Martin.


FixedPointtende ad essere troppo lungo e può essere emulato con //.:#//.x_:>StringReplace[x,#2->#3]&
Martin Ender,

Grazie @MartinEnder. È un buon modo di mettersi ReplaceRepeatedal lavoro per le stringhe!
A Simmons,

tra l'altro, questo farà solo cicli $RecursionLimit, che è 2^16di default, non che influisca sulla tua risposta
ngenesi

@ngenesis Non sono sicuro che ReplaceRepeatedsia controllato da $RecursionLimit- L'ho appena testato impostando il limite su 20 e il programma continua ancora felicemente per input non terminanti ..
A Simmons

Perché ReplaceRepeatedc'è un'opzione separata (che non può essere utilizzata con la //.sintassi), chiamata MaxIterations. Quello di default è 2 ^ 16. (cc @ngenisis)
Martin Ender,

1

Rubino, 29 byte

->a,b,c{1while a.gsub! b,c;a}

Dati 3 argomenti, applica la sostituzione al primo fino a quando non c'è più nulla da sostituire.

Spiegazione

  • 1prima che whilesia semplicemente un nop
  • gsub!restituisce la stringa o nilse non si è verificata alcuna sostituzione


1

/// , 3 byte

///

Inserisci la stringa B dopo la prima barra, C dopo la seconda e A alla fine, ovvero:

/<B>/<C>/<A>

Provalo online!


Non penso che questo sia un modo accettabile di ricevere input
Leo

Per quanto ne sappia, ///non accetta input in nessun altro modo.
steenbergh,

2
Bene, penso che sarebbe interessante discutere se questo è accettabile o meno, quindi :) Comunque, ho notato un altro problema con la tua presentazione: non funziona se a /è presente in una delle stringhe di input
Leo

1

JavaScript (Firefox 48 o precedente), 43 byte

c=>b=>g=a=>a==(a=a.replace(b,c,'g'))?a:g(a)

Accetta gli argomenti in ordine inverso. Firefox aveva un terzo parametro non standard a replacecui specificare i flag regexp. Questo parametro è stato rimosso in Firefox 49.


0

SmileBASIC, 72 68 byte

I=0DEF R A,B,C
I=INSTR(A,B)?A*(I<0)A=SUBST$(A,I,LEN(B),C)R A,B,C
END

Uno dei rari casi in cui la creazione di una funzione è in realtà SHORTER in SmileBASIC.


0

Javascript 130 byte

f=(a,b,c)=>a.indexOf(b)<0?a:f(eval("a.replace(/"+b.replace(/([\/\,\!\\\^\$\{\}\[\]\(\)\.\*\+\?\|\<\>\-\&])/g,"\\$&")+"/g,c)"),b,c)

Javascript sostituirà tutti contemporaneamente se gli dai una regex. Per far funzionare questo regex per tutti i valori, tutti i caratteri utilizzati per regex devono essere sostituiti con la versione con escape. Infine, la sostituzione viene valutata per sostituire tutte le istanze di B in A con C e passarle nuovamente alla funzione.



0

Cheddar, 37 byte

(a,b,c)f->a has b?f(a.sub(b,c),b,c):a

Al telefono quindi il collegamento TIO è un po 'difficile da aggiungere. Fondamentalmente usa la ricorsione mentre il controllo è b è in a. La soluzione potrebbe essere stata (a,b,c)->a.sub(Regex{b,"cr"},c)ma non funziona per qualche motivo.


Sub sostituisce tutto o solo il primo?
fəˈnɛtɪk,

@LliwTelracs perché sono stringhe .sub sostituirà tutto
Downgoat

Questo non sembra funzionare? Provalo online!
Conor O'Brien,

@ ConorO'Brien cazzate sciocchezze lati del ternario sono fuori
Downgoat

0

Perl 6 , 40 byte

{$^b;$^c;($^a,{S:g/$b/$c/}...*eq*)[*-1]}

Provalo (se tio.run viene aggiornato)
Prova una versione modificata

Allargato:

{
  $^b;           # declare second parameter ( not used here )
  $^c;           # declare third parameter  ( not used here )

  (

    $^a,         # declare first parameter, and use it to seed the sequence

    {S:g/$b/$c/} # replace globally

    ...          # keep doing that

    * eq *       # until there are two that match

  )[*-1]
}


0

PHP, 102 byte

list($n,$s,$a,$b)=$argv;$f=str_replace($a,$b,$s);while($s!=$f){$s=$f;$f=str_replace($a,$b,$s);}echo$f;

Casi di test (funzionali)

Caso di prova con errore loop


Ciao! Di solito, quando si inoltra una funzione, è necessario aggiungere al conteggio tutto ciò che è necessario per definire la funzione (nel tuo caso function replace(...){...}, altrimenti l'invio è solo uno snippet, che non
Leone,

@Leo Non lo sapevo, ha modificato la mia risposta;)
roberto06,

0

Java - 157 byte

String r(String f){if(f.length()<1)return "";String[]x=f.split("/");if(x[0].contains(x[1]))return r(x[0].replace(x[1],x[2])+'/'+x[1]+'/'+x[2]);return x[0];}

Per input vuoto restituisce una stringa vuota.

Si arresta in modo anomalo StackOverflowExceptionquando Bè vuoto o viene alimentato con dati come questoA/A/A .

Come funziona:

r("ABCD/A/F") returns value of r("FBCD/A/F") which returns FBCD
If there is no more characters to be replaced it returns the final output

Codice di codice non registrato con commenti:

String r (String f) {
    if(f.length() < 1)
        return ""; // For empty input return empty output
    String[] x = f.split("/"); // Get all 3 parameters
    if (x[0].contains(x[1])) // If input contains replaced value
        return r(x[0].replace(x[1],x[2])+'/'+x[1]+'/'+x[2]); // Return value of r() with one character replaced
    return x[0]; // If nothing to replace return the output(modified input)
}

0

Tasto di scelta automatica, 87 byte

StringCaseSense,On
Loop{
IfNotInString,1,%2%,Break
StringReplace,1,1,%2%,%3%
}
Send,%1%

%1%,, %2%e %3%sono i primi 3 argomenti passati a una funzione
Se una funzione prevede un argomento variabile, le %s vengono eliminate La
modifica dell'impostazione della distinzione tra maiuscole e minuscole costa 19 byte ma, senza di essa, si ottengono cose simili downpercase is down.

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.