シーケンス内で最も1が多いサブストリングを見つける


16

前書き

私はほとんどとサブ見つけたい1「の順にS 0、S」と1のを。

入力

プログラムには、シーケンスとサブストリングの長さの2つの入力があります。

シーケンスは、任意の数である0のと1の:

01001010101101111011101001010100010101101010101010101101101010010110110110

サブストリングの長さは任意の正の非ゼロの整数です。

5

出力

プログラムは、指定された長さの最初の部分文字列の開始インデックスを出力します1。上記の入力では、出力は次のとおりです。

10

文字列の最初の文字はのインデックスで始まり0ます。

得点

最短のコードが勝ちます!

ルール

  • プログラムは、有効な入力に対して常に正しいインデックスを出力する必要があります。
  • デフォルトのオプションで正のスコアを持つ回答から入力/出力方法を選択できます。回答で選択する方法を指定してください。

タイトルと紹介文には、「1が最も多い部分文字列を見つけてください」と書かれています。しかし、プログラムの説明では、部分文字列の長さを指定し、最初の部分文字列のインデックスを探していると書かれています。それで、タイトルと紹介が間違っていると仮定すべきですか?ほとんどの人は最初の部分を解決しているようです。誰が勝ちますか?
-swstephe

@swstephe私はあなたの混乱を理解しているかどうかわかりません。ほとんど1のに関連付けられた複数の部分文字列がある場合、最初に見つかった部分文字列を出力します。部分文字列は、その部分文字列の最初の文字のインデックスで識別します。それは役立ちますか?
hmatt1

さて、あなたは部分文字列のシーケンスを壊し、最初の部分文字列のインデックスを最も1で返していますか?1の部分文字列を探しているように聞こえました。
-swstephe

実行不可能な長さ、たとえばlength = 99を指定する場合、要件「指定された入力に対して常に正しいインデックスを常に出力する必要があります」が適用されますか?
-smci

有効な入力として想定できる@smci。部分文字列の長さがシーケンスよりも長い場合を処理する必要はありません。
hmatt1

回答:


11

Dyalog APL、11

(-∘1+⍳⌈/)+/

ここで試してみてください。使用法:

   f ← (-∘1+⍳⌈/)+/
   4 f 0 1 1 0 1 1 1 0 0 0 0 1 1
1

説明

これは、左から部分文字列の長さをとり、右からシーケンスをとる二項(バイナリを意味する)関数です。その構造は次のとおりです。

   ┌───┴────┐
 ┌─┴──┐     /
 ∘  ┌─┼─┐ ┌─┘
┌┴┐ + ⍳ / +  
- 1   ┌─┘    
      ⌈      

爆発による説明:

(-∘1+⍳⌈/)+/
(       )+/  ⍝ Take sums of substrings of given length, and feed to function in parentheses
    + ⌈/     ⍝ The array of sums itself, and its maximum
     ⍳       ⍝ First index of right argument in left
 -∘1         ⍝ Subtract 1 (APL arrays are 1-indexed)

例として、4および0 1 1 0 1 1 1 0入力としてみましょう。まず+/、それらに関数を適用して取得し2 3 3 3 3ます。次いで、+及び⌈/このアレイに適用自体与えると3、と2 3 3 3 3 ⍳ 3に評価2するので、3第一、第二の要素として生じます。減算して最終結果として1取得1します。


あなたの例では、長さは4ですが、行に4つの同じ項目がない(01101110)ので、何も出力しないのはなぜですか?
トーマスウェラー

しゅう チャレンジの例では、いずれかの行には5つの同じアイテムを持っていない、まだ出力がIタスクを解釈する方法は、私が有する所定の長さのサブストリングの最初のインデックスを見つける必要があることである10であるmもの、mであるが最大。
ズガーブ

10

ルビー、42

f=->s,n{(0..s.size).max_by{|i|s[i,n].sum}}

呼び出して入力を取得します。例えば

f['01001010101101111011101001010100010101101010101010101101101010010110110110',5]

これは、合計ASCII値を使用して部分文字列を比較し、最大のインデックスを返します。max_byRubyの仕様で安定する必要があるかどうかはわかりませんが、C実装にあるようです。


6

Python 2、56

lambda s,l:max(range(len(s)),key=lambda i:sum(s[i:i+l]))

整数の配列、次に長さを受け入れます。


これは、文字列で始まる場合ので、あなたがする必要がある、入力として整数の配列を必要とします:[int(s) for s in "010010...0"]
SMCI

バグ:(f(ss, 999)なしの代わりに)0を返します。直せますか?これはおそらくルール1に違反しています。
smci

@smciあなたが何を言っているのか分かりません。変数の内容を知るにはどうすればよいですssか?None答えが整数であるため、どのような場合でも望ましい出力ではありません。
-feersum

5

バッチ-222

バッチは明らかにこの種の操作に最適な言語です。

@echo off&setLocal enableDelayedExpansion&set s=%1&set l=-%2
:c
if defined s set/Al+=1&set "s=%s:~1%"&goto c
set s=%1&set x=0&for /l %%a in (0,1,%l%)do set c=!s:~%%a,%2!&set c=!c:0=!&if !c! GTR !x! set x=!c!&set y=%%a
echo !y!

ゴルフなし/解剖:

初期セットアップ。変数sは入力文字列でありl、入力文字列の長さからサブ文字列の長さ(マイナス%2で初期化され%2、指定されたサブ文字列の長さ)になります。

@echo off
setLocal enableDelayedExpansion
set s=%1
set l=-%2

l純粋なバッチ文字列の長さのソリューションを使用して、入力の長さをとして取得します。これによりs、入力文字列を含む変数が破損するため、再度設定します。

:c
if defined s (
    set /A l += 1
    set "s=%s:~1%"
    goto c
)
set s=%1

の値は、xどの部分文字列の最大数が1であるかを確認するために使用されます。0から文字列の長さからサブ文字列の長さ(変数l)を引いたループを開始します。ループ内の現在のポイント(%%a)から始まる部分文字列を取得します。これcは、入力文字列として設定され、(指定された部分文字列の長さ)文字%%aを取得し%2ます。からすべて0のsが削除されc、の値cが比較されますx-つまり111、より大きい値である11ため、 'string'を使用して比較よりも大きいことができます。y次に、文字列内の現在の位置に設定されます-最終的に出力されます。

set x=0
for /l %%a in (0, 1, %l%) do (
    set c=!s:~%%a,%2!
    set c=!c:0=!
    if !c! GTR !x! (
        set x=!c!
        set y=%%a
    )
)
echo !y!

OPの使用例-

h:\>sub1.bat 01001010101101111011101001010100010101101010101010101101101010010110110110 5
10

5

C#(正規表現)、196

class Test{static void Main(string[]a){System.Console.Write(System.Text.RegularExpressions.Regex.Match(a[1],"(?=((?<o>1)|0){"+a[0]+"})(?!.+(?=[10]{"+a[0]+"})(?!((?<-o>1)|0){"+a[0]+"}))").Index);}}

実際の正規表現はそれほど長くはありませんが、C#プログラムが2倍のサイズのコードをコンパイルするために必要なすべての毛羽立っています。

長さを5に設定する実際の正規表現:

(?=((?<o>1)|0){5})(?!.+(?=[10]{5})(?!((?<-o>1)|0){5}))
  • (?=((?<o>1)|0){5}):消費せずに5文字を先読みし、すべて1の文字を "stack"にプッシュしますo
  • (?=[10]{5})(?!((?<-o>1)|0){5}):5文字先の位置では、「スタック」oに飛び出すのに十分なアイテムがありません。つまり、部分文字列は1現在の位置にあるものよりも厳密に多くあります。
  • (?!.+(?=[10]{5})(?!((?<-o>1)|0){5})):上記のような位置は、文字列の残りの部分では見つかりません。つまり、すべての位置はの数以下です1

最初の結果を取得すると答えが得られます。なぜなら、その前のすべての部分文字列には、さらに1' が続く部分文字列があり、現在のインデックスよりも大きいインデックスの数が1' 以下であることが確認されているからです。

(そして、私は何か良いことを学びます:バックスタックで「スタック」が復元されます)。


1
非常にクールな、正規表現でこれを行うことができるとは思いませんでした。
-histocrat

4

パイス、12

Mho/<>GNHZUG

これは、g入力として数値のリストと数値を必要とする関数を定義します。例えば

Mho/<>GNHZUGg[0 1 0 0 1 0 1 0 1 0 1 1 0 1 1 1 1 0 1 1 1 0 1 0 0 1 0 1 0 1 0 0 0 1 0 1 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 0 1 1 0 1 0 1 0 0 1 0 1 1 0 1 1 0 1 1 0)5

ここでテストできます:Pyth Compiler / Executor

説明:

Mho/<>GNHZUG
M             defines a function g(G,H), G is the sequence, H the sequence length
  o       UG  orders the numbers between 0 and len(G)-1 according to the following key
    <>GNH     take the subsequence G[N:N+5]
   /     Z    count the zeros in this subsequence (this is the key)
 h            return the first value of the sorted list (minimum)

代替案:

Mho_s<>GNHUG

値の文字列(01001 ...)を受け取るプログラムを使用して同じ長さの答えを得ることができます。ho/<>zNQ\0Uz悲しいことに、文字列をカウントしても、探しているものが文字列に自動変換されません:(
FryAmTheEggman

4

J、15 14文字

   ([:(i.>./)+/\)

   5 ([:(i.>./)+/\) 0 1 0 0 1 0 1 0 1 0 1 1 0 1 1 1 1 0 1 1 1 0 1 0 0 1 0 1 0 1 0 0 0 1 0 1 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 0 1 1 0 1 0 1 0 0 1 0 1 1 0 1 1 0 1 1 0
10

実際の言語がコードゴルフ用に特別に作られた言語を打ち負かしたとき、私はそれが面白いと思います。Kエントリが食べられたか、投稿されたはずですが、とにかく20文字になりました。
JasonN

4

Matlab(42)

s文字列とn部分文字列の長さを示しましょう。結果はrです。

s1のシーケンスでの畳み込みを計算しn、最大値を見つけます。畳み込みはを使用して簡単に実行できconvmax関数は最初の最大値の位置を返します。1Matlabのインデックス作成はからで1はなくから始まるため、結果のインデックスを減算する必要があり0ます。

[~, r] = max(conv(s, ones(1,n), 'valid'));
r = r-1;

ゴルフ:

[~,r]=max(conv(s,ones(1,n),'valid'));r=r-1

4

Haskell、64 62バイト

n#l=0-(snd$maximum[(sum$take n$drop x l,-x)|x<-[0..length l]])

使用法:

5#[0,1,0,0,1,0,1,0,1,0,1,1,0,1,1,1,1,0,1,1,1,0,1,0,0,1,0,1,0,1,0,0,0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,1,0,1,0,1,0,0,1,0,1,1,0,1,1,0,1,1,0]

中置関数を定義することで2バイトを節約できますn#l=...
。– Zgarb

には中置関数を使用できますp。また、私0は(カッコはそうではありませんが、それの代わりにスペースが必要かもしれませんが)冗長であると思います0
誇りに思ってhaskeller

3

JavaScript(ES6)73

要求された値を返す関数。forループは、現在の合計を維持しながら入力文字列をスキャンし、最大値の位置を保存します。

F=(a,n)=>(x=>{for(r=t=i=x;a[i];t>x&&(x=t,r=i-n))t+=a[i]-~~a[i++-n]})(0)|r

非ゴルフ

F=(a, n) => {
   for(x = r = t = i = 0; a[i]; i++)
     t += a[i] - ~~a[i-n], // ~~ convert undefined values (at negative index) to 0
     t > x && (x=t, r=i-n+1);
   return r;
}

FireFox / FireBugコンソールでテストする

F("01001010101101111011101001010100010101101010101010101101101010010110110110",5)

出力 10


コードを削減するために、変数xとを定義する必要はありませんr。これにより、4バイトが削減され、最終的な長さは69バイトになります。また、あなたはおそらく、交換することができるかもしれない&&&。しかし、~~トリックのある素敵なものです!
イスマエルミゲル

@IsmaelMiguelあなたはxを初期化する必要があり、そうでなければ最初にエラーが発生しt > xます。rを初期化する必要があります:try F("00000")。そして、エミュレートするには&&が必要です。if
edc6515年

あなたは完全に正しいです。がより小さいか等しい(x=t, r=i-n+1)場合tに無視することを期待していることに気づきませんでしたx。それは遅延評価の良い使い方です!どこかで切り落とせたらいいのにと思いますが、あなたはすべての仕事をしたと思います。
イスマエルミゲル

3

PHP(96)

for($a=$b=$c=0;(($d=@substr_count($s,1,$a,$n))>$c&&($b=$a)&&($c=$d))||$a++<strlen($s););echo $b;

http://3v4l.org/J4vqa

変数$s$nは、それぞれコマンド文字列と検索文字列の長さに対して定義する必要があります。

これは、substr_count()およびに適切な機能を備えたC言語のような言語でも動作しますstrlen()


3

Mathematica、38 36

f=#-1&@@Ordering[-MovingAverage@##]&

例:

f[{0,1,0,0,1,0,1,0,1,0,1,1,0,1,1,1,1,0,1,1,1,0,1,0,0,1,0,1,0,1,0,0,0,1,0,1,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,1,0,1,0,1,0,0,1,0,1,1,0,1,1,0,1,1,0},5]

出力:

10


2

C#(Linq)、148バイト

using System.Linq;class C{int F(string s,int l){return s.IndexOf(s.Skip(l-1).Select((c,i)=>s.Substring(i,l)).OrderBy(p=>-p.Sum(c=>c)).First());}}

フォーマット済み:

using System.Linq;

class C
{
    int F(string s, int l)
    {
        return s.IndexOf(
            s
                .Skip(l - 1)
                .Select((c, i) => s.Substring(i, l))
                .OrderBy(p => -p.Sum(c => c))
                .First()
        );
    }
}

メソッドのパラメーターとして入力を受け取ります。

それが何をする:

string result = s // string is also char collection
    .Skip(l - 1) // make it collection shorter by l-1
    .Select((c, i) => s.Substring(i, l)) // so we can iterate, and select all substrings
    .OrderBy(p => -p.Sum(c => c)) // order substrings descending by sum of characters
    .First() // take first (most ones)

return s.IndexOf(result); // find index of result string

2

Scala-70バイト

readLine.sliding(readInt).zipWithIndex.maxBy(x=>x._1.count(_=='1'))._2

しかし、zipWithIndexの関数名では、Scalaはコードゴルフに最適な選択肢ではないと思います。


2

C、245 185

#include <stdio.h>
main(int argc,char **argv){char *p,*q;int i,s,m=0;for(p=argv[1];*p;p++){for(s=0,q=p;q-p<atoi(argv[2])&&*q;q++)s+=*q-'0';if(s>m){m=s;i=p-argv[1];}}printf("%d\n", i);}

フォーマット済み:

#include <stdio.h>
main(int argc, char **argv) {
        char *p, *q;
        int i, s, m = 0;
        for (p = argv[1]; *p; p++) {
                for (s = 0, q = p; q - p < atoi(argv[2]) && *q; q++)
                        s += *q - '0';
                if (s > m) {
                        m = s;
                        i = p - argv[1];
                }
        }
        printf("%d\n", i);
}

使用法:

$ ./m1s 01001010101101111011101001010100010101101010101010101101101010010110110110 5
10

1

CJam、25 21バイト

q~_,,{1$>2$<:+~}$(]W=

ここでテストしてください。

部分文字列の長さの整数として入力を受け取り、シーケンスとしてゼロと1の配列を受け取ります。

5 
[0 1 0 0 1 0 1 0 1 0 1 1 0 1 1 1 1 0 1 1 1 0 1 0 0 1 0 1 0 1 0 0 0 1 0 1 0 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 1 0 1 1 0 1 0 1 0 0 1 0 1 1 0 1 1 0 1 1 0]

説明

q~_,,{1$>2$<:+~}$(p];
q~                    "Read and evaluate the input.";
  _,                  "Duplicate the sequence and get its length N.";
    ,                 "Get an array [0 1 ... N-1].";
     {         }$     "Sort this array stably by the result of the given block.";
      1$              "Copy the sequence.";
        >             "Slice off the first i bits.";
         2$           "Copy the substring length.";
           <          "Truncate the sequence.";
            :+        "Get the sum to find the number of 1s.":
              ~       "Bitwise complement in order to sort from highest to lowest.";
                 (    "Shift off the first index from the sorted list.";
                  ]   "Wrap the entire stack in an array.";
                   W= "Extract the last element (the result), discarding the rest.";

結果はプログラムの最後に自動的に印刷されます。

必要な部分文字列の長さよりも端に近いところから始まるスライスも検討していることに注意してください。ただし、それらは最後の有効な部分文字列の部分文字列であり、したがって1最後の有効な部分文字列よりも多くのsを持たないため、大丈夫です。


1

Java 329バイト

.matches(regex)を実装するつもりでしたが、上記のPythonソリューションとほぼ同じだったので、代わりにスライディングウィンドウを試しました。ここで新しいので、誰かが何かポインタを持っている場合、それらを聞いて喜んでいます。

public class ssMostOnes{
public static void main(String[] a){
    int b=0,w=0;
    for(int i=0;i<a[0].length()-Integer.valueOf(a[1]);i++){
        int c=a[0].substring(i,i+Integer.valueOf(a[1])).length() - a[0].substring(i,i+Integer.valueOf(a[1])).replace("1","").length();
        if(c>w){w=c;b=i;}
    }
    System.out.println(b);
}

}


いくつかのヒント:i3行目で初期化できます。空白のほとんどは削除できます。使用しますSystem.out.print((改行は不要です)。代わりにInteger.valueOf(、を使用できますnew Integer(
Ypnypn
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.