在列表中查找True值的范围


26

挑战:

编写一个接受布尔值列表并返回True的所有范围的函数或程序。

测试用例:

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

规则:

  • 您可以选择输入的编码方式,例如列表,数组,字符串等。
  • 必须将输出编码为类似列表的类似列表或显示这样的字符串,因此数组,列表,元组,矩阵,向量等。
  • 布尔值必须被编码为常量,否则可以将T / F进行任何简单的转换为所需的常量
  • 编辑:允许在运行时评估或类似评估
  • 不要忘记解释如何将输入传递给程序/函数并给出测试用例的输入/输出
  • 转换为所需的输入格式不计在内
  • 不允许出现标准漏洞
  • 如果您的语言具有执行此功能的功能,则不允许
  • 我不会接受我自己的提交
  • 编辑:输出格式是灵活的。如果未打印列表或类似内容,则范围值必须用一个非数字字符分隔,并且也必须分隔范围。

得分:

  • 分数以字节为单位,除非不适合您的语言(例如Piet中的代码)
  • 最低分获胜

输入和输出具有很大的灵活性,但是不允许将T / F替换为可以完成所有工作的功能的解决方案。

调试:

如果您用Haskell编写您的代码或可以从Haskell调用它,则以下内容将检查您的函数/程序:

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
我可能会丢失一些内容,但是我看不到有关如何在输出中表示范围的描述。
彼得·泰勒

1
输出可以为1索引吗?
LegionMammal978 '16

范围可以排除一半吗?
lirtosiast

1
@ LegionMammal978仅当您的语言默认值为1索引时,例如Mathematica
Michael Klein

@ThomasKwa Nope,对于“边缘”案例而言似乎太过不同了
Michael Klein

Answers:


7

Pyth,17 16字节

fT.b*Y,~+ZNtZrQ8

使用一些花哨的后分配计数器魔法和游程长度编码。

将输入作为0s和1s 的数组,例如[1, 1, 0, 1, 0]。挑战中的输出,例如[[0, 1], [3, 3]]

测试套件


我添加了一个测试套件。如果修改被批准并且没有人狙击,则您的有效答案最短。
Michael Klein


7

视网膜82 34 27字节

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

S_`:

空行应包含一个空格。

输入_为true和:false 的纯字符串。输出是用空格分隔的对,每对在单独的行上。

在线尝试。

说明

通过正确选择对与错的表示,可以从82字节压缩到27字节。我_为真选择了一个单词字符,(不是数字),:为假选择了一个非单词字符,(不需要转义)。这使我能够将范围的末端检测为单词边界。

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

我们匹配单词边界。我们要用真实值的相应索引替换该边界。原则上,使用Retina的最新$#功能相当容易,该功能可以统计一组的捕获次数。我们只需将该位置前面的每个字符捕获到一个组中即可。通过计算这些字符,我们得到了位置。唯一的问题是,范围的两端现在相差一。实际上,我们想要匹配项前面的字符索引。也可以通过可选地匹配_未捕获的a 来轻松解决此问题,从而当我们在范围的结尾时跳过一个字符。

_+
<space>

现在,我们用空格替换所有下划线。也就是说,我们在每个范围的开头和结尾之间插入了一个空格,同时删除了下划线。

S_`:

这样就留下了冒号(并且我们仍然需要分开成对的)。通过将整个字符串分成围绕每个冒号的行来实现。该S活性拆分模式,_禁止显示空段,使得没有得到吨的空行,当我们有冒号的运行。


5

Python 2,69个字节

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

输出示例:

2 3; 7 16; 18 18;

直接方法,没有内置方法。跟踪当前值x和上一个值p。当这些不同时,我们切换了运行。切换0到时1,打印当前索引i。切换1到时0,输出当前索引减一,后跟分号。

if很臭。也许递归会更好,


5

MATL,17 18 20字节

j'T+'1X32X34$2#XX

使用语言/编译器的当前版本(9.1.0)

输入是一个包含字符T和的字符串F。输出为两行表,其中每一列均使用1-indexing指示范围,该语言是默认语言。

感谢Stewie Griffin删除了2个字节。

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

说明

它基于一个简单的正则表达式:

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

八度,43字节

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

find(diff([0,x,0]))查找输入数组在true和false之间变化的所有位置。通过将其重塑为2×n矩阵,我们实现了两件事:从true到false以及从false到true的更改分为两行。这样就可以从这些行的每一行中减去1和2。从第一行减去1是必要的,因为八度是1索引,而不是零索引。从第二行减去2是必要的,因为find(diff())在我们想要最后一个真值的同时,找到了第一个假值的位置。减法部分只能在Octave中使用,而不能在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
善用广播!
路易斯·门多

4

CJam,27 25字节

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

期望输入类似TTFTFT在线尝试

说明

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字节

这次尝试一种新方法确实奏效了。

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

在线尝试!

输入是带有Ffor falseTfor 的字符串true。输出是一个数组数组;字符串表示形式使其看起来像单个数组。

怎么运行的

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

注意:我现在看到有几个人已经提出了该算法,但是我是独立发现的。

非竞争版本,22字节

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

最新的GitHub commit中,我添加了一个新功能:领导;将变量设置A-J,L为不同的值。A设置为空数组,因此无需手动创建它。


3

Haskell,74个字节

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

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

怎么运行的:

                               -- 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个字节

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

这是一个未命名的单子动词(一元函数),可返回2D数组或整数。它的用法如下。

  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

说明

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

红宝石,39岁

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

样本调用:

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

..就是Ruby表示包含范围的方式。

这里有趣的一件事是如何获取范围末端的索引。有点奇怪。我动态创建一个正则表达式,该表达式匹配范围的最后一个字符,然后匹配所有后续字符以及字符串的末尾,以强制正确匹配。然后,我用它=~来获取该正则表达式在原始字符串中的索引。

怀疑在Ruby中使用-naF标志可以有一种更短的方法。


2

JavaScript(ES6),59

匿名函数,输入作为串TF,返回输出作为数组的数组

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

测试

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>


哇,我刚刚在Japt中提出了相同的解决方案,并且打算将其转换为JS。好人:)
ETHproductions 2016年

2

𝔼𝕊𝕄𝕚𝕟,18个字符/ 28个字节

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

Try it here (Firefox only).

说明

ïħ`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个字节

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

输入0和1的列表作为输入。

给定列表l,将其两边都填充0并计算连续对的索引列表。例如

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

然后,提取与连续元素(0,1)和相对应的索引(1,0),它们是0和1的块的起点,从0的起点减去1得到1的终点,并压缩结果。


哇,这比我认为Haskell所采用的语法更难。它等效于zip [i |(i,0,1)<-s] [i-1 |(i)中的“ fl = let s = zip3 [0 ..](0:l)(l ++ [0]) ,1,0)<-s]“?
迈克尔·克莱因

1
@MichaelKlein是的,我在这里从 nimi得知了绑定后卫的技巧。它也等效于更长的通过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字节

m-VdU2cx1aV+ZQ+QZ2

说明:

             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

在这里尝试。


2

Perl,47个字节

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

使用以下perlrun选项-lpe

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

输出以行分隔(34字节)的替代方法:

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

1

Python 2,108个字节

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

测试用例:

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

当然,有比这更短的解决方案,但是它可行。


1

Haskell:123个字节(例如,无法获胜)

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

少打高尔夫球:

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

即使不打高尔夫球: allTrue s e = and (subList s e)也可能 allTrue = (and.) . sublist
nimi 2016年

好的,出于某种原因,我不记得了,当我取消高尔夫运动时,我认为这更加“清晰” ...(编辑)
Michael Klein

1
哦,可以肯定的是,关于“明确”的观点是不同的。我也认为all (==True) (subList s e)很清楚。
nimi 2016年


1

Japt,27个字节

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

必须有一种方法可以击倒这个...

无论如何,这和我的回答是一样的。


哇,我自己想出了这个解决方案。
ETHproductions 2016年

1

APL,17个字符

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

⎕IO←0和中⎕ML←3。用英语:

  • ⍵×⍳⍴⍵:只要参数为false,则将索引向量的元素归零
  • ⍵⊂:在每次真理的开端切开,并丢弃假的
  • (↑,↑∘⊖)¨:获取每个子数组的第一个和最后一个元素

0

PowerShell,82个字节

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

正则表达式解决方案,使用MatchInfo对象的属性。

PS > .\BoolRange.ps1 'F'


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

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

0

Mathematica,45个字节

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

不太有趣;使用内置的。


0

Clojure,109个字符

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

基于reduce和,我想到的第一件事partition-by

简单的测试用例(映射TtrueFfalse):

(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]))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.