Substitution de chaîne récursive

25

La tâche

Ecrivez un programme ou une fonction qui, à partir de trois chaînes, A, B, Cproduit une chaîne de sortie dans laquelle chaque instance de Bin Aa été récursivement remplacée par C. Substituer récursivement signifie répéter une substitution où à chaque étape toutes les instances non chevauchantes de Bin A(choisies avec avidité de gauche à droite) sont remplacées par Cjusqu'à ce Bqu'elles ne soient plus contenues dans A.

Entrée sortie

  • Vous pouvez utiliser l' une des méthodes par défaut pour les E / S .
  • Les chaînes ne contiendront que des caractères ASCII imprimables (et peuvent contenir n'importe lequel d'entre eux).
  • Bne sera jamais une chaîne vide, tandis que Aet Cpourrait l'être.
  • Les chaînes doivent être considérées comme du texte en clair, vous ne pouvez pas par exemple traiter Bcomme un modèle Regex.
  • Certaines combinaisons d'entrées ne se termineront jamais. Votre programme peut tout faire dans ces cas.

Cas de test

Ce sont au format: 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}
)

Exemples qui ne se terminent pas:

grow/ow/oow

loop/lo/lo
Leo
la source
3
Un autre cas de test:((())())())/()/
Conor O'Brien
@ ConorO'Brien ajouté
Leo
1
Au début, je n'ai pas réussi à le rendre sensible à la casse. downpercase is down
Engineer Toast

Réponses:

7

05AB1E , 2 octets

`:

Essayez-le en ligne!

Explication

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

Cela pourrait être :pour 1 octet si nous n'avions pas à gérer des chaînes vides.

Emigna
la source
3
Si je comprends bien, votre solution à 4 octets est valide. "Certaines combinaisons d'entrées ne se termineront jamais. Votre programme peut tout faire dans ces cas."
Leo
@Leo. Tu as raison. J'ai survolé cette partie :)
Emigna
1
Donc, fondamentalement, :est-ce une solution intégrée qui résout tout le défi? J'aurais dû interdire les buildins;)
Leo
@Leo: S'il n'y avait pas les chaînes vides, un seul intégré résoudrait ce oui. Et la seule différence avec les chaînes vides est que nous devons spécifier qu'il y a 3 entrées, qui autrement seraient implicitement déduites par l'opération :)
Emigna
Est-ce que quelque chose comme ça est également possible?
Adnan
9

Python 2 , 43 octets

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

Essayez-le en ligne!

Évalue une chaîne du formulaire

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

Pour atteindre un point fixe s'il en existe un, il suffit de faire des remplacements égaux à la longueur de la chaîne d'origine.

xnor
la source
7

ES6 (Javascript), 47, 43 octets

  • 4 octets enregistrés en utilisant le curry (Merci @Neil!)

Golfé

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

Essayez-le

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

Zeppelin
la source
Vous pouvez économiser 4 octets en curryant les arguments dans l'ordre inverse:c=>b=>g=a=>a==(a=a.split(b).join(c))?a:g(a)
Neil
Oops. i.imgur.com/vPCycwR.png
Metoniem
@MetoniemSome combinations of inputs will never terminate. Your program can do anything in those cases.
zeppelin
@zeppelin Oh, je vois.
Metoniem
5

Rétine , 27 octets

Le nombre d'octets suppose un codage ISO 8859-1.

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

L'entrée doit être séparée par un saut de ligne.

Essayez-le en ligne! (Pour plus de commodité, utilise un format d'entrée de suite de tests où chaque ligne est un cas de test séparé par une barre oblique.)

Martin Ender
la source
4

C #, 44 octets

Version courte:

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

Exemple de programme:

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

Explication: La fonction est écrite comme une expression récursive de queue, en évitant le mot-clé return et les accolades en exploitant ce qui suit:

  • Une affectation entre parenthèses renvoie la valeur attribuée
  • Le côté gauche du contrôle d'égalité sera évalué avant l'affectation du côté droit, ce qui nous permet de comparer avant / après en ligne, et toujours accéder au résultat

Cela nous permet de le garder à une seule déclaration.

EDIT: Nous sommes revenus à l'omission du type de fonction r, car cela semble acceptable. Avec une déclaration de type utilisant des tableaux, elle est de 68 caractères. Sans, c'est 44 caractères.

Daniel
la source
Si la fonction ne fonctionne que si elle reçoit un nom spécifique, vous devrez dépenser les octets pour donner à la fonction ce nom. Ce n'est pas immédiatement évident pour moi si c'est 2 octets pour r=ou beaucoup plus pour une déclaration (en partie parce que je ne connais pas complètement les règles, en partie parce que je ne connais pas assez bien C # pour les appliquer).
Ouais, je corrigeais juste cela après avoir lu le commentaire de quelqu'un d'autre sur une entrée différente. Et c'est beaucoup plus, car les types doivent tous être spécifiés. Je suis passé à l'utilisation d'un tableau pour économiser sur cela et économiser des octets sur l'appel récursif.
Daniel
Que voulez-vous dire par ne produit pas la sortie correcte ? Je ne pense pas que vous ayez besoin de produire l'entrée, en fait, certaines des autres réponses ne le font pas. Ai-je manqué un commentaire disant que je dois sortir l'entrée?
auhmaan
Peu importe, j'ai trouvé le problème, ce n'est pas récursif.
auhmaan
2

Japt , 15 octets

@¥(U=UqV qW}a@U

Testez-le en ligne!

Comment ça marche

@¥(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 a un remplacement récursif intégré, mais il voit la première entrée comme une expression régulière. Si les entrées étaient garanties de ne contenir que des caractères alphanumériques, cette solution à trois octets fonctionnerait:

eVW

Si l'entrée ont été autorisés à contenir tout sauf omble chevalier ^, \ou ], cette solution de 12 octets serait valable à la place:

eV®"[{Z}]"ÃW
ETHproductions
la source
2

C #, 33 49 octets

Probablement, l'un des plus petits extraits écrits en C # ... Et comme il Replaceest natif de la stringstructure, il n'y a pas besoin de usings (du moins pas sur la fonction intégrée VS, C # Interactive ... )

De plus, comme Bil a toujours une valeur, le code n'a besoin d'aucune validation.


Golfé

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

Non golfé

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

    return a;
}

Code complet

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

Communiqués

  • v1.1 - +19 bytes- Solution fixe non récursive.
  • v1.0 -  33 bytes- Solution initiale.
auhmaan
la source
1
I see c # I upvote
Nelz
@NelsonCasanova Sonne comme moi.
Metoniem
Est-ce que ReplaceN'effectuer le remplacement récursif?
Laikoni
@Laikoni no. Par exemple, "((())())())".Replace("()", "")renvoie(())) .
auhmaan
Alors cette solution n'est pas valable selon les règles du challenge. Vous devez le supprimer pour éviter les votes négatifs, puis corriger votre solution pour gérer le remplacement récursif et enfin le supprimer.
Laikoni
1

Traitement, 75 72 octets

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

Imprime les résultats. Appelez ça commeg("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);
}
Kritixi Lithos
la source
1

Mathematica, 35 32 octets

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

Arguments donnés sous forme de séquence. Ne se termine jamais par growexemple, retourneloop par loopexemple. Trois octets de moins grâce à la suggestion de Martin.

A Simmons
la source
FixedPointa tendance à être trop long et peut être émulé avec //.:#//.x_:>StringReplace[x,#2->#3]&
Martin Ender
Merci @MartinEnder. C'est un bon moyen de se mettre ReplaceRepeatedau travail pour les cordes!
A Simmons
btw, cela ne fera que boucler les $RecursionLimittemps, ce qui est 2^16par défaut, pas que cela affecte votre réponse
ngenisis
@ngenesis Je ne suis pas sûr que cela ReplaceRepeatedsoit contrôlé par $RecursionLimit- je viens de le tester en fixant la limite à 20 et le programme continue de faire le tour avec plaisir pour une entrée sans fin.
Un Simmons
Car ReplaceRepeatedil y a une option distincte (qui ne peut pas être utilisée avec la //.syntaxe), appelée MaxIterations. Celui- ci par défaut est 2 ^ 16. (cc @ngenisis)
Martin Ender
1

Rubis, 29 octets

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

Étant donné 3 arguments, appliquez la substitution au premier jusqu'à ce qu'il n'y ait plus rien à substituer.

Explication

  • 1avant whileest tout simplement un nop
  • gsub!renvoie la chaîne ou nilsi aucune substitution ne s'est produite
GB
la source
1

/// , 3 octets

///

Mettez la chaîne B après la première barre oblique, C après la seconde et A à la fin, c'est-à-dire:

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

Essayez-le en ligne!

steenbergh
la source
Je ne pense pas que ce soit une façon acceptable de prendre des contributions
Leo
À ma connaissance, ///n'accepte aucune entrée d'une autre manière.
steenbergh
2
Eh bien, je pense qu'il serait intéressant de discuter si cela est acceptable ou non, alors :) Quoi qu'il en soit, j'ai remarqué un autre problème avec votre soumission: cela ne fonctionne pas si un /est présent dans l'une des chaînes d'entrée
Leo
1

JavaScript (Firefox 48 ou version antérieure), 43 octets

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

Prend les arguments au curry dans l'ordre inverse. Firefox avait auparavant un troisième paramètre non standard replaceauquel spécifiaient les drapeaux d'expression régulière. Ce paramètre a été supprimé dans Firefox 49.

Neil
la source
0

SmileBASIC, 72 68 octets

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

L'un des rares cas où la création d'une fonction est en fait PLUS COURT dans SmileBASIC.

12Me21
la source
0

Javascript 130 octets

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

Javascript ne remplacera tous simultanément que si vous lui donnez une expression régulière. Pour que cette expression régulière fonctionne pour toutes les valeurs, tous les caractères utilisés pour l'expression régulière doivent être remplacés par la version d'échappement. Enfin, le remplacement est évalué pour remplacer toutes les instances de B dans A par C et les renvoyer à la fonction.

fəˈnɛtɪk
la source
0

q, 15 octets

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

Exemple:

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

lien vers le téléchargement de l'interpréteur

Explication: ssr , / (convergent)

skeevey
la source
0

Cheddar, 37 octets

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

Au téléphone, le lien TIO est donc un peu difficile à ajouter. Utilise essentiellement la récursivité tout en vérifiant que b est dans a. La solution pourrait avoir été, (a,b,c)->a.sub(Regex{b,"cr"},c)mais ne fonctionne pas pour une raison quelconque.

Downgoat
la source
Sub remplace-t-il tout ou seulement le premier?
fəˈnɛtɪk
@LliwTelracs car ce sont des chaînes .sub remplacera tout
Downgoat
Cela ne semble pas fonctionner? Essayez-le en ligne!
Conor O'Brien
@ ConorO'Brien merde idiot erreur côtés du ternaire sont désactivés
Downgoat
0

Perl 6 , 40 octets

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

Essayez-le (si tio.run est mis à jour)
Essayez une version modifiée

Étendu:

{
  $^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]
}
Brad Gilbert b2gills
la source
0

PHP, 46 octets

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

PHP, 102 octets

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;

Cas de test (fonctionnels)

Cas de test avec erreur de boucle

roberto06
la source
Salut! Habituellement, lors de la soumission d'une fonction, vous devez ajouter au décompte toutes les choses nécessaires à la définition de la fonction (dans votre cas function replace(...){...}, sinon votre soumission n'est qu'un extrait de code, ce qui est interdit par défaut
Leo
@Leo Je ne le savais pas, a modifié ma réponse;)
roberto06
0

Java - 157 octets

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

Pour une entrée vide, elle renvoie une chaîne vide.

Se bloque avec une StackOverflowExceptionerreur lorsqu'il Best vide ou qu'il est alimenté avec des données comme celle-ciA/A/A .

Comment ça marche:

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

Code de code non golfé avec commentaires:

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)
}
biscuit
la source
0

AutoHotkey, 87 octets

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

%1%,, %2%et %3%sont les 3 premiers arguments passés à une fonction
Si une fonction attend un argument variable, les %s sont supprimés La
modification du paramètre de sensibilité à la casse coûte 19 octets mais, sans lui, vous obtenez des choses comme downpercase is down.

Ingénieur Toast
la source