The challenge

Complete the function/method so that it takes a PascalCase string and returns the string in snake_case notation. Lowercase characters can be numbers. If the method gets a number as input, it should return a string.

Examples:

"TestController"  -->  "test_controller"
"MoviesAndBooks"  -->  "movies_and_books"
"App7Test"        -->  "app7_test"
1                 -->  "1"

The solution in Python code

Option 1:

import re

def to_underscore(string):
    return re.sub(r'(.)([A-Z])', r'\1_\2', str(string)).lower()    

Option 2:

def to_underscore(string):
    string = str(string)
    camel_case = string[0].lower()
    for c in string[1:]:
        camel_case += '_{}'.format(c.lower()) if c.isupper() else c
    return camel_case

Option 3:

def to_underscore(s):   
    return "".join(["_" + c.lower() if c.isupper() else c for c in str(s)]).strip("_")

Test cases to validate our solution

import test
from solution import *

@test.describe("Sample tests")
def sample_tests():
    @test.it("Tests")
    def it_1():
        test.assert_equals(to_underscore("TestController"), "test_controller")
        test.assert_equals(to_underscore("MoviesAndBooks"), "movies_and_books")
        test.assert_equals(to_underscore("App7Test"), "app7_test")
        test.assert_equals(to_underscore(1), "1")