Advent of Code 2019: Day 4
Overall, I like this. To really nitpick, I don't really like the use of rules[::2]. [::2] conveys that we are picking out every even element of rules as if that was significant. But in this case, it is more like it just happens to be that the first and last rules are what we want to pick out and that happened to match up with choosing all even elements.

I would probably just name the rules as follows. If the visual grouping of the rules is important you could wrap them in a class as static methods.

from itertools import groupby

bounds = (265275, 781584)

def digits_never_decreasing(s):
    return all(int(s[i]) &lt;= int(s[i+1]) for i in range(len(s)-1))

def adjacent_digits_equal(s):
    return any(s[i] == s[i+1] for i in range(len(s)-1))

def adjacent_digits_not_in_larger_group(s):
    return any(len(list(v)) == 2 for _, v in groupby(s))


def test(num, *rules):
    return all(f(str(num)) for f in rules)

def solve(bounds, *rules):
    return sum(1 for i in range(bounds[0], bounds[1]+1) if test(i, *rules))

def part_one():
    return solve(bounds, digits_never_decreasing, adjacent_digits_equal)

def part_two():
    return solve(bounds, digits_never_decreasing, adjacent_digits_not_in_larger_group)


print(part_one())  # 960
print(part_two())  # 626