Найти диапазоны значений 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 в требуемые константы.
  • РЕДАКТИРОВАТЬ: Eval или подобное во время выполнения IS разрешено.
  • Не забудьте объяснить, как ввод передается программе / функции, и дать его ввод / вывод для тестовых случаев.
  • Преобразование в желаемый формат ввода не учитывается
  • Стандартные лазейки запрещены
  • Если у вашего языка есть функция для этого, это не разрешено
  • Я не приму мое собственное представление
  • РЕДАКТИРОВАТЬ: Формат вывода является гибким. Если список не распечатывается и т. П., Значения диапазона должны быть разделены одним нечисловым символом, а также отдельными диапазонами.

Подсчет очков:

  • Оценка в байтах, если не подходит для вашего языка (например, кодов в 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
Майкл Кляйн

@ThomasKwa Нет, это кажется слишком отличным для «крайних» дел
Майкл Кляйн

Ответы:


7

Pyth, 17 16 байт

fT.b*Y,~+ZNtZrQ8

Использует некоторую причудливую маску счетчика после назначения вместе с кодированием длины пробега.

Принимает ввод в виде массива 0s и 1s, например [1, 1, 0, 1, 0]. Выходы как в вызове, например [[0, 1], [3, 3]].

Тестирование


Я добавил тестовый набор. Если редактирование одобрено и никто не стреляет, у вас есть самый короткий действительный ответ.
Майкл Кляйн

9

Pyth, 18 байт

CxR.:++~Zkz02_B_`T

Тестирование

True представляется как 1, False как 0.

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


Можете ли вы добавить объяснение?
lirtosiast

Конечно, когда-нибудь еще.
Исаак

7

Retina , 82 34 27 байт

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

S_`:

Пустая строка должна содержать один пробел.

Ввод представляет собой плоскую строку _для истинного и :ложного. Выходные данные разделены пробелами, каждая на отдельной строке.

Попробуйте онлайн.

объяснение

Тяжелая игра в гольф от 82 до 27 байтов была возможна благодаря умному выбору представления истинного и ложного. Я выбрал символ слова _, (это не цифра) для истины, а не символ слова :, (не нужно экранировать) для ложного. Это позволяет мне определять концы диапазонов как границы слов.

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

Мы сопоставляем границу слова. Мы хотим заменить эту границу соответствующим индексом истинного значения. В принципе, это довольно просто с недавней $#функцией 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-индексации, которая является языком по умолчанию.

Спасибо 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]))находит все позиции, где входной массив изменяется между истиной и ложью. Преобразуя это в матрицу 2 на n, мы достигаем двух вещей: изменения с истинного на ложное и с ложного на истинное делятся на две строки. Это позволяет вычесть 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

Попробуйте онлайн!

Ввод - это строка с Ffor falseи Tfor 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

Это безымянный монадический глагол (унарная функция), который возвращает двумерный массив или целые числа. Используется следующим образом.

  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

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, вычтя 1 из начала 0, чтобы получить концы 1, и заархивируйте результаты.


Вау, это изгибает синтаксис больше, чем я думал, что Хаскелл возьмет. Это эквивалентно "fl = let 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

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)это очень ясно.
Ними,


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

Решение Regex, используя свойства объекта 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.

Простой тестовый пример (отображается 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.