Rechercher des plages de valeurs vraies dans une liste


26

Défi:

Écrivez une fonction ou un programme qui accepte une liste de valeurs booléennes et retourne toutes les plages de True.

Cas de test:

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]]

Règles:

  • Vous pouvez choisir la façon dont l'entrée est codée, par exemple une liste, un tableau, une chaîne, etc.
  • La sortie doit être codée comme une liste de listes ou comme une chaîne qui les affiche, donc des tableaux, des listes, des tuples, des matrices, des vecteurs, etc.
  • Les valeurs booléennes doivent être codées sous forme de constantes, mais sinon, toute simple conversion de T / F en constantes souhaitées est autorisée
  • EDIT: eval ou similaire pendant l'exécution EST autorisé.
  • N'oubliez pas d'expliquer comment l'entrée est transmise au programme / fonction et donnez son entrée / sortie pour les cas de test
  • Conversion au format d'entrée souhaité non compté
  • Les failles standard sont interdites
  • Si votre langue a une fonction pour ce faire, ce n'est pas autorisé
  • Je n'accepterai pas ma propre soumission
  • EDIT: le format de sortie est flexible. Si vous n'imprimez pas de liste ou similaire, les valeurs de plage doivent être séparées par un caractère non numérique et des plages distinctes également.

Notation:

  • Le score est en octets, sauf s'il ne convient pas à votre langue (comme les codels dans Piet)
  • Le score le plus bas gagne

Il y a une bonne flexibilité en entrée et en sortie, mais les solutions où T / F sont remplacées par des fonctions qui font tout le travail sont interdites.

Débogage:

Si vous écrivez le vôtre dans Haskell ou si vous pouvez l'appeler depuis Haskell, ce qui suit vérifiera votre fonction / programme:

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
Il me manque peut-être quelque chose, mais je ne vois pas de description de la façon dont une plage est représentée dans la sortie.
Peter Taylor

1
La sortie peut-elle être indexée 1?
LegionMammal978

Les gammes peuvent-elles être semi-exclusives?
lirtosiast

1
@ LegionMammal978 Uniquement si votre langue par défaut est indexée 1, par exemple Mathematica
Michael Klein

@ThomasKwa Nope, cela semble trop différent pour les cas "marginaux"
Michael Klein

Réponses:


7

Pyth, 17 16 octets

fT.b*Y,~+ZNtZrQ8

Utilise une certaine magie de compteur post-assignation fantaisie avec un encodage de longueur de course.

Prend l'entrée comme un tableau de 0s et 1s, par exemple [1, 1, 0, 1, 0]. Sorties comme dans le défi, par exemple [[0, 1], [3, 3]].

Suite de tests


J'ai ajouté une suite de tests. Si la modification est approuvée et que personne ne snipe, vous avez la réponse valide la plus courte.
Michael Klein

9

Pyth, 18 octets

CxR.:++~Zkz02_B_`T

Suite de tests

Vrai est représenté comme 1, Faux comme 0.

Les plages sont représentées de manière inclusive.


Pouvez-vous ajouter une explication?
lirtosiast

Bien sûr, autrefois.
isaacg

7

Rétine , 82 34 27 octets

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

S_`:

La ligne vide doit contenir un seul espace.

L'entrée est une chaîne plate de _pour vrai et :pour faux. La sortie est constituée de paires séparées par des espaces, chacune sur une ligne distincte.

Essayez-le en ligne.

Explication

Le golf lourd de 82 à 27 octets a été possible par un choix intelligent de la représentation du vrai et du faux. J'ai choisi un caractère de mot _, (qui n'est pas un chiffre) pour vrai et un caractère non-mot,, :(qui n'a pas besoin d'être échappé) pour faux. Cela me permet de détecter les extrémités des plages comme limites de mots.

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

Nous faisons correspondre une limite de mot. Nous voulons remplacer cette frontière par l'indice correspondant de la valeur véridique. En principe, c'est assez facile avec la $#fonction récente de Retina , qui compte le nombre de captures d'un groupe. Nous capturons simplement chaque personnage devant cette position dans un groupe. En comptant ces caractères, nous obtenons la position. Le seul hic, c'est que les extrémités de la plage sont maintenant décalées d'une unité. Nous voulons en fait l'index du personnage devant le match. Cela est également facilement corrigé en faisant correspondre éventuellement un _qui n'est pas capturé, sautant ainsi un caractère lorsque nous sommes à la fin d'une plage.

_+
<space>

Maintenant, nous remplaçons tous les traits de soulignement par un espace. Autrement dit, nous insérons un espace entre le début et la fin de chaque plage, tout en nous débarrassant des traits de soulignement.

S_`:

Cela laisse les deux points (et nous devons encore séparer les paires). Nous faisons cela en divisant la chaîne entière en lignes autour de chaque deux-points. Le Smode de partage actif et le _supprime les segments vides de telle sorte que les lignes vides ne reçoivent pas des tonnes de lignes doubles.


5

Python 2, 69 octets

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

Exemple de sortie:

2 3; 7 16; 18 18;

Une approche directe, pas intégrée. Suit la valeur actuelle xet la valeur précédente p. Lorsque ceux-ci sont différents, nous avons changé de série. Lors du basculement 0vers 1, imprime l'index en cours i. Lors du basculement 1vers 0, imprime l'index actuel moins un suivi d'un point-virgule.

C'est ifassez malodorant. Peut-être que la récursivité serait mieux,


5

MATL , 17 18 20 octets

j'T+'1X32X34$2#XX

Utilise la version actuelle (9.1.0) du langage / compilateur.

L'entrée est une chaîne contenant des caractères Tet F. La sortie est un tableau à deux lignes, où chaque colonne indique une plage utilisant l'indexation 1, qui est la langue par défaut.

Merci à Stewie Griffin d' avoir supprimé 2 octets.

Exemple

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

Explication

Il est basé sur une simple expression régulière:

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

Octave, 43 octets

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

find(diff([0,x,0]))recherche toutes les positions où le tableau d'entrée change entre vrai et faux. En remodelant cela en une matrice 2 par n, nous obtenons deux choses: les changements de vrai à faux et de faux à vrai sont divisés en deux rangées. Cela permet de soustraire 1 et 2 de chacune de ces lignes. Il est nécessaire de soustraire 1 de la ligne un car Octave est indexé 1 et non indexé zéro. Il est nécessaire de soustraire 2 de la ligne deux car la find(diff())recherche la position de la première fausse valeur, tandis que nous voulons la dernière vraie valeur. La partie de soustraction n'est possible que dans Octave, pas dans 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
Bonne utilisation de la radiodiffusion!
Luis Mendo

4

CJam, 27 25 octets

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

Attend une entrée comme TTFTFT. Essayez-le en ligne .

Explication

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 octets

Essayer une nouvelle approche a vraiment fonctionné cette fois.

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

Essayez-le en ligne!

L'entrée est une chaîne avec Fpour falseet Tpour true. La sortie est un tableau de tableaux; la représentation sous forme de chaîne le fait ressembler à un seul tableau.

Comment ça marche

          // 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

Remarque: je vois maintenant que plusieurs personnes avaient déjà développé cet algorithme, mais je l'ai découvert indépendamment.

Version non concurrente, 22 octets

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

Dans le dernier commit GitHub , j'ai ajouté une nouvelle fonctionnalité: un interligne ;définit les variables A-J,Lsur différentes valeurs. Aest défini sur un tableau vide, éliminant ainsi la nécessité de le créer manuellement.


3

Haskell, 74 octets

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

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

Comment ça marche:

                               -- 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 octets

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

Il s'agit d'un verbe monadique sans nom (fonction unaire) qui renvoie un tableau 2D ou des entiers. Il est utilisé comme suit.

  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

Explication

[: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

Rubis, 39

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

Exemple d'appel:

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

C'est ..ainsi que Ruby représente les plages inclusives.

La seule chose intéressante ici est de savoir comment obtenir l'index de la fin de la plage. C'est étrange. Je crée dynamiquement une expression régulière qui correspond au dernier caractère de la plage, puis à tous les caractères suivants et à la fin de la chaîne afin de forcer la correspondance correcte. Ensuite, j'utilise =~pour obtenir l'index de cette expression régulière dans la chaîne d'origine.

Vous pensez qu'il pourrait y avoir un moyen plus court de le faire dans Ruby en utilisant les indicateurs -naF.


2

JavaScript (ES6), 59

Une fonction anonyme, entrée sous forme de chaîne Tet F, renvoyant la sortie sous forme de tableau de tableaux

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

TESTER

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, je viens de proposer la même solution dans Japt et j'étais sur le point de la traduire en JS. Nice one :)
ETHproductions

2

𝔼𝕊𝕄𝕚𝕟, 18 caractères / 28 octets

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

Try it here (Firefox only).

Explication

ïħ`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 octets

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

Prend en entrée une liste de 0 et de 1.

Compte tenu de la liste l, la remplit avec 0 des deux côtés et calcule la liste indexée des paires consécutives. Par exemple

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

Ensuite, extrayez les indices correspondant aux éléments consécutifs (0,1)et (1,0), qui sont les débuts des blocs de 0 et 1, soustrayez 1 des débuts de 0 pour obtenir les fins de 1, et zippez les résultats.


Wow, cela plie la syntaxe plus que je ne le pensais. Est-ce équivalent à "fl = let s = zip3 [0 ..] (0: l) (l ++ [0]) dans zip [i | (i, 0,1) <- s] [i-1 | (i , 1,0) <- s] "?
Michael Klein

1
@MichaelKlein Oui, j'ai appris l'astuce de la liaison chez les gardes de nimi ici . Il est également équivalent à la liaison plus longue via 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 octets

m-VdU2cx1aV+ZQ+QZ2

Explication:

             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

Essayez-le ici .


2

Perl, 47 octets

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

Avec les options perlrun suivantes -lpe:

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

Alternative où la sortie est séparée par ligne (34 octets):

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

1

Python 2, 108 octets

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

Cas de test:

$ 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]]

Il existe certainement une solution plus courte que celle-ci, mais cela fonctionne.


1

Haskell: 123 octets (exemple, ne peut pas gagner)

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)]

Moins golfé:

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

Même sans jouer au golf: allTrue s e = and (subList s e)ou peut-être allTrue = (and.) . sublist.
nimi

Ok, pour une raison que je ne me souviens pas, je pensais que c'était plus "clair" quand je ne jouais pas au golf ... (Modifié)
Michael Klein

1
Oh, bien sûr, les opinions divergent sur ce qui est "clair". Je pense aussi que all (==True) (subList s e)c'est très clair.
nimi

1

CJam, 30 octets

0l~0++2ewee{1=$2,=},{~0=-}%2/`

Entrée sous forme de tableau de style CJam 0 s et 1s. Sortie sous forme de tableau de paires de style CJam.

Exécutez tous les cas de test. (Prend soin de la conversion des formats d'entrée.)


1

Japt, 27 octets

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

Il doit y avoir un moyen de jouer au golf ...

Quoi qu'il en soit, c'est la même chose que ma réponse.


Wow, je viens de trouver cette solution moi-même .... Nice algorithme!
ETHproductions

1

APL, 17 caractères

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

Dans ⎕IO←0et ⎕ML←3. En anglais:

  • ⍵×⍳⍴⍵: mettre à zéro les éléments du vecteur d'index tant que l'argument où l'argument est faux
  • ⍵⊂: couper au début de chaque série de vérités et jeter les fausses
  • (↑,↑∘⊖)¨: prendre le premier et le dernier élément de chaque sous-tableau

0

PowerShell, 82 octets

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

Solution Regex, utilisant les propriétés de l'objet MatchInfo .

Exemple

PS > .\BoolRange.ps1 'F'


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

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

0

Mathematica, 45 octets

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

Pas particulièrement intéressant; utilise une fonction intégrée.


0

Clojure, 109 caractères

#(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 %)))

La première chose qui m'est venue à l'esprit, basée sur reduceet partition-by.

Cas de test simple (correspond Tà trueet Fà 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]))
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.