<jupyter_start><jupyter_text>Chapter 1 - Introduction ***Terminology**Abstract Data Type**: a logical description of how we view the data and the operations that are allowed without regard to how they will be implemented.**Class**: a description of what the data look like (the state) and what the data can do (the behavior). Classes are analogous to abstract data types because a user of a class only sees the state and behavior of a data item. Data items are called objects in the object-oriented paradigm. An object is an instance of a class.**Lists**, **strings**, and **tuples** are ordered collections.**Sets** and **dictionaries** are unordered collections.**Raised Exception** - when a program run into the logical error**Handle Exception** - a programmer can intervene with exception (hanlde it) by using a **try** statement***Built-in Data Types (Collections)**Lists** - mutableOperations: - indexing([]) - concatenations(+) - repetition(*)- membership(in) - length(len)- slicing([:])Methods:```python>>> alist.append(item)>>> alist.insert(pos, item)>>> alist.pop()         remove and return the last item in the list>>> alist.pop(i)        remove and return the ith item in the list>>> alist.sort()        modifies a list to be sorted>>> alist.reverse()     modifies a list to be in reverse order>>> del alist[pos]      delete an item in the ith position>>> alist.index(item)   return the index of the first occurance of item>>> alist.count(item)   returns the number of occurances of item>>> alist.remove(item)  removes the first occurance of item```*****Strings** - immutableMethods:```python>>> astring.center(w)     returns a string centered of size w>>> astring.count(item)   returns the number of occurances of item>>> astring.ljust(w)      returns a string left-justified of size w>>> astring.lower()       returns a string in all lowercase>>> astring.find(item)    return the index of first occurance of item>>> astring.split(schar)  splits a string into substrings of schar```*****Tuples** - immutable- same methods as lists, but cannot change*****Sets**   - immutableOperations:```python>>> membership (in)>>> length (len)>>> aset | otherset   returns a new combined set>>> aset & otherset   returns a new set with elements common to both sets>>> aset - otherset   returns a new set with items in first not in second>>> aset <= otherset  asks if all elements in first are in second```Methods:```python>>> aset.union(otherset)         a new set with elements from both sets>>> aset.intersection(otherset)  a new set with elements common to both>>> aset.difference(otherset)    a new set with elements from first not second>>> aset.issubset(otherset)      asks whether all elements of one set are in the other>>> aset.add(item)               adds item to the set>>> aset.remove(item)            removes item from the set>>> aset.pop()                   removes an arbitrary element from the set>>> aset.clear()                 removes all elements from the set```*****Dictionaries** - mutableOperations:```python>>> adict[k]        returns the value associated with k, otherwise an error>>> key in adict    returns True if key is in the dictionary, False otherwise>>> del adict[key]  removes the entry from the dictionary```Methods:```python>>> adict.keys()      returns the keys of the dictionary in a dict_keys(list) object>>> adict.values()    returns the values of the dictionary in a dict_values(list) object>>> adict.items()     returns the key-value pairs in a dict_items(tuple) object>>> adict.get(k,alt)  returns the values associated with k, alt otherwise```***String Formatting and List Comprehensions```python>> print("hello world", sep/end="***")>> print("%s is %d years old." % (aName, age))>> sqlist = [x*x for x in range(1,11) if x%2 != 0]>> upper = [ch.upper() for ch in 'comprehension' if ch not in 'aeiou']```Format Characters:```python>>> d  integer>>> i  integer>>> u  unsigned integer>>> f  floating point as m.ddddd>>> e  floating point as m.dddde+/-xx>>> E  floating point as m.ddddE+/-xx>>> g  use %e for exponents less than -4 or greater than +5, otherwise %f>>> c  single character>>> s  string or any python data object that can be converted to a string using the **str** function- %  insert a literal % character```Format Modifier```python>>> %20d      field width of 20>>> %-20d     20 characters wide, left-justified>>> %+20d     20 characters wide, right-justified>>> %020d     20 characters wide, fill in with leading zeros>>> %20.2f    20 characters wide with 2 characters to the right of the decimal point>>> %(name)d  get the value from the supplied dictionary using name as the key```Use **.format** method for clarity***Exception HandlingSyntax Error:- a syntactical error while writing a program:```python>>> for i in range(10)SyntaxError: invalid syntax (, line 1)```Logical Error:- program executes but gives the wrong result- this can be due to an error in the underlying algorithm or an error in the translation of that algorithm- for example:  - trying to divide by zero  - trying to access an item in a list where the index of the item is outside the bounds of the list- the logic error will lead to a runtime error that causes the program to terminae- these types of runtime errors are typically called **exceptions**Hanlding Exceptions:- there is a way to handle these exceptions- there is a way to write custom exceptions- use **try** statement to catch/handle exceptionsBelow is the case when a negative value was entered into math.sqrt():```python>>> anumber = int(input("Please enter an integer "))Please enter an integer -23>>> print(math.sqrt(anumber))Traceback (most recent call last):  File "", line 1, in     print(math.sqrt(anumber))ValueError: math domain error```To handle the exception use the **try/except** block:```pythontry:    print(math.sqrt(anumber))except:    print("Bad Value for square root")    print("Using absolute value instead")    print(math.sqrt(abs(anumber)))    Bad Value for square rootUsing absolute value instead4.79583152331```Let's create our own **RuntimeError** exception:```pythonif anumber < 0:   raise RuntimeError("You can't use a negative number")else:    print(math.sqrt(anumber))...Traceback (most recent call last):  File "", line 2, in RuntimeError: You can't use a negative number```***Self-Check Challenge: The Infinite Monkey TheoremProblem:The theorem states that a monkey hitting keys at random on a typewriter keyboard for an infinite amount of time will almost surely type a given text (i.e. the complete works of William Shakespeare). Let's start with generating a simple sentence:    methinks it is like a weasel    Solution:1. Write a function that generates a string of 27 characters long by choosing random letters from the 26 letters in the alphabet, plus the space.2. Write another function that will score each generated string by comparing the randomly generated string to the goal.3. Write a third function that will repeatedly call generate and score functions, then if 100% of the letters are correct, we are done! If the letters are note correct then we will genereate a whole new string. To make it easier to follow your program's progress this third function should print out the best string generated so far and its score every 1000 tries.4. Then improve the algorithm by keeping letters that are correct and only modifying one character in the best string so far. This is a type of algorithm in the class of **hill climbing** algorithms, that is we only keep the result if it is better than the previous one.<jupyter_code>"""
    inf_monkey.py - <NAME> - 10/18/2016
    1. func_1 - Generate a string of 27 characters chosen randomly from 26 letters + space character
    2. func_2 - Score the generated string by comparing to the goal string: "methinks it is like a weasel"
    3. func_3 - Repeatedly call generate(func_1) and score(func_2), until 100% match is found
              - Print out the best string generated so far and its score after 1000 tries
"""
import random
import string

def random_string(length=1):
    """
    Generates a string of random characters
    of length length.
    
    :arg str length:
        The random string length. 
    """
    random_text = ''.join([random.choice(string.ascii_letters + " ") for n in range(length)])
    return random_text


def score_string(goal_str, generated_str):
    pass<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.0980835614807761, 'fraction_numerical': 0.011189144149506012, 'mean_word_length': 4.274325172630258, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 179, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '218302', 'license': 'MIT', 'n_tokens_mistral': 2234, 'n_tokens_neox': 2108, 'n_words': 1115, 'path': '1t_DataAnalysisMLPython/1h_Problem_Solving_Algorithms_DS_Python/Chapter_1.ipynb', 'repo_name': 'yevheniyc/C', 'size': '8409'}