じゃんけんで繰り返してはいけない


26

CodegolfがRock-Paper-Scissorsトーナメント開催するとの噂があるので、スクエアフリーワードのトピックを調べます。手紙で作られた言葉はRPSである無平方それが二回繰り返し、そのシーケンスが含まれていない場合。つまり、単語は次のように書くことはできません

a x x b

ここで、aおよびb任意の長さの単語であり、x長さの単語すべての文字からなる少なくとも一つですRPS

仕事

生成するプログラムを書く正方形無文字の単語RPS長さのn数を1 <= n <= 10入力としたが。

たとえば、長さ3 の正方形のない単語は

RPRRSRRPSRSPSPSSRSSRPSPRPRPPSPPSRPRS

長さ4のものは

RPRSRPSRRPSPRSRPRSPRRSPSPRPSPRSRPRSPPSRPPSRSPSPRSRPRSRPSSRSPSPRPSPRSSPSR

そして、例えば、SPSPまたはPRPR正方形ではないことに注意してください

ルール

  • これはcodegolfで、最短のプログラムが勝ち、標準的な抜け穴が閉じられます。
  • 単語を印刷したり、メモリに作成したりできます。
  • プログラムは関数として書かれている場合があります。

参照資料

スクエアフリーの単語に関するウィキペディアのエントリ

指定された長さの正方形のない三項単語の数はhttps://oeis.org/A006156にあります

関連:任意長の3項Squarefreeワード


4
n>3繰り返される文字と繰り返されるシーケンスについて混乱が生じているため、テストケースを作成することをお勧めします。
ライコニ

計画されているフォローアップについてサンドボックスでコメントしてください:codegolf.meta.stackexchange.com/a/14133/45211
mschauer

6
「自然言語」タグがここに適用されるとは思わない
レオ

1
ああ、「単語」は「自然言語」で拡張されたので、削除しました。
mschauer

1
いいえ、正方形SP SPが含まれています
mschauer

回答:


20

ルビー、39バイト

->n{(?P*n..?S*n).grep_v /[^RPS]|(.+)\1/}

この陽気に非効率的な関数は、N PsとN Ssの間にアルファベット順にある長さNのすべての文字列を生成し、非RPS文字を含む圧倒的多数を除外します。実際のsquarefreeチェックでは、正規表現の後方参照を使用します(.+)\1

N = 10で妥当な時間内に終了する、より慣用的な65バイト

->n{%w[R P S].repeated_permutation(n).map(&:join).grep_v /(.+)\1/}

編集:GBのおかげで1バイト保存しました。


grep_vには括弧は必要ありません。grep_vとスラッシュの間にスペースを入れるだけ(1バイト保存)
GB

6
陽気に非効率的」は、おそらくこのサイトでかなりの数の答えを説明しています。
ファンドモニカの訴訟

10

ゼリー15 14バイト

“RPS”ṗẆ;"f$$Ðḟ

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

使い方

“RPS”ṗẆ;"f$$Ðḟ  Main link. Argument: n

“RPS”ṗ          Cartesian power; yield all strings of length n over this alphabet.
            Ðḟ  Filterfalse; keep only strings for which the quicklink to the left 
                returns a falsy result.
           $      Monadic chain. Argument: s (string)
      Ẇ             Window; yield the array A of all substrings of s.
          $         Monadic chain. Argument: A
       ;"             Concatenate all strings in A with themselves.
         f            Filter; yield all results that belong to A as well.

7

網膜、28バイト

+%1`1
R$'¶$`P$'¶$`S
A`(.+)\1

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

入力を単項で取ります。

説明

+%1`1
R$'¶$`P$'¶$`S

これにより、長さで構成されるすべての文字列が生成RPSされnます。これを行う方法は1、各行の最初の行を繰り返し置き換えることです。のは、あるラインについて考えてみよう<1><試合の前にあるすべてのもので、>試合後のすべてです(彼らがしている$`$'、それぞれの正規表現置換構文ではなく、それらの一見あまり直感的)。我々は交換する1R>¶<P>¶<S、どこ改行されています。だから、この置換の完全な結果が実際にある<R>¶<P>¶<S>と、ラインの3つのコピーである、1と交換しRPS、それぞれ、3つのコピーの各インチ すべて1のが置換されると、このプロセスは停止します。

A`(.+)\1

最後に、繰り返しを含むすべての行を単純に破棄します。


繰り返し置き換え1(.*)$1R¶$1P¶$1Sいましたが、バイト数は同じです。
ニール

6

ハスク15 14バイト

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

fȯεfoE½QΠR"RPS

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

正しい長さのすべての可能なシーケンスを構築し、すべてのサブストリング(空のものを除く)が2つの異なる半分で構成されているシーケンスのみを保持します。

くそー、私は本当にここでゼリーを倒したかった。


3
Jellyと結び付ける14バイト
Zgarb


5

Java 8、285 277バイト

import java.util.*;Set r=new HashSet();n->p("",((1<<3*n)+"").replaceAll(".","PRS"),n)void p(String p,String s,int n){int l=s.length(),i=0;if(l<1&&(s=p.substring(0,n)).equals(s.replaceAll("(.*)\\1","")))r.add(s);for(;i<l;p(p+s.charAt(i),s.substring(0,i)+s.substring(++i,l),n));}

Javaはほとんど常に冗長ですが、この場合は間違いなく、このような課題に適した言語ではありません。部分文字列を使用して順列を生成すると、パフォーマンスが低下し、効率が低下します。

しかし、間違いなくもう少しゴルフができます。

@Jakobのおかげで-8バイト。

説明:

ここで試してみてください。(パフォーマンスは3を超えるテストケースには悪すぎますが、ローカルでは機能します。)

import java.util.*;   // Required import for Set and HashSet

Set r=new HashSet();  // Result-Set on class-level

n->                   // Method with integer parameter and no return-type
  p("",((1<<3*n)+"").replaceAll(".","PRS"),n)
                      //  Get all permutations and save them in the Set
                      // End of method (implicit / single-line return-statement)

void p(String p,String s,int n){
                      // Separated method with 2 String & int parameters and no return-type
  int l=s.length(),   //  The length of the second input-String
      i=0;            //  Index-integer, starting at 0
  if(l<1              //  If the length is 0,
     &&(s=p.substring(0,n)).equals(s.replaceAll("(.*)\\1","")))
                      //  and it doesn't contain a repeated part:
    r.add(s);         //   Add it to the result-Set
  for(;i<l;           //  Loop (2) from 0 to `l`
    p(                //   Recursive-call with:
      p+s.charAt(i),  //    Prefix-input + the character of the second input at index `i`
      s.substring(0,i)+s.substring(++i,l),
                      //    and the second input except for this character
      n)              //    and `n`
  );                  //  End of loop (2)
}                     // End of separated method

1
このラムダはどうですか:n->p("",((1<<3*n)+"").replaceAll(".","PRS"),n)。また、リファクタリングfor(;i<1;p(...));してみませんwhile(i<l)p(...);か?
ヤコブ

@Jakobありがとう。そしてfor(;...;)正直に言うと、私は常にcodegolfing-habbitを使いません。最悪の場合、それはと同じバイト数ですwhile(...)。最良の場合、for-loop内に何かを置いてバイトを節約できます。だからwhile、とにかくバイトカウントに利益をもたらさないので、私はコードゴルフでまったく使わないようにしています。それはそれを増やすか、同じままなので、私は個人的には読みやすさを気にしません。;)
ケビンクルーイッセン

1
ええ、私は常にゴルフのコードを特定のバイト数で可能な限り読みやすくしようとしています。おそらく無駄な追求!
ヤコブ

待って、私のラムダは実際にここで動作しますか?私は少し不注意でした...それはn PRSシーケンスの文字列を生成しますが、元のループは2 ^(n -2)シーケンスで生成しました。
ヤコブ

@Jakob ntimes "PRS"は正しいです。私の場合、バイト数を節約したためパフォーマンスが向上しました(そしてパフォーマンスは低下しましたが、codegolfでそれを気にしている人)。;)
ケビンクルーッセン




3

R、97バイト

cat((x=unique(combn(rep(c('p','r','s'),n),n<-scan(),paste,collapse='')))[!grepl("(.+)\\1",x,,T)])

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

combn(rep(c('p','r','s'),n),n,paste,collapse='')すべての計算nで-character文字列をprs、それは残念ながら、我々はそれをuniquifyので、(*)の多くを複製して、正規表現にマッチするものを取る(.+)\1、我々は結果のリストをプリントアウトし、Perlスタイルのマッチングを使用して、。

(*)技術的には、3n文字のすべての組み合わせを一度にp,r,s3回繰り返して生成し、文字列を直接計算するのではなく各組み合わせにn適用paste(..., collapse='')します3^nが、これはexpand.grid(真のデカルト積)よりもゴルファーです。


3

JavaScript(Firefox 30-57)、69バイト

f=n=>n?[for(x of f(n-1))for(y of'RPS')if(!/(.+)\1/.test(y+=x))y]:['']

無平方の単語のすべての部分文字列も無平方なので、チェックは再帰的に実行できます。



2

JavaScript(ES6)、93バイト

n=>[...Array(3**n)].map(g=(d=n,i)=>d?'RPS'[i%3]+g(d-1,i/3|0):'').filter(s=>!/(.+)\1/.test(s))

0から3ⁿまでのすべての整数を(逆パディングされた)基数3にRPS数字として使用して変換し、それらを正方形のない単語でフィルタリングします。


2

ジュリア、88

f(n)=[filter(A->!ismatch.(r"(.+)\1",join(A)),Iterators.product(repeated("RPS",n)...))...]

派手なものは何もありません。


1

C#/ LINQ、169

Enumerable.Range(0,(int)Math.Pow(3,n)).Select(i=>string.Concat(Enumerable.Range(1,n).Select(p=>"PRS"[(i/(int)Math.Pow(3,n-p))%3]))).Where(s=>!Regex.IsMatch(s,@"(.+)\1"))

これを行うにはより良い方法が必要です:)



1

k、56バイト

f:{$[x;(,/"RPS",/:\:f x-1){x@&~~/'(2,y)#/:x}/1_!x;,""]}

ネイティブの正規表現が存在しないため、kが1回だけ曲線の後ろにあります。それを実装するキャラクターは、より単純なスクエアフリーチェックによって保存されたため、再帰的なソリューションを使用しました。

$[ test ; if-true ; if-false ]

はkの三項演算子です。ここでは、長さ0以外の興味深い処理を行い、長さ0の単語を要求された場合は単一の空の文字列を返します。

(,/"RPS",/:\:f x-1)

「RPS」のデカルト積と、すべてのn-1の長さの正方形のない単語を取ります。、/:\:右の各要素を左に結合し、長さnの配列の長さ3の配列を提供します。、/これを長さ3nの配列に平坦化します。

{x@&~~/'(2,y)#/:x}

各文字列の最初のn文字を取得し、それを2番目のnと比較し、一致しない場合にのみ配列を縮小します。前の結果には平方がないことがわかっているため、最初の文字から始まる部分文字列のみが一致する必要があります-ここでのチェックを単純化することは、再帰の実装に費やされる文字の価値がありました。最後に、

/1_!x

左側の初期結果セットにラムダを適用し、1から(語長)-1までの各部分文字列の長さにわたって繰り返します。!xは0〜x-1のリストを生成し、1_は最初の要素を削除します(長さ0の部分文字列は常に一致するため)

いくつかの文字を犠牲にすることで、関数名に依存するのではなく、.zsを使用して自己参照することができ、長さn-1までの部分文字列をチェックする代わりに、floor(n / 2)のパフォーマンスのみをチェックします。7700kでは約120秒ですべての長さ49ワード(うち5207706)が検出されますが、それを超えると4GBの32ビットの空き領域kが制限されます。

{$[x;(,/"RPS",/:\:.z.s x-1){x@&~~/'(2,y)#/:x}/1+!_x%2;,""]}

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