Знайдіть діапазони значень 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 в потрібні константи
  • EDIT: eval або подібне під час виконання IS дозволено.
  • Не забудьте пояснити, як вхід передається програмі / функції та дайте свій вхід / вихід для тестових випадків
  • Перерахунок у потрібний формат введення не враховується
  • Стандартні лазівки заборонені
  • Якщо ваша мова має функцію для цього, це заборонено
  • Я не прийму власного подання
  • EDIT: Формат виводу гнучкий. Якщо не друкується список або подібне, значення діапазону повинні бути розділені одним нечисловим символом та окремими діапазонами.

Оцінка:

  • Оцінка в байтах, якщо не відповідає вашій мові (наприклад, коделі в 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

Чи можуть бути діапазони наполовину ексклюзивними?
lirtosiast

1
@ LegionMammal978 Тільки якщо ваша мова за замовчуванням є 1-індексованою, наприклад, Mathematica
Michael Klein

@ThomasKwa Nope, що здається занадто різним для "крайових" випадків
Michael Klein

Відповіді:


7

Pyth, 17 16 байт

fT.b*Y,~+ZNtZrQ8

Використовує деяку фантастичну магію лічильника після призначення, а також кодування довжини запуску.

Приймає введення як масив 0s і 1s, наприклад [1, 1, 0, 1, 0]. Виходи, як у виклику, наприклад [[0, 1], [3, 3]].

Тестовий сюїт


Я додав тестовий набір. Якщо редакція затверджена і ніхто не чинить, у вас є найкоротший вірний відповідь.
Майкл Кляйн

9

Піт, 18 байт

CxR.:++~Zkz02_B_`T

Тестовий набір

Правда представлена ​​як 1, помилково як 0.

Діапазони представлені включно.


Чи можете ви додати пояснення?
lirtosiast

Звичайно, колись ще.
isaacg

7

Сітківка , 82 34 27 байт

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

S_`:

Порожній рядок повинен містити єдиний пробіл.

Введення - це плоский рядок _for true та :for false. Вихід - пари, розділені пробілом, кожна в окремому рядку.

Спробуйте в Інтернеті.

Пояснення

Важкий гольф від 82 до 27 байт був можливий завдяки розумному вибору представлення істинного та хибного. Я вибрав слово символу,, _(це не цифра) для істинного, а несловесного символу :, (для якого не потрібно бігти) для помилкового. Це дозволяє мені визначати кінці діапазонів як межі слів.

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

Ми співставляємо межу слова. Ми хочемо замінити цю межу відповідним індексом величини "truthy". В принципі, це досить легко з недавньою $#функцією Retina , яка підраховує кількість захоплень групи. Ми просто захоплюємо кожного персонажа перед цією позицією в групу. Підраховуючи ці символи, ми отримуємо позицію. Єдина уловка полягає в тому, що кінці діапазону відірвані на один момент. Ми насправді хочемо, щоб індекс персонажа перед матчем. Це також легко виправити, якщо ви необов’язково співпадаєте з _не захопленим, тим самим пропускаючи один символ, коли ми знаходимося в кінці діапазону.

_+
<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-індексацію, яка є мовою за замовчуванням.

Завдяки Стюі Гріффін за видалення 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]))знаходить усі позиції, де вхідний масив змінюється між істинним та хибним. Перерозподіляючи це в 2-х-матричну матрицю, ми досягаємо двох речей: Зміни від істинного до помилкового і від хибного до істинного поділяються на два ряди. Це дає можливість відняти 1 і 2 з кожного з цих рядків. Віднімання 1 з першого рядка необхідно, оскільки Octave є 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

Спробуйте в Інтернеті!

Введення - це рядок з Fдля falseі Tдля 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

Це неназване монадичне дієслово (unary функція), яке повертає 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

Анонімна функція, що вводиться як рядок 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

Хаскелл, 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, віднімаючи 1 від стартів 0, щоб отримати кінці 1, і записувати результати.


Нічого собі, це вигинає синтаксис більше, ніж я думав, що візьме Хаскелл. Чи еквівалентно "fl = нехай s = zip3 [0 ..] (0: l) (l ++ [0]) в zip [i | (i, 0,1) <- s] [i-1 | (i , 1,0) <- s] "?
Майкл Кляйн

1
@MichaelKlein Так, я дізнався про трюк прив’язки у гвардії від німі тут . Це також еквівалентно більш тривалому зв'язуванню через лямбда f l=(\s->zip[i|(i,0,1)<-s][i-1|(i,1,0)<-s])$zip3[0..](0:l)$l++[0].
xnor

2

Піт, 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.
німі

Гаразд, з тієї причини, яку я не пам’ятаю, я вважав, що це було «зрозуміліше», коли я робив ульгольфінг ... (Відредаговано)
Майкл Кляйн

1
О, звичайно, думки відрізняються від того, що "зрозуміло". Я також думаю, що all (==True) (subList s e)це дуже зрозуміло.
німі


1

Japt, 27 байт

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

Повинен бути спосіб пограти в гольф ...

У всякому разі, це те саме, що моя відповідь.


Нічого собі, я просто сам придумав це рішення .... Гарний алгоритм!
ETHproductions

1

APL, 17 символів

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

В ⎕IO←0і ⎕ML←3. Англійською:

  • ⍵×⍳⍴⍵: нуль елементів вектора індексу, доки аргумент, де аргумент помилковий
  • ⍵⊂: виріжте на початку кожного прогону істин і викиньте хибні
  • (↑,↑∘⊖)¨: взяти перший і останній елемент кожного підмножина

0

PowerShell, 82 байти

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

Рішення Regex, використовуючи властивості об'єкта MatchInfo .

Приклад

PS > .\BoolRange.ps1 'F'


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

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

0

Математика, 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.

Простий тестовий випадок (карти Tдо trueта 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]))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.