Sustitución recursiva de cuerdas


25

La tarea

Escribir un programa o función que con tres cadenas A, B, Cproduce una cadena de salida donde cada instancia de Bin Aha sido sustituida recursivamente con C. Sustituir recursivamente significa repetir una sustitución en la que en cada paso todas las instancias no superpuestas de Bin A(elegidas con avidez de izquierda a derecha) se reemplazan por Chasta que Bya no estén contenidas A.

De entrada y salida

  • Puede utilizar cualquiera de los métodos predeterminados de E / S .
  • Las cadenas contendrán solo caracteres ASCII imprimibles (y pueden contener cualquiera de ellos).
  • BNunca será una cadena vacía, mientras que Ay Cque podría ser.
  • Las cadenas deben considerarse texto plano, por ejemplo, no puede tratarse Bcomo un patrón Regex.
  • Algunas combinaciones de entradas nunca terminarán. Su programa puede hacer cualquier cosa en esos casos.

Casos de prueba

Estos están en el 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}
)

Ejemplos que no terminan:

grow/ow/oow

loop/lo/lo

3
Otro caso de prueba:((())())())/()/
Conor O'Brien

@ ConorO'Brien agregado
Leo

1
Al principio, no pude hacerlo sensible a mayúsculas y minúsculas. downpercase is down
Ingeniero Toast

Respuestas:


7

05AB1E , 2 bytes

`:

Pruébalo en línea!

Explicación

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

Esto podría ser :por 1 byte si no tuviéramos que lidiar con cadenas vacías.


3
Si lo entiendo correctamente, su solución de 4 bytes es válida. "Algunas combinaciones de entradas nunca terminarán. Su programa puede hacer cualquier cosa en esos casos".
Leo

@León. Estás en lo correcto.
Leí

1
Entonces, ¿ :es básicamente una construcción que resuelve todo el desafío? Debería haber prohibido los builtins;)
Leo

@Leo: Si no fuera por las cadenas vacías, un solo incorporado resolvería esto sí. Y la única diferencia con las cadenas vacías es que necesitamos especificar que hay 3 entradas, que de lo contrario se deducirían implícitamente por la operación :)
Emigna

¿Es posible algo como esto también?
Adnan

9

Python 2 , 43 bytes

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

Pruébalo en línea!

Evalúa una cadena de la forma

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

Para alcanzar un punto fijo si existe, es suficiente hacer reemplazos iguales a la longitud de la cadena original.


7

ES6 (Javascript), 47, 43 bytes

  • Guardado 4 bytes usando curry (¡Gracias @Neil!)

Golfed

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

Intentalo

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"/>


Puede guardar 4 bytes cursando los argumentos en orden 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.
zepelín

@zeppelin Oh, ya veo.
Metoniem

5

Retina , 27 bytes

El recuento de bytes asume la codificación ISO 8859-1.

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

La entrada debe estar separada por salto de línea.

Pruébalo en línea! (Para mayor comodidad, utiliza un formato de entrada de conjunto de pruebas donde cada línea es un caso de prueba separado por barras).


4

C #, 44 bytes

Version corta:

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

Programa de ejemplo:

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

Explicación: La función se escribe como una expresión recursiva de cola, evitando la palabra clave return y los corchetes explotando lo siguiente:

  • Una asignación entre paréntesis devuelve el valor asignado
  • El lado izquierdo de la verificación de igualdad se evaluará antes de la asignación del lado derecho, lo que nos permitirá comparar antes / después en línea, y aún acceder al resultado

Esto nos permite mantenerlo en una sola declaración.

EDITAR: Volvió a omitir el tipo de función r, ya que parece ser aceptable. Con la declaración de tipo utilizando matrices, tiene 68 caracteres. Sin, son 44 caracteres.


Si la función solo funcionará si se le da un nombre específico, deberá gastar los bytes para darle ese nombre a la función. No es inmediatamente obvio para mí si son 2 bytes r=o más para una declaración (en parte porque no conozco completamente las reglas, en parte porque no conozco C # lo suficiente como para aplicarlas).

Sí, estaba arreglando eso después de haber leído el comentario de otra persona en una entrada diferente. Y es mucho más, ya que todos los tipos deben especificarse. Cambié a usar una matriz para ahorrar en eso y guardar bytes en la llamada recursiva.
Daniel

¿Qué quieres decir con que no produce la salida correcta ? No creo que necesite generar la entrada, de hecho, algunas de las otras respuestas no lo hacen. ¿Me perdí un comentario que decía que necesitaba generar la entrada?
auhmaan

No importa, he encontrado el problema, no es recursivo.
auhmaan

2

Japt , 15 bytes

@¥(U=UqV qW}a@U

¡Pruébelo en línea!

Cómo funciona

@¥(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 tiene un reemplazo recursivo incorporado, pero ve la primera entrada como una expresión regular. Si se garantizara que las entradas solo contienen caracteres alfanuméricos, esta solución de tres bytes funcionaría:

eVW

Si la entrada se les permitió contener cualquier carbón, excepto ^, \o ], esta solución de 12 bytes sería válido en su lugar:

eV®"[{Z}]"ÃW

2

C #, 33 49 bytes

Probablemente, uno de los fragmentos más pequeños escritos en C # ... Y dado que Replacees nativo de la stringestructura, no hay necesidad de usings ( al menos no en la función incorporada VS, C # Interactive ... )

Además, como Bsiempre tiene un valor, el código no necesita ninguna validación.


Golfed

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

Sin golf

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

    return a;
}

Código 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();
        }
    }
}

Lanzamientos

  • v1.1 - +19 bytes- La solución fija no es recursiva.
  • v1.0 -  33 bytes- Solución inicial.

1
Veo C # Me upvote
Nelz

@NelsonCasanova Suena como yo.
Metoniem

¿ ReplaceRealiza reemplazo recursivo?
Laikoni

@Laikoni no. Por ejemplo, "((())())())".Replace("()", "")vuelve (())).
auhmaan

Entonces esta solución no es válida bajo las reglas del desafío. Debe eliminarlo para evitar votos negativos, luego corregir su solución para manejar el reemplazo recursivo y finalmente recuperarlo.
Laikoni

1

Procesamiento, 75 72 bytes

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

Imprime los resultados. Llámalo comog("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 Bytes

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

Argumentos dados como una secuencia. Nunca termina por growejemplo, vuelve looppor loopejemplo. Tres bytes de descuento gracias a la sugerencia de Martin.


FixedPointtiende a ser demasiado largo y se puede emular con //.:#//.x_:>StringReplace[x,#2->#3]&
Martin Ender

Gracias @MartinEnder. ¡Esa es una buena manera de llegar ReplaceRepeateda trabajar por cuerdas!
Un Simmons

Por cierto, esto sólo bucle $RecursionLimittiempos, que es 2^16por defecto, no que afecta a su respuesta
ngenisis

@ngenesis No estoy seguro de que ReplaceRepeatedesté controlado por $RecursionLimit: solo lo probé estableciendo el límite en 20 y el programa sigue felizmente en bucle para la entrada sin terminación ...
Un Simmons

Porque ReplaceRepeatedhay una opción separada (que no se puede usar con la //.sintaxis), llamada MaxIterations. Ese predeterminado es 2 ^ 16. (cc @ngenisis)
Martin Ender

1

Ruby, 29 bytes

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

Dados 3 argumentos, aplique la sustitución al primero hasta que ya no haya nada que sustituir.

Explicación

  • 1antes de que whilesea ​​simplemente un nop
  • gsub!devuelve la cadena o nilsi no se produjo ninguna sustitución


1

/// , 3 bytes

///

Coloque la cadena B después de la primera barra inclinada, C después de la segunda y A al final, es decir:

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

Pruébalo en línea!


No creo que esta sea una forma aceptable de recibir aportes
Leo

Que yo sepa, ///no acepta aportes de ninguna otra manera.
steenbergh

2
Bueno, creo que sería interesante discutir si esto es aceptable o no, entonces :) De todos modos, he notado otro problema con su envío: no funciona si hay un /presente en cualquiera de las cadenas de entrada
Leo

1

JavaScript (Firefox 48 o anterior), 43 bytes

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

Toma argumentos curry en orden inverso. Firefox solía tener un tercer parámetro no estándar en el replaceque se especificaban las marcas de expresión regular. Este parámetro fue eliminado en Firefox 49.


0

SmileBASIC, 72 68 bytes

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 de los casos raros en los que hacer una función es en realidad MÁS CORTO en SmileBASIC.


0

Javascript 130 bytes

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

Javascript solo reemplazará a todos simultáneamente si le da una expresión regular. Para hacer que esta expresión regular funcione para todos los valores, todos los caracteres que se utilizan para la expresión regular deben reemplazarse con la versión escapada. Finalmente, el reemplazo se evalúa para reemplazar todas las instancias de B en A con C y pasarlo nuevamente a la función nuevamente.


0

q, 15 bytes

{ssr[;y;z]/[x]}

Ejemplo:

q){ssr[;y;z]/[x]}["llllrrrr";"lr";"rl"]
"rrrrllll"

enlace a la descarga del intérprete

Explicación: ssr , / (converge)


0

Cheddar, 37 bytes

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

En el teléfono, el enlace TIO es un poco difícil de agregar. Básicamente usa la recursión mientras que la comprobación es b está en a. La solución podría haber sido (a,b,c)->a.sub(Regex{b,"cr"},c)pero no funciona por alguna razón.


¿Sub reemplaza todo o solo el primero?
fəˈnɛtɪk

@LliwTelracs porque son cadenas .sub reemplazará a todos
Downgoat

Esto no parece funcionar? Pruébalo en línea!
Conor O'Brien

@ ConorO'Brien mierda errores tontos lados de
ternary

0

Perl 6 , 40 bytes

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

Pruébelo (si tio.run se actualiza)
Pruebe una versión alterada

Expandido:

{
  $^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, 46 bytes

function g($a,$b,$c){echo strtr($a,[$b=>$c]);}

0

PHP, 102 bytes

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;

Casos de prueba (funcional)

Caso de prueba con error de bucle


¡Hola! Por lo general, al enviar una función, debe agregar a la cuenta de byte todas las cosas necesarias para que se defina la función (en su caso function replace(...){...}, de lo contrario, su envío es solo un fragmento, que no
Leo

@Leo no lo sabía, editó mi respuesta;)
roberto06

0

Java - 157 bytes

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

Para una entrada vacía, devuelve una cadena vacía.

Se bloquea con un StackOverflowExceptionerror cuando Bestá vacío o se alimenta con datos como este A/A/A.

Cómo funciona:

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

Código de código sin golf con comentarios:

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

AutoHotkey, 87 bytes

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

%1%,, %2%y %3%son los primeros 3 argumentos pasados ​​a una función
Si una función espera un argumento variable, los %s se descartan
Cambiar la configuración de mayúsculas y minúsculas cuesta 19 bytes pero, sin ella, obtienes cosas como downpercase is down.

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