Suchen Sie den Teilstring mit den meisten Einsen in einer Sequenz

16

Einführung

Ich möchte den Teilstring mit den meisten 1in einer Folge von 0's und 1' s finden.

Eingang

Ihr Programm hat zwei Eingänge , die Sequenz und die Länge des Teilstrings.

Die Reihenfolge ist eine beliebige Anzahl von 0's und 1' s:

01001010101101111011101001010100010101101010101010101101101010010110110110

Die Länge der Teilzeichenfolge ist eine positive Ganzzahl ungleich Null:

5

Ausgabe

Ihr Programm sollte den Startindex des ersten Teilstrings der angegebenen Länge ausgeben, der die meisten enthält 1. Mit der obigen Eingabe ist die Ausgabe:

10

Das erste Zeichen in der Zeichenfolge beginnt bei einem Index von 0.

Wertung

Kürzester Code gewinnt!

Regeln

  • Ihr Programm muss immer den richtigen Index für alle gültigen Eingaben ausgeben.
  • Sie können Ihre Eingabe- / Ausgabemethode aus jeder Antwort mit positiver Punktzahl für die Standardoptionen auswählen . Bitte geben Sie die Methode an, die Sie in Ihrer Antwort auswählen.
hmatt1
quelle
In Ihrem Titel und Ihrer Einführung steht "Finde den Teilstring mit den meisten Einsen". Ihre Programmbeschreibung besagt jedoch, dass Sie eine Teilzeichenfolgenlänge angeben und nach dem Index der ersten Teilzeichenfolge suchen. Sollen wir also davon ausgehen, dass Titel und Einleitung falsch sind? Die meisten Leute scheinen den ersten Teil zu lösen. Wer gewinnt?
Swstephe
@swstephe Ich bin mir nicht sicher, ob ich deine Verwirrung verstehe. Wenn mehr als eine Teilzeichenfolge für die meisten verknüpft ist 1, geben Sie die erste Teilzeichenfolge aus, die Sie gefunden haben. Sie identifizieren die Teilzeichenfolgen mit dem Index des ersten Zeichens in dieser Teilzeichenfolge. Hilft das?
hmatt1
Okay, Sie brechen also die Sequenz in Teilzeichenfolgen auf und geben den Index der ersten Teilzeichenfolge mit den meisten Einsen zurück? Es hörte sich an, als ob Sie nach Teilzeichenfolgen von 1 gesucht hätten.
Swstephe
Gilt die Anforderung "muss für alle Eingaben immer den richtigen Index ausgeben" weiterhin, wenn wir unmögliche Längen angeben, z. B. Länge = 99?
smci
@smci können Sie für eine gültige Eingabe annehmen. Sie müssen keinen Fall behandeln, in dem die Länge der Teilzeichenfolge länger als die Sequenz ist.
hmatt1

Antworten:

11

Dyalog APL, 11

(-∘1+⍳⌈/)+/

Probieren Sie es hier aus. Verwendung:

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

Erläuterung

Dies ist eine dyadische (dh binäre) Funktion, die die Länge der Teilzeichenfolge von links und die Reihenfolge von rechts angibt. Ihre Struktur ist wie folgt:

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

Erklärung durch Explosion:

(-∘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)

Nehmen wir als Beispiel 4und 0 1 1 0 1 1 1 0als Eingaben. Zuerst wenden wir die Funktion +/auf sie an und erhalten 2 3 3 3 3. Dann, +und ⌈/auf dieses Array angewendet, geben Sie sich und 3, und wird 2 3 3 3 3 ⍳ 3ausgewertet 2, da 3zuerst als zweites Element auftritt. Wir subtrahieren 1und erhalten 1als Endergebnis.

Zgarb
quelle
In Ihrem Beispiel ist die Länge 4, aber es gibt keine 4 gleichen Elemente in einer Reihe (01101110). Warum wird also überhaupt etwas ausgegeben?
Thomas Weller
@ThomasW. Das Beispiel in der Challenge hat keine 5 gleichen Elemente in einer Reihe, und dennoch ist die Ausgabe 10. Die Art und Weise, wie ich die Aufgabe interpretiere, ist, dass ich den ersten Index eines Teilstrings der angegebenen Länge finden muss, der mEinsen hat, wo sich mbefindet maximal.
Zgarb
10

Rubin, 42

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

Übernimmt Eingaben durch Aufruf, z

f['01001010101101111011101001010100010101101010101010101101101010010110110110',5]

Dadurch werden Teilzeichenfolgen mit ihrem gesamten ASCII-Wert verglichen und der Index des Maximums zurückgegeben. Ich bin mir nicht sicher, ob max_bydie Ruby-Spezifikation stabil sein muss, aber es scheint, dass sie in der C-Implementierung enthalten ist.

Histokrat
quelle
6

Python 2, 56

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

Akzeptiert ein Array von ganzen Zahlen und dann die Länge.

Feersum
quelle
Dies erfordert ein Array von Ganzzahlen als Eingabe. Wenn Sie also mit einer Zeichenfolge beginnen, müssen Sie [int(s) for s in "010010...0"]
Folgendes
Bug: f(ss, 999)Gibt 0 zurück (anstelle von None). Können Sie das beheben? Dies verstößt
möglicherweise
@smci Ich habe keine Ahnung, wovon du sprichst. Wie soll ich wissen, was in der Variablen ist ss? Noneist in keinem Fall eine gewünschte Ausgabe, da die Antwort eine ganze Zahl ist.
Feersum
5

Charge - 222

Batch ist offensichtlich die perfekte Sprache für diese Art von Operation.

@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!

Nicht golfen / seziert:

Ersteinrichtung. Die Variable sist die Eingabezeichenfolge, und lwird die Länge des Eingabestrings, minus der Teilstringlänge sein (initialisiert auf negativ , %2wo %2die gegebene Teilstringlänge).

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

Ermitteln Sie die Länge der Eingabe wie lfolgt: Verwenden Sie eine reine Batch-String-Längenlösung. Dadurch wird die Variable, sdie den Eingabe-String enthält, unkenntlich gemacht und anschließend erneut festgelegt.

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

Der Wert von xwird verwendet, um zu überprüfen, welcher Teilstring die größte Anzahl von Einsen hatte. Starten Sie eine Schleife von 0 bis zur Länge der Zeichenfolge abzüglich der Länge der Unterzeichenfolge (variabel l). Ruft die Unterzeichenfolge ab dem aktuellen Punkt in der Schleife ( %%a) ab, cwird als Eingabezeichenfolge festgelegt %%a, die mit %2(der angegebenen Länge der Unterzeichenfolge) beginnt und Zeichen annimmt. Werden alle 0s aus entfernt c, wird der Wert von cmit verglichen x- dh 111ist eine größere Zahl als, 11so können wir einfach die 'Zeichenfolge' verwenden, um einen Größer-als-Vergleich durchzuführen. ywird dann auf die aktuelle Position in der Zeichenfolge gesetzt - die schließlich ausgegeben wird.

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!

Beispiel für die Verwendung von OPs -

h:\>sub1.bat 01001010101101111011101001010100010101101010101010101101101010010110110110 5
10
unclemeat
quelle
5

C # (Regex), 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);}}

Der eigentliche reguläre Ausdruck ist nicht so lang, aber alle für ein C # -Programm zum Kompilieren der doppelten Größe des Codes erforderlichen Flusen.

Der eigentliche reguläre Ausdruck, der die Länge auf 5 setzt:

(?=((?<o>1)|0){5})(?!.+(?=[10]{5})(?!((?<-o>1)|0){5}))
  • (?=((?<o>1)|0){5}): Sieh voraus, um 5 Zeichen zu lesen, ohne sie zu verbrauchen, und drücke alle 1in den Stapel o.
  • (?=[10]{5})(?!((?<-o>1)|0){5}): An einer Position, die 5 Zeichen voraus hat, ist nicht genügend Element im "Stapel" ozum Herausspringen vorhanden, dh die Teilzeichenfolge hat streng mehr 1als das, was wir an der aktuellen Position haben.
  • (?!.+(?=[10]{5})(?!((?<-o>1)|0){5})): Eine Position wie oben beschrieben kann für den Rest der Zeichenkette nicht gefunden werden, dh alle Positionen haben weniger als oder die gleiche Anzahl von 1's.

Wenn Sie das erste Ergebnis nehmen, erhalten Sie die Antwort, da allen Teilzeichenfolgen davor ein Teilzeichenfolge mit mehr 1vorangestellt ist und wir überprüfen, ob jeder Index, der größer als der aktuelle Index ist, weniger als oder gleich viele hat 1.

(Und ich lerne etwas Schönes: Der "Stack" wird beim Backtracking wiederhergestellt).

n̴̖̋h̴̖̋ã̷͉h̷̭̿d̷̰̀ĥ̷̳
quelle
1
Sehr cool, ich hätte nicht gedacht, dass du das mit einem Regex machen könntest.
Histokrat
4

Pyth , 12

Mho/<>GNHZUG

Dies definiert eine Funktion g, die eine Liste von Zahlen und eine Zahl als Eingabe benötigt. Z.B

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

Sie können es hier testen: Pyth Compiler / Executor

Erläuterung:

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)

Alternative:

Mho_s<>GNHUG
Jakube
quelle
Sie können eine Antwort mit der gleichen Länge erhalten, indem Sie ein Programm verwenden, das eine Zeichenfolge von Werten (01001 ...) und dann die Zahl verwendet: ho/<>zNQ\0UzLeider konvertiert die Zählung einer Zeichenfolge nicht automatisch, wonach Sie suchen, in eine Zeichenfolge :(
FryAmTheEggman
4

J, 15 14 Zeichen

   ([:(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
randomra
quelle
Ich finde es interessant, wenn echte Sprachen Sprachen schlagen, die speziell für Codegolf entwickelt wurden. Mein K-Eintrag wurde gegessen oder ich hätte ihn gepostet, aber es kamen trotzdem 20 Zeichen.
JasonN
4

Matlab (42)

Lassen Sie sdie Zeichenfolge bezeichnen und ndie Teillänge. Das Ergebnis ist r.

Berechne die Faltung von smit einer Folge von nEinsen und finde dann das Maximum. Faltung ist einfach mit conv, und die maxFunktion gibt die Position des ersten Maximums zurück. Es ist notwendig, 1den resultierenden Index zu subtrahieren , da die Matlab-Indizierung bei beginnt 1, nicht bei 0.

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

Golf gespielt:

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

Haskell, 64 62 Bytes

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

Verwendung:

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]
nimi
quelle
Sie können 2 Bytes sparen, indem Sie eine Infix-Funktion definieren:n#l=...
Zgarb
Sie könnten eine Infix-Funktion für verwenden p. Ich denke auch, dass das 0überflüssig ist (obwohl die Klammern das nicht sind und Sie stattdessen möglicherweise ein Leerzeichen benötigen 0).
stolzer Haskeller
3

JavaScript (ES6) 73

Eine Funktion, die den angeforderten Wert zurückgibt. Die for-Schleife durchsucht die Eingabezeichenfolge unter Beibehaltung einer laufenden Summe und speichert die Position des Maximalwerts.

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

Ungolfed

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;
}

Test In FireFox / Firebug - Konsole

F("01001010101101111011101001010100010101101010101010101101101010010110110110",5)

Ausgabe 10

edc65
quelle
Um Ihren Code zu reduzieren, müssen Sie die Variablen xund nicht definieren r. Dies sollte 4 Bytes reduzieren, was der endgültigen Länge von 69 Bytes entspricht. Auch könnten Sie wahrscheinlich in der Lage sein , zu ersetzen &&mit &. Aber schön mit dem ~~Trick!
Ismael Miguel
@IsmaelMiguel du musst x initialisieren, sonst Fehler zuerst t > x. Sie müssen r: try einleiten F("00000"). Und && wird benötigt, um und zu emulierenif
edc65
Du hast vollkommen recht. Ich habe nicht bemerkt, dass Sie damit gerechnet haben, dass es ignoriert wird, (x=t, r=i-n+1)wenn tes kleiner oder gleich ist x. Das ist eine gute Verwendung von Lazy Evaluation! Ich wünschte, es könnte irgendwo abgehackt werden, aber ich denke, Sie haben die ganze Arbeit erledigt.
Ismael Miguel
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

Variablen $sund $nsollten in der Befehlszeile für die Suchzeichenfolge bzw. die Länge der Teilzeichenfolge definiert werden.

Dies würde auch in jeder C-ähnlichen Sprache mit entsprechenden Funktionen für substr_count()und funktionieren strlen().

Stephen
quelle
3

Mathematica, 38, 36

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

Beispiel:

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]

Ausgabe:

10

Alephalpha
quelle
2

C # (Linq), 148 Bytes

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());}}

Formatiert:

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()
        );
    }
}

Nimmt Eingaben als Methodenparameter entgegen.

Was es macht:

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
Krzysztof
quelle
2

Scala - 70 Bytes

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

Aber mit Funktionsnamen, solange zipWithIndex vorhanden ist, ist Scala wohl nicht die beste Wahl für Code-Golf.

Dominik Müller
quelle
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);}

Formatiert:

#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);
}

Verwendung:

$ ./m1s 01001010101101111011101001010100010101101010101010101101101010010110110110 5
10
Ari Malinen
quelle
1

CJam, 25 21 Bytes

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

Teste es hier.

Nimmt die Eingabe als Ganzzahl für die Länge der Teilzeichenfolge und ein Array von Nullen und Einsen als Folge:

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]

Erläuterung

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.";

Das Ergebnis wird am Ende des Programms automatisch ausgedruckt.

Beachten Sie, dass ich auch Slices in Betracht ziehe, die näher am Ende als die gewünschte Länge der Teilzeichenfolge beginnen, aber das ist in Ordnung, da es sich um Teilzeichenfolgen der letzten gültigen Teilzeichenfolge handelt und daher niemals mehr 1s als diese letzte gültige Teilzeichenfolge hat.

Martin Ender
quelle
1

Java 329 Bytes

Ich wollte ein .matches (Regex) implementieren, aber es wäre fast identisch mit den obigen Python-Lösungen gewesen, also habe ich stattdessen ein Schiebefenster ausprobiert. neu hier, also wenn jemand irgendwelche hinweise hat, sei froh, sie zu hören.

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);
}

}

Bryan Devaney
quelle
Einige Tipps: Sie können iin der dritten Zeile initialisieren . Der Großteil des Leerzeichens kann entfernt werden. Verwenden Sie System.out.print((kein Zeilenvorschub erforderlich). Stattdessen Integer.valueOf(können Sie verwenden new Integer(.
Ypnypn