การแทนที่สตริงแบบเรียกซ้ำ


25

งาน

เขียนโปรแกรมหรือฟังก์ชั่นที่ได้รับสามสายA, B, Cสร้างสายออกที่แต่ละอินสแตนซ์ของBในAได้ถูกแทนที่ด้วยCซ้ำ การแทนที่แบบเรียกซ้ำหมายถึงการทำซ้ำการแทนที่โดยในแต่ละขั้นตอนอินสแตนซ์ที่ไม่ซ้ำซ้อนทั้งหมดของBในA(เลือกอย่างตะกละตะกลามจากซ้ายไปขวา) จะถูกแทนที่ด้วยCจนกว่าBจะไม่มีอยู่ในAนั้นอีก

Input / Output

  • คุณสามารถใช้ใด ๆ ของ วิธีการเริ่มต้นสำหรับ I / O
  • สตริงจะมีอักขระ ASCII ที่พิมพ์ได้เท่านั้น (และอาจมี ใด ๆ ก็ได้ )
  • Bจะไม่เป็นสตริงว่างเปล่าในขณะที่AและCอาจเป็น
  • สตริงจะถือว่าเป็นธรรมดาคุณไม่สามารถยกตัวอย่างเช่นถือว่าBเป็นรูปแบบ Regex
  • ชุดค่าผสมบางอย่างจะไม่สิ้นสุด โปรแกรมของคุณสามารถทำอะไรก็ได้ในกรณีเหล่านั้น

กรณีทดสอบ

สิ่งเหล่านี้อยู่ในรูปแบบ: 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}
)

ตัวอย่างที่ไม่สิ้นสุด:

grow/ow/oow

loop/lo/lo

3
อีกกรณีทดสอบ:((())())())/()/
Conor O'Brien

@ ConorO'Brien เพิ่มแล้ว
Leo

1
ตอนแรกฉันไม่ได้คำนึงถึงตัวพิมพ์ใหญ่ - เล็ก downpercase is down
Engineer Toast

คำตอบ:


7

05AB1E , 2 ไบต์

`:

ลองออนไลน์!

คำอธิบาย

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

ซึ่งอาจเป็น:สำหรับ1 ไบต์ถ้าเราไม่ได้มีการจัดการกับสตริงที่ว่างเปล่า


3
ถ้าฉันเข้าใจถูกต้องแสดงว่าโซลูชัน 4 ไบต์ของคุณนั้นถูกต้อง "ชุดค่าผสมบางอย่างจะไม่สิ้นสุดโปรแกรมของคุณสามารถทำอะไรก็ได้ในกรณีเหล่านั้น"
Leo

@สิงห์. ใช่คุณ ฉันอ่านส่วนนี้ :)
2560

1
ดังนั้นโดยทั่วไปแล้ว:บิวอินจะช่วยแก้ปัญหาทั้งหมดได้หรือไม่? ฉันควรสั่งห้าม buildins;)
Leo

@Leo: ถ้ามันไม่ได้สำหรับสตริงที่ว่างเปล่าตัวเดียวในตัวจะแก้ปัญหานี้ได้ใช่ และความแตกต่างเฉพาะกับสตริงที่ว่างเปล่าคือการที่เราจะต้องระบุว่ามี 3 ปัจจัยการผลิตซึ่งจะสรุปโดยปริยายการดำเนินงาน :)
Emigna

สิ่งนี้เป็นไปได้ไหม
Adnan

9

Python 2 , 43 ไบต์

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

ลองออนไลน์!

หาค่าสตริงของฟอร์ม

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

ในการเข้าถึงจุดคงที่หากมีอยู่ก็พอเพียงที่จะทำการแทนที่เท่ากับความยาวของสตริงเดิม


7

ES6 (Javascript) 47, 43 ไบต์

  • บันทึก 4 ไบต์โดยใช้การแกง (ขอบคุณ @Neil!)

แข็งแรงเล่นกอล์ฟ

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

ลองมัน

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


คุณสามารถบันทึก 4 ไบต์โดย curating อาร์กิวเมนต์ในลำดับย้อนกลับ: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 โอ้ฉันเห็นแล้ว
Metoniem

5

เรติน่า 27 ไบต์

จำนวนไบต์ถือว่าการเข้ารหัส ISO 8859-1

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

อินพุตควรคั่นด้วยตัวป้อนบรรทัด

ลองออนไลน์! (เพื่อความสะดวกให้ใช้รูปแบบอินพุตของชุดทดสอบโดยที่แต่ละบรรทัดเป็นกรณีทดสอบที่คั่นด้วยสแลช)


4

C #, 44 ไบต์

เวอร์ชั่นสั้น:

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

โปรแกรมตัวอย่าง:

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

คำอธิบาย: ฟังก์ชันถูกเขียนเป็นนิพจน์แบบเรียกซ้ำหางหลีกเลี่ยงคำหลักส่งคืนและวงเล็บปีกกาโดยการใช้ประโยชน์ดังต่อไปนี้:

  • การกำหนดภายในวงเล็บส่งคืนค่าที่กำหนด
  • ด้านซ้ายของการตรวจสอบความเท่าเทียมกันจะได้รับการประเมินก่อนการมอบหมายด้านขวาทำให้เราสามารถเปรียบเทียบก่อน / หลังอินไลน์และยังเข้าถึงผลลัพธ์

สิ่งนี้ช่วยให้เราสามารถเก็บไว้ในคำสั่งเดียว

แก้ไข: กลับไปที่ละเว้นประเภทของฟังก์ชั่น r เนื่องจากเป็นที่ยอมรับได้ ด้วยการประกาศประเภทโดยใช้อาร์เรย์มันเป็น 68 ตัวอักษร หากไม่มีก็คือ 44 ตัวอักษร


หากฟังก์ชั่นนี้จะใช้งานได้ถ้าให้ชื่อเฉพาะคุณจะต้องใช้ไบต์เพื่อให้ชื่อนั้นทำงาน ไม่ชัดเจนสำหรับฉันทันทีว่ามีขนาด 2 ไบต์r=หรือมากกว่าสำหรับการประกาศ (ส่วนหนึ่งเป็นเพราะฉันไม่รู้จักกฎอย่างสมบูรณ์ส่วนหนึ่งเป็นเพราะฉันไม่รู้จัก C # ดีพอที่จะนำมาใช้)

ใช่ฉันแค่แก้ไขว่าหลังจากที่ได้อ่านความคิดเห็นของคนอื่นในรายการที่แตกต่าง และมันก็ยังมีอีกมากมายเนื่องจากต้องระบุชนิดทั้งหมด ฉันสลับไปใช้อาร์เรย์เพื่อบันทึกและบันทึกไบต์บนการเรียกซ้ำ
แดเนียล

คุณหมายถึงอะไรด้วยไม่สร้างผลลัพธ์ที่ถูกต้อง ? ฉันไม่คิดว่าคุณจะต้องส่งออกข้อมูลที่จริงแล้วคำตอบอื่น ๆ ไม่ได้ทำ ฉันพลาดความคิดเห็นที่บอกว่าฉันต้องการที่จะออกอินพุต
auhmaan

ไม่เป็นไรฉันพบปัญหามันไม่ได้เกิดขึ้นซ้ำแล้วซ้ำอีก
auhmaan

2

Japt 15 ไบต์

@¥(U=UqV qW}a@U

ทดสอบออนไลน์!

มันทำงานอย่างไร

@¥(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 มี built-in แบบแทนที่แบบเรียกซ้ำ แต่จะเห็นอินพุตแรกเป็น regex หากอินพุตมีการรับประกันว่ามีเพียงตัวอักษรและตัวเลขโซลูชันสามไบต์นี้จะทำงาน:

eVW

ถ้าใส่ได้รับอนุญาตให้มีถ่านใด ๆ ยกเว้น^, \หรือ]นี้สารละลาย 12 ไบต์จะเป็นที่ถูกต้องแทน:

eV®"[{Z}]"ÃW

2

C #, 33 49 ไบต์

อาจเป็นหนึ่งในตัวอย่างที่เล็กที่สุดที่เขียนใน C # ... และเนื่องจากReplaceมีถิ่นกำเนิดในโครงสร้างstringจึงไม่จำเป็นต้องusingมี s ( อย่างน้อยไม่ได้อยู่ในฟีเจอร์ในตัวของ VS, C # Interactive ... )

นอกจากนี้เนื่องจากBมีค่าอยู่เสมอรหัสจึงไม่จำเป็นต้องมีการตรวจสอบใด ๆ


แข็งแรงเล่นกอล์ฟ

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

รหัสเต็ม

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

ข่าว

  • v1.1 - +19 bytes- แก้ไขปัญหาที่ไม่ต้องเรียกซ้ำ
  • v1.0 -  33 bytes- โซลูชั่นเริ่มต้น

1
ฉันเห็น c # I upvote
Nelz

@NelsonCasanova ฟังดูเหมือนฉัน
Metoniem

ไม่Replaceดำเนินการเปลี่ยน recursive?
Laikoni

@Laikoni no ยกตัวอย่างเช่นผลตอบแทน"((())())())".Replace("()", "") (()))
auhmaan

จากนั้นโซลูชันนี้ไม่สามารถใช้งานได้ภายใต้กฎของการท้าทาย คุณควรลบเพื่อป้องกันการลงคะแนนจากนั้นแก้ไขโซลูชันของคุณเพื่อจัดการการแทนที่แบบเรียกซ้ำและยกเลิกการลบในที่สุด
Laikoni

1

กำลังประมวลผล75 72 ไบต์

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

พิมพ์ผลลัพธ์ เรียกว่าชอบg("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 ไบต์

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

อาร์กิวเมนต์ที่กำหนดเป็นลำดับ ไม่เคยสิ้นสุดสำหรับgrowตัวอย่างเช่นผลตอบแทนloopสำหรับloopตัวอย่างเช่น ปิดสามไบต์ด้วยคำแนะนำของ Martin


FixedPointมีแนวโน้มที่จะยาวเกินไปและสามารถเลียนแบบได้ด้วย//.:#//.x_:>StringReplace[x,#2->#3]&
Martin Ender

ขอบคุณ @MartinEnder นั่นเป็นวิธีที่ดีในการReplaceRepeatedทำงานกับสายอักขระ!
ซิมมอนส์

btw นี่จะวนซ้ำ$RecursionLimitครั้งเดียวเท่านั้นซึ่ง2^16โดยค่าเริ่มต้นไม่ใช่ว่าจะมีผลกับคำตอบของคุณ
ngenisis

@ngenesis ฉันไม่แน่ใจว่าReplaceRepeatedถูกควบคุมโดย$RecursionLimit- ฉันเพิ่งทดสอบโดยตั้งค่าขีด จำกัด เป็น 20 และโปรแกรมยังคงลูปอย่างมีความสุขพร้อมสำหรับการป้อนข้อมูลไม่สิ้นสุด ..
ซิมมอนส์

สำหรับ ReplaceRepeatedมีตัวเลือกแยกต่างหาก (ซึ่งไม่สามารถใช้กับ//.ไวยากรณ์) MaxIterationsได้ ค่าเริ่มต้นหนึ่งคือ 2 ^ 16 (cc @ngenisis)
Martin Ender

1

Ruby, 29 ไบต์

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

ได้รับ 3 ข้อโต้แย้งใช้การทดแทนกับคนแรกจนกว่าจะไม่มีอะไรมาแทนที่อีกต่อไป

คำอธิบาย

  • 1ก่อนที่whileจะเป็นเพียงแค่ nop
  • gsub!ส่งคืนสตริงหรือnilหากไม่มีการทดแทนเกิดขึ้น


1

/// , 3 ไบต์

///

ใส่สตริง B หลังเครื่องหมายทับแรก, C หลังจากวินาทีและ A ท้ายที่สุดคือ:

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

ลองออนไลน์!


ฉันไม่คิดว่านี่เป็นวิธีที่ยอมรับได้ของการป้อนข้อมูล
Leo

สำหรับความรู้ของฉัน///ไม่ยอมรับการป้อนข้อมูลด้วยวิธีอื่นใด
steenbergh

2
ดีฉันคิดว่ามันน่าสนใจที่จะพูดคุยว่ามันเป็นที่ยอมรับหรือไม่แล้ว :) อย่างไรก็ตามฉันได้สังเกตเห็นปัญหาอื่น ๆ ที่คุณส่ง: มันไม่ทำงานถ้ามี/อยู่ในสตริงอินพุต
Leo

1

JavaScript (Firefox 48 หรือรุ่นก่อนหน้า), 43 ไบต์

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

รับอาร์กิวเมนต์ curated ตามลำดับย้อนกลับ Firefox เคยมีพารามิเตอร์ที่สามที่ไม่ได้มาตรฐานreplaceซึ่งระบุค่าสถานะ regexp พารามิเตอร์นี้ถูกลบใน Firefox 49


0

SmileBASIC, 72 68 ไบต์

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

หนึ่งในกรณีที่หาได้ยากซึ่งการใช้ฟังก์ชั่น SHORTER ใน SmileBASIC


0

Javascript 130 ไบต์

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

Javascript จะแทนที่ทั้งหมดพร้อมกันหากคุณให้ regex ในการทำให้ regex นี้ใช้งานได้กับค่าทั้งหมดอักขระทั้งหมดที่ใช้สำหรับ regex จะต้องถูกแทนที่ด้วยเวอร์ชันที่ใช้ Escape ในที่สุดการแทนที่จะถูกประเมินเพื่อแทนที่อินสแตนซ์ทั้งหมดของ B ใน A ด้วย C และส่งผ่านสิ่งนั้นกลับไปที่ฟังก์ชันอีกครั้ง



0

Cheddar, 37 ไบต์

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

บนโทรศัพท์ลิงก์ TIO จะเพิ่มได้ยาก โดยทั่วไปใช้การสอบถามซ้ำในขณะที่การตรวจสอบคือ b อยู่ใน a วิธีแก้ปัญหาอาจเป็นไปได้(a,b,c)->a.sub(Regex{b,"cr"},c)แต่ไม่ได้ผลด้วยเหตุผลบางประการ


ย่อยแทนที่ทั้งหมดหรือเพียงแค่อันแรกหรือไม่?
fəˈnɛtɪk

@LliwTelracs เพราะพวกเขาเป็นสตริง. sub จะแทนที่ทั้งหมด
Downgoat

ดูเหมือนว่าจะใช้งานไม่ได้? ลองออนไลน์!
Conor O'Brien

@ ConorO'Brien อึด้านผิดพลาดโง่เขลาของ
ไตรภาคี

0

Perl 6 , 40 ไบต์

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

ลองใช้ (หากมีการอัปเดต tio.run)
ลองใช้เวอร์ชันที่แก้ไข

ขยาย:

{
  $^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 ไบต์

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;

กรณีทดสอบ (ฟังก์ชั่น)

กรณีทดสอบพร้อมข้อผิดพลาดแบบวนซ้ำ


Hi! โดยปกติเมื่อส่งฟังก์ชั่นคุณควรเพิ่มจำนวนทั้งหมดที่จำเป็นสำหรับฟังก์ชั่นที่จะกำหนด (ในกรณีfunction replace(...){...}ของคุณมิฉะนั้นการส่งของคุณเป็นเพียงตัวอย่างซึ่งไม่ได้รับอนุญาตโดยค่าเริ่มต้น
Leo

@Leo ไม่รู้ว่าแก้ไขคำตอบของฉันแล้ว;)
roberto06

0

Java - 157 ไบต์

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

สำหรับการป้อนข้อมูลที่ว่างเปล่ามันจะส่งคืนสตริงว่าง

เกิดปัญหากับStackOverflowExceptionข้อผิดพลาดเมื่อเป็นที่ว่างเปล่าหรือจะเป็นอาหารที่มีข้อมูลเช่นนี้BA/A/A

มันทำงานอย่างไร:

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

โค้ดโค้ดที่ไม่ได้ถูกฟอล์กพร้อมความคิดเห็น:

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 ไบต์

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

%1%, %2%และ%3%เป็นอาร์กิวเมนต์ 3 ข้อแรกที่ส่งผ่านไปยังฟังก์ชัน
หากฟังก์ชันคาดว่าจะมีอาร์กิวเมนต์ตัวแปรค่า%s จะลดลง
การเปลี่ยนการตั้งค่า case-sensitive ราคา 19 ไบต์ แต่ถ้าไม่มีคุณจะได้ค่าต่างdownpercase is down

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.