ペアリング可能な文字列


28

文字列があるペア可能で、それが連続して2回繰り返した文字列で、それぞれのsubtrings、に分割することができます。たとえば、次のようにaabaaababbbabaペアリング可能です:

aaba aaba
b b
ba ba

空ではないa'sとb' s の文字列を指定すると、ペアリング可能な場合はTruthy値を出力し、ペアリングできない場合はFalsey値を出力します。

ペアリング可能:

aa
abaaba
bbababbb
aabaaababbbaba
babababa
bbbbbbbbbbbb
aaababbabbabbbababbaabaabaababaaba
aaaabaab

ペアリング不可:

a
ba
baab
abaabaaba
bbbbbbbbbbbbbbb
baababbabaaaab
aaaaabbaaaaa

あなたの言語で既に短い正規表現の回答がある場合でも、正規表現に基づいていないソリューションを考え出すことをお勧めします。「正規表現なし」としてマークできます。正規表現とは、組み込みの文字列パターンマッチングサブシステムを意味します。


リーダーボード:


以外のものを使用できますabか?
エリックアウトゴルファー16年

bbababbbがペアリング可能な場合、baabとaaaaabbaaaaaがペアリングできないのはなぜですか?
rnso

私の理解では、bbababbbは3つのペアとして流出できます:bb、abab、bbはこの順序で連結して元の文字列を形成しますが、他の2つはできません。
サニーしゃれ

「各(部分文字列)は連続して2回繰り返される文字列である」という質問によって、bbababbbに満足していません。それ以外の場合、baabはbaabに、aaaaaabbaaaaaはaaaaa bb aaaaaに分割することもできます。
rnso

@rnsoどういう意味かわかりません。連続するということは、2つの繰り返しが隣り合っていることを意味します。「baa b」では、2つのbはaで区切られているため、機能しません。
xnor

回答:


11

Python 2、68 63バイト

f=lambda s,n=1:s==2*s[:n]or''<s[n:]>-f(s,n+1)<f(s[n:])*f(s[:n])

TrueまたはFalseを返します。Ideoneでテストします。


4
ダブルの中心とパーティションの中心の両方にインデックスを使用する、本当にクリーンな再帰です。真実が何かよりも小さいとチェックされるのは面白いです。いくつかの改善が見られます
...-xnor

8

網膜、11バイト

^((.+)\2)+$

すべてのテストケースを試してください。最初の2バイトにより、複数行になります。

すべてのRetinaプログラムがそうであるように、ルールのかなり文字通りの解釈は明らかに正規表現を使用します。


2
ダンギット、私はこれを投稿するのに3週間待っていました
...-ETHproductions

2
マーティンも待っていました
xnor

5
おっと!私も彼を10秒だけ倒しました。
FryAmTheEggman

5
@FryAmTheEggman楽しみにしています。:)
マーティン・エンダー

2
Perlでもまったく同じですperl -pE '$_=/^((.+)\2)+$/'
Dada

8

ゼリー、10 バイト

ẆŒPẋ€€2F€ċ

正確ではありません... オンラインで試してみてください!

使い方

ẆŒPẋ€€2F€ċ  Main link. Argument: s (string)

Ẇ           Window, generate the array of all substrings of s.
 ŒP         Powerset; generate all subarrays of substrings of s.
   ẋ€€2     Repeat each substring in each subarray twice.
            For example, ["ab", "a", "b"] becomes ["abab", "aa", "bb"].
       F€   Flatten the subarrays by concatenating their strings.
         ċ  Count how many times s appears in the generated strings.

これは効率が悪いようです。これは妥当な時間枠でどれくらいの入力を処理できますか?
ジョンドヴォルザーク

1
これは非常に非効率的です(O(2 ^ n ^ 2)、と思います)。ローカルで確認する必要があります。TIOは、長さ6のストリングのメモリーを使い果たします。
デニス

8
私のマシンでは、長さ6の文字列は3:20分かかり、6 GBのメモリが必要です。
デニス

1
@Dennis すべてがクラッシュするので、長さ100の入力を行わないようにしましょう。はい、TIOも。
エリックアウトゴルファー16年

@EriktheGolferこれは、他の用途でTIOを不必要に遅くするので良い考えですが、クラッシュしません。システムのメモリが不足するとすぐに、プロセスはOOMによって強制終了されます。
デニス

5

Haskell、72 69バイト(正規表現なし)

g(a:b:c)|a==b=g c
g x=x==[]
any(g.words.concat).mapM(\c->[[c],c:" "])

総当たり的なアプローチ。Ideoneで試してみてください

-3バイトのBlackCapに感謝します。

説明

ヘルパー関数gは文字列のリストを取り、それがのような同一の文字列のペアで構成されていることを確認し["aa","aa","bba","bba","ab","ab"]ます。(匿名の)main関数は、考えられるすべての方法で文字列を分割し、少なくとも1つの分割がg受け入れ可能なリストになることを確認します。

g(a:b:c)                                  g on list with elements a, b and tail c,
        |a==b                              in the case that a==b,
             =g c                          recurses to the tail c.
g x=                                      g on any other list x
    x==[]                                  checks that x is empty.
                                           This includes the case where a is not equal
                                           to b, resulting in False.
any(g.words.concat).mapM(\c->[[c],c:" "]) The main function:
                    mapM(\c->[[c],c:" "])  Replace each letter c with either "c" or "c "
                                           in all possible ways, return list of results.
any(              ).                       Check that at least one result satisfies this:
            concat                          Concatenate the 1- or 2-letter strings,
      words.                                split again at each space,
    g.                                      apply g.

あなたは置き換えることができor.mapany
BlackCap

@BlackCapもちろん、ありがとう!私が最初に持っていたany g.map(words.concat)し、「ちょっと、私はゴルフができ思ったanyor...」
Zgarb

5

Python 2、60バイト

f=lambda s,t='':''<s>f(s[1:],t+s[0])|f(t and s)*f(t)>-(s==t)

これが正しいことを願っています。実行はかなり遅く、and最適に見えません。


1
文字列を使用してみましたが、インデックスベースのスコアに近づきませんでした。それはandあなたがそこに持っている一つの賢いことです。
デニス

おめでとうございます!パーティションの再帰は、私が念頭に置いていたトリックでした。
XNOR

4

ゼリー、12 バイト

ŒṖµœs€2ZEµ€S

私の他の答えよりも2バイト長いですが、このアプローチははるかに効率的であり、テストケースの1つを除くすべてを処理します。

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

使い方

ŒṖµœs€2ZEµ€S  Main link. Argument: s (string)

ŒṖ            Generate all partitions of s.
  µ      µ€   Map the monadic chain between the µ's over the partitions.
   œs€2         Split each string in the partition into two chunks of equal length.
       Z        Zip/transpose, collecting the first halves in one array and the
                second halves in another.
        E       Test the arrays of halves for equality.
           S  Return the sum of the results, counting the number of different
              ways s can be paired.

3

Pyth-正規表現なし-13 12バイト

パーティションのいずれかが、2つに分割されたときに互いに等しいすべての文字列で構成されているかどうかをチェックします。

sm.AqMcL2d./

テストスイート


3

Brachylog、14バイト(正規表現なし)

lye~l:1j@2zcc?

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

これは、一部のテストケースには遅すぎる

説明

ly                  The list [0, …, length(Input)]
  e~l               A list whose length is an element of the previous list
     :1j            Append itself to this list
        @2zc        Split in half, zip and concatenate so that the list contains pairs of
                      consecutive identical elements
            c?      The concatenation of that list must result in the Input

3

JavaScript(ES6)、正規表現なし、75 74バイト

f=s=>!s|[...s].some((_,i)=>i&&s[e='slice'](0,i)==s[e](i,i+=i)&&f(s[e](i)))

1それ以外の場合はpairableを返します0。編集:@ edc65のおかげで1バイト保存されました。


いいね!substr変更せずに使用した同じカウントi。しかし、でslice繰り返し3回あなたがそれをエイリアシング1つのバイトを保存することができます
edc65

@ edc65変更せずに同じカウントを取得するにはどうすればよいですiか?私はそれs.substr(i,i+i)が同じを返しますが、後でs.slice(i,i+=i)変更された値を使用することを理解していますi
ニール

それはs.substr(i,i)2バイト少なく、その後s.slice(i+i)2バイト多く
-edc65

@ edc65ああ、もちろんです。もっとコーヒーが必要です...-
ニール

3

Python、58バイト

f=lambda s,p='':s>''and(f(p)>-(s==p)<f(s))|f(s[1:],p+s[0])

これは、デニスの再帰的方法に基づいています。ブール否定のトリックも同様に使用されます。

新しいアイデアは(p,s)、で始まり('',s)、の最初の文字を繰り返し移動してs、の最後の文字になるように、元の文字列のパーティションを再帰処理することですp。これにより、文字列をスライスせずにパーツを直接参照できます。しかし、パーティションはp空で始まるため、f(s)呼び出しの無限ループを避けるように注意する必要がありますf(s)


2

JavaScript(ES6)、24バイト

x=>/^((.+)\2)+$/.test(x)

おそらくこれより短くならないでしょう。


そうじゃない\2
ニール

@Neil何らかの理由で、私はそれが動作すると思っていましたが\1aab戻りますtrue...修正してくれてありがとう。
ETHproductions



1

ラケット230バイト

(let((sl string-length)(ss substring))(if(odd?(sl s))(printf ".~n")(begin(let p((s s))(if(equal? s "")(printf "!")
(for((i(range 1(add1(/(sl s)2)))))(when(equal?(ss s 0 i)(ss s i(* 2 i)))(p(ss s(* 2 i)(sl s)))))))(printf ".~n"))))

「!」を印刷します 文字列がペアリング可能な方法ごとに。「。」を印刷します 最後に。

ゴルフをしていない:

(define (f s)
  (let ((sl string-length)                              ; create short names of built-in fns
        (ss substring))
    (if (odd? (sl s))  (printf ".~n")                   ; odd length strings cannot be pairable; end here.
        (begin
          (let loop ((s s))                             ; start testing here
            (if (equal? s "") (printf "!")              ; if no remaining string, it must be pairable
                (for ((i (range 1 (add1 (/(sl s)2)))))  ; ch lengths varying from 1 to half of string length
                  (when (equal? (ss s 0 i)              ; ch if substrings are same
                                (ss s i (* 2 i)))
                    (loop (ss s (* 2 i) (sl s) ))))))   ; if yes, loop to check remaining string.
          (printf ".~n")))))                            ; End of testing.

テスト:

(println "Following should be pairable")
(f "bbaabbaa")            ; should produce 2 '!' since 2 ways are possible.
(f "aa")
(f "abaaba")
(f "bbababbb")
(f "aabaaababbbaba")
(f "babababa")                    ; should be pairable in 2 ways.
(f "bbbbbbbbbbbb")                ; should be pairable in many ways.
(f "aaababbabbabbbababbaabaabaababaaba")
(f "aaaabaab")
(println "Following should be unpairable")
; (f "a")
(f "ba")
(f "baab")
(f "abaabaaba")
(f "bbbbbbbbbbbbbbb")
(f "baababbabaaaab")
(f "aaaaabbaaaaa")

出力:

"Following should be pairable"
!!.
!.
!.
!.
!.
!!.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.
!.
!.
"Following should be unpairable"
.
.
.
.
.
.

1

Perl、16 +2 = 18バイト(正規表現付き)

-nlフラグで実行します。 -E無料です。

say/^((.+)\2)+$/

として実行:

perl -nlE 'say/^((.+)\2)+$/'

ペアリング可能な場合はキャプチャグループのリスト(真実)を返し、ペアリングできない場合はNULL文字列を返します。

説明

-nlフラグは、(ループ内のコードを実行する-n(のために除去改行で入力を入れ、)-l変数に)$_、プログラムを手動で終了するまで、各時間入力は、入力されたコードを評価し、毎回。この-Eフラグを使用すると、コマンドラインでコードを評価し、コマンドを有効にすることができますsay

say/^((.+)\2)+$/

   /^((.+)\2)+$/  #The regex engine
      (.+)\2      #Find any set of at least one character, followed by itself
     (      )+    #Do this at least one time
   /^         $/  #Make sure that this matches the entire string from start to end
say               #Output the result of the regex

一致が見つかった場合(たとえば、文字列がペアリング可能な場合)、正規表現はキャプチャグループのリストを返します。キャプチャグループは真偽と評価され、次にそれがに渡されsayて出力されます。一致するものが見つからない場合、正規表現は空の文字列を返します。空の文字列はfalsyと評価され、に渡されsayて出力されます。

サンプル:

$ perl -nlE 'say/^((.+)\2)+$/'
aaababbabbabbbababbaabaabaababaaba
baababaababaaba                      #Truthy
baababbabaaaab
                                     #Falsy
bbababbb
bbb                                  #Truthy
aabaaababbbaba
bababa                               #Truthy
abaabaaba
                                     #Falsy

1

GNU Prolog、49 46バイト

おそらく他のバリアントでも機能しますが、それらはすべて同じ方法で文字列を表すわけではありません。GNU Prologの表現は、この問題に役立つものです。

これが正規表現の使用としてカウントされるかどうかは不明です。正規表現のような機能は使用していませんが、言語のセマンティクス全体は正規表現のセマンティクスに似ています。

新しいバージョン(他の回答で見られる再帰トリックを使用):

s(X):-append(A,B,X),(A=B;A\=X,B\=X,s(A),s(B)).

古いバージョン:

s(X):-X=[];append(A,B,X),B\=X,append(C,C,A),s(B).

これは、s完全なプログラムではなく、述部(Prologの関数に相当する)と呼ばれます。次のように使用します。

| ?- s("aa").
true ?
yes
| ?- s("aaababbabbabbbababbaabaabaababaaba").
true ?
yes
| ?- s("baababbabaaaab").
no
| ?- s("bbbbbbbbbbbbbbb").
no

古いソリューションの興味深い機能は、インタプリタに「他にソリューションはありますか?」上記のようにプロンプ​​トでreturnを押して「何かありますか」と尋ねるのではなく;true ?プロンプトで使用すると、文字列を表現できるさまざまな方法の数に等しい回数「true」を返します与えられた形で(例えばそれはで二回「真」を返しs("aaaa").、これはとして解析することができますよう、(a a)(a a)またはとして(aa aa))。

多くの場合、Prologプログラムは可逆です(指定されたプロパティを持つ文字列のリストs生成できます)。古いものはそうではありません(無限ループに入ります)が、それは、Cが空でないことを確認するために使用したゴルフ法のためです。Cを明示的に非空として指定するようにプログラムを書き換えると、「aa」、「aabb」、「aabbcc」などの形式の文字列が生成されます(PrologはPrologであり、それらを作成する文字のIDは指定しません最大で、どの文字が同じかの仕様のみ)。新しい方は、「aa」、「abab」、「abcabc」などの形式の文字列を生成します。これはそれ自体が無限ループであるため、長さゼロの文字列の検出に失敗したためにスタックするポイントに到達することはありません。


1

Brainfuck、177バイト

+[<<<<,]>>>>[>+[>+[[>>]<+<[<<]>+>-]<[>+<-]>>>,>>[>>]+<<[<+>>-<-]<[>+<-]>>[,>[-<<
<<]<[<<<<]>]<[[<<]>]>>]>>[[>+>>>]>>>[>]<<<<[>+[-<<<,<]<[<<<[[<<<<]>>]<]>]>>]<[[-
>>>>]>>[<]<]<<]<.

フォーマット済み:

+[<<<<,]
>>>>
[
  >+
  [
    >+
    [
      [>>]
      <+<[<<]
      >+>-
    ]
    <[>+<-]>
    >>,>>[>>]
    +<<[<+> >-<-]
    <[>+<-]>
    >
    [
      not equal
      ,>[-<<<<]
      <[<<<<]
      >
    ]
    <
    [
      equal
      [<<]
      >
    ]
    >>
  ]
  >>
  [
    mismatch
    [>+>>>]
    >>>[>]
    <<<<
    [
      backtrack
      >+[-<<<,<]
      <
      [
        not done yet
        <<<
        [
          [<<<<]
          >>
        ]
        <
      ]
      >
    ]
    >>
  ]
  <
  [
    match
    [->>>>]
    >>[<]
    <
  ]
  <<
]
<.

末尾の改行なしで入力を期待します。プリント\x00偽のためと\x01真のために。

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

これにより、深さ優先検索が実装されます。特に、現在のサフィックスから始まる長さが増加する繰り返しプレフィックスをチェックし、一致が見つかった場合は次のサフィックスに移動し、そうでない場合はバックトラックします。

最初に、文字列が反転され、センチネル\x01が最後に配置されます。

テープは4セルのノードに分割されます。ノードのメモリレイアウトは次のとおりです。

c h x 0

where cは文字でh、文字が繰り返しプレフィックスの前半にあるかどうかのフラグでxあり、比較されている文字の現在のペアを追跡するためのフラグです。h一方、フラグが所定の位置にとどまるxフラグが移動ウィンドウを形成します。

文字列がペアリング可能である場合、ポインターはメインループの最後でセンチネルの隣に着地します。そうでない場合、ポインタはバックトラック中に文字列の左側から落ちます。


1

Brachylog、5バイト

~c~jᵐ

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

このアルゴリズムは、入力文字列のすべての可能なパーティションをチェックするため、特に偽の場合には非常に長い時間がかかることに注意してください。

説明

~c     Reversed concatenate: find a list that, when concatenated, results in the input string
       This examines all partitions of the input
  ~jᵐ  Map reversed juxtapose: for each string in that list, is it the result of concatenating
       a string to itself?

のような入力文字列の場合"ababcc"、に~c到達するまでさまざまなパーティションを試行し["abab", "cc"]、その時点で~jリストの両方の項目、outputs ["ab", "c"]、およびpredicateが成功します。



0

Lithp、57文字

#S::((? (!= (null) (match S "^((.+)\\2)+$")) true false))

サンプル使用法:

% pairable_strings.lithp
(
    (def f #S::((? (!= (null) (match S "^((.+)\\2)+$")) true false)))
    (print (f "aa"))
    (print (f "aabaaababbbaba"))
    (print (f "aaababbabbabbbababbaabaabaababaaba"))
    (print (f "ba"))
)

# ./run.js pairable_strings.lithp
AtomValue { value: 2, type: 'Atom', name: 'true' }
AtomValue { value: 2, type: 'Atom', name: 'true' }
AtomValue { value: 2, type: 'Atom', name: 'true' }
AtomValue { value: 3, type: 'Atom', name: 'false' }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.