文字列の減算


37

目的

文字列の連結を逆にする関数を作成します

入力

2つの文字列(英数字+スペース)。一方を他方から減算する必要があります。

  • 減算される文字列が他の文字列より大きくなることはないと想定できます。

出力

減算の結果

減算

別の文字列の先頭または末尾から1つの文字列を削除する必要があります。文字列が最初と最後に存在する場合、削除できるのは1つだけで、削除されるのはユーザー次第です。
文字列が先頭または末尾にない場合、または完全に一致しない場合、無効な減算であり、元の文字列を出力する必要があります。

テストケース

有効な減算

'abcde','ab' -> 'cde'
'abcde','cde' -> 'ab'
'abab','ab' -> 'ab'
'abcab','ab' -> 'abc' or 'cab'
'ababcde','ab' -> 'abcde'
'acdbcd','cd' -> 'acdb'
'abcde','abcde' -> ''
'abcde','' -> 'abcde'
'','' -> ''

無効な減算(元の文字列を返します)

'abcde','ae' -> 'abcde'
'abcde','aa' -> 'abcde'
'abcde','bcd' -> 'abcde'
'abcde','xab' -> 'abcde'
'abcde','yde' -> 'abcde'

無効な入力(処理する必要はありません)

'','a' -> ''

これはなので、バイト単位の最短コードが勝ちです!


4
最初のケースの結果はなぜではないのcdeですか?有効とはどういう意味ですか?入力の有効性を判断する必要がありますか、それとも無効な入力を受け取らないという意味ですか?
リーキー修道女

7
くそー、'abcde','bcd' -> 'abcde'私の解決策を破ったため、
ジョンドヴォルザーク

5
文字列が正規表現に対して安全であると想定できますか(英数字+スペース)?
ジョンドヴォルザーク

2
テストケースとして'ababcde', 'ab''abcde'をお勧めします。いくつかの素朴なアルゴリズムはその上で失敗します。

2
@Rod「逆文字列の連結」という課題のタイトルを変更することを検討してください
MD XF

回答:


19

Java 8、46 45 44 40バイト

TheLethalCoderのおかげで-1バイト

バカだから-1バイト(ロッドに感謝!)

Kevin Cruijssenのおかげで-4バイト

a->b->a.replaceFirst("^"+b+"|"+b+"$","")

オンラインでお試しください!(すべてのテストケースを含む)

Javaの答えは、実際には他のいくつかの実用的な言語に勝っています。笑顔。(そして今ではJSに勝っています!)


カリーを使用してバイトを保存するa->b->
-TheLethalCoder

@TheLethalCoderありがとう。
Okx

オンラインの例で未使用のハッシュマップを残したのはなぜですか?
マイケル

Firstto Allを-2バイトに変更できます。^andのため、$常にStringの末尾または先頭のいずれかにあるため、たとえreplaceAllそれが1回だけ置き換えられます。ここで試してみてください。PS:以前の取り消し線のバイトカウントを回答に追加しました。これは通常、PPCGでコードゴルフを編集した後に行われます。
ケビンCruijssen

@KevinCruijssen取り消し線については知っていましたが、今回は忘れていたと思います。ただし、のAll代わりに使用する場合First、これは真になります"abab" + "ab" -> ""
。– Okx

9

JavaScript(ES6)、41バイト

s=>t=>s.replace(eval(`/^${t}|${t}$/`),'')

カリー化構文、つまりを介して入力を受け取りますf("abab")("ab")


3
さて、なぜeval()以前にRegExの構築に使用することを考えたことがなかったのでしょうか?!
シャギー

9

Brachylog(Try It Online!)、12バイト

~cpĊh.∧Ċtw|w

オンラインでお試しください!

標準入力から減算する文字列と、コマンドライン引数として減算する文字列を取ります。

説明

~cpĊh.∧Ċtw|w
~c            Split {the input} into pieces
  p           and (possibly) rearrange those pieces
   Ċ          such that there are two pieces
    h         and the first
     .        matches the command line argument
      ∧       then
         w    print
        t     the last
       Ċ      piece.
          |   If all else fails,
           w  print {the input}.


6

JavaScript(ES6)、76 70 45 41バイト

s=>t=>s.replace(RegExp(`^${t}|${t}$`),"")

それを試してみてください

f=
s=>t=>s.replace(RegExp(`^${t}|${t}$`),"")
o.innerText=f(i.value="abcde")(j.value="ab")
i.oninput=j.oninput=_=>o.innerText=f(i.value)(j.value)
<input id=i><input id=j><pre id=o>


2
必要ありませんnew
Programmer5000

@ programmer500、ETHのバージョンを見たとき、この作業をやめました!:D更新されました。ありがとう。
シャギー



3

TI-Basic(TI-84 Plus CE)、63バイト

Prompt Str0,Str2
inString(Str0,Str2
If Ans
sub(Str0,1,Ans-1)+sub(Str0,Ans+length(Str2),length(Str0)-Ans+1-length(Str2→Str0
Str0

質問があります。なぜStr1を変数として使用しなかったのですか?
ザカリー

@Zacharý当時は何かが保存されていたと思う。私は本当に覚えていない。
pizzapants184

Ans4行目でも何を指していますか?
ザカリー

@Zacharý Ansは最後に評価された値を参照するため、この場合はによって返される値を参照しますinString(。これは、文字列Str2内の部分文字列のインデックス、Str0または部分文字列が表示されない場合は0です。ifステートメントはAnsの値を変更しないため、4行目ではインデックスはまだですAns
pizzapants184

ああ、私はどのようにinString働いたか忘れていました。素敵なゴルフ!
ザカリー

3

Mathematica、162バイト

(c=Characters;a=c@#;b=c@#2;l=Length;t={};If[l@Intersection[a,b]==l@b,If[MemberQ[Partition[a,l@b,1],b],t=a;Table[t=DeleteCases[t,b[[i]],1,1],{i,l@b}]],t=a];""<>t)&

テスト入力スタイル["abcde"、 "ab"]


1
いい解決策!#代わりにを使用してバイトを保存できます#1—それらはまったく同じ意味です。また、を使用する代わりStringJoin@tに、に空の文字列を結合することでチートできます。これにより""<>t、すべてが自動的に結合さtれます。Mathematicaゴルフのヒントのページを見たことがありますか?
木ではない

バイトを節約するためにできることは他にもいくつかあります(t={};たとえば、最初に定義する必要はないと思います)が、完全に別のアプローチを使用する方が簡単かもしれません。StringReplace関数?
ツリーではない

あなたが本当に必要としないようにするには、入力としてString配列を取ることが許可されているc=Characters;a=c@#;b=c@#2;
JungHwan分を

また、l@Intersection[a,b]ですl[a∩b]
ジョンファンミン

3

Python、69 68 64 57 51 45バイト

これは、Regexとはまったく異なるソリューションになりました。

-2バイトのValue Inkに感謝します!
そしてフェリペ・ナルディバティスタ巨大-6バイトのために!

import re
lambda s,c:re.sub(c+'$|^'+c,'',s,1)

オンラインでお試しください!


-2バイトの場合:re.sub(c.join("^|$"),'',s,1)
値インク

1
-6バイトの場合:c+'$|^'+c
フェリペナルディバティスタ

3

バッシュ66 61 49バイト

case $1 in *$2)echo ${1%$2};;*)echo ${1#$2};;esac

オンラインでお試しください!

少ないゴルフ:

a=$1;
case $1 in 
    *$2)  c=${a%$2};;       
    $2*)  c=${a#$2};;
      *)  c=$1;;
esac;
echo $c

ケースを使用して、開始または終了、および配列接頭辞/接尾辞(%/#)の減算をテストします


1
の素晴らしい使用法ですcaseが、必要以上に長いです。2番目と3番目のパターンを単一のパターンにマージできます*)c=${1#$2};;。それから2つのブランチだけechoでは、変数を使用する代わりにそれぞれに直接短くなります$ccase $1 in *$2)echo ${1%$2};;*)echo ${1#$2};;esac。または、それを使用し続けることができますが、なしでcasec=${1%$2};[[ $c = $1 ]]&&c=${1#$2};echo $c
マナトワーク

3

APL(Dyalog)31 30バイト

-1Zacharýに感謝します

これは実際には逆(つまり、逆)連結を使用します!元の文字列を左引数として取り、減算するものを右引数として取ります。

{0::⍺{0::⍺⋄,∘⍵⍣¯1⊢⍺}⍵⋄⍵,⍣¯1⊢⍺}

オンラインでお試しください!

ゴルフをしていない:

{
    0::⍺{          if an error happens, apply the following function on the arguments
        0::⍺           if an error happens, return the left argument unmodified
        ,∘⍵⍣¯1⊢⍺       inverse-append right argument on left argument
        }⍵
    ⍵,⍣¯1⊢⍺       inverse-prepend the right argument on the left argument
}

伝説:

{} 匿名関数

 現在の関数の左引数

 現在の関数の右引数

0::…エラーが発生した場合は、これを実行し、そうでなければ…

⍣¯1⊢ 逆

,∘⍵を右側に 連結します

⍵,左側の 連結


でバイトを節約できると思います{0::⍺{0::⍺⋄,∘⍵⍣¯1⊢⍺}⍵⋄⍵,⍣¯1⊢⍺}
ザカリー

@ザカリーはい、ありがとう。
アダム



2

Haskell、49バイト

f s a b|s==b=a|a/=b,h:t<-a=f(s++[h])t b|1<3=s
f""

オンラインでお試しください!使用法:f"" "abcdef" "ab"。または、次のように定義(-)=f""して使用します "abcdef" - "ab"

この正規表現を使用しないソリューションは、すべての前後の文字列を再帰的に分割し、減算する文字列がそれらのいずれかに一致するかどうかをチェックすることで機能します。



1

C#、88バイト

s=>r=>s.StartsWith(r)?s.Substring(r.Length):s.EndsWith(r)?s.Substring(0,s.IndexOf(r)):s;

にコンパイルしますFunc<string, Func<string, string>>


1

Ruby(ラムダ式)、29バイト

->a,b{a.sub /^#{b}|#{b}$/,""}

正規表現補間に賛成です!正規表現に安全なサブトラウンドが必要ですが、課題ごとに問題ありません。


1

Tcl、37バイト

proc s {a b} {regsub "^$b|$b$" $a {}}

オンラインでお試しください!(現在すべてのテストを実行しています)

Tclは簡単です。パラメータとを受け取るproc s {a b}という名前の関数を定義します。の開始時または終了時の値を、空の文字列で置換します。戻り値は暗黙的です。sabregsub{}ba


1

C、96バイト

Cでの文字列操作は面倒なことであるというのは一般的な知識です。エクステンションゴルフは境界線の自虐的だからです。私には申し分なく聞こえます。

f(a,b,t,l)char**a,*b,*t;{t=*a;l=strlen(b);bcmp(t,b,l)?bcmp(t+=strlen(t)-l,b,l)||(*t=0):(*a+=l);}

私が書いた読みにくいプログラムの1つ。(関数がどのように見えるかに関係なく)2つの入力char**を受け取ります。char*削除する文字列です。入力ポインタはその場で編集され、出力になります(とにかくメモリリークが発生する場合)。

使用例:

char *a = malloc(6);
strcpy(a, "abcde");
char *b = malloc(4);
strcpy(b, "abc");
f(&a,b);
printf("%s\n", a); // "de"

1

AWK21 32バイト

{sub("^"$2"|"$2"$",z,$1);$0=$1}1

オンラインでお試しください!

最初の送信では、最初または最後だけでなく、最初の文字列内のテキストが単純に置き換えられました。

{sub($2,z,$1);$0=$1}1

オンラインでお試しください!

もともと中括弧なしで試してみましたが、空の行を印刷するためのトリックや、このバージョンよりも多くのバイトを追加することになった不一致が必要でした。


1

R、20 42 41バイト

pryr::f(sub(sprintf('^%s|%s$',b,b),'',a))

MickyTのおかげで-1バイト!

匿名関数を返します(順番に引数がありますb,a)。文字列の差を計算しますa-bsubパターンの最初の出現を、この場合は空の文字列と交換する単純な置換です''sprintf文字列の最初と最後でのみ一致する正規表現を構築します。が必要ですpryrパッケージをインストールするます。

TIOリンクで、さらにfunction(a,b)4バイトの関数のより詳細な定義を使用します。

オンラインでお試しください!


1
およそ何'abcde','bcd' -> 'abcde'場合?
ジョナサンアラン

sub単に最初の出現スワップという単純な置換であるbにおけるa2番目の文字列が最初の文字列の途中にある場合、このスワップウィルは:」?
TheLethalCoder

質問を読み間違えました!おっとっと。キャッチしてくれてありがとう!
ジュゼッペ

あなたが1人のバイトの背中を取得することができますsprintf('^%s|%s$',b,b)
MickyT

@MickyT、ありがとう!一定。
ジュゼッペ

1

Common Lisp、121バイト

(lambda(x y)(cond((equal(#1=subseq x 0 #3=(length y))y)(#1#x #3#))((equal(#1#x #2=(-(length x)#3#))y)(#1#x 0 #2#))(t x)))

オンラインでお試しください!

通常の冗長なCommon Lisp!

ゴルフされていないバージョン:

(defun f(x y)
  (cond ((equal (subseq x 0 (length y)) y)               ; if x starts with y
         (subseq x (length y)))                          ; return rest of x
        ((equal (subseq x (- (length x) (length y))) y)  ; if x ends with x
         (subseq x 0 (- (length x) (length y))))         ; return first part of x
        (t x)))                                          ; else return x


1

Powershell、34 40バイト

Invalid Subtractionテストケースが追加された場合は+6バイト

param($s,$t)$s-replace"^$t(?!.*$t$)|$t$"

コメント:

正規表現^$t|$t$は期待どおりに機能しません。1つの代わりに両方の一致を置き換えます(フラグg。常にオン)。そのため、負の先読みグループを使用する必要があります。

テストスクリプト:

$f = {
    param($s,$t)$s-replace"^$t(?!.*$t$)|$t$"
}

@(
    ,('abcde','ab', 'cde')
    ,('abcde','cde', 'ab')
    ,('abab','ab', 'ab')
    ,('abcab','ab', 'abc', 'cab')
    ,('ababcde','ab', 'abcde')
    ,('acdbcd','cd', 'acdb')
    ,('abcde','abcde', '')
    ,('abcde','', 'abcde')
    ,('','', '')

    ,('abcde','ae', 'abcde')
    ,('abcde','aa', 'abcde')
    ,('abcde','bcd', 'abcde')
    ,('abcde','xab', 'abcde')
    ,('abcde','yde', 'abcde')

    ,('','a', '')
) | % {
    $s,$t,$e = $_
    $r = &$f $s $t
    "$($r-in$e): $r"
}

出力:

True: cde
True: ab
True: ab
True: abc
True: abcde
True: acdb
True:
True: abcde
True:

0

QBIC、57バイト

これはQBIC / QBasicの混乱です...

B=@ `+B┘x=instr(;,;)~x|?_t_sB,x-1|+_sB,x+_lC|,_lB|||\?B

B=@ `+B          Prepend a string to B$. Thisis a hack to avoid errors with 
                 removing substrings stating at index 1
┘                Line-break in QBasic output
       (;,;)     Read the string (B$) and the to-be-removed substring (C$)
x=instr          And make x to be the starting index of the first C$ in B$
~x|              IF X <> 0 (ie C$ is present in B$)
?                PRINT
 _t                trimmed version (drops the prepended space)
  _sB,x-1|+        of a substring from 1 to x (the start of C$) -1
  _sB,x+_lC|,_lB   and the rest of the string, starting after C$
                     _l takes the length of a string
  |||              End TRIM, end Substring, end Length
\?B              When missing C$, just print B$


0

最初に指示を読み違えました。ØrjanJohansen、私の間違いを指摘してくれてありがとう!

PowerShell46 51バイト

Function F($o,$a){([regex]"^$a").replace($o,'',1);}

オンラインでお試しください!


「abcde」「bcd」の場合、これは失敗します。
Ørjanヨハンセン

私はそのテストケースから期待される結果を見ています-TIOはこちら
ジェフフリーマン

これはOPのリストされたテストケースであり、結果はabcde- bcd文字列のどちらの端でも発生しません。
Ørjanヨハンセン

あなたは正しいです。指示を読み間違えました。それを指摘してくれてありがとう!
ジェフフリーマン

0

Excel、129バイト

=IFERROR(IF(FIND(B1,A1)=1,SUBSTITUTE(A1,B1,"",1),IF(FIND(B1,A1,LEN(A1)-LEN(B1))>LEN(A1)-LEN(B1),LEFT(A1,LEN(A1)-LEN(B1)),A1)),A1)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.