# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# **1**. (25 points)
#
# - Write a **recursive** function that returns the length of the hailstone sequence staring with a positive integer $n$.  (15 points)
#
# The hailstone sequence is defined by the following rules:
# ```
# - If n is 1, stop
# - If n is even, divide by 2 and repeat
# - If n is odd, multiply by 3 and add 1 and repeat
# ```
# For example, the hailstone sequence starting with $n = 3$ has length 8:
# ```
# - 3, 10, 5, 16, 8, 4, 2, 1
# ```
#
# Use the `functools` package to avoid duplicate function calls.
#
# - Find the number that gives the longest sequence for starting numbers less than 100,000. Report the number and the length of the generated sequence. (10 points)
#

from functools import lru_cache


@lru_cache(None)
def hailstone(n, k=1):
    """Reprots length of hailstone (Collatz) sequence startign with n."""
    if n == 1:
        return k
    else:
        if n % 2 == 0:
            return hailstone(n // 2, k+1)
        else:
            return hailstone(n*3 + 1, k+1)


best = [0, 0]
for i in range(1, 100000):
    s = hailstone(i)
    if s > best[1]:
        best = (i, s)

best


# An alternative solution.

@lru_cache(None)
def hailstone_alt(n):
    """Reprots length of hailstone (Collatz) sequence startign with n."""
    if n == 1:
        return 1
    else:
        if n % 2 == 0:
            return 1 + hailstone_alt(n // 2)
        else:
            return 1 + hailstone_alt(n*3 + 1)


hailstone_alt(3)

best = [0, 0]
for i in range(1, 100000):
    s = hailstone_alt(i)
    if s > best[1]:
        best = (i, s)

best

# **2**. (25 points)
#
# - Create a `pnadas` DataFrame called `df` from the data set at https://bit.ly/2ksKr8f, taking care to only read in the `time` and `value` columns. (5 points)
# - Fill all rows with missing values with the value from the last non-missing value (i.e. forward fill) (5 points)
# - Convert to a `pandas` Series `s` using `time` as the index (5 points)
# - Create a new series `s1` with the rolling average using a shifting window of size 7 and a minimum period of 1 (5 points)
# - Report the `time` and value for the largest rolling average (5 points)

import pandas as pd

df = pd.read_csv('https://bit.ly/2ksKr8f', usecols=['time', 'value'])

df = df.fillna(method='ffill')

df.head()

# Note: The pd.Series constructor has quite unintuitive behavior when the `index` argument is provided. See  `DataFrame_to_Series.ipynb` for this.

s = pd.Series(data=df['value'])
s.index = df['time']

s.head()

s1 = s.rolling(7, 1).mean()

s1.head()

s1.sort_values(ascending=False).head(1)

# **3**. (25 points)
#
# - Get information in JSON format about startship 23 from the Star Wars API https://swapi.co/api using the `requests` package (5 points)
# - Report the time interval between `created` and `edited` in minutes using the `pendulum` package (5 points)
# - Replace the URL values stored at the `films` key with the titles of the actual films (5 points)
# - Save the new JSON (with film titles and not URLs) to a file `ship.json` (5 points)
# - Read in the JSON file you have just saved as a Python dictionary (5 points)

import requests

url = 'https://swapi.co/api/starships/23'
ship = requests.get(url).json()
ship

import pendulum

created = pendulum.parse(ship['created'])

edited = pendulum.parse(ship['edited'])

(edited - created).in_minutes()

films = [requests.get(film).json()['title'] for film in ship['films']]    

films

ship['films'] = films

import json

with open('ship.json', 'w') as f:
    json.dump(ship, f)

with open('ship.json') as f:
    ship = json.load(f)

ship

# **4**. (25 points)
#
# Use SQL to answer the following questions using the SQLite3 database `anemia.db`:
#
# - Count the number of male and female patients (5 points)
# - Find the average age of male and female patients (as of right now) (5 points)
# - Show the sex, hb and name of patients with severe anemia ordered by severity. Severe anemia is defined as
#     - Hb < 7 if female
#     - Hb < 8 if male
#     
# (15 points)
#
# You many assume `pid` is the PRIMARY KEY in the patients table and the FOREIGN KEY in the labs table. 
#    
# Note: Hb is short for hemoglobin levels.
#
# Hint: In SQLite3, you can use `DATE('now')` to get today's date.

# %load_ext sql

# %sql sqlite:///anemia.db

# + language="sql"
#
# SELECT * FROM sqlite_master WHERe type='table'

# + language="sql"
#
# SELECT * FROM patients LIMIT 3

# + language="sql"
#
# SELECT * FROM labs LIMIT 3

# + language="sql"
#
# SELECT sex, COUNT(sex)
# FROM patients
# GROUP BY sex

# + language="sql"
#
# SELECT date('now')

# + language="sql"
#
# SELECT sex, round(AVG(date('now') - birthday), 1)
# FROM patients
# GROUP BY sex

# + language="sql"
#
# SELECT sex, hb, name
# FROM patients, labs
# WHERE patients.pid = labs.pid AND 
# ((sex = 'M' AND hb < 8) OR (sex = 'F' AND hb < 7))
# ORDER BY hb
# -



StarcoderdataJupyterScriptsDedupFiltered