Falsify brief truths
Jelly, 8 bytes
ṣ0¬¬M¦j0
Try it online! or verify all test cases.
How it works
ṣ0¬¬M¦j0 Main link. Argument: A (list of Booleans)
ṣ0 Split at zeroes. This leaves a 2D list of ones.
¬ Negate each 1, replacing it with 0.
¦ Conditional application:
M Yield all maximal indices.
In lexicographical list comparison, a shorter list of zeroes is less
than a longer one, so this identifies the longest runs.
¬ Negate the items in those lists, changing zeroes back to ones.
j0 Join, separating by single zeroes.
Haskell, 59, 58, 55, 64 bytes
import Data.List
((=<<)=<<(=<<)(<$).(==).maximum.([1<2]:)).group
Fun note, this works on any list of values where falsy < truthy
. So False/True
, 0/1
, 'f'/'t'
, etc.
Note:
As several people have pointed out (including @proud haskeller
and @nimi
), the previous version failed on a list of all falsy values. The addition of .([1<2]:)
has fixed this, as suggested by @proud haskeller
. I'm leaving the explanation the same for now, because I think it still makes sense. If anyone comments, asking for an explanation of the edit, I'll edit.
Explanation:
I'll first desugar without the group
, and then add it back.
First, I find that words are often easier on the eyes than symbols, so I'll make a few substitutions. (Note that =<<
is 'classy' so it applies differently for lists and functions. I'm calling bind
the version of =<<
for functions.)
bind :: (a -> b -> c) -> (b -> a) -> b -> c
bind k f = k =<< f
bind k f = \ r -> k (f r) r
f = ((=<<)=<<(=<<)(<$).(==).maximum)
f = ((bind) concatMap (bind)(<$).equals.maximum)
f = (bind concatMap (bind (<$) . equals . maximum))
f = bind concatMap ((bind (<$)) . equals . maximum))
f = bind concatMap ((\f r -> (<$) (f r) r) . equals . maximum))
f = bind concatMap ((\f r -> (f r) <$ r) . equals . maximum)
f = bind concatMap ((\g r -> (g r) <$ r) . equals . maximum)
f = (\h r -> concatMap (h r) r) ((\g r -> (g r) <$ r) . equals . maximum)
f = \r -> concatMap (((\g r -> (g r) <$ r) . equals . maximum) r) r
f = \r -> concatMap (((\g r -> (g r) <$ r) . equals) (maximum r)) r
f = \r -> concatMap (((\g s -> (g s) <$ s)) (equals (maximum r))) r
f = \r -> concatMap (((\s -> ((equals (maximum r)) s) <$ s))) r
f = \r -> concatMap (\s -> (s == (maximum r)) <$ s) r
f . group = ((=<<)=<<(=<<)(<$).(==).maximum).group
f . group = \r -> concatMap (\s -> (s == (maximum (group r))) <$ s) (group r)
The last details are that x <$ list
replaces every element of the list
with x
and group list
splits the list
up into chunks of equal elements. So group [1, 1, 2, 3, 3, 3] == [[1, 1], [2], [3, 3, 3]]
.
To sum it all up, the function splits the list of values into groups of only true and groups of only false. Then for each group, replace each element with the result of the statement this is the biggest group
(the largest group of true
's will be the biggest) and concatenate the groups.
Four bytes saved by @Zgarb
Retina, 47 43 36
0
!
T`p`0`\b(1+)\b(?<=(?=.*1\1).*)|!
Try it online! or try all the test cases
Thanks to msh210 for golfing 4 bytes!
Also big thanks to Martin for 7 bytes!
Explanation:
0
!
Replace all 0
s with !
s. This is done to make matching groups of 1
s shorter, as now 1!
and !1
will have a word boundary (\b
) between them, which also matches either the start or the end of the string.
T`p`0`
This is a configuration option saying that after applying the regex after the backtick to the input, in every match translate every printable ascii character into a 0
character.
\b(1+)\b(?<=(?=.*1\1).*)|!
This regex matches groups of 1
s that are surrounded by zeroes, but do cannot match a 1
followed by itself anywhere in the string. These are the non-maximal groups that will be falsified. In addition, this also matches the !
characters we added to convert them back into 0
s.