The challenge

Let’s make it so Bob never misses another interesting number. We’ve hacked into his car’s computer, and we have a box hooked up that reads mileage numbers. We’ve got a box glued to his dash that lights up yellow or green depending on whether it receives a 1 or a 2 (respectively).

It’s up to you, intrepid warrior, to glue the parts together. Write the function that parses the mileage number input, and returns a 2 if the number is “interesting” (see below), a 1 if an interesting number occurs within the next two miles, or a `` if the number is not interesting.

Note: In Haskell, we use NoAlmost and Yes instead of ``, 1 and 2.

“Interesting” Numbers

Interesting numbers are 3-or-more digit numbers that meet one or more of the following criteria:

  • Any digit followed by all zeros: 10090000
  • Every digit is the same number: 1111
  • The digits are sequential, incementing1234
  • The digits are sequential, decrementing4321
  • The digits are a palindrome: 1221 or 73837
  • The digits match one of the values in the awesome_phrases array

So, you should expect these inputs and outputs:

# "boring" numbers
is_interesting(3, [1337, 256])    # 0
is_interesting(3236, [1337, 256]) # 0

# progress as we near an "interesting" number
is_interesting(11207, []) # 0
is_interesting(11208, []) # 0
is_interesting(11209, []) # 1
is_interesting(11210, []) # 1
is_interesting(11211, []) # 2

# nearing a provided "awesome phrase"
is_interesting(1335, [1337, 256]) # 1
is_interesting(1336, [1337, 256]) # 1
is_interesting(1337, [1337, 256]) # 2

Error Checking

  • A number is only interesting if it is greater than 99!
  • Input will always be an integer greater than ``, and less than 1,000,000,000.
  • The awesomePhrases array will always be provided, and will always be an array, but may be empty. (Not everyone thinks numbers spell funny words…)
  • You should only ever output ``, 1, or 2.

Test cases

test.describe("Basic inputs")
test.it("Should handle {0}".format(format_msg(0, "boring numbers")))
test.assert_equals(is_interesting(1, []), 0, result_msg(1, 0))
test.assert_equals(is_interesting(30, []), 0, result_msg(30, 0))
test.assert_equals(is_interesting(88, []), 0, result_msg(88, 0))
test.assert_equals(is_interesting(97, []), 0, result_msg(97, 0))
test.assert_equals(is_interesting(7382, []), 0, result_msg(7382, 0))
test.assert_equals(is_interesting(99919911, []), 0, result_msg(99919911, 0))

test.it("Should handle {0}".format(format_msg(0, "ordered yet still boring numbers")))
test.assert_equals(is_interesting(7540, []), 0, result_msg(7540, 0))
test.assert_equals(is_interesting(1590, []), 0, result_msg(1590, 0))

Some solutions in Python code

Option 1 (using helper functions):

def is_incrementing(number): return str(number) in '1234567890'
def is_decrementing(number): return str(number) in '9876543210'
def is_palindrome(number):   return str(number) == str(number)[::-1]
def is_round(number):        return set(str(number)[1:]) == set('0')

def is_interesting(number, awesome_phrases):
    tests = (is_round, is_incrementing, is_decrementing,
             is_palindrome, awesome_phrases.__contains__)
       
    for num, color in zip(range(number, number+3), (2, 1, 1)):
        if num >= 100 and any(test(num) for test in tests):
            return color
    return 0

Option 2 (all inline):

def is_good(n, awesome):
    return n in awesome or str(n) in "1234567890 9876543210" or str(n) == str(n)[::-1] or int(str(n)[1:]) == 0

def is_interesting(n, awesome):
    if n > 99 and is_good(n, awesome):
        return 2
    if n > 97 and (is_good(n + 1, awesome) or is_good(n + 2, awesome)):
        return 1
    return 0

Option 3 (using any):

def is_interesting(number, awesome_phrases):
    for i in [number, number+1, number+2]:
        if i<100 :
            continue
        j=str(i)
        if any([
            i in awesome_phrases,
            all([j[x]=='0' for x in range(1,len(j))]),
            all([j[x]==j[0] for x in range(1,len(j))]),
            j == j[::-1],
            j in '1234567890',
            j in '9876543210'
                ]):
            return 2-bool(number-i)
    return 0

Option 4 (using zip):

def is_interesting(number, awesome_phrases):
    for r, num in zip((2, 1, 1), range(number, number + 3)):
        num_str = str(num)
        if num in awesome_phrases or num > 99 and (int(num_str[1:]) == 0 or num_str[::-1] == num_str or num_str in '1234567890' or num_str in '9876543210'):
            return r
    return 0