# ---
# 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
# ---

# # Python Language Basics, IPython, and Jupyter Notebooks
#
#
# *****
# ___________
# # %quickref
#
# ____________________
# start Jupyter app:
# $jupyter notebook --port=9876

import numpy as np
np.random.seed(12345)
np.set_printoptions(precision=4, suppress=True)

import numpy as np
data = {i : np.random.randn() for i in range(7)}
data

# +
from numpy.random import randn

data = {i : randn() for i in range(7)}  #makes an index starting at zero
#data = {randn() for i in range(7)}     #no index number
print(data)

# +
#tab completion and inspect objects by adding '?'
# print?
# -

#push current directory to the stack, move to the new directory
# %pushd pass

# %popd #move to the stack you popped off earlier

# %dirs

# %dhist

_dh

# %env

# %matplotlib

#returns an object, is a list of the console output
# ip_info = !ifconfig virbr0 | grep "inet"

# !ifconfig

ip_info[0].strip()





def add_concat(coconutA, coconutB):
    """
    This is an example of a doc string
    Add two coconuts together
  
    Returns
    -------
    the_sum : type of arguments
    """
    return coconutA + coconutB



add_concat('bowling with   ', 'coconuts -->')


# +
# #add_concat?
# add_concat??

# +
# np.*load*?
# -

# ### The %run Command
#

# +
def sir_Robin(x, y, z):
    return (x + y) / z

a = 5
b = 6
c = 7.5

result = sir_Robin(a, b, c)

# -

sir_Robin(55,77,22)

# ```python
# # %run ipython_script_test.py
# # %load ipython_script_test.py
# ```

# #### Interrupting running code
#
#
# ____________________________________
# Executing Code from the Clipboard
#
# # %paste
#
# # %cpaste
#
# # %timeit
#
# # %time
#
# # %debug
#
# # %pwd
#
#

# ### Matplotlib Integration

# %matplotlib

# %matplotlib inline

# ## Python Language Basics

# ### Language Semantics
#
#
# Everything is an object.
#
# Indentation seperates code blocks,  not braces.
#
# for x in array:     #colon means more stuff tabbed in on next line
#
#     if x < pivot:
#     
#         less.append(x)
#         
#     else:
#     
#         greater.append(x)
#         
# Single line, multiple arguments seperated by semicolon
# a_thing = 5; b_obj = 6; c_semprini = 7
#
# Comments # single line
#          '''
#          multi
#          line
#          comments
#          '''

# #### Variables and argument passing

a = [1, 2, 3]

b = a

a.append(4)
b


def append_element(some_list, element):
    some_list.append(element)


import string as st
sir_Robin = st.ascii_letters + st.digits
#st.printable
#st.hexdigits
#st.octdigits
#letters concats lower & upper
print(sir_Robin)

append_element(a, 'semprini')
print(a)

# #### Dynamic references, strong types

#a = 5
#type(a)
a = 'foo'
type(a)

'5' + 5

a = 4.5
b = 2
# String formatting, to be visited later
print('a is {0}, b is {1}'.format(type(a), type(b)))
a / b

a = 5
isinstance(a, int)

a = 5; b = 4.5
isinstance(a, (int, float))
isinstance(b, (int, float))

# #### Attributes and methods

# ```python
# In [1]: a = 'foo'
#
# In [2]: a.<Press Tab>
# a.capitalize  a.format      a.isupper     a.rindex      a.strip
# a.center      a.index       a.join        a.rjust       a.swapcase
# a.count       a.isalnum     a.ljust       a.rpartition  a.title
# a.decode      a.isalpha     a.lower       a.rsplit      a.translate
# a.encode      a.isdigit     a.lstrip      a.rstrip      a.upper
# a.endswith    a.islower     a.partition   a.split       a.zfill
# a.expandtabs  a.isspace     a.replace     a.splitlines
# a.find        a.istitle     a.rfind       a.startswith
# ```

a = 'coconut_foo'

type(a)

getattr(a, 'split')


# #### Duck typing

def isiterable(obj):
    try:
        iter(obj)
        return True
    except TypeError: # not iterable
        return False


print(isiterable('a string'))
print(isiterable([1, 2, 3]))
print(isiterable(5))

x = [5, 6, 7, 9]

if not isinstance(x, list) and isiterable(x):
    x = list(x)
    print(x)

# #### Imports

# ```python
# # some_module.py
# PI = 3.14159
#
# def f(x):
#     return x + 2
#
# def g(a, b):
#     return a + b
# ```

# import some_module
# result = some_module.f(5)
# pi = some_module.PI

# from some_module import f, g, PI
# result = g(5, PI)

# import some_module as sm
# from some_module import PI as pi, g as gf
#
# r1 = sm.f(pi)
# r2 = gf(6, pi)

# #### Binary operators and comparisons

5 - 7
12 + 21.5
5 <= 2

a = [1, 2, 3]
b = a
c = list(a)
a is b
a is not c

a == c

a = None
a is None

# #### Mutable and immutable objects

a_list = ['foo', 2, [4, 5]]
a_list[2] = (3, 4)
a_list

a_tuple = (3, 5, (4, 5))
a_tuple[1] = 'four'

# ### Scalar Types

# #### Numeric types

ival = 17239871
ival ** 6

fval = 7.243
fval2 = 6.78e-5

3 / 2

3 // 2

# %time
import math
g = [1,3,5,7,17,21]
p = [12,122,112,1212,1222,1112]
t =[-12,-122,-112,-1212,-1222,-1112]
for x in g:
    print(hex(x))
for y in p:
    print(oct(y))
for f in g:
    print(math.factorial(f))
for h in t:
    print(abs(h))

import math
for u in p:
    print(math.sin(u))

pII = math.pi
print(math.sin(pII/2)) 
print(math.cos(pII))
print(math.tan(pII))
#print(math.asin(pII))
#math.acos
#math.atan

PII = math.pi
round(pII, 50)

complex(99,88)

for x in g:
    print(bin(x))
for y in p:
    print(math.sqrt(y))
for w in g:
    print(math.log(w))
print('^-----semprini-----^')


def kung_pow(x, y):
    print(math.pow(x,y))


kung_pow(8, 8)

for x in g:
    print(math.pow(x,2))



# #### Strings
# Strings can be coded with single or double quotes, use doubles if string has one single in it.
# Escape characters are \t for tab and \n for newline

a = 'one way of writing a string'
b = "another way"

a.replace('writing', 'inflating')

print(a)

b.split

a.splitlines()

c = """
This is a longer string that \n
spans multiple lines \n
I am the bottom line
"""

c.split('\n')

c.count('\n')

c.splitlines()

a = 'this is a string'
a[10] = 'f'
b = a.replace('string', 'longer string')
b

print(type(a))
print(type(s))

a = 5.6
s = str(a)
print(s)

s = 'python'
list(s)
s[:3]

s = '12\\34'
print(s)

s = r'this\has\no\special\characters'
s

a = 'this is the first half '
b = 'and this is the second half'
a + b

template = '{0:.2f} {1:s} are worth US${2:d}'

template.format(4.5560, 'Argentine Pesos', 1)

"Whizzo butter time is {0} GMT".format('15:00')

'semPriNi'.capitalize()

'.sEmPriNi'.lower()

'semprini'.upper()

#Center the string between the given spaces/padding, optional fill character
'Semprini'.center(13, '~')

'Semprini'.ljust(13, '~')

'Semprini'.rjust(13,'^')

'44444'.rjust(7,'0')

#true if matches end of string
'Semprini'.endswith('ini')

#return the index position of a substring, limit search with optional start/end positions 
'Semprini'.find('mp')

#True if all characters are letters or digits
'43234', 'semprini', '#$%#@'.isalnum()


'{_43.2$34', 'semprini', '#$%#@'.isalpha()

# #### Bytes and Unicode

val = "español"
val

val_utf8 = val.encode('utf-8')
val_utf8
type(val_utf8)

val_utf8.decode('utf-8')

val.encode('latin1')
val.encode('utf-16')
val.encode('utf-16le')

bytes_val = b'this is bytes'
bytes_val
decoded = bytes_val.decode('utf8')
decoded  # this is str (Unicode) now

# #### Booleans

True and True
False or True

# ### Type Casting and Type Conversions
# '''
# Use built-in functions to convert from one type to another.
# float(x)
# list(x)
# int(x)
#
#
# '''

s = '3.14159'
fval = float(s)
print(type(fval))
#int(fval)
#bool(fval)
#bool(0)
print(fval)

# #### None
# None is the Python null value type. If a function does not explicitly
# return a value, it implicitly returns None.

a = None
a is None
b = 5
b is not None


#none is also a common default value for function arguments
def add_and_maybe_multiply(a, b, c=None):
    result = a + b

    if c is not None:
        result = result * c

    return result


#None is also a unique
type(None)

# #### Dates and times

from datetime import datetime, date, time
dt = datetime(2019, 10, 28, 20, 15, 35)
#dt.day
#dt.minute

print(dt.date())
print(dt.time())

dt.strftime('%m/%d/%Y %H:%M')

#convert the dt into international scientific date format
dt.strftime('%A %d-%b-%Y %H:%M:%S.%f') 

datetime.strptime('20091031', '%Y%m%d')

dt.replace(minute=0, second=0)

dt2 = datetime(2011, 11, 15, 22, 30)
delta = dt2 - dt
delta
type(delta)

dt
dt + delta


# ### Control Flow
# """
# Python has several built-in keywords for conditional logic, loops and
# other standard control flow concepts found in other languages.

# #### if, elif, and else
# The if statement is one of the most well-known control flow statement
# types. It checks a condition that, if True, evaluates the code
# if ..elif in 4 lines may not be the adaptable or consise
# y if x else z is the same as *=(((x and y) or z))

def bad_words(badw):
    if badw < 0:
        print('Sorry, you are out of money ;)')
    elif badw == 0:
        print('Do you need House credits?')
    elif 0 < badw < 5:
        print('Cleaning out your pocket change?')
    else:
        print('Oooh, a big spender !!!')
        print('You have this many credits:-->', badw)


bad_words(40)

if x < 0:
    print('It's negative')
elif x == 0:
    print('Equal to zero')
elif 0 < x < 5:
    print('Positive but smaller than 5')
else:
    print('Positive and larger than or equal to 5')

a = 5; b = 7
c = 8; d = 4
if a < b or c > d:
    print('Made it')

test_pidgen = 4 > 8 > 2 > 1

tp = test_pidgen
if tp == True:
    print('Mr <NAME> approves!')
if tp == False:
    print('No, no, no, no, no spam for you ;(')

gui_drop_menu = 'coconuts'
print({'gumbys': 1.55,
       'brain specialist': 5.23,
       'parrot eggs': 0.99,
       'moustach': 0.49,
       'lupines': 1.23,
       'semprini': 9.99,
       'coconuts': 2.56,
       '': "Type something in, I'm no mind reader"}[gui_drop_menu])

menu_branch = {'gumbys': 1.55,
               'brain specialist': 5.23,
               'parrot eggs': 0.99,
               'moustach': 0.49,
               'lupines': 1.23,
               'semprini': 9.99,
               'coconuts': 2.56,
               'lemon curry?': 4.35,
               '': "Type something in, I'm no mind reader"}  #catch empty strings

print(menu_branch.get('lemon curry?', 'Choose well you will --Yoda'))


def poc_order_up(c):
    choice = c
    if choice in menu_branch:
        print(menu_branch[choice])
    else:
        print('No, no, no, no, no spam for you ;(')


poc_order_up('parrot eggs')

# ##Boolean Tests and the value of being truthful.
# True and False are custom versions of ints 1 and 0, more readable.
# A T/F value is inherent in all objects.
# Nonzero numbers & nonempty = True.
# Zero numbers, empty objects, None(special object) = False.
# and & or can return true or false, always return a coconut.
# Once the results are known, the statement stops evaluating.
# and
# or 
# not
# 'Short-circtuit evaluation' = py stops when it finds the first true operand.

#return left side if false
45 and 54, 54 and 99, 66 and 989  #both are true, returns the right

#here '[]' is false, stops and returns
[] and {}

#here 321 is true, so 
321 and []

# ###for loops

# for value in collection:
#     # do something with value

sequence = [1, 2, None, 4, None, 5]
total = 0
for value in sequence:
    if value is None:
        continue
    total += value
    print(value)

sequence = [1, 2, 0, 4, 6, 5, 2, 1]
total_until_5 = 0
for value in sequence:
    if value == 5:
        break
    total_until_5 += value
    print(value)

for g in range(85, 88, 1):
    for j in range(4, 8):
        if j > g:
            break
        print((g, j))

a = ((x and y) or z)

a = y if x else z

#boolean cheat codes
#select from a set of objects
#assigns x to the first nonempty 
x = a or b or c or None #or default
#good for 

L = [1, 0, 2, 0, '<NAME>', '', 'rumham', []]

#fetch the true values
list(filter(bool, L))

[x for x in L if x]

#truth aggregate
any(L), all(L)

# ## while loops
# The general iteration construct in Python,
# it keeps executing a block or blocks until test at top == True.
# When it becomes false the control moves to the block that follows.
# If starts at false, the block never runs and the while statement is skipped

#slice off the string until the last letter
x = 'semprini'
while x:
    print(x, end=' ')
    x = x[1:]

a=5; b=115
while a < b:
    print(a, end=' ')
    a *= 2

x = 256
total = 0
while x > 0:
    if total > 500:
        break
    total += x
    x = x // 2

# #### pass
# used during function development, place holder for return statements.  

if x < 0:
    print('negative!')
elif x == 0:
    # TODO: put something smart here
    pass
else:
    print('positive!')

# #### Range settings for generators of lists, etc

range(10)
list(range(10))

print(list(range(0, 20, 2)))
print(list(range(5, 0, -1)))

seq = [1, 2, 3, 4]
for i in range(len(seq)):
    val = seq[i]
print(seq)

seq = (1,2,3,4)
for i in range(len(seq)):
    val = seq[i]
    if i % 3 == 0 or i % 5 == 0:
        seq += 1

sum = ()
for i in range(355, 666):
    # % is the modulo operator
    if i % 9 == 0 or i % 5 == 0:
        print(i,i/2)

# #### Ternary expressions
# if/else multiline statements can be constructed on one line. eg
# if x:
#    a = y
# else:
#    a = z
#  
# this can be rewriten as: a = y if x else z, 

if x:
    a = y
else:
    a = z

a = 'trew' if 'spam' else 'flause'
print(a)

a = 'trew' if '' else 'flause'
print(a)

# %%writefile DnD_dice.py
#code source <NAME> 03_02_double_dice
import random
for x in range(1, 2):
    die_4 = random.randint(1,4)
    die_6 = random.randint(1, 6)
    die_8 = random.randint(1,8)
    die_10 = random.randint(1,10)
    die_12 = random.randint(1,12)
    die_20 = random.randint(1,20)
    total = die_4 + die_6 + die_8 + die_10 + die_12 + die_20
    print("Total=", total)
    if total == 6:
        print('Lucky Sixes!')
    if total == 11:
        print('Eleven Thrown!')
    if die_12 == die_20:
        print('Double Thrown!')
    print("D20 =", die_20)
    if die_20 == 20:
        print('Max D20!!')
    print("D12 =", die_12)
    if die_12 == 12:
        print('Max D12!!')             
    print("D08 =", die_8)
    if die_8 == 8:
        print('Max D8!!')
    print("D06 =", die_6)
    if die_6 == 6:
        print('Max D6!!')
    print("D04 =", die_4)
    if die_4 == 4:
        print('Max D4!!')

# !python DnD_dice.py

x = -5
'Non-negative' if x >= 0 else 'Negative'

# +
# %%writefile bridge_keeper.py
#source code from <NAME> 04_09_hangman_full_solution
import random

words = ['albatross', 'spam', 'camelot', 'spamalot', 'crunchyfrog', 'deadparrot', 'semprini',]
lives_remaining = 42
guessed_letters = ''



def play():
	word = pick_a_word()
	while True:
		guess = get_guess(word)
		if process_guess(guess, word):
			print('You win 3 thingies! Well Done!')
			break
		if lives_remaining == 0:
			print('A witch! Buuurn her!!')
			print('The word was: ' + word)
			break
	
def pick_a_word():
	word_position = random.randint(0, len(words) - 1)
	return words[word_position]
	
def get_guess(word):
	print_word_with_blanks(word)
	print('Lives Remaining: ' + str(lives_remaining))
	guess = input(' Guess a letter or whole word?')
	return guess

def print_word_with_blanks(word):
     #create an empty new global variable, 
	display_word = ''
	for letter in word:
		if guessed_letters.find(letter) > -1:
			# letter found
			display_word = display_word + letter
		else:
			# letter not found
			display_word = display_word + '-'
	print(display_word)
			
def process_guess(guess, word):
	if len(guess) > 1 and len(guess) == len(word):
		return whole_word_guess(guess, word)
	else:
		return single_letter_guess(guess, word)

			
def whole_word_guess(guess, word):
	global lives_remaining
	if guess.lower() == word.lower():
		return True
	else:
		lives_remaining = lives_remaining - 1
		return False

def single_letter_guess(guess, word):
	global guessed_letters
	global lives_remaining
	if word.find(guess) == -1:
		# letter guess was incorrect
		lives_remaining = lives_remaining - 1
	guessed_letters = guessed_letters + guess.lower()
	if all_letters_guessed(word):
		return True
	return False

def all_letters_guessed(word):
	for letter in word:
		if guessed_letters.find(letter.lower()) == -1:
			return False
	return True
	
play()
# -

# #try and except example from <NAME>
#
# Read each line in a file, find a match for 'semprini'. Exeption is raised if file is not found.
#
#
# 06_03_file_readline.py
#
#

# +
# %%writefile semprini_detector.py


words_file = 'data/monty_python_keywords.txt'
try:
	f = open(words_file)
	line = f.readline()
	while line != '':
		if line == 'semprini\n':
			print('A semprini has been detected in the file')
			break
		line = f.readline()
	f.close()	
except IOError:
	print("Cannot find file: " + words_file)
# -

# !python semprini_detector.py

#

StarcoderdataJupyterScriptsDedupFiltered