Ho ho! So you think you know integers, do you? Well then, young wizard, tell us what the Nth digit of the [Champernowne constant](https://en.wikipedia.org/wiki/Champernowne_constant) is!

The constant proceeds like this: `0.12345678910111213141516...`

I hope you see the pattern!

Conjure a function that will accept an integer, `n`, and return the (one-indexed) `n`th digit of Champernowne's constant. Can you get it to run in _constant_ time?

For example:

`n = 1` should return `0` (the very first digit)

`n = 2` should return `1` (we ignore the period character since it's not a digit!)

`n = 20` should return `4` (that's the `4` in the number `14`, 20th in sequence)

For any invalid values, such as `0` and below, or non-integers, return... `NaN`!

I hope (for your sake) that you've been practicing your mathemagical spells, because a naïve solution will _not_ be fast enough to compete in this championship!

Invoke with _precision_, and be wary of rounding errors in the realms of enormity!

May the best integer win!

Difficulty: introductory

Starter code:

def champernowneDigit(n):
	

Solutions:
def champernowne_digit(n):
    if not type(n) is int or n < 1:
        return float("NaN")
    i, l = 1, 11
    while l <= n:
        i, l = i + 1, l + 9 * (i + 1) * 10**i
    return ((n - l) // (i * 10**(i - 1 - (n - l) % i))) % 10

champernowneDigit = champernowne_digit


DIGIT_CNTS = [1] + [(10**i - 10**(i-1)) * i for i in range(1, 20)]

def champernowneDigit(n):
    if not isinstance(n, int) or n is True or n <= 0:
        return float('nan')
    n -= 1
    for digits, cnt in enumerate(DIGIT_CNTS):
        if n < cnt:
            break
        n -= cnt
    start = int(10 ** (digits-1))
    q, r = divmod(n, digits) if digits > 1 else (n, 0)
    return int(str(start + q)[r])

def champernowneDigit(n):
    if not isinstance(n, int) or isinstance(n, bool) or n <= 0:
        return float('nan')
    elif n <= 10:
        return n - 1
    nr_digits = 1
    mag_len = 10
    while n > mag_len:
        n -= mag_len
        nr_digits += 1
        mag_len = nr_digits * (10**nr_digits - 10**(nr_digits-1))
        print(n, nr_digits, mag_len)
    quoitent, reminder = divmod(n-1, nr_digits)
    print(quoitent, reminder)
    return int(str(quoitent + 10**(nr_digits-1))[reminder])

def champernowneDigit(n):

    result=float("NaN")
    if type(n)==int and n>0:
        if n<=10:
            result=n-1
        else:
            i=1
            c=10
            while n>c:
                i+=1
                c=c+i*9*10**(i-1)
            
            number=(n-c)//i+10**i-1
            reste=(n-c)%i
            if reste:
                number+=1
            result=int(str(number)[reste-1])
    return result

from math import floor
def champernowneDigit(n):
    print(n)
    if n == None or isinstance(n, bool) or not isinstance(n, int) or n < 1: return float('nan')
    t, c = 10, 1
    while t < n: 
        c += 1
        t += 9 * 10**(c-1) * c
    num = str(10**c - 1 - floor((t-n)/c))
    return int(num[c - 1 - (t-n)%c])

def champernowneDigit(n):
    if not n or type(n)!=int or n<0: return float('nan')
    if n<=10: return n-1
    digs=1
    tot=1
    while 1:
        if tot+digs*9*10**(digs-1)>=n: break
        tot+=digs*9*10**(digs-1)
        digs+=1
    number=(n-tot-1)//digs+10**(digs-1)
    return int(str(number)[(n-tot-1)%digs])

def champernowneDigit(n):
    if not isinstance(n, int) or isinstance(n, bool) or n < 1:
        return float("nan")
    n -= 1
    sc = [9 * (x + 1) * pow(10, x) for x in range(50)]
    i = 0
    while n > sc[i]:
        n -= sc[i]
        i += 1
    L, d = divmod((n-1), i + 1)
    return int(str(pow(10, i) + L)[d])

def champernowne_digit(n):
    if not type(n) is int or n < 1:
        return float("NaN")
    n, i, l = n-1, 1, 10
    while n >= l: 
        n, i, l = n-l, i+1, 9 * (i+1) * 10**i
    return (n//(i*10**(i-1-n%i)))%10 + (n%i<1) - (i<2) 

champernowneDigit = champernowne_digit


# 1.6160180568695068 sec for [1, 10000]
g1 = lambda n: (9*(n+1)*10**n - 10**(n+1) + 1) // 9

# 2.1931352615356445 seconds for [1, 10000]
g2 = lambda n: int(''.join((str(n-1), "8"*(n-1), "9")))

L = [g1(x) for x in range(1, 1000)]

def champernowneDigit(n):
    if not (type(n) == int and 0 < n): return float("nan")
    if n == 1: return 0
    n -= 1
    x = next(i for i,v in enumerate(L, 1) if v > n)
    q, r = divmod(L[x-1]-n, x)
    return int(str(10**x-1-q)[-r-1])

def champernowneDigit(n):
    if not n or not type(n) == int or n < 1: return float('nan')
    
    dig, i = 10, 1
    while dig < n: 
        i += 1
        dig += 9 * 10 ** (i - 1) * i
    
    num = str(10 ** i - 1 - (dig - n) // i)
    
    return int(num[-1 - (dig - n) % i])