Случай соответствия Найти заменить

14

Возьмите три ввода, строку текста T; строка символов для замены F; и строка символов , чтобы заменить их, R. Для каждой подстроки Tс такими же (без учета регистра) символами, как F, замените их на символы в R. Тем не менее, сохраните тот же случай, что и исходный текст.

Если есть больше символов , Rчем F, дополнительные символы должны быть тот же случай , когда они находятся в R. Если в нем есть цифры или символы F, то соответствующие символы Rдолжны быть в том же регистре R. Fне обязательно появится в T.

Вы можете предположить, что весь текст будет в диапазоне ASCII для печати.

Примеры

"Text input", "text", "test" -> "Test input"

"tHiS Is a PiEcE oF tExT", "is", "abcde" -> "tHaBcde Abcde a PiEcE oF tExT"

"The birch canoe slid on the smooth planks", "o", " OH MY " -> "The birch can OH MY e slid  OH MY n the sm OH MY  OH MY th planks"

"The score was 10 to 5", "10", "tEn" -> "The score was tEn to 5"

"I wrote my code in Brain$#@!", "$#@!", "Friend" -> "I wrote my code in BrainFriend"

"This challenge was created by Andrew Piliser", "Andrew Piliser", "Martin Ender" -> "This challenge was created by Martin Ender"

// Has a match, but does not match case 
"John does not know", "John Doe", "Jane Doe" -> "Jane does not know"

// No match
"Glue the sheet to the dark blue background", "Glue the sheet to the dark-blue background", "foo" -> "Glue the sheet to the dark blue background"

// Only take full matches
"aaa", "aa", "b" -> "ba"

// Apply matching once across the string as a whole, do not iterate on replaced text
"aaaa", "aa", "a" -> "aa"

"TeXT input", "text", "test" -> "TeST input"

Песочница ссылка

Андрей
источник
Запрос примера со странным корпусом:"TeXT input", "text", "test"
Инженер Тост
@EngineerToast Добавил пример
Эндрю
Не знаю, почему я нашел "The birch canoe slid on the smooth planks", "o", " OH MY "такой юмористический, но мне понравился этот пример.
Волшебная Урна Осьминога

Ответы:

3

Сетчатка , 116 байт

i`(.+)(?=.*¶\1(¶.*)$)|.*¶.*$
¶¶$2¶$1¶¶
{T`l`L`¶¶.(?=.*¶[A-Z])
T`L`l`¶¶.(?=.*¶[a-z])
}`¶¶¶(.)(.*¶).
$1¶¶¶$2
¶¶¶¶.*|¶

Попробуйте онлайн! Объяснение:

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

Этот поиск Tи всякий раз, когда есть нечувствительное к регистру совпадение с предвкушением к Fсовпадению, окружается множеством новых строк, и предвосхищение Rтакже вставляется.

{T`l`L`¶¶.(?=.*¶[A-Z])
T`L`l`¶¶.(?=.*¶[a-z])
}`¶¶¶(.)(.*¶).
$1¶¶¶$2

Каждая буква копии Rкорректируется, чтобы соответствовать букве совпадения, после чего она перемещается из рабочей области, так что следующая буква может быть обработана до тех пор, пока в копии Rили совпадении не закончатся буквы.

¶¶¶¶.*|¶

Если в копии Rзаканчиваются буквы, то до конца совпадения будут предшествовать 4 новых строки, поэтому удалите их. В противном случае все, что останется, будет оставленными частями копий, Rкоторые должны быть объединены с несовпадающими частями ввода для получения результата.

Нил
источник
3

APL (Dyalog) , 75 73 72 байта

Подсказки для T , Rи Fв таком порядке. Rдолжен Fбыть задан в формате преобразования Dyalog и должен быть задан в формате PCRE.

⍞⎕R(⍞∘{(⊣⌿d)l¨⍨(1∘⌷≠(⊢⌿d∊⎕A,lA)∧≠⌿)d≠(l819⌶)d←↑⍺⍵.Match↑¨⍨≢⍺})⍠1⊢⍞

Попробуйте онлайн!

 подсказывать T

 дать это (отделяет 1 и T)

⍞⎕R(... )⍠1 запроситьF и R eplace матчи с результатом следующей функции:

⍞∘{…} получить монадическую функцию, привязав запрос в Rкачестве левого аргумента к:

  ≢⍺ посчитать количество букв в R

  ⍺⍵.Match↑¨⍨ возьмите столько букв от каждого из, Rи совпадение
   - левый аргумент, который мы связали R.
   пространство имен, в которомMatch содержится найденная строка

   смешать эти два в матрицу из двух строк

  d← хранить как d

  (...)   Примените к этому следующую молчаливую функцию:

   819⌶ строчные (мнемоника: 819 выглядит как большой )

   l← сохранить эту функцию как l

  d≠ Логическое где d отличается (т.е. дает 0/1 для каждой строчной / заглавной буквы)

  () Примените к этому следующую молчаливую функцию:

   ≠⌿ вертикальный XOR

   ()∧ Логическое И со следующим массивом:

    l⎕A строчная lphabet

    ⎕A, перед именем прописной lphabet

    d∊ Логическое значение для каждой буквы в d, является ли ее членом (т.е. является ли буква)

    ⊢⌿ последняя строка, т.е. для символа совпадения, является ли это буквой

   1∘⌷≠ XOR с первой строкой, т.е. является ли каждый символ Rзаглавными

  (...)l¨⍨  Используйте это, чтобы строчные (если 0) или прописные (если 1) каждая буква:

   ⊣⌿ первый ряд, т.е. R


* Количество байтов для Dyalog Classic ⎕OPT вместо .

Адам
источник
2

Изъятое. Ответ Дома превосходит его длинным выстрелом.

# Perl 5 , 136 + 1 (-p) = 137 байт

$f=<>;chomp$f;@R=($r=<>)=~/./g;for$i(/\Q$f/gi){$c=$n='';$"=$R[$c++],$n.=/[A-Z]/?uc$":/[a-z]/?lc$":$"for$i=~/./g;s/\Q$i/$n.substr$r,$c/e}

Попробуйте онлайн!

сделал огромный разрез после упоминания @Dom Hastings \Q

# Perl 5 , 176 + 1 (-p) = 177 байт

sub h($){chomp@_;pop=~s/[^a-z0-9 ]/\\$&/gir}$f=h<>;@R=($r=<>)=~/./g;for$i(/$f/gi){$c=$n='';$"=$R[$c++],$n.=/[A-Z]/?uc$":/[a-z]/?lc$":$"for$i=~/./g;$i=h$i;s/$i/$n.substr$r,$c/e}

Попробуйте онлайн!

Xcali
источник
Проходит все тестовые случаи сейчас;) 108: Попробуйте онлайн!
Дом Гастингс
Вы должны опубликовать это. Это немного превосходит мое.
Xcali
Справедливо! Было весело делать это. Я наслаждаюсь вызовом!
Дом Гастингс
2

PowerShell , 190 байт

param($T,$F,$R)[regex]::Replace($T,'(?i)'+[regex]::escape($F),{param($m)-join(0..$R.Length|%{(($y=$R[$_]),("$y"."To$((('Low','Upp')[($z="$m"[$_])-cmatch($C='[A-Z]')]))er"()))[$z-match$C]})})

Попробуйте онлайн!

Объяснение:

[Regex]::Replace( 
    input text T,
    Find text F with case insensitive and [regex]::escape() for symbols,
    {scriptblock} for computing the replacement
)

Блок сценария замены выполняет:

$m is the matched text with case information
loop over each character in R as $y
    $z is the same index character in $m ($null if R overruns)
    $z-match'[A-Z]' checks if alphabetic, so we must to case-match
      otherwise, non-alphabetic or null, no case-match, return $y unchanged.
    if case-matching, check if z case-sensitive matches '[A-Z]' and
      use dynamic method calling from a generated string, either 
      $y."ToLower"()
      $y."ToUpper"()
      to force the match
-join the loop output into a replacement string

Тестовые случаи:

function f {
param($T,$F,$R)[regex]::Replace($T,'(?i)'+[regex]::escape($F),{param($m)-join(0..$R.Length|%{(($y=$R[$_]),("$y"."To$((('Low','Upp')[($z="$m"[$_])-cmatch($C='[A-Z]')]))er"()))[$z-match$C]})})
}

Import-Module Pester

$Cases = @(
    @{Text = "Text input"; Find = "text"; Replace = "test"; Result = "Test input" }
    @{Text = "tHiS Is a PiEcE oF tExT"; Find = "is"; Replace = "abcde"; Result = "tHaBcde Abcde a PiEcE oF tExT" }
    @{Text = "The birch canoe slid on the smooth planks"; Find = "o"; Replace = " OH MY "; Result = "The birch can OH MY e slid  OH MY n the sm OH MY  OH MY th planks" }
    @{Text = "The score was 10 to 5"; Find = "10"; Replace = "tEn"; Result = "The score was tEn to 5" }
    @{Text = "I wrote my code in Brain$#@!"; Find = "$#@!"; Replace = "Friend"; Result = "I wrote my code in BrainFriend" }
    @{Text = "This challenge was created by Andrew Piliser"; Find = "Andrew Piliser"; Replace = "Martin Ender"; Result = "This challenge was created by Martin Ender" }
    @{Text = "John does not know"; Find = "John Doe"; Replace = "Jane Doe" ; Result ="Jane does not know" }
    @{Text = "Glue the sheet to the dark blue background"; Find = "Glue the sheet to the dark-blue background"; Replace = "foo"; Result ="Glue the sheet to the dark blue background" }
    @{Text = "aaa" ; Find = "aa"; Replace = "b"; Result ="ba" }
    @{Text = "aaaa"; Find = "aa"; Replace = "a"; Result ="aa" }
    @{Text = "TeXT input"; Find = "text"; Replace = "test"; Result ="TeST input" }
)

Describe "Tests" {

    It "works on /<Text>/<Find>/<Replace>/ == '<Result>'" -TestCases $Cases {
        param($Text, $Find, $Replace, $Result)
        f $Text $Find $Replace | Should -BeExactly $Result
    }

}
TessellatingHeckler
источник
1

TXR Lisp, 285 байт

(defun f(s f r)(let*((w(copy s))(x(regex-compile ^(compound,(upcase-str f))))(m(reverse(tok-where(upcase-str s)x))))(each((n m))(set[w n]r) (for((i(from n)))((< i (min(to n)(len w))))((inc i))(cond((chr-isupper[s i])(upd[w i]chr-toupper))((chr-islower[s i])(upd[w i]chr-tolower)))))w))

Традиционно отформатированный оригинал:

(defun f (s f r)
  (let* ((w (copy s))
         (x (regex-compile ^(compound ,(upcase-str f))))
         (m (reverse (tok-where (upcase-str s) x))))
    (each ((n m))
      (set [w n] r)
      (for ((i (from n))) ((< i (min (to n) (len w)))) ((inc i))
        (cond ((chr-isupper [s i]) (upd [w i] chr-toupper))
              ((chr-islower [s i]) (upd [w i] chr-tolower)))))
    w))
Kaz
источник
1

JavaScript, 177 байт

(T,F,R)=>T.replace(eval(`/${F.replace(/[-\/\\^$*+?.()|[\]{}]/g,'\\$&')}/gi`),F=>[...R].map((r,i)=>/[A-Z]/i.test(f=F[i]||'')?r[`to${f>'`'&&f<'{'?'Low':'Upp'}erCase`]():r).join``)

Меньше гольфа:

(T,F,R) => T.replace(
    eval(`/${F.replace(/[-\/\\^$*+?.()|[\]{}]/g,'\\$&')}/gi`),
    F=>[...R].map((r,i) =>
        /[A-Z]/i.test(f = F[i] || '')
            ? r[`to${
                f > '`' && f < '{'
                    ? 'Low'
                    : 'Upp'
                }erCase`]()
            : r
    ).join``
)

47 байтов было получено из этой escape-функции регулярного выражения, поскольку программа должна обрабатывать символы. :(

darrylyeo
источник
1

Python 2 , 193 200 байт

T,F,R=input()
w=str.lower
i=-len(T)
l=len(F)
T+=' '
while i:
 s=T[i:i+l]
 if w(s)==w(F):T=T[:i]+`[[y,[w(y),y.upper()][x<'a']][x.isalpha()]for x,y in zip(s,R)]`[2::5]+R[l:]+T[i+l:];i+=l-1
 i+=1
print T

Попробуйте онлайн!

прут
источник
Это (193 байта, из ссылки TIO) не сможет найти совпадения в конце строки.
Техми
1

Python 3 , 183 байта

import re
j="".join
f=lambda T,F,R:j((p,j((y,(y.lower(),y.upper())[x<'a'])[x.isalpha()]for(x,y)in zip(p,R))+R[len(F):])[i%2>0]for i,p in enumerate(re.split('('+re.escape(F)+')',T,0,2)))

Попробуйте онлайн!

re.split + оставьте все четные элементы и замените все нечетные элементы правильным преобразованием строки замены:

>>> re.split("(is)","tHiS Is a PiEcE oF tExT",0,2) # 2=re.IGNORE_CASE
['tH', 'iS', ' ', 'Is', ' a PiEcE oF tExT']
jferard
источник
1

С (ССЗ) , 210 211 207 189 байт

Пришлось добавить один байт, чтобы исправить ошибку с заглавными буквами для теста "BrainFriend"

Вау, это было утомительно ... Теперь, чтобы убрать несколько байтов

char*c,*p;d,l;f(t,f,r){for(d=isalpha(*(p=f)),p=c=t;c=strcasestr(c,f);p=c+=l>0?l:0){for(l=strlen(f);p<c;)putchar(*p++);for(p=r;*p;p++,c+=l-->0)putchar(d*l<1?*p:*c&32?*p|32:*p&~32);}puts(p);}

Попробуйте онлайн!

cleblanc
источник
Я, вероятно, упускаю что-то очевидное, но зачем вам нужно, *(p=f)когда вы садитесь p=c=tсразу после этого? Я попробовал это просто, *fи это не сработало, поэтому оно не сразу перезаписывается.
Андрей
f - это по умолчанию int, поэтому мы не можем разыменовать его, чтобы получить символ, но p - это символ *
cleblanc
Ах, это имеет смысл. Так что это более короткий способ написания *((char*)f)? Здорово!
Андрей
1

C # (моно C # компилятор) , 241 байт

using System.Text.RegularExpressions;
class Program {
static void Main(string[] args) {
r("Text input","text","Test");
}
static void r(string v,string i,string u)
{
System.Console.WriteLine(Regex.Replace(v,i,u,RegexOptions.IgnoreCase)); 
}
}

Попробуйте онлайн!

rivalC
источник
1
Добро пожаловать в PPCG! Здесь вы можете удалить довольно много пробелов, и на самом деле вам нужно либо принимать входные данные в качестве аргументов, либо входные данные (их кодирование запрещено), или вы можете просто включить функцию; вам даже не нужна Action<string,string,string> r =роль
HyperNeutrino