# Biostat823 Assignment2

**Number theory and a Google recruitment puzzle**

Find the first 10-digit prime in the decimal expansion of 17π. 

The first 5 digits in the decimal expansion of π are 14159. The first 4-digit prime in the decimal expansion of π are 4159. You are asked to find the first 10-digit prime in the decimal expansion of 17π. First solve sub-problems (divide and conquer):

- Write a function to generate an arbitrary large expansion of a mathematical expression like π. Hint: You can use the standard library `decimal` or the 3rd party library `sympy` to do this
- Write a function to check if a number is prime. Hint: See Sieve of Eratosthenes
- Write a function to generate sliding windows of a specified width from a long iterable (e.g. a string representation of a number)

Write unit tests for each of these three functions. You are encouraged, but not required, to try [test-driven development](https://en.wikipedia.org/wiki/Test-driven_development).

Now use these helper functions to write the function that you need.
Write a unit test for this final function, given that the first 10-digit prime in the expansion e is 7427466391. Finally, solve the given problem.

This assignment can be found in my github blog (named as Biostat 823 Assignment2): https://ashleyhmy.github.io/BIOS823_blog/


```python
import sympy as sym
import math
import unittest
```


```python
# Write a function to generate large arbitary expression for scientific expression
def num_expansion(expr, args):
    """
    generate an arbitary large expansion for a scientific expression like pi and e, returns numeric expression.
    
    expr is the mathematical expression to be converted eg, expr = sym.exp(1) use the sympy package to get scientific expression for e
    args is the number of significant numbers required eg, args = 5
    
    Examples to get arbitary expression for e with 5 significant numbers:
    >>> num_expansion(expr, 5)
    2.7183
    """
    num = expr.evalf(args)
    return num
```


```python
# Write a function to check if a number is a prime
def is_prime(num):
    """
    Take input num to check if num is a prime, if num is a prime return True, 
    if num is not a prime return False.
    Example:
    >>>is_prime(17)
    False
    """
    
    if num<2:
        return False
    if num==2:
        return True
    if num>2 and num%2 == 0:
        return False
    for i in range(3, 1 + math.floor(math.sqrt(num)), 2):
        if num%i == 0:
            return False
    return True
```


```python
# Write a function to generate sliding windows of a sequence
def get_window(seq, digits):
    """
    seq is the input, a list of numbers 
    win_size is the size of the window
    
    Example:
    seq = [1,2,3,4,5,6]
    win_size = 2
    >>> window(seq, win_size, step)
    [[1,2], [2,3], [3,4], [4,5], [5,6]]
    """
    
    num_of_chunk = int(len(seq)-digits + 1)
    for i in range(0, num_of_chunk):
        yield seq[i:i+digits]
```


```python
# Use unittest package to test the three functions above (num_expansion, is_prime, get_window)
class TestFunctions(unittest.TestCase):

    def test_num_expansion(self):
        result = pi.evalf(5)
        self.assertEqual(num_expansion(pi, 5), result)

    def test_is_prime(self):
        self.assertEqual(is_prime(17), True)
        self.assertEqual(is_prime(10), False)

    def test_window(self):
        seq = [1,2,3,4]
        self.assertEqual(list(get_window(seq, 3)), [[1,2,3],[2,3,4]])

if __name__ == "__main__":
    unittest.main(argv=[''], verbosity =2, exit=False)
```

    test_is_prime (__main__.TestFunctions) ... ok
    test_num_expansion (__main__.TestFunctions) ... ok
    test_window (__main__.TestFunctions) ... ok
    
    ----------------------------------------------------------------------
    Ran 3 tests in 0.002s
    
    OK



```python
# Now use the three helper function above to write a function to get the first 10 digit of a number
def get_first_prime(expr, args, digits):
    """
    The input expr is the methametical expression that want to be expanded
    The input args represents how many significant number is required from the methametical expression
    The input digits represents the number of digits is in the prime
    Example:
    >>>get_first_prime(pi, 200, 10)
    5926535897
    """
    num1 = num_expansion(expr, args)
    str1 = str(num1)
    list1 = str1.split('.')
    lst = [''.join(list1[0:2])]
    num = lst[0]
    seq = [int(a) for a in str(num)]
    windows = list(window(seq, digits))
    prime_lst = []
    for win in windows:
        str1 = ''.join(map(str, win))
        num_to_check = int(str1)
        if is_prime(num_to_check) == True:
            prime_lst.append(num_to_check)
    prime = prime_lst[0]
    return prime
```


```python
# test get_first_prime() function
class TestFunctions(unittest.TestCase):
    '''To check whether the output of get_first_prime() function is equal to 7427466391
    '''
    def test_get_first_prime(self):
        expr = sym.exp(1)
        self.assertEqual(get_first_prime(expr, 200, 10), 7427466391)


if __name__ == "__main__":
    unittest.main(argv=[''], verbosity =2, exit=False)
```

    test_get_first_prime (__main__.TestFunctions) ... ok
    
    ----------------------------------------------------------------------
    Ran 1 test in 0.025s
    
    OK



```python
# Find the first 10 digits of 17pi
get_first_prime(pi*17, 50, 10)
print("The first 10 digit prime of 17\u03C0 is", get_first_prime(pi*17, 50, 10))
```

    The first 10 digit prime of 17π is 8649375157


989b37ec0f2d29e43074b64b29df83279ff0cbbe
ipynb
Jupyter Notebook
_notebooks/2021-09-17-823-Assignment2.ipynb
AshleyHMY/BIOS823_blog
ced31b0dcee7e4820852ab45077a551e65ccf433
Apache-2.0
_notebooks/2021-09-17-823-Assignment2.ipynb
AshleyHMY/BIOS823_blog
ced31b0dcee7e4820852ab45077a551e65ccf433
Apache-2.0
_notebooks/2021-09-17-823-Assignment2.ipynb
AshleyHMY/BIOS823_blog
ced31b0dcee7e4820852ab45077a551e65ccf433
Apache-2.0
Qwen/Qwen-72B
1. YES
2. YES