リスト内の真の値の範囲を見つける


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から目的の定数への単純な変換が許可されます
  • 編集:ランタイム中のevalまたは類似のISが許可されます。
  • 入力がプログラム/関数にどのように渡されるかを説明し、テストケースの入力/出力を与えることを忘れないでください
  • カウントされない目的の入力形式への変換
  • 標準的な抜け穴は許可されていません
  • 言語にこれを行う機能がある場合、許可されていません
  • 私は自分の提出を受け入れません
  • 編集:出力形式は柔軟です。リストなどを印刷しない場合は、範囲の値を1つの数字以外の文字で区切り、範囲も区切る必要があります。

得点:

  • 言語に合わない場合を除き、スコアはバイト単位です(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

範囲を半分だけに限定できますか?
リルトシアスト

1
@ LegionMammal978たとえばMathematica
Michael Klein

@ThomasKwaいいえ、それは「エッジ」の場合にはあまりにも異なるようです
マイケルクライン

回答:


7

Pyth、17 16バイト

fT.b*Y,~+ZNtZrQ8

ランレングスエンコーディングとともに、いくつかの派手な割り当て後カウンターマジックを使用します。

入力を0sと1sの配列として受け取ります(例:)[1, 1, 0, 1, 0]。チャレンジなどの出力[[0, 1], [3, 3]]

テストスイート


テストスイートを追加しました。編集が承認され、誰もスナイプしない場合、最短の有効な回答があります。
マイケルクライン


7

網膜82 34 27バイト

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

S_`:

空行には単一のスペースが含まれている必要があります。

入力は、_trueおよび:falseのフラット文字列です。出力はスペースで区切られたペアで、それぞれが個別の行にあります。

オンラインでお試しください。

説明

真と偽の表現を賢く選択することにより、82バイトから27バイトまでの重いゴルフが可能になりました。_trueの場合は単語文字、(数字:ではない)、falseの場合は単語以外の文字、(エスケープする必要がない)を選択しました。これにより、範囲の終わりを単語の境界として検出できます。

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

単語の境界に一致します。この境界を、真理値の対応するインデックスに置き換えます。原則$#として、グループのキャプチャの数をカウントするRetinaの最近の機能を使用すると、非常に簡単です。その位置の前にある各キャラクターをグループにキャプチャするだけです。それらの文字を数えることで、位置を取得します。唯一の問題は、範囲の両端が1つずれていることです。実際、マッチの前にキャラクターのインデックスが必要です。また_、キャプチャされていないをオプションで一致させることで簡単に修正できます。これにより、範囲の最後にあるときに1文字をスキップします。

_+
<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。これらが異なる場合、実行を切り替えました。に切り替える01、現在のインデックスを出力しますi。に切り替える10、現在のインデックスから1を引いた後、セミコロンが出力されます。

ifかなり臭いです。おそらく再帰がより良いでしょう、


5

MATL、17 18 20バイト

j'T+'1X32X34$2#XX

言語/コンパイラの現在のバージョン(9.1.0)を使用します。

入力文字を含む文字列であるTF。出力は2行のテーブルです。各列は、言語のデフォルトである1インデックスを使用して範囲を示します。

2バイトを削除してくれたStewie Griffinに感謝します。

>> 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列の行列に再形成することにより、2つのことを実現します。trueからfalseへの変更とfalseからtrueへの変更は2行に分割されます。これにより、これらの各行から1と2を減算できます。Octaveはインデックスがゼロではなく1であるため、行1から1を引く必要があります。行2から2を減算する必要がありfind(diff())ます。最初のfalse値の位置を見つけるので、最後のtrue値が必要だからです。減算部分は、MATLABではなく、Octaveでのみ可能です。

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のコミット最新有数:、私は新しい機能追加した;セットの変数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が包括的範囲を表す方法です。

ここで興味深いのは、範囲の終わりのインデックスを取得する方法です。それは奇妙だ。範囲の最後の文字に一致する正規表現を動的に作成してから、正しい一致を強制するために、後続のすべての文字と文字列の末尾に一致します。次に=~、元の文字列でその正規表現のインデックスを取得するために使用します。

-naFフラグを使用して、Rubyでこれを行うより短い方法があるかもしれません。


2

JavaScript(ES6)、59

Tおよびの文字列として入力され、F出力を配列の配列として返す無名関数

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

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のブロックの開始点である連続した要素(0,1)とに対応するインデックスを抽出し、(1,0)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-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バイト

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

わかりませんが、覚えていない理由で、私はアンゴルフをしていたときにそれがより「クリア」であると思った...(編集)
マイケルクライン

1
ああ、確かに、「明確な」ものについて意見は異なります。私もall (==True) (subList s e)非常に明確だと思います。
nimi


1

Japt、27バイト

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

これを下にゴルフする方法がなければなりません...

とにかく、それは私の答えと同じです。


うわー、私は自分でこの解決策を思いついたばかりです。
-ETHproductions

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

単純なテストケース(TtrueFにマップ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]))
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.