文字列内で最大の連続する素数を見つける


8

公平に言えば、これはStackExchangeの質問に基づいていますが、良い質問です。

挑戦はかなり簡単です:

  1. 一連の数字を取る
  2. 文字列内の最大の連続する素数を見つけて出力します

得点:

  • 最も少ない数のキャラクターが勝利します。
  • ビクターはゴルフスクリプトのエントリーになる可能性がありますが、私たちはそれに対してそれを保持することはありません。
  • 私が実際に緑色のボタンをチェックしていないことに気付いたときに、当選者に授与されます。

仮定:

  • 文字列は数字のみです
    • 文字列に文字が含まれている場合、動作が未定義である可能性があります
  • 文字列に少なくとも1つの素数が含まれています
    • 文字列に1つの有効な素数が含まれていない場合、動作が未定義である可能性があります
  • 速度は制約ではありません
    • 高速なアルゴリズムよりも短い素数アルゴリズムを使用します。
    • エントリが最終的に終了する場合、それは問題ありません。宇宙の熱死の前にそれが証明可能であることを確認してください。
  • 文字列の長さは15文字未満と想定できます

例えば:

>> Input:  3571
<< Output: 3571

>> Input:  123
<< Output: 23

>> Input:  1236503
<< Output: 236503

>> Input:  46462
<< Output:  2

>> Input:  4684
<< Output: ValueError: max() arg is an empty sequence

>> Input:  460
<< Output: 0   # Note, zero is not a prime, but the above string has no valid prime

>> Input:  4601
<< Output: 601

>> Input:  "12 monkeys is a pretty good movie, but not as good as se7en"
<< Output: ValueError: Fight Club was also good, I find Brad Pitt to be a consistantly good actor.

可能な実装:

  1. 入力のすべての部分文字列を検索し、それらが素数であるかどうかを確認します。- Legostormtroopr(オリジナル)
  2. 入力より小さいすべての整数を見つけ、それらが入力にあるかどうかを確認し、それが素数かどうかを確認します-Ben Reich
  3. 入力よりも小さいすべての素数のリストを取り、それが入力にあるかどうかを確認します-daniero

1
これは基本的には次のようです。文字列の各部分文字列を反復処理する方法を見つけ、部分文字列の素数を確認します。楽しい問題のように聞こえます。
ジャスティン

1
@Quincunx正解。しかし、できるだけ明確にしたかったのです。また、ポップカルチャーの参照も削除します。

1
@Quincunxただし、可能なアルゴリズムはこれだけではありません。次のように記述できる私の答えを確認してください。入力よりも小さいすべての整数を反復処理し、入力の部分文字列でありかつ素数である最大のものを決定します。
ベン・ライヒ

@BenReichまたは私が行ったように、入力以下のすべての素数を反復処理し、それらが文字列内にあることを確認します。
daniero 2014年

1
なぜ私は平等な競技場を気にするのですか?勝つスクリプトはわかっていますが、勝つことがすべてではありませんか?あなたの好きな言語でできる限り短くて賢いコードを作成してください。

回答:


6

GolfScript 40 37

.{`\`?)}+\~),\,{.,(;\{\%!}+,,1=},)\;

これは、入力以下のすべての数値を調べ、入力の部分文字列である数値までフィルタリングしてから、さらに素数までフィルタリングします。次に、そのような要素の中で最も大きいものを使用します(これは、明らかに最も多くの桁を持つことが保証されています)。

それを2つの主要なセクションに分けましょう:

.{`\`?)}+\~,\,

コードのこの部分は、入力に含まれるすべての整数文字列にフィルターをかけます。アクサングラーブを使用して、数値を文字列に変換し?、部分文字列のインデックスを決定します。以降?戻り-1用いない封じ込めの場合には、インクリメント)出力されるように0してうまく動作します非サブストリングのための,フィルタリング。

{.,(;\{\%!}+,,1=},

コードのこの部分は、与えられた数より少ない因数の数を数えることにより素数までフィルタリングします(整数number factor %!は1の場合のみ因数になります)素数はそれ自身よりも厳密に1だけ小さい因数を持つため、そうします1=

番号が正しいので、最後の番号を取り、スタックをクリアしてください )\;

これは明らかに効率的ではありませんが(入力よりも小さいすべての整数に対していくらか不必要に反復するため)、それでも1236503私のコンピューターでは比較的高速(1分)のような大きな入力で終了します。


1
あなたのおかげで、私はあなたが使ったのと同じくらい多くの答えを剃った:P

1
入力が素数の場合、最初のフィルターはそれを含むがそれを含まない数値に適用されるため、これはそれを見つけられません。修正には1文字かかりますが、ブロックと連結するのではなく、変数に入力を格納することで保存される文字が2つあります(その方法でフリップをいくつか削除するため)。
Peter Taylor

4

Python 2.7〜84

これは、ビートのリファレンス実装です。質問の出力例に使用したので、動作することが保証されています * 実際の保証ではありません

Ben Reichに基づく恥知らずな改善は、私の元の解決策よりもはるかに優れています。ボラティリティからの大きな支援を得て

N=input()
print max(x for x in range(N+1)if(`x`in`N`)&all(x%i for i in range(2,x)))

2行目の以前の呪文は次のとおりです。

print max(x for x in range(N+1)if`x`in`N`and 0 not in(x%i for i in range(2,x)))
print max(x for x in range(N+1)if`x`in`N`and sum(x%i<1 for i in range(2,x))<1)

元のバージョン-143

N=`input()`
p=lambda n:[n%i for i in range(2,n)if n%i==0]
print max(int(N[j:i])for i in range(len(N)+1)for j in range(i)if not p(int(N[j:i])))

2
取り除いpて置き換えnot p(x)てくださいsum(x%i for i in range(2,x))<1-それはうまくいくはずで、86文字まで下がります。
ボラティリティ2014年

@ボラティリティかなりないですが、sum(x%i for i in range(2,x))ほとんどの数値ではかなり高くなります。しかし、発電機は素晴らしいアイディアだと私は91にそれを得た

実は、あなたは何を知っているでしょう、all(x%i for i in range(2,x))代わりに使うことができると思います。
ボラティリティ2014年

もう1つ

に切り替えてall(`x`in`N`)さらにいくつかを節約します!

1

ルビー61

Nまでのすべての素数を取り、それらが文字列内にあるかどうかを確認します

require'prime'
p Prime.each(gets.to_i).select{|i|~/#{i}/}.max

これはRuby 1.9以降でのみ機能すると思いますが、よくわかりません。


最後のテスト例でプログラムは何を返しますか?素数の2が含まれていますが、認識されるべきではありません(要件を正しく理解している場合)。
DavidC 2014年

1
@DavidCarraher:前提条件:文字列は数値のみです。文字列に文字が含まれている場合、未定義の動作が発生する可能性があります。「未定義の動作」とは、2を吐き出す、ドロドロを吐き出す可能性があることを意味すると思います
Kyle Kanos

カイル、とても良い観察!
DavidC 2014年

1

Scala(83文字)

プログラムに入力を提供する方法がわからなかったのでn、入力であると考えました。これが実際の解です(これに基づいて解の長さが評価されます)。その下には、実行用のソリューションの実行形式(まだゴルフされていません)と出力(サンプルではOPが持っています)が一緒に実行されます。

解決:

n.inits.flatMap(_.tails.toList.init.map(BigInt(_))).filter(_ isProbablePrime 1).max

実行可能なソリューション:

object A {
  def main(x:Array[String])=List("3571","123","23","1236503","46462","4684","460","4601","12 monkeys..").foreach(e=>println(e+" => "+q(e)))

  private def p(n: String)=n.inits.flatMap(_.tails.toList.init.map(BigInt(_))).filter(_ isProbablePrime 1).max
  private def q(n: String)=try p(n)catch{case e=>e.toString}
}

出力例:

3571 => 3571
123 => 23
23 => 23
1236503 => 236503
46462 => 2
4684 => java.lang.UnsupportedOperationException: empty.max
460 => java.lang.UnsupportedOperationException: empty.max
4601 => 601
12 monkeys.. => java.lang.NumberFormatException: For input string: "12 "

説明:

手順は非常に簡単です。

入力->すべての部分文字列を検索->非素数をフィルター->最長の値を検索

  • main(Array[String]):メソッドはサンプル入力を提供しq(String)、各入力に対してメソッドを実行します
  • q(String):実際のプログラムロジックをラップしp(String)て、例外が適切に報告されるようにします。無効な入力はNumberFormatExceptions を取得するため、出力をより適切にフォーマットするのに役立ちます。素数がないと、UnsupportedOperationException
  • p(String):プログラムの実際のロジック。この説明をいくつかの部分に分けましょう
    • n.initsIterator文字列入力(n)を反復するを作成します
    • flatMap(f):に操作を適用しIterator、結果をにプッシュしますList
      • _.tails.toList.init.map(BigInt(_)):を分割し、結果からStringStringのを削除しますList。最後Stringに、BigIntをと同等のa に変換しjava.math.BigIntegerます。ゴルフの理由で、BigIntが選択されています(短い名前)。
    • filter(f):がf返された場合false、結果から値が削除されますList
      • _ isProbablePrime 1:この行は次のように書くことができます_.isProbablePrime(1)が、使用される表現は1バイトを節約します。この行は、値が素数かどうかを実際にチェックします(確率的に。certaintyがに設定されているため1、実行時間が長くなりますが、システムは数値が素数であることを(多かれ少なかれ)確認します。
    • max:最大値を検索します(Stringベースの長さではありません。実際の最大値)

1

J(24 22)

キーボードからの読み取りは、実際には関数を定義するよりも短くなります。

>./(*1&p:);".\.\1!:1[1

テスト:

   >./(*1&p:);".\.\1!:1[1
3571
3571
   >./(*1&p:);".\.\1!:1[1
46462
2
   >./(*1&p:);".\.\1!:1[1
1236503
236503
   >./(*1&p:);".\.\1!:1[1
4684
0
   >./(*1&p:);".\.\1!:1[1
4680
0
   >./(*1&p:);".\.\1!:1[1
twelve monkeys is a pretty good movie
__

説明:

  • 1!:1[1:キーボードから1行のテキストを読み取る
  • ".\.\:文字列の各プレフィックス()の".各サフィックス(\.)の評価()\
  • ;:マトリックスを平坦化
  • *1&p::各値に素数であるかどうかで乗算します(したがって、すべての非素数はゼロになります)
  • >./:リストの最大値を取得します

1

Haskell、94

main=getLine>>=print.maximum.filter(\x->and$map((0/=).mod x)[2..x-1]).map read.init.scanr(:)[]


3
Haskellを行わない人のために、この背後にあるプロセスを説明してくれませんか?

@LegoStormtrooprもちろん、試してみる。main = getLine >>= print . maximum . filter isPrime . map read . allNums元の形です。それは行を取得し、それを>>=大きな結合関数()に与えます- .中置演算子と結合され、演算子は単に右関数の結果を左関数に入れます。のようなもの(\x -> ...)はラムダ式です。関数パラメーターは括弧なしで適用され、関数は部分的に適用できます((0/=)たとえば、数値が0でないかどうかをチェックする関数です)。
Vektorweg 2014年

allNums = init . scanr (:) []scanrscansとinitは、scanerの結果の最後の値を削除します。これは、Integerに読み取ることができない空の文字列です。map read文字列のリストを宛先の値に読み取ります。この場合、整数またはIntegral型クラスからの何か、Integral isPrimeが必要なため。 filter isPrimeそれが言うことを正確に行います。isPrime x = and $ map ((0/=). mod x) [2..(x-1)]つまり、2から(x-1)までのリストが与えられた場合、分割チェックを行いand、ブールリストに適用します。
Vektorweg 2014年

他の標準モジュールには、より明確で強力な機能がいくつかありますが、Preludeモジュールのみを使用してみました。;)
Vektorweg 2014年

1

Perl 6(40文字、41バイト)

$_=get;say max grep &is-prime,+«m:ex/.+/

への最初のget入力$_。これにより、正規表現一致呼び出しが短くなります。:ex正規表現の完全一致を提供し、すべての可能性を提供します。ハイパーOP (または+<<あまりにも動作しますが)試合の数字を作るものはに渡され、オブジェクトgrep&is-primeセレクタとしてサブ。最後に、残りのリストの最大値を取得して出力します。


0

Mathematica 67 47

StringCases[#,a__/;PrimeQ@ToExpression@a]〚1〛&

説明

コードは純粋な関数です。名前はありません。その中で、#完全な入力文字列を表します。

StringCases入力#を受け取り、a素数である1文字以上のサブストリングをチェックします(そのため、_の代わりに__が使用されました)。PrimeQは、部分文字列に対してTrueを返す必要があります。

すべての有利なケース、つまり素数である部分文字列は、デフォルトでリストで返されます。 〚1〛、または[[1]]最初の部分、つまり素数のリストの最初の要素を取ります。element[[1]]はの省略形ですPart[element, 1]。複数の素数がある場合、最初のものは最長の素数になります(StringCases最長の部分文字列を最初にチェックします)。

StringCases[#,a__/;PrimeQ@ToExpression@a]〚1〛&["1236503"]

「236503」

StringCases[#,a__/;PrimeQ@ToExpression@a]〚1〛&/@ 
{"1236503", "123", "46462", "4684", "460", "4601", 
"12 monkeys is a pretty good movie, but not as good as se7en"}

{"236503"、 "23"、 "2"、{} [[1]]、{} [[1]]、 "601"、 "2"}


Mathematicaを行わない人のために、この背後にあるプロセスを説明してくれませんか?

1
私は〚1〛、非Mathematicaのプログラマーにとって、文字の使い方がサディスティックだったと言わざるを得ません。(私は必死に私はこの1つはない間、彼らは、シャープに見えることを混同して、他の括弧を見て、その後、ブラインドに行くんだと心配キュー!)
eithed

〚1〛二重括弧があり、と同等[[1]]です。二重括弧は1文字として数えるので使用しました。
DavidC 2014年

@David Carraherええ、でも私はそれを2バイトとして数える必要があると思います。
マイケル・スターン

しかし、バイトではなく文字をカウントしています。説明してください。
DavidC 2014年

0

Perl 6(50文字、51バイト)

say max +«get.match(/(.+)<?{(+$0).is-prime}>/,:ex)

文字列を数値にマップしmax、最大の数値を取得しget、線を受け取ります。/(.+)<?{(+$0).is-prime}>/すべての素数を取得する正規表現<?{}>はコードアサーションです。is-primeあるInt数が素数であるかどうかを確認するクラスメソッドは。デフォルト+であるので、を使用して値を数値にキャストする必要がありStrます。すべての一致(他と重複するものを含む):exを見つけようとすることを意味します。Rakudo Perlのバグのため、現在、ここでは使用できません。m//

これは任意の数値で機能し、削除するmax(またはで置き換えるsort)と、数値のすべての素数のリストが表示され、追加のボーナスが得られます(ポイントなどは得られません)。たとえば(sortこの場合は):

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