재귀 문자열 대체


25

작업

세 개의 문자열이 주어진 프로그램이나 함수를 작성하면 in의 A, B, C각 인스턴스 가로 반복적으로 대체 되는 출력 문자열이 생성 됩니다 . 재귀 각 단계에서의 모든 비 중첩 경우 교체 반복 대체 수단 에서가 로 대체된다 (왼쪽에서 오른쪽으로 탐욕를 선택) 할 때까지 더 이상 포함된다 .BACBACBA

입출력

  • I / O에 기본 방법을 사용할 수 있습니다 .
  • 문자열은 인쇄 가능한 ASCII 문자 만 포함하며 문자를 포함 수 있습니다 .
  • B반면, 빈 문자열하지 않습니다 AC수 있습니다.
  • 문자열은 일반 텍스트로 간주되어야합니다. 예를 들어 B정규식 패턴으로 취급 할 수 없습니다 .
  • 일부 입력 조합은 종료되지 않습니다. 이 경우 프로그램은 무엇이든 할 수 있습니다.

테스트 사례

형식은 다음과 같습니다. 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
엔지니어 토스트

답변:


7

05AB1E , 2 바이트

`:

온라인으로 사용해보십시오!

설명

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

이 수 :에 대한 1 바이트 우리가 빈 문자열 처리하지 않은 경우.


3
올바르게 이해하면 4 바이트 솔루션이 유효합니다. "일부 입력 조합은 종료되지 않습니다. 프로그램은 이러한 경우에 무엇이든 할 수 있습니다."
Leo

@사자 별자리. 맞습니다. 나는 그 부분 :) 이상 미끄러 져
Emigna

1
기본적으로 :모든 도전 과제를 해결하는 빌트인입니까? 나는 내장을 금지 했어야했다;)
Leo Leo

@ 레오 : 빈 문자열이 아닌 경우 내장 된 단일 문자열 로이 예를 해결할 수 있습니다. 그리고 빈 문자열과의 유일한 차이점은 3 개의 입력이 있음을 지정해야한다는 것입니다. 그렇지 않으면 연산에 의해 암시 적으로 유추됩니다 :)
Emigna

같은 것입니다 또한 가능?
Adnan

9

파이썬 2 , 43 바이트

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

온라인으로 사용해보십시오!

양식의 문자열을 평가합니다

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

고정 점이 존재하면 원래 문자열의 길이와 동일한 교체를 수행하면 충분합니다.


7

ES6 (자바 스크립트) 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 바이트를 절약 할 수 있습니다.c=>b=>g=a=>a==(a=a.split(b).join(c))?a:g(a)
Neil

죄송합니다. i.imgur.com/vPCycwR.png
Metoniem

@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 자입니다.


특정 이름이 주어진 경우에만 함수가 작동하면 해당 이름을 함수에 제공하기 위해 바이트를 소비해야합니다. r=선언에 2 바이트 이상 인지 여부는 명확 하지 않습니다 (부분적으로 규칙을 완전히 알지 못하기 때문에 부분적으로 적용 할만 큼 C #을 잘 모르기 때문에).

예, 다른 항목에 대한 다른 사람의 의견을 읽은 후에 고쳤습니다. 그리고 유형을 모두 지정해야하기 때문에 훨씬 더 많습니다. 나는 그것을 저장하기 위해 배열을 사용하고 재귀 호출에 바이트를 저장하기로 전환했다.
다니엘

올바른 출력을 얻지 못한다는 것은 무엇을 의미 합니까? 나는 당신이 입력을 출력 할 필요가 없다고 생각합니다. 사실 다른 답변 중 일부는 그렇지 않습니다. 입력을 출력해야한다는 의견을 놓쳤습니까?
auhmaan

신경 쓰지 마라, 나는 문제를 발견했다. 그것은 재귀 적이 지 않다.
auhmaan 2019

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에는 재귀 대체 기능이 내장되어 있지만 첫 번째 입력은 정규식으로 간주됩니다. 입력에 영숫자 만 포함되도록 보장 된 경우이 3 바이트 솔루션이 작동합니다.

eVW

입력이를 제외한 모든 문자를 포함 할 수 있었다 경우 ^, \또는 ]이 12 바이트 솔루션 대신에 유효 할 것이다 :

eV®"[{Z}]"ÃW

2

C #, 33 49 바이트

아마도 C #으로 작성된 가장 작은 스 니펫 중 하나 일 것입니다 ... 그리고 구조체에 Replace고유 string하므로 usings 가 필요 하지 않습니다 ( 적어도 VS 내장 기능인 C # Interactive에서는 아닙니다 ... )

또한 B항상 값을 가지므로 코드에는 유효성 검사가 필요하지 않습니다.


골프

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

언 골프

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

자료

  • 버전 1.1 - +19 bytes- 고정 솔루션은 순환되지 않는.
  • V1.0 -  33 bytes- 초기 솔루션입니다.

1
내가 upvote에 C #을 참조
Nelz

@NelsonCasanova 나 같은 소리.
Metoniem

Replace재귀 교체를 수행 합니까 ?
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

매스 매 티카, 35 32 바이트

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

시퀀스로 주어진 인수. grow예 를 들어 종료하지 않고 예 를 들어 반환 loop합니다 loop. Martin의 제안 덕분에 3 바이트가 줄었습니다.


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

루비, 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
음, 내가이 다음, 허용 여부 논의하기 위해 재미있을 것이라고 생각합니다 :) 어쨌든, 나는 당신의 제출에 또 다른 문제를 발견했습니다 : A는 경우 일을하지 않는 /입력 문자열의에 존재
레오

1

자바 스크립트 (Firefox 48 이하), 43 바이트

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

카레 인수를 역순으로 취합니다. Firefox는 replace정규 표현식 플래그를 지정하는 비표준 세 번째 매개 변수를 사용했습니다. 이 매개 변수는 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

함수를 만드는 것이 실제로 SmileBASIC에서 SHORTER 인 드문 경우 중 하나입니다.


0

자바 스크립트 130 바이트

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

Javascript는 정규식을 제공하는 경우에만 모두 동시에 바꿉니다. 이 정규식을 모든 값에 적용하려면 정규식에 사용되는 모든 문자를 이스케이프 된 버전으로 바꿔야합니다. 마지막으로, 바꾸기는 A에서 B의 모든 인스턴스를 C로 바꾸고 다시 함수에 다시 전달하도록 평가됩니다.



0

체다, 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)하지만 어떤 이유로 작동하지 않습니다.


sub가 첫 번째 또는 전부를 대체합니까?
fəˈnɛtɪk

@LliwTelracs는 문자열이기 때문에 .sub는 모두 대체됩니다
Downgoat


원의 ConorO'Brien 쓰레기 어리석은 실수 측면 @ 꺼져
Downgoat


0

PHP, 46 바이트

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

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;

테스트 사례 (기능)

루프 오류가있는 테스트 사례


안녕! 일반적으로 함수를 제출할 때 함수를 정의하는 데 필요한 모든 것을 바이트 수에 추가해야합니다 (귀하의 경우 function replace(...){...}제출은 스니 펫일뿐입니다. 기본적으로 허용되지 않는
Leo

@Leo 몰랐습니다, 내 답변을 편집;)
roberto06

0

자바-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할 때 오류가 B비어 있거나이 같은 데이터가 공급된다 A/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

오토 핫키, 87 바이트

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

%1%,, %2%%3%함수에 전달되는 첫 번째 3 개의 인수입니다
. 함수가 가변 인수를 기대하면 %s가 삭제됩니다
. 대소 문자 구분 설정을 변경하면 19 바이트가 소요되지만 그렇지 않으면 다음과 같은 결과가 나타납니다 downpercase is down.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.