Finden Sie Bereiche von wahren Werten in einer Liste


26

Herausforderung:

Schreiben Sie eine Funktion oder ein Programm, das eine Liste von Booleschen Werten akzeptiert und alle Bereiche von True zurückgibt.

Testfälle:

f [F]                               = []
f [T]                               = [[0,0]]
f [T,T,F,T]                         = [[0,1],[3,3]]
f [F,T,T,F,F,T,T,T]                 = [[1,2],[5,7]]
f [F,T,T,F,F,F,T,T,T,T]             = [[1,2],[6,9]]
f [T,T,F,F,F,T,T,T,T,T,T,T,T,T,T,F] = [[0,1],[5,14]]
f [F,F,T,T,F,F,F,F,F,F,F,F,T,T,T,T,T,T,T,T,F,F,F,F,F,F,F,F,F,F,F,F,F,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,T,T] = [[2,3],[12,19],[33,54],[93,94]]

Regeln:

  • Sie können auswählen, wie die Eingabe codiert werden soll, z. B. eine Liste, ein Array, eine Zeichenfolge usw.
  • Die Ausgabe muss in Form einer Liste oder einer Zeichenfolge codiert werden, die eine Liste enthält, also in Form von Arrays, Listen, Tupeln, Matrizen, Vektoren usw.
  • Die Booleschen Werte müssen als Konstanten codiert werden, ansonsten ist jede einfache Konvertierung von T / F in gewünschte Konstanten zulässig
  • EDIT: eval oder ähnliches zur Laufzeit ist erlaubt.
  • Vergessen Sie nicht zu erklären, wie die Eingabe an das Programm / die Funktion übergeben wird, und geben Sie die Eingabe / Ausgabe für die Testfälle an
  • Konvertierung in gewünschtes Eingabeformat nicht mitgezählt
  • Standardlücken sind nicht zulässig
  • Wenn Ihre Sprache dazu eine Funktion hat, ist dies nicht zulässig
  • Ich werde meine eigene Vorlage nicht akzeptieren
  • EDIT: Ausgabeformat ist flexibel. Wenn Sie keine Liste oder Ähnliches drucken, müssen die Bereichswerte durch ein nicht numerisches Zeichen und separate Bereiche getrennt werden.

Wertung:

  • Die Bewertung erfolgt in Bytes, sofern dies nicht für Ihre Sprache ungeeignet ist (z. B. Codels in Piet).
  • Die niedrigste Punktzahl gewinnt

Es gibt ein gutes Maß an Flexibilität bei der Eingabe und Ausgabe, aber Lösungen, bei denen T / F durch Funktionen ersetzt werden, die die gesamte Arbeit erledigen, sind nicht zulässig.

Debugging:

Wenn Sie in Haskell schreiben oder es von Haskell aus aufrufen können, überprüft Folgendes Ihre Funktion / Ihr Programm:

import Test.QuickCheck

tf = cycle [True,False]
gen l = foldl (++) [] $ map (\i -> [tf!!i | x<-[1..i]]) l
putIn (a,b) l = zipWith (||) l [(a <= p) && (p <= b) | p <- [0..length l]]
putAllIn rs len = foldr putIn [False|i<-[1..len]] rs
main = print $ quickCheck (check functionNameGoesHere)

1
Möglicherweise fehlt etwas, aber es wird keine Beschreibung angezeigt, wie ein Bereich in der Ausgabe dargestellt wird.
Peter Taylor

1
Kann die Ausgabe 1-indiziert werden?
LegionMammal978

Können die Bereiche zur Hälfte exklusiv sein?
Lirtosiast

1
@ LegionMammal978 Nur wenn Ihre Standardsprache 1-indiziert ist, z. B. Mathematica
Michael Klein

@ ThomasKwa Nein, das scheint zu unterschiedlich für "Rand" -Fälle
Michael Klein

Antworten:


7

Pyth, 17 16 Bytes

fT.b*Y,~+ZNtZrQ8

Verwendet einige ausgefallene Post-Assign-Zählermagie zusammen mit Lauflängencodierung.

Nimmt die Eingabe als Array von 0s und 1s, z [1, 1, 0, 1, 0]. Ausgänge wie bei der Challenge, z [[0, 1], [3, 3]].

Test Suite


Ich habe eine Testsuite hinzugefügt. Wenn die Bearbeitung genehmigt wird und niemand schnippt, haben Sie die kürzeste gültige Antwort.
Michael Klein

9

Pyth, 18 Bytes

CxR.:++~Zkz02_B_`T

Testsuite

Wahr ist dargestellt als 1, Falsch als 0.

Bereiche werden inklusive dargestellt.


Können Sie eine Erklärung hinzufügen?
Lirtosiast

Sicher, irgendwann anders.
Isaacg

7

Retina , 82 34 27 Bytes

\b(?<=(.)*_?)
$#1
_+

S_`:

Die leere Zeile sollte ein einzelnes Leerzeichen enthalten.

Die Eingabe ist eine flache Zeichenfolge _für wahr und :falsch. Die Ausgabe erfolgt durch durch Leerzeichen getrennte Paare, jeweils in einer separaten Zeile.

Probieren Sie es online aus.

Erläuterung

Das schwere Golfen von 82 auf 27 Bytes war durch geschickte Wahl der Darstellung von wahr und falsch möglich. Ich habe ein Wortzeichen _(das keine Ziffer ist) für wahr und ein Nichtwortzeichen :(das kein Escapezeichen benötigt) für falsch ausgewählt. Dadurch kann ich die Enden von Bereichen als Wortgrenzen erkennen.

\b(?<=(.)*_?)
$#1

Wir stimmen mit einer Wortgrenze überein. Wir wollen diese Grenze durch den entsprechenden Index des Wahrheitswerts ersetzen. Im Prinzip ist das mit Retinas neuester $#Funktion, die die Anzahl der Erfassungen einer Gruppe zählt , recht einfach . Wir erfassen einfach jeden Charakter vor dieser Position in einer Gruppe. Durch Zählen dieser Zeichen erhalten wir die Position. Der einzige Haken ist, dass die Enden des Bereichs jetzt um eins verschoben sind. Wir wollen eigentlich den Index des Charakters vor dem Match. Dies lässt sich auch leicht beheben, indem optional ein _nicht erfasstes Zeichen abgeglichen wird und ein Zeichen übersprungen wird, wenn das Ende eines Bereichs erreicht ist.

_+
<space>

Jetzt ersetzen wir alle Unterstriche durch ein Leerzeichen. Das heißt, wir fügen zwischen dem Anfang und dem Ende jedes Bereichs ein Leerzeichen ein und entfernen dabei die Unterstriche.

S_`:

Das lässt die Doppelpunkte (und wir müssen immer noch Paare trennen). Dazu teilen wir die gesamte Zeichenfolge in Zeilen um jeden Doppelpunkt auf. Der Saktive Split-Modus und das _Unterdrücken leerer Segmente, sodass bei Doppelpunktfolgen nicht jede Menge Leerzeilen entstehen.


5

MATL , 17 18 20 Bytes

j'T+'1X32X34$2#XX

Verwendet die aktuelle Version (9.1.0) der Sprache / des Compilers.

Die Eingabe ist eine Zeichenfolge mit den Zeichen Tund F. Die Ausgabe ist eine zweizeilige Tabelle, in der jede Spalte einen Bereich mit 1-Indexierung angibt. Dies ist die Standardsprache.

Vielen Dank an Stewie Griffin für das Entfernen von 2 Bytes.

Beispiel

>> matl
 > j'T+'1X32X34$2#XX
 >
> FTTFFFTTTT
2 7
3 10

Erläuterung

Es basiert auf einem einfachen regulären Ausdruck:

j         % input string
'T+'      % regular expression: match one or more `T` in a row
1X3       % predefined string literal: 'start'
2X3       % predefined string literal: 'end'
4$2#XX    % regexp with 4 inputs (all the above) and 2 outputs (start and end indices)
          % implicitly display start and end indices

4

Oktave, 43 Bytes

@(x)reshape(find(diff([0,x,0])),2,[])-[1;2]

find(diff([0,x,0]))Findet alle Positionen, an denen das Eingabearray zwischen true und false wechselt. Indem wir dies in eine 2-mal-n-Matrix umformen, erreichen wir zwei Dinge: Die Änderungen von wahr zu falsch und von falsch zu wahr werden in zwei Zeilen unterteilt. Dies ermöglicht es, 1 und 2 von jeder dieser Zeilen zu subtrahieren. Das Subtrahieren von 1 von Zeile 1 ist erforderlich, da Octave 1-indiziert und nicht null-indiziert ist. Das Subtrahieren von 2 von find(diff())der zweiten Zeile ist notwendig, da das die Position des ersten falschen Werts findet, während wir den letzten wahren Wert wollen. Der Subtraktionsteil ist nur in Octave möglich, nicht in MATLAB.

F=0;T=1;
x=[F,F,T,T,F,F,F,F,F,F,F,F,T,T,T,T,T,T,T,T,F,F,F,F,F,F,F,F,F,F,F,F,F,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,F,T,T]

reshape(find(diff([0,x,0])),2,[])-[1;2]
ans =    
    2   12   33   93
    3   19   54   94

x=[T,T,F,F,F,T,T,T,T,T,T,T,T,T,T,F]
reshape(find(diff([0,x,0])),2,[])-[1;2]
ans =    
    0    5
    1   14

1
Gute Nutzung des Rundfunks!
Luis Mendo

4

CJam, 27 25 Bytes

0qe`{~~{+}{1$+:X(]pX}?}/;

Erwartet Eingaben wie TTFTFT. Probieren Sie es online aus .

Erläuterung

0                               Push 0, to kick off index
qe`                             Push input and run length encode
                                e.g. FFFFTTTFT -> [[4 'F] [3 'T] [1 'F] [1 'T]]
{                 }/            For each pair in the RLE...
 ~                                Unwrap the pair
  ~                               Evaluate T -> 0 (falsy), F -> 15 (truthy)
   { }{         }?                 Ternary based on T/F
    +                                If 'F: add count to index
       1$+:X(]pX                     If 'T: output inclusive range, updating index
;                               Discard the remaining index at the top of the stack

4

Japt, 34 31 25 Bytes

Diesmal hat es wirklich geklappt, einen neuen Ansatz zu versuchen.

V=[]Ur"T+"@Vp[YY-1+Xl]};V

Probieren Sie es online!

Die Eingabe ist eine Zeichenfolge mit Ffür falseund Tfür true. Die Ausgabe ist ein Array von Arrays. Die Zeichenfolgendarstellung lässt es wie ein einzelnes Array aussehen.

Wie es funktioniert

          // Implicit: U = input string
V=[]      // Set V to an empty array. (Why don't I have a variable pre-defined to this? :P)
Ur"T+"    // Take each group of one or more "T"s in the input,
@         // and map each matched string X and its index Y to:
Vp[       //  Push the following to an array in V:
Y         //   Y,
Y-1+Xl    //   Y - 1 + X.length.
]};       //  This pushes the inclusive start and end of the string to V.
V         // Implicit: output last expression

Hinweis: Ich sehe jetzt, dass einige Leute bereits auf diesen Algorithmus gekommen sind, aber ich habe ihn unabhängig entdeckt.

Nicht konkurrierende Version, 22 Bytes

;Ur"T+"@Ap[YY-1+Xl]};A

Im neuesten GitHub-Commit habe ich eine neue Funktion hinzugefügt: Ein Lead ;setzt die Variablen A-J,Lauf unterschiedliche Werte. Awird auf ein leeres Array gesetzt, sodass es nicht mehr manuell erstellt werden muss.


4

Python 2, 69 Bytes

p=i=0
for x in input()+[0]:
 if x-p:b=x<p;print`i-b`+';'*b,
 p=x;i+=1

Beispielausgabe:

2 3; 7 16; 18 18;

Ein direkter Ansatz, keine Einbauten. Verfolgt den aktuellen Wert xund den vorherigen Wert p. Wenn dies anders ist, haben wir die Läufe gewechselt. Beim Umschalten 0auf 1wird der aktuelle Index gedruckt i. Beim Umschalten 1auf 0wird der aktuelle Index minus eins gedruckt, gefolgt von einem Semikolon.

Das ifist ziemlich stinkend. Vielleicht wäre Rekursion besser,


3

Haskell, 74 Bytes

import Data.Lists
map(\l->(fst$l!!0,fst$last l)).wordsBy(not.snd).zip[0..]

Anwendungsbeispiel: map(\l->(fst$l!!0,fst$last l)).wordsBy(not.snd).zip[0..] $ [True,False,True,True,False]-> [(0,0),(2,3)].

Wie es funktioniert:

                               -- example input: [True,False,True,True,False]

zip[0..]                       -- pair each element of the input with it's index
                               -- -> [(0,True),(1,False),(2,True),(3,True),(4,False)]
wordsBy(not.snd)               -- split at "False" values into a list of lists
                               -- -> [[(0,True)],[(2,True),(3,True)]]
map                            -- for every element of this list
   (\l->(fst$l!!0,fst$last l)) -- take the first element of the first pair and the
                               -- first element of the last pair
                               -- -> [(0,0),(2,3)]

3

J, 26 Bytes

[:I.&.|:3(<`[/,]`>/)\0,,&0

Dies ist ein unbenanntes monadisches Verb (unäre Funktion), das ein 2D-Array oder Ganzzahlen zurückgibt. Es wird wie folgt verwendet.

  f =: [:I.&.|:3(<`[/,]`>/)\0,,&0
  f 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 0
0  1
5 14

Erläuterung

[:I.&.|:3(<`[/,]`>/)\0,,&0
                       ,&0  Append 0 to input
                     0,     then prepend 0.
        3(         )\       For each 3-element sublist (a b c):
               ]`>/           Compute b>c
          <`[/                Compute a<b
              ,               Concatenate them
                            Now we have a 2D array with 1's on left (right) column
                            indicating starts (ends) or 1-runs.
[:I.&.|:                    Transpose, get indices of 1's on each row, transpose back.

3

Rubin, 39

->s{s.scan(/T+/){p$`.size..s=~/.#$'$/}}

Beispielaufruf:

2.2.3 :266 > f=->s{s.scan(/T+/){p$`.size..s=~/.#$'$/}}
 => #<Proc:0x007fe8c5b4a2e8@(irb):266 (lambda)> 
2.2.3 :267 > f["TTFTTFTTTFT"]
0..1
3..4
6..8
10..10

Das ..ist , wie Ruby - inclusive - Bereiche darstellt.

Das einzig Interessante hier ist, wie ich den Index des Bereichsendes erhalte. Es ist komisch. Ich erstelle dynamisch einen regulären Ausdruck, der mit dem letzten Zeichen des Bereichs und anschließend mit allen nachfolgenden Zeichen und dem Ende der Zeichenfolge übereinstimmt, um die korrekte Übereinstimmung zu erzwingen. Dann benutze ich =~, um den Index dieses Regex in der ursprünglichen Zeichenfolge zu erhalten.

Vermutlich gibt es in Ruby einen kürzeren Weg, dies mit den -naF-Flags zu tun.


2

JavaScript (ES6), 59

Eine anonyme Funktion, die als Zeichenfolge von Tund Fals Array von Arrays ausgegeben wird

x=>x.replace(/T+/g,(a,i)=>o.push([i,a.length+i-1]),o=[])&&o

PRÜFUNG

f=x=>x.replace(/T+/g,(a,i)=>o.push([i,a.length+i-1]),o=[])&&o

// TEST

arrayOut=a=>`[${a.map(e=>e.map?arrayOut(e):e).join`,`}]`

console.log=x=>O.textContent+=x+'\n'

;[
  'F','T','TTFT','FTTFFTTT','FTTFFFTTTT','TTFFFTTTTTTTTTTF',
  'FFTTFFFFFFFFTTTTTTTTFFFFFFFFFFFFFTTTTTTTTTTTTTTTTTTTTTTFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFTT'
].forEach(t=>console.log(t+'\n'+arrayOut(f(t))+'\n'))
<pre id=O></pre>


Wow, ich bin gerade auf die gleiche Lösung in Japt gekommen und wollte sie in JS übersetzen. Schön :)
ETHproductions

2

𝔼𝕊𝕄𝕚𝕟 18 Zeichen / 28 Byte

ïħ`T+`,↪ᵖ[_,$Ꝉ+‡_]

Try it here (Firefox only).

Erläuterung

ïħ`T+`,↪ᵖ[_,$Ꝉ+‡_] // implicit: ï=input
ïħ`T+`,            // for each T-sequence...
       ↪ᵖ[_,$Ꝉ+‡_] // push [start index of sequence, end index of sequence] to the stack
                   // implicit stack output

2

Haskell, 62 Bytes

f l|s<-zip3[0..](0:l)$l++[0]=zip[i|(i,0,1)<-s][i-1|(i,1,0)<-s]

Nimmt als Eingabe eine Liste von 0en und 1en.

Füllt die Liste lmit 0 auf beiden Seiten auf und berechnet die indizierte Liste aufeinanderfolgender Paare. Beispielsweise

l = [1,1,0]
s = [(0,0,1),(1,1,1),(2,1,0),(3,0,0)]

Extrahieren Sie dann die Indizes, die aufeinanderfolgenden Elementen entsprechen (0,1)und (1,0)die die Starts der Blöcke 0 und 1 sind, subtrahieren Sie 1 von den Starts von 0, um die Endes von 1 zu erhalten, und komprimieren Sie die Ergebnisse.


Wow, das verbiegt die Syntax mehr als ich gedacht habe. Ist es äquivalent zu "fl = let s = zip3 [0 ..] (0: l) (l ++ [0]) in zip [i | (i, 0,1) <- s] [i-1 | (i 1,0) <- s] "?
Michael Klein

1
@MichaelKlein Ja, habe ich gelernt , den Tricks der Bindung in Wachen hier aus nimi . Es entspricht auch der längeren Bindung über Lambda f l=(\s->zip[i|(i,0,1)<-s][i-1|(i,1,0)<-s])$zip3[0..](0:l)$l++[0].
Xnor

2

Pyth, 19 18 Bytes

m-VdU2cx1aV+ZQ+QZ2

Erläuterung:

             implicit: Q=input
m            map lambda d:
  -V         Vectorized subtraction by [0,1]
     d
     U2     
c            split every 2 elements
  x            find all indexes of
    1          1s
    aV         in vectorized xor:
       +ZQ     Q with a 0 on the front
       +QZ     Q with a 0 on the end
  2

Probieren Sie es hier aus .


2

Perl, 47 Bytes

s/F*(T*)(T)F*/[$-[0],$+[1]],/g;chop$_;$_="[$_]"

Mit den folgenden Perlrun-Optionen -lpe:

$ perl -lpe's/F*(T*)(T)F*/[$-[0],$+[1]],/g;chop$_;$_="[$_]"' <<< 'TTFFFTTTTTTTTTTF'
[[0,1],[5,14]]

Alternative bei zeilengetrennter Ausgabe (34 Byte):

$ perl -pE's/F*(T*)(T)F*/$-[0] $+[1]\n/g;chomp' <<< TTFFFTTTTTTTTTTF
0 1
5 15

1

Python 2, 108 Bytes

l=input();l+=[0];o=[];s=k=0
for i,j in enumerate(l):s=j*~k*i or s;~j*l[i-1]and o.append([s,i-1]);k=j
print o

Testfälle:

$ python2 rangesinlists2.py
[0]
[]
$ python2 rangesinlists2.py
[-1]
[[0, 0]]
$ python2 rangesinlists2.py
[-1,-1,0,-1]
[[0, 1], [3, 3]]
$ python2 rangesinlists2.py
[0,-1,-1,0,0,-1,-1,-1]
[[1, 2], [5, 7]]
$ python2 rangesinlists2.py
[0,-1,-1,0,0,0,-1,-1,-1,-1]
[[1, 2], [6, 9]]
$ python2 rangesinlists2.py
[-1,-1,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0]
[[0, 1], [5, 14]]
$ python2 rangesinlists2.py
[0,0,-1,-1,0,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,-1,-1]
[[2, 3], [12, 19], [33, 54], [93, 94]]

Sicher gibt es eine kürzere Lösung als diese, aber es funktioniert.


1

Haskell: 123 Bytes (Beispiel, kann nicht gewinnen)

f l=[(s,e)|let m=length l-1,let r=[0..m],s<-r,e<-r,and[l!!x|x<-[s..e]],s<=e,let(#)p=not$l!!p,s==0||(#)(s-1),e==m||(#)(e+1)]

Weniger golfen:

f l = [(start,end) | start <- [0..max], end <- [0..max], allTrue start end, start <= end, notBelow start, notAbove end]
  where
    max = (length l) - 1
    allTrue s e = and (subList s e)
    subList s e = [l !! i | i <- [s,e]]
    notBelow  s = (s == 0) || (not (l !! (s-1)))
    notAbove  e = (s == m) || (not (l !! (e+1)))

Auch wenn Sie nicht Golf spielen: allTrue s e = and (subList s e)oder vielleicht allTrue = (and.) . sublist.
nimi

Ok, aus einem Grund, an den ich mich nicht erinnere, dachte ich, dass das "klarer" war, als ich ungolfing war ... (Bearbeitet)
Michael Klein

1
Oh, klar, die Meinungen darüber, was "klar" ist, sind unterschiedlich. Ich denke auch all (==True) (subList s e)ist sehr klar.
nimi


1

Japt, 27 Bytes

A=[];Ur"T+"@Ap[YXl +´Y]};A·

Es muss einen Weg geben, wie man Golf spielen kann ...

Wie auch immer, es ist das gleiche wie meine Antwort.


Wow, ich habe mir diese Lösung gerade selbst ausgedacht ... Netter Algorithmus!
ETHproductions

1

APL, 17 Zeichen

{(↑,↑∘⊖)¨⍵⊂⍵×⍳⍴⍵}

In ⎕IO←0und ⎕ML←3. Auf Englisch:

  • ⍵×⍳⍴⍵: Nullen Sie die Elemente des Indexvektors, solange das Argument falsch ist
  • ⍵⊂: Schneiden Sie am Anfang jeder Reihe von Wahrheiten und werfen Sie die falschen weg
  • (↑,↑∘⊖)¨: Nimm das erste und letzte Element jedes Subarrays

0

PowerShell, 82 Byte

("$args"|sls 't+'-A).Matches|%{if($_){'{0},{1}'-f$_.Index,($_.Index+$_.Length-1)}}

Regex-Lösung unter Verwendung der Eigenschaften des MatchInfo- Objekts.

Beispiel

PS > .\BoolRange.ps1 'F'


PS > .\BoolRange.ps1 'T'
0,0

PS > .\BoolRange.ps1 'TTFFFTTTTTTTTTTF'
0,1
5,14

0

Mathematica, 45 Bytes

SequencePosition[#,{True..},Overlaps->False]&

Nicht besonders interessant; verwendet ein eingebautes.


0

Clojure, 109 Zeichen

#(first(reduce(fn[[r i]p](let[e(+(count p)i)][(if(first p)(conj r[i(dec e)])r)e]))[[]0](partition-by not %)))

Das erste, was mir in den Sinn kam, basierend auf reduceund partition-by.

Einfacher Testfall (Karten Tzu trueund Fzu false):

(def f #(first(reduce(fn[[r i]p](let[e(+(count p)i)][(if(first p)(conj r[i(dec e)])r)e]))[[]0](partition-by not %))))
(f (map #(= 'T %) '[F,T,T,F,F,T,T,T]))
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.