From 9e047fdf2c40aa5db91a2c9c6a8fc97abe9f6fa4 Mon Sep 17 00:00:00 2001 From: eduardocerqueira Date: Wed, 12 Feb 2025 17:13:21 +0000 Subject: [PATCH] 2025-02-12 17:13:21.654078 new snippets --- seeker/report.txt | 37 + seeker/snippet/DICT_char_count.py | 11 + seeker/snippet/LIST_output_string.py | 7 + seeker/snippet/crawler.py | 140 + seeker/snippet/electron_patcher.py | 114 + seeker/snippet/enemy.py | 68 + .../snippet/firefox-bookmarks-to-obsidian.py | 210 + seeker/snippet/food.py | 48 + seeker/snippet/get-vscode-commands.sh | 40 - seeker/snippet/homework.py | 333 ++ seeker/snippet/install_v7.sh | 183 - seeker/snippet/main.py | 240 +- seeker/snippet/manage_pack_resources.py | 353 ++ seeker/snippet/pacman.py | 69 + seeker/snippet/practic_basic.py | 4184 +++++++++++++++++ seeker/snippet/query.java | 13 - seeker/snippet/replace_network_id.sh | 17 - seeker/snippet/sample_pipeline.py | 56 + seeker/snippet/segmentio_consumer_lag.go | 145 + seeker/snippet/snake_game.py | 189 + seeker/snippet/terraform-module-mover.sh | 12 - seeker/snippet/testzep.py | 59 - seeker/snippet/wol | 44 - 23 files changed, 6156 insertions(+), 416 deletions(-) create mode 100644 seeker/snippet/DICT_char_count.py create mode 100644 seeker/snippet/LIST_output_string.py create mode 100644 seeker/snippet/crawler.py create mode 100644 seeker/snippet/electron_patcher.py create mode 100644 seeker/snippet/enemy.py create mode 100644 seeker/snippet/firefox-bookmarks-to-obsidian.py create mode 100644 seeker/snippet/food.py delete mode 100644 seeker/snippet/get-vscode-commands.sh create mode 100644 seeker/snippet/homework.py delete mode 100644 seeker/snippet/install_v7.sh create mode 100644 seeker/snippet/manage_pack_resources.py create mode 100644 seeker/snippet/pacman.py create mode 100644 seeker/snippet/practic_basic.py delete mode 100644 seeker/snippet/query.java delete mode 100644 seeker/snippet/replace_network_id.sh create mode 100644 seeker/snippet/sample_pipeline.py create mode 100644 seeker/snippet/segmentio_consumer_lag.go create mode 100644 seeker/snippet/snake_game.py delete mode 100644 seeker/snippet/terraform-module-mover.sh delete mode 100644 seeker/snippet/testzep.py delete mode 100644 seeker/snippet/wol diff --git a/seeker/report.txt b/seeker/report.txt index 06c02289..8a07c665 100644 --- a/seeker/report.txt +++ b/seeker/report.txt @@ -1,3 +1,40 @@ +-------------------------------------------------------------------------------- + 2025-02-12 17:13:21.654078 +-------------------------------------------------------------------------------- + On branch main +Your branch is up to date with 'origin/main'. + +Changes not staged for commit: + (use "git add/rm ..." to update what will be committed) + (use "git restore ..." to discard changes in working directory) + deleted: snippet/get-vscode-commands.sh + deleted: snippet/install_v7.sh + modified: snippet/main.py + deleted: snippet/query.java + deleted: snippet/replace_network_id.sh + deleted: snippet/terraform-module-mover.sh + deleted: snippet/testzep.py + deleted: snippet/wol + +Untracked files: + (use "git add ..." to include in what will be committed) + snippet/DICT_char_count.py + snippet/LIST_output_string.py + snippet/crawler.py + snippet/electron_patcher.py + snippet/enemy.py + snippet/firefox-bookmarks-to-obsidian.py + snippet/food.py + snippet/homework.py + snippet/manage_pack_resources.py + snippet/pacman.py + snippet/practic_basic.py + snippet/sample_pipeline.py + snippet/segmentio_consumer_lag.go + snippet/snake_game.py + +no changes added to commit (use "git add" and/or "git commit -a") + -------------------------------------------------------------------------------- 2025-02-11 17:13:16.853057 -------------------------------------------------------------------------------- diff --git a/seeker/snippet/DICT_char_count.py b/seeker/snippet/DICT_char_count.py new file mode 100644 index 00000000..4007a077 --- /dev/null +++ b/seeker/snippet/DICT_char_count.py @@ -0,0 +1,11 @@ +#date: 2025-02-12T16:54:11Z +#url: https://api.github.com/gists/a292f93a0b84f4ac1fa83837197d5b35 +#owner: https://api.github.com/users/idenise + +stri = "what can I do" +char_d={} +for c in stri: + if c not in char_d: + char_d[c] = 0 + char_d[c] = char_d[c] + 1 +print(char_d) \ No newline at end of file diff --git a/seeker/snippet/LIST_output_string.py b/seeker/snippet/LIST_output_string.py new file mode 100644 index 00000000..076c25e4 --- /dev/null +++ b/seeker/snippet/LIST_output_string.py @@ -0,0 +1,7 @@ +#date: 2025-02-12T16:50:00Z +#url: https://api.github.com/gists/4f80890574f6a5cd7b8a91bd5783176d +#owner: https://api.github.com/users/idenise + +str1 = "OH THE PLACES YOU'LL GO" +output = str1.split() +print(output) \ No newline at end of file diff --git a/seeker/snippet/crawler.py b/seeker/snippet/crawler.py new file mode 100644 index 00000000..43cd78dc --- /dev/null +++ b/seeker/snippet/crawler.py @@ -0,0 +1,140 @@ +#date: 2025-02-12T16:58:29Z +#url: https://api.github.com/gists/c6db3798f9cb0b8c1dd104063e40e5d5 +#owner: https://api.github.com/users/zedr + +import sys +import time +import json +from pathlib import Path + +import pandas as pd +import requests +from bs4 import BeautifulSoup + +# Creo un set: https://docs.python.org/3/tutorial/datastructures.html#sets +# Questo mi permette di aggiungere in tempo O1 (nei casi pratici) +# e verificare la presenza di una chiave sempre in tempo 01. +# Posso fare lo stesso usando i dict, mentre le liste sono +# molto meno efficienti (On per la verifica) +ignored = { + "index.html", + "https://books.toscrape.com/index.html", +} + +# L'URL da cui partire +base_url = "https://books.toscrape.com/" + +financial_keys = ( + 'Price (excl. tax)', + 'Price (incl. tax)', + 'Tax' +) +numerical_keys = ( + "Number of reviews", +) + +data = [] + + +def get_parent_url(url): + """Get the parent of the given URL + + e.g. https://www.example.com/abc/cde.html -> https://www.example.com/abc/ + """ + *parent_parts, _ = url.split("/") + return "/".join(parent_parts) + + +def rows_to_dict(rows): + """Convert a sequence of rows of an HTML table to a dict""" + rows_data = {el.th.text: el.td.text for el in rows} + for key, val in rows_data.items(): + if key in financial_keys: + # Correggi il dato e lo trasformo in decimale + # '£51.77' -> 51.77 + # Per farlo escludo i primi due caratteri + rows_data[key] = float(val[2:]) + if key in numerical_keys: + # Converti il dato in un numero intero + rows_data[key] = int(val) + return rows_data + +def crawl(url): + """Crawl the page at the given URL + Any tables will be added as dicts to the + module-level name "data". + + Perform the crawl using the breadth-first + algorithm (BFS). + """ + + # Prendo la URL base + parent_url = get_parent_url(url) + + # Invio una chiamata GET usando l'URL + response = requests.get(url) + + status_code = response.status_code + if status_code != 200: + raise Exception(f"Il server ha risposto con uno status code inaspettato: {status_code}") + + # Faccio il parsing del HTML della pagina + soup = BeautifulSoup(response.text, features="html.parser") + + # Cerco tutti gli element tr (table row) nella pagina (se ci sono) + rows = soup.find_all("tr") + + # Se li trovo, li converto in un dict e li aggiungo ai dati + row_data = rows_to_dict(rows) + if row_data: + data.append(row_data) + # Aspetto un secondo prima di proseguire + # in modo da non caricare troppo il server + time.sleep(1) + + # Ora cerco tutti i link all'interno della prima sezione della pagina + links = soup.find_all("section")[0].find_all("a") + print(f"Crawled: {url} and found {len(links)} new links and {len(rows)} table rows.", file=sys.stderr) + for link in links: + # Prendo il link (nell'attributo HREF) + link_rel = link.attrs["href"] + + # Ignora i link che tornano indietro + if ".." in link_rel: + continue + + # Se non è un link assoluto (che comincia con "http")... + if not link_rel.startswith("http"): + # ... lo rendo assoluto usando la URL base + url = "/".join([parent_url, link_rel]) + else: + url = link_rel + + # I link esterni vanno ignorati + if not url.startswith(base_url): + continue + + # Se ho già incontrato il link, lo ignoro + if url in ignored: + continue + + # Aggiungo la URL alla lista da ignorare + ignored.add(url) + + # Chiamata ricorsiva + crawl(url) + + +# Faccio partire il crawl +try: + crawl(base_url) +except KeyboardInterrupt: + pass + +# Creo e stampo il dataframe +df = pd.DataFrame(data) +print(df) + +# Salvo i dati JSON in un file per poterli utilizzare dopo +with open("books.json", "w") as fd: + fd.write(json.dumps(data)) \ No newline at end of file diff --git a/seeker/snippet/electron_patcher.py b/seeker/snippet/electron_patcher.py new file mode 100644 index 00000000..0a081faf --- /dev/null +++ b/seeker/snippet/electron_patcher.py @@ -0,0 +1,114 @@ +#date: 2025-02-12T16:56:39Z +#url: https://api.github.com/gists/7373d551ebb11c38a6f7cb8702998dc3 +#owner: https://api.github.com/users/matthew-mclaren + +""" +electron_patcher.py: Enforce 'use-angle@1' in Chrome and Electron applications + +Version 1.0.1 (2025-02-12) +""" + +import enum +import json + +from pathlib import Path + + +class ChromiumSettingsPatcher: + + class AngleVariant(enum.Enum): + Default = "0" + OpenGL = "1" + Metal = "2" + + def __init__(self, state_file: str) -> None: + self._local_state_file = Path(state_file).expanduser() + + + def patch(self) -> None: + """ + Ensure 'use-angle@1' is set in Chrome's experimental settings + """ + _desired_key = "use-angle" + _desired_value = self.AngleVariant.OpenGL.value + + if not self._local_state_file.exists(): + print(" Local State missing, creating...") + self._local_state_file.parent.mkdir(parents=True, exist_ok=True) + state_data = {} + else: + print(" Parsing Local State file") + state_data = json.loads(self._local_state_file.read_bytes()) + + + if "browser" not in state_data: + state_data["browser"] = {} + if "enabled_labs_experiments" not in state_data["browser"]: + state_data["browser"]["enabled_labs_experiments"] = [] + + for key in state_data["browser"]["enabled_labs_experiments"]: + if "@" not in key: + continue + + key_pair = key.split("@") + if len(key_pair) < 2: + continue + if key_pair[0] != _desired_key: + continue + if key_pair[1] == _desired_value: + print(f" {_desired_key}@{_desired_value} is already set") + break + + index = state_data["browser"]["enabled_labs_experiments"].index(key) + state_data["browser"]["enabled_labs_experiments"][index] = f"{_desired_key}@{_desired_value}" + print(f" Updated {_desired_key}@{_desired_value}") + + if f"{_desired_key}@{_desired_value}" not in state_data["browser"]["enabled_labs_experiments"]: + state_data["browser"]["enabled_labs_experiments"].append(f"{_desired_key}@{_desired_value}") + print(f" Added {_desired_key}@{_desired_value}") + + print(" Writing to Local State file") + self._local_state_file.write_text(json.dumps(state_data, indent=4)) + + +def main(): + # Patch all Electron applications + for directory in Path("~/Library/Application Support").expanduser().iterdir(): + if not directory.is_dir(): + continue + + state_file = directory / "Local State" + if not state_file.exists(): + continue + + print(f"Patching {directory.name}") + patcher = ChromiumSettingsPatcher(state_file) + patcher.patch() + + # Patch all Chrome variants + if Path("~/Library/Application Support/Google").expanduser().exists(): + for directory in Path("~/Library/Application Support/Google").expanduser().iterdir(): + if not directory.is_dir(): + continue + + state_file = directory / "Local State" + if not state_file.exists(): + continue + + print(f"Patching {directory.name}") + patcher = ChromiumSettingsPatcher(state_file) + patcher.patch() + + # Patch Microsoft Teams + teams_path = Path( + "~/Library/Containers/com.microsoft.teams2/Data/Library/Application Support/Microsoft/MSTeams/EBWebView/Local State" + ).expanduser() + + if teams_path.exists(): + print("Patching Microsoft Teams") + patcher = ChromiumSettingsPatcher(teams_path) + patcher.patch() + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/seeker/snippet/enemy.py b/seeker/snippet/enemy.py new file mode 100644 index 00000000..ad665c08 --- /dev/null +++ b/seeker/snippet/enemy.py @@ -0,0 +1,68 @@ +#date: 2025-02-12T17:02:37Z +#url: https://api.github.com/gists/8230fe747a806b0d092da288f3f92073 +#owner: https://api.github.com/users/zoeburke + +#ENEMY.PY +import pygame #Importing the pygame module +import random #Importing the random module to be used in the relocate function +#-------------------------------------------------------------------------------- +class Enemy: #Creating the Enemy class, which takes self, x and y coordinates, radius, colour of the enemy and the speed + def __init__(self, x, y, radius, colour, speed): + self._x = x + self._y = y + self._radius = radius + self._colour = colour + self._speed = speed + + def __str__(self): #This is a string representation of the object, which can be called to check the position and colour of the object + return f"Enemy at ({self._x}, {self._y}) with colour {self._colour}" + + def draw(self, display): #This function will draw the enemy as a circle, it takes the parameters of self and display (self having colour, coordinates and radius) + pygame.draw.circle(display, self._colour, [self._x, self._y], self._radius) + + def move(self, direction, display_width=None, display_height=None): #This function moves the enemy based on the direction specified and the speed of the enemy + if direction == "UP": #If the direction is up, the y coordinate decreases by the speed + self._y -= self._speed + if self._y - self._radius < 0: # Move to bottom if it goes beyond the top + self._y = self._radius + elif direction == "DOWN": #If the direction is down, the y coordinate increases by the speed + self._y += self._speed + if display_height and self._y + self._radius > display_height: # Move to top if it goes beyond the bottom + self._y = display_height - self._radius + elif direction == "LEFT": #If the direction is left, the x coordinate decreases by the speed + self._x -= self._speed + if self._x - self._radius < 0: # Move to right edge if it goes beyond the left + self._x = self._radius + elif direction == "RIGHT": #If the direction is right, the x coordinate increases by the speed + self._x += self._speed + if display_width and self._x + self._radius > display_width: # Move to left edge if it goes beyond the right + self._x = display_width - self._radius + + def relocate(self, display_width, display_height): #This function relocates the enemy to a random position on the screen, by setting the x and y coordinates to random integers. + self._x = random.randint(self._radius, display_width - self._radius) + self._y = random.randint(self._radius, display_height - self._radius) + + ''' + The functions below are getters, which return the coordinates and radius so that they can be used within the main file. + ''' + def get_x(self): + return self._x + + def get_y(self): + return self._y + + def get_radius(self): + return self._radius + +#-------------------------------------------------------------------------------- +#CODE SUMMARY +''' +We created this file to contain the Enemy class, which is used to create an enemy object. +The enemy object has attributes such as x and y coordinates, radius, colour and speed. +The class contains methods such as draw, move, relocate and getters for the x and y coordinates and radius. +The draw method is used to draw the enemy as a circle on the screen. +The move method is used to move the enemy in a specified direction with a specified speed. +The relocate method is used to relocate the enemy to a random position on the screen. +The getters are used to get the x and y coordinates and radius of the enemy object. +''' +#-------------------------------------------------------------------------------- \ No newline at end of file diff --git a/seeker/snippet/firefox-bookmarks-to-obsidian.py b/seeker/snippet/firefox-bookmarks-to-obsidian.py new file mode 100644 index 00000000..7a1b9515 --- /dev/null +++ b/seeker/snippet/firefox-bookmarks-to-obsidian.py @@ -0,0 +1,210 @@ +#date: 2025-02-12T16:42:58Z +#url: https://api.github.com/gists/5517b73a7f74e8cbff65ab76983e684c +#owner: https://api.github.com/users/Lu1sDV + +#!/usr/bin/env python3 +import argparse +import os +import configparser +import sqlite3 + +OBSIDIAN_VAULT_PATH = "" +FIREFOX_PROFILE_PATH = "" + +try: + SYSTEM_MAX_PATH_LENGTH = os.pathconf('/', 'PC_PATH_MAX') + SYSTEM_MAX_FILENAME_LENGTH = os.pathconf('/', 'PC_NAME_MAX') +except OSError as e: + print(e) + exit(1) + +def load_firefox_database(db_path): + """Loads bookmarks from a Firefox database file using optimized SQL. + Args: + path (str): The path to the Firefox database file (places.sqlite). + Returns: + list: A list of bookmarks, where each bookmark is a list of tags + (strings) representing the folder hierarchy, and a tuple + containing the bookmark title and URL. Returns empty list if + there are any exceptions. + Example: + [['tag1', 'tag2', ('bookmark_title', 'bookmark_url')]] + """ + books = list() + conn = sqlite3.connect(f"file:{db_path}?mode=ro", uri=True) + cur = conn.cursor() + + try: + res = cur.execute(""" + SELECT + p.url, + bm.title AS bookmark_title, + GROUP_CONCAT(DISTINCT tag_bm.title) AS tags, + bm.parent + FROM + moz_bookmarks bm + JOIN + moz_places p ON bm.fk = p.id + LEFT JOIN + moz_bookmarks tag_bm ON bm.parent = tag_bm.id + WHERE + bm.type = 1 + GROUP BY + p.url, bookmark_title, bm.parent + """) + + for row in res.fetchall(): + url, bookmark_title, tags_str, parent_id = row + bookmark_tags = [] + + # Extract tags and handle hierarchy (simplified, may need further refinement for complex hierarchies) + if tags_str: + bookmark_tags = [tag.strip() for tag in tags_str.split(',')] + + # Fetch parent folder titles - simplified, fetches only immediate parent + parent_tags = [] + current_parent_id = parent_id + while current_parent_id and current_parent_id != 2 and current_parent_id != 1: # Stop at "Bookmarks Menu" (id 2) and "Bookmarks Toolbar" (id 1) + parent_res = cur.execute('SELECT title, parent FROM moz_bookmarks WHERE id=?', (current_parent_id,)) + parent_row = parent_res.fetchone() + if parent_row: + parent_title, current_parent_id = parent_row + parent_tags.append(parent_title) + else: + break # No more parent found + + bookmark_tags.extend(parent_tags) + + + bookmark_title = bookmark_title or '' + bookmark_tags = bookmark_tags[::-1] # Reverse to get correct hierarchy order + bookmark_tags = [tag for tag in bookmark_tags if tag not in ("Bookmarks Menu", "Bookmarks Toolbar")] # Remove Bookmarks Menu and Toolbar + bookmark_tags.append(tuple((bookmark_title, url))) + books.append(bookmark_tags) + + + except Exception as e: + print(f"Database error: {e}") + books = [] + finally: + cur.close() + conn.close() + return books + + +def get_default_firefox_profile_path(): + """ + Finds the default Firefox profile path from the profile.ini file. + + Returns: + str: Path to the default Firefox profile, or None if not found. + """ + mozilla_dir = os.path.expanduser("~/.mozilla/firefox") + profile_ini_path = os.path.join(mozilla_dir, "profiles.ini") + + if not os.path.exists(profile_ini_path): + return None + + config = configparser.ConfigParser() + config.read(profile_ini_path) + + for section in config.sections(): + if section.startswith("Install"): + if "Default" in config[section]: + default_profile_name = config[section]["Default"] + profile_path_relative = default_profile_name + return os.path.join(mozilla_dir, profile_path_relative) + + return None + +def copy_bookmarks_to_obsidian(bookmarks, obsidian_vault_path): + """ + Copies the Firefox bookmarks file to the Obsidian vault. + + Args: + bookmarks (list): List of bookmarks to copy. + obsidian_vault_path (str): Path to the Obsidian vault directory. + Returns: + bool: True if the copy was successful, False otherwise. + """ + + dirs = list() + for i, b in enumerate(bookmarks): + if len(b) == 1: + b.insert(0, "Orphaned") + dirs.append("/".join(b[:-1])) + + dirs = list(set(dirs)) + + [os.makedirs(os.path.join(obsidian_vault_path, d), exist_ok=True) for d in dirs] + + for b in bookmarks: + + bookmark_title, bookmark_url = b[-1] + bookmark_title = bookmark_title.replace('/', "-") # sanitize the title to avoid creating subfolders + bookmark_title = f"{bookmark_title}.md" + bookmark_tags = "/".join(b[:-1]) + + bookmark_path = os.path.join(obsidian_vault_path, bookmark_tags, bookmark_title) + + if len(bookmark_path) > SYSTEM_MAX_PATH_LENGTH: + print(f"Error: Path too long: {bookmark_path}") + continue + + if len(bookmark_title) > SYSTEM_MAX_FILENAME_LENGTH: + print(f"Error: Filename too long: {bookmark_title}") + continue + + with open(bookmark_path, "w") as f: + f.write(f"[{bookmark_title}]({bookmark_url})") + + return True + +def main(): + parser = argparse.ArgumentParser(description="Copy Firefox bookmarks to Obsidian Vault.") + + parser.add_argument( + "--firefox-profile", + type=str, + default=False if FIREFOX_PROFILE_PATH == "" else FIREFOX_PROFILE_PATH, + help="Path to the Firefox profile directory. If not provided, tries to find the default.", + ) + parser.add_argument( + "--obsidian-vault", + type=str, + default=False if OBSIDIAN_VAULT_PATH == "" else OBSIDIAN_VAULT_PATH, + help="Path to the Obsidian Vault directory target folder.", + required=True if OBSIDIAN_VAULT_PATH == "" else False, + ) + + args = parser.parse_args() + + obsidian_vault_path = args.obsidian_vault + firefox_profile_path = args.firefox_profile + + if not args.firefox_profile: + print("Firefox profile path not provided. Trying to find default profile...") + firefox_profile_path = get_default_firefox_profile_path() + if not firefox_profile_path: + print("Error: Could not find default Firefox profile. Please provide the Firefox profile path using --firefox-profile argument.") + return + + print(f"Firefox profile path: {firefox_profile_path}") + if not os.path.exists(firefox_profile_path): + print(f"Error: Firefox profile path not found: {firefox_profile_path}") + return + + if not os.path.exists(obsidian_vault_path): + print(f"Error: Obsidian vault path not found: {obsidian_vault_path}") + return + + bookmarks = load_firefox_database(os.path.join(firefox_profile_path, "places.sqlite")) + + if copy_bookmarks_to_obsidian(bookmarks, obsidian_vault_path): + print("Script finished successfully.") + else: + print("Script finished with errors.") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/seeker/snippet/food.py b/seeker/snippet/food.py new file mode 100644 index 00000000..0c4ac639 --- /dev/null +++ b/seeker/snippet/food.py @@ -0,0 +1,48 @@ +#date: 2025-02-12T17:02:37Z +#url: https://api.github.com/gists/8230fe747a806b0d092da288f3f92073 +#owner: https://api.github.com/users/zoeburke + +#FOOD.PY +import pygame #Importing the pygame module +import random #Importing the random module to be used in the relocate function + +#-------------------------------------------------------------------------------- + +class Food: #Creating the Food class, which takes self, x and y coordinates, radius and colour of the food + def __init__(self, x, y, radius, colour): + self._x = x + self._y = y + self._radius = radius + self._colour = colour #Used an instance variable here instead of specifying the colour within the class so that the colour can be changed in the main file and allows for more flexibility. + + def __str__(self): #This is a string representation of the object, which can be called to check the position and colour of the object + return f"Food at ({self._x}, {self._y}) with colour {self._colour}" + + def draw(self, display): #This function will draw the food as a circle, it takes the parameters of self and display (self having colour, coordinates and radius) + pygame.draw.circle(display, self._colour, (self._x, self._y), self._radius) + + def relocate(self, display_width, display_height): #This function relocates the food to a random position on the screen, by setting the x and y coordinates to random integers. + self._x = random.randint(self._radius, display_width - self._radius) #This is done to ensure that the food does not disappear off the screen. + self._y = random.randint(self._radius, display_height - self._radius) + + def get_x(self): #This function returns the x coordinate of the food + return self._x + + def get_y(self): #This function returns the y coordinate of the food + return self._y + + def get_radius(self): #This function returns the radius of the food + return self._radius + +#-------------------------------------------------------------------------------- +#CODE SUMMARY +''' +This file has all of the code for the food class, which is used to create a food object within the game for the Pacman and Enemy to chase. +The food object has attributes such as x and y coordinates, radius and colour. +The class contains methods such as draw, relocate and getters for the x and y coordinates and radius. +The draw method is used to draw the food as a circle on the screen. +The relocate method is used to relocate the food to a random position on the screen. +The getters are used to get the x and y coordinates and radius of the food object. +''' + +#-------------------------------------------------------------------------------- \ No newline at end of file diff --git a/seeker/snippet/get-vscode-commands.sh b/seeker/snippet/get-vscode-commands.sh deleted file mode 100644 index 24a508c8..00000000 --- a/seeker/snippet/get-vscode-commands.sh +++ /dev/null @@ -1,40 +0,0 @@ -#date: 2025-02-10T17:07:48Z -#url: https://api.github.com/gists/08ac86fc0cc72817d6c715b759961c82 -#owner: https://api.github.com/users/tgran2028 - -#!/bin/bash - -# manually save the default keybindings to a file -defaults="$TEMP/keybindings.vscode-default.jsonc" - -mapfile -t used_commands < <( - jsonc read < "$defaults" | - jq -M '.[].command' | - xargs -n1 -) - -mapfile -t unused_commands < <( - grep -E '^[[:space:]]*\/\/[[:space:]]*-[[:space:]]+[A-Za-z0-9_.-]+' "$defaults" | - sed -E 's/^[[:space:]]*\/\/[[:space:]]*-[[:space:]]+//' | - xargs -n1d -) - -declare -a commands=( "${used_commands[@]}" "${unused_commands[@]}" ) - -# Capture commands as JSON array -commands_json=$(printf "%s\n" "${commands[@]}" | grep -v '^$' | jq -R . | jq -s .) - -# Build extensions JSON array: -# This command produces one JSON object per extension, assuming that each non-empty line -# from code-insider --list-extensions --show-versions consists of two fields: id and version. -extensions_json=$(code --list-extensions --show-versions | awk 'NF {print "{\"id\":\"" $1 "\",\"version\":\"" $2 "\"}"}' | jq -s .) - -# Build the final JSON object with metadata and the commands array. -jq -n \ - --arg vscode "code" \ - --arg current_datetime "$(date +'%Y-%m-%dT%H:%M:%S%z')" \ - --arg version "$(code --version | head -n1)" \ - --argjson extensions "$extensions_json" \ - --argjson commands "$commands_json" \ - '{vscode: $vscode, current_datetime: $current_datetime, version: $version, extensions: $extensions, commands: $commands}' >| commands.json - diff --git a/seeker/snippet/homework.py b/seeker/snippet/homework.py new file mode 100644 index 00000000..1f180d9b --- /dev/null +++ b/seeker/snippet/homework.py @@ -0,0 +1,333 @@ +#date: 2025-02-12T16:55:44Z +#url: https://api.github.com/gists/59e26e9ddf87254a2b35b2e23a6d30ed +#owner: https://api.github.com/users/bnszekely + +# HOMEWORK: Dictionaries +# Read carefully until the end before you start solving the exercises. + +# Basic Dictionary + +# Create an empty dictionary and then add a few of your friends. Make the key their email (can be fake) +# and the value their name. When you're done, create the same dictionary as a pre-populated dictionary. +friends = {} + +friends['jess@gmail.com'] = 'Jess' +friends['justin@gmail.com'] = 'Justin' +friends['bob@gmail.com'] = 'Bob' +# ---------------------------------------------------------------------------------------------------------------------- + +# Nested Dictionary + +# Create a nested dictionary for a list of 5 company employees. +# The key should be their employee id (an integer from 1-5 will do) and the value should be a dictionary with +# the name, department and salary of the employee. + +employees = { + 1: { + 'name': 'Bob', + 'department': 'HR', + 'salary': '45K' + }, + 2: { + 'name': 'Barry', + 'department': 'Marketing', + 'salary': '55K' + }, + 3: { + 'name': 'Mary', + 'department': 'Customer Service', + 'salary': '40K' + }, + 4: { + 'name': 'Mark', + 'department': 'IT', + 'salary': '65K' + }, + 5: { + 'name': 'Dan', + 'department': 'Real Estate', + 'salary': '45K' + } +} + + +# ---------------------------------------------------------------------------------------------------------------------- + +# Accessing Values + +# Use the previous nested dictionary and write some print statements that will answer the following: + +# - Print a list of the employee IDs +# - Print the employee data for employee with the ID 3. +# - Loop over the employees and print all their names and salaries. +print(list(employees.keys())) + +print(employees[3]) + +for employee_id in employees: + print(employees[employee_id]['name'], "-", employees[employee_id]['salary']) +# ---------------------------------------------------------------------------------------------------------------------- + +# Updating Values + +# We have the following dictionary with employee salaries. + +salaries = { + 'james' : 10000, + 'tom' : 15000, + 'ryan' : 16000, + 'julia' : 17000 +} + +# We need to increase everyone's salary by 1,000 and also add a new employee joseph with a salary of 18,000. +# Please come up with a way to do this using update() + +revised_salaries = { + 'james': 11000, + 'tom': 16000, + 'ryan': 17000, + 'julia': 18000, + 'joseph': 18000, +} + +salaries.update(revised_salaries) +print(salaries) +# ---------------------------------------------------------------------------------------------------------------------- + +# Deleting Values + +# You remember those employees from Updating Values section? Well, Julia got fired, so we need to remove her +# name from the salaries dictionary. How would you do that? + +salaries.pop('julia') +print(salaries) + +# ---------------------------------------------------------------------------------------------------------------------- + +# Iterating over Dictionaries + +# Given the list of movies below, please use view objects (keys(), values(), items() - where necessary) to answer +# the questions: + +# - Is Black Panther in the list of movies? +# - Is there any movie for the year 2021? +# - Print a message for each element that shows the year, the title and the position in the dictionary (1-5). +# Hint: use a counter. + +films = { + 2016: "Star Wars: Episode VII - The Force Awakens", + 2017: "Star Wars: Episode VIII - The Last Jedi", + 2018: "Black Panther", + 2019: "Avengers: Endgame", + 2020: "Bad Boys for Life" +} +print('Black Panther' in films.values()) +print(2021 in films) +counter = 1 +for year, title in films.items(): + print(f"{counter}. In {year}, the movie '{title}' was released.") + counter +=1 +# ---------------------------------------------------------------------------------------------------------------------- + +# Exercise 1. Animal Shelter Volunteer + +# You volunteer in a local animal shelter and you've stored information +# about different pets in a Python dictionary. +# Your task is to create a Python program that helps you: + +# - Access the age of specific pets by their names. +# - Find out which pets are not yet adopted. +# - Identify the most common animal type in the shelter (e.g., dog, cat). + +# Pre-code +# Initialize the shelter_pets dictionary +shelter_pets = { + 'Whiskers': {'Age': 2, 'Type': 'Cat', 'Adopted': False}, + 'Fido': {'Age': 4, 'Type': 'Dog', 'Adopted': True}, + 'Patch': {'Age': 1, 'Type': 'Dog', 'Adopted': False}, + 'Snowball': {'Age': 3, 'Type': 'Rabbit', 'Adopted': True} + } + +# Access and print the age of Whiskers +print(shelter_pets['Whiskers']['Age']) # Should output 2 + +# Access and print if Patch is a dog or cat +print(shelter_pets['Patch']['Type']) + +# Access and print if Snowball is adopted or not +print(shelter_pets['Snowball']['Adopted']) + +# Find out which pets are not yet adopted and print their names +for pet_name, pet_info in shelter_pets.items(): + if not pet_info['Adopted']: + print(pet_name) + +# ---------------------------------------------------------------------------------------------------------------------- + +# Exercise 2. Best - selling books + +# Create a Python program to manage a collection of best-selling books +# and their publication years. Your initial list of best-selling books may have inaccuracies +# or could be outdated. Therefore, you'll also practice updating single and multiple entries +# in your dictionary. Specifically, you will: + +# - Update the title of a book for a specific year due to a naming convention change. +# - Update the titles for multiple books at once based on new sales data. +# - Delete a book and its year from the collection as it's no longer considered a best-seller. +# - Print the title of the book published in a specific year. + +# Pre-code: +# Initialize a dictionary called best_selling_books to store your collection. + +best_selling_books = { + 1997: "Harry Potter and the Philosopher's Stone", + 1984: "Neuromancer", + 2003: "The Kite Runner", + 2015: "Go Set a Watchman" + } + +# The U.S. title for the Harry Potter book published in 1997 is "Harry Potter and the Sorcerer's Stone". +# Update the title to its U.S. version. +best_selling_books[1997] = "Harry Potter and the Sorcerer's Stone" + +# New sales data reveals that "The Hunt for Red October" was the actual best-seller for 1984 +# and "The Da Vinci Code" for 2003. +# Update these in a single operation. + +best_selling_books.update({ + 1984: "The Hunt for Red October", + 2003: "The Da Vinci Code", +}) + +# The book published in 2015, "Go Set a Watchman," is no longer considered a best-seller. +# Use the del keyword to remove this entry from the dictionary. + +del best_selling_books[2015] + +# Print the updated dictionary of best selling books. +print(best_selling_books) +# ---------------------------------------------------------------------------------------------------------------------- + +# Exercise 3. Manage Music Collection +# Create a Python program that manages a collection of music albums and their release years. +# You will use a dictionary where the keys are the release years and the values are the names of albums. +# The program should allow you to: + +# - Print all the release years (keys) from the dictionary. +# - Print all the album names (values) from the dictionary. +# - Print both the release years and album names together. +# - Check if a particular year or album exists in the collection. + + +# Steps and pre-code +# Initialize a dictionary to store Bob Dylan's albums +dylan_albums = { + 1962: "Bob Dylan", + 1963: "The Freewheelin' Bob Dylan", + 1975: "Blood on the Tracks", + 1997: "Time Out of Mind" +} + +# Use .keys() to loop through and print out all the release years +for year in dylan_albums.keys(): + print(year) + +# Use .values() to loop through and print out all the album names +for album_name in dylan_albums.values(): + print(album_name) + +# Use .items() to loop through and print out both the release year and album name + +for year, album_name in dylan_albums.items(): + print(year, album_name) + +if 1998 in dylan_albums.keys(): + print('True') +else: + print('False') +# Use the 'in' keyword to check if a particular year or album is in the dictionary (pick any year and any album) +# Remember the keyword by default checks only the keys, not the values. +# If you want to check if a particular value (in this case, an album name), +# you need to specify that you're searching within the dictionary's values. + +# ---------------------------------------------------------------------------------------------------------------------- + +# Exercise 4. Remove duplicates +# Remove duplicates from the following dictionary: +person = { + 'first': 'Jeff', + 'name': 'Jeff', + 'last': 'Smith', + 'last_name': 'Smith', + 'state': 'CA', + 'age': 55 +} + +del person['first'] +del person['last'] +print(person) + +# Steps: +# - Create a dict person +# - Create an empty dictionary result = {} +# - Make a for loop to iterate over person dictionary +# - If item’s value not in result dict, add key value part into result. + +person = { + 'Name': 'Brittany', + 'Age': 40, + 'City': 'Beulah' +} + +result = {} + +for key, value in person.items(): + if value not in result.values(): + result[key] = value + +print(result) + + +# ---------------------------------------------------------------------------------------------------------------------- + +# Exercise 5. Find the highest score +# Create a Python function named find_max_score that takes a dictionary of names and scores as an argument. +# The function should return the name and score of the person with the highest score in the form of a dictionary. + +# Sample test_scores dictionary +test_scores = { + 'James': 83, + 'Julia': 91, + 'Ryan': 90, + 'Maria': 80, + 'David': 79, + 'Adam': 96, + 'Jennifer': 97, + 'Susan': 77 + } + +# Find the person with the highest test score and display both their name and score + +# Steps: +# - Define a function called find_max_score that takes one argument, scores_dict, which is a dictionary of names +# (as keys) and scores (as values). +# - Create an empty result variable +# - Assume the initial maximum score is 0 +# - Iterate over each key-value pair in the test_scores, using the .items() method +# - Check if the current score (v) is >= to the current maximum score +# - If so, update the max score and assign the key-value pair to the result +# - Return result and test the function + +def find_max_score(scores_dict): + max_score = 0 + result = None + + for name, score in scores_dict.items(): + if score >= max_score: + max_score = score + result = (name, score) + + return result + +highest_scorer = find_max_score(test_scores) +print(f'The highest scorer is {highest_scorer[0]} with a score of {highest_scorer[1]}') \ No newline at end of file diff --git a/seeker/snippet/install_v7.sh b/seeker/snippet/install_v7.sh deleted file mode 100644 index 3bb05842..00000000 --- a/seeker/snippet/install_v7.sh +++ /dev/null @@ -1,183 +0,0 @@ -#date: 2025-02-10T16:55:38Z -#url: https://api.github.com/gists/da1b4302afac8e0edd8d2af9100c2967 -#owner: https://api.github.com/users/EvilSupahFly - -#!/usr/bin/env bash - -# Function to check if color output is supported -supports_color() { - if ! [ -t 1 ]; then - return 1 # No color support (output is being piped) - fi - - if command -v tput &> /dev/null && [ "$(tput colors)" -ge 8 ]; then - return 0 # Supports color - fi - - return 1 # No color support -} - -# Define colors only if supported -if supports_color; then - RED=$(tput setaf 1) - GREEN=$(tput setaf 2) - YELLOW=$(tput setaf 3) - PURPLE=$(tput setaf 5) - WHITE=$(tput setaf 7) - RESET=$(tput sgr0) -else - RED="" - GREEN="" - YELLOW="" - PURPLE="" - WHITE="" - RESET="" -fi - -# Enable case-insensitive globbing for better directory matching -shopt -s nocaseglob - -# Function to determine the package manager -detect_package_manager() { - if command -v apt &> /dev/null; then - echo "apt" - elif command -v dnf &> /dev/null; then - echo "dnf" - elif command -v pacman &> /dev/null; then - echo "pacman" - elif command -v zypper &> /dev/null; then - echo "zypper" - elif command -v yum &> /dev/null; then - echo "yum" - elif command -v brew &> /dev/null; then - echo "brew" - else - echo "unknown" - fi -} - -# Function to install missing dependencies -install_package() { - local package="$1" - local manager - manager=$(detect_package_manager) - - if [ "$manager" = "unknown" ]; then - echo -e "${RED}Could not detect a package manager. Please install $package manually.${RESET}" - exit 1 - fi - - echo -e "${YELLOW}$package is missing. Would you like to install it now? (y/n)${RESET}" - read -rp "Enter choice: " choice - - if [[ "$choice" =~ ^[Yy]$ ]]; then - case "$manager" in - apt) sudo apt update && sudo apt install -y "$package" ;; - dnf) sudo dnf install -y "$package" ;; - pacman) sudo pacman -Sy --noconfirm "$package" ;; - zypper) sudo zypper install -y "$package" ;; - yum) sudo yum install -y "$package" ;; - brew) brew install "$package" ;; - esac - - if command -v "$package" &> /dev/null; then - echo -e "${GREEN}$package installed successfully.${RESET}" - else - echo -e "${RED}Failed to install $package. Please install it manually.${RESET}" - exit 1 - fi - else - echo -e "${RED}$package is required to run this script. Exiting.${RESET}" - exit 1 - fi -} - -# Check for required dependencies -for cmd in wine curl jq; do - if ! command -v "$cmd" &> /dev/null; then - install_package "$cmd" - fi -done - -# Ensure script is not run as root -if [ "$EUID" -eq 0 ]; then - echo -e "${RED}Do not run this script as root. Exiting.${RESET}" - exit 1 -fi - -# Function to list and select a directory -select_directory() { - local search_dir="$1" - local dirs=("$search_dir"/*/) - - if [ "${#dirs[@]}" -eq 0 ]; then - echo -e "${RED}No directories found in $search_dir.${RESET}" - return 1 - fi - - echo -e "${WHITE}Select a directory:${RESET}" - for i in "${!dirs[@]}"; do - echo -e "${GREEN}$((i + 1)).${RESET} ${YELLOW}${dirs[$i]##*/}${RESET}" - done - - local choice - while true; do - read -rp "Enter the number of the directory: " choice - if [[ "$choice" -ge 1 && "$choice" -le "${#dirs[@]}" ]]; then - echo "${dirs[$((choice - 1))]}" - return 0 - else - echo -e "${RED}Invalid selection. Please try again.${RESET}" - fi - done -} - -# Function to confirm settings before proceeding -final_confirmation() { - while true; do - echo -e "${PURPLE}-------------------------------------${RESET}" - echo -e "${WHITE} Final Confirmation${RESET}" - echo -e "${PURPLE}-------------------------------------${RESET}" - echo -e "${GREEN}1.${RESET} WINE Prefix: ${YELLOW}$WINEPREFIX${RESET}" - echo -e "${GREEN}2.${RESET} Installer Path: ${YELLOW}${INSTALLER_PATH:-'Not Set'}${RESET}" - echo -e "${GREEN}3.${RESET} Selected EXE: ${YELLOW}${GAME_EXE_PATH:-'Not Set'}${RESET}" - echo -e "${GREEN}4.${RESET} Proceed with installation" - echo -e "${GREEN}5.${RESET} Cancel Installation" - echo -e "${PURPLE}-------------------------------------${RESET}" - - read -rp "Select an option to modify or confirm (1-5): " choice - case "$choice" in - 1) read -rp "Enter new WINE prefix: " WINEPREFIX ;; - 2) read -rp "Enter new installer path: " INSTALLER_PATH ;; - 3) GAME_EXE_PATH=$(select_directory "$HOME/Games") ;; - 4) echo -e "${GREEN}Proceeding with installation...${RESET}"; break ;; - 5) echo -e "${RED}Installation canceled.${RESET}"; exit 1 ;; - *) echo -e "${RED}Invalid choice, please try again.${RESET}" ;; - esac - done -} - -# Start script execution -echo -e "${WHITE}Welcome to the WINE Game Installer!${RESET}" -echo -e "${WHITE}Scanning for game directories...${RESET}" - -GAMES_DIR="$HOME/Games" -SELECTED_DIR=$(select_directory "$GAMES_DIR") -if [ -z "$SELECTED_DIR" ]; then - echo -e "${RED}No valid game directory selected. Exiting.${RESET}" - exit 1 -fi - -WINEPREFIX="$HOME/.wine" -INSTALLER_PATH="$SELECTED_DIR/installer.exe" -GAME_EXE_PATH="$SELECTED_DIR/game.exe" - -final_confirmation - -# Run the installer -if [ -f "$INSTALLER_PATH" ]; then - echo -e "${WHITE}Running installer: ${YELLOW}$INSTALLER_PATH${RESET}" - wine "$INSTALLER_PATH" -fi - -echo -e "${GREEN}Installation complete!${RESET}" diff --git a/seeker/snippet/main.py b/seeker/snippet/main.py index d378f6e8..8fe2d0b2 100644 --- a/seeker/snippet/main.py +++ b/seeker/snippet/main.py @@ -1,49 +1,193 @@ -#date: 2025-02-11T16:58:40Z -#url: https://api.github.com/gists/72f5143d27d6af35dc1ecb0a56aafd1a -#owner: https://api.github.com/users/kakira9618 - -import numpy as np -import matplotlib.pyplot as plt -import japanize_matplotlib -from scipy.special import gamma - -def generalized_normal_pdf(x, beta, mu=0): - """ - 分散を1に標準化した一般化正規分布の確率密度関数を返す。 - パラメータ: - beta : 形状パラメータ - mu : 平均(ここでは 0 とする) - """ - # 分散1にするためのα - alpha = np.sqrt(gamma(1/beta) / gamma(3/beta)) - coeff = beta / (2 * alpha * gamma(1/beta)) - return coeff * np.exp(- (np.abs(x-mu) / alpha)**beta) - -def excess_kurtosis(beta): - """ - 一般化正規分布の理論上の尖度(第四中心モーメント/分散の2乗)から余尖度を返す。 - """ - kurt = (gamma(5/beta) * gamma(1/beta)) / (gamma(3/beta)**2) - return kurt - 3 - -# 描画用のx軸の範囲(重たい裾の場合を考慮して広めに) -x = np.linspace(-5, 5, 1000) - -# 比較する β の値:β=1 (leptokurtic), β=2 (正規分布), β=4 (platykurtic) -beta_values = [1, 2, 4] -colors = ['blue', 'green', 'red'] - -plt.figure(figsize=(8, 5)) -for beta, color in zip(beta_values, colors): - pdf = generalized_normal_pdf(x, beta) - exc_kurt = excess_kurtosis(beta) - label = f"β = {beta}, excess kurtosis = {exc_kurt:.2f}" - plt.plot(x, pdf, label=label, color=color, lw=2) - -plt.title("一般化正規分布の確率密度 (分散=1)") -plt.xlabel("x") -plt.ylabel("Probability Density") -plt.legend() -plt.grid(True) -plt.show() +#date: 2025-02-12T17:02:37Z +#url: https://api.github.com/gists/8230fe747a806b0d092da288f3f92073 +#owner: https://api.github.com/users/zoeburke +#MAIN.PY +from pacman import Pacman +from enemy import Enemy +from food import Food +import pygame +import random + +''' +The above section imports the classes Pacman, Enemy and Food from their respective files. +Pacman, Enemy, and Food are implemented as separate classes to ensure modularity. +This allows for easier debugging, testing, and modification of individual game components without affecting the rest of the code. +Each class handles its own data (position, movement, and drawing), following object-oriented programming principles. +It also imports the pygame module so we can use those features, and also the random mdoule to generate random numbers for the food and enemy +''' +#-------------------------------------------------------------------------------- +pygame.init() # Initialise the pygame module + +# Setup +DISPLAY_WIDTH = 500 +DISPLAY_HEIGHT = 500 +DISPLAY_SIZE = (DISPLAY_WIDTH, DISPLAY_HEIGHT) + +# Creating a display window +display = pygame.display.set_mode(DISPLAY_SIZE) + +# Characteristics of the display +black = (0, 0, 0) +clock = pygame.time.Clock() # Clock object to control the frame rate + +# Creating Pacman +''' +Creating an instance of the Pacman class inputting the coordinates, radius, colour and speed of the pacman. +''' +pacman = Pacman(DISPLAY_WIDTH // 2, 50, 20,(252, 3, 198), 3) + +# Creating Enemy +''' +Creating an instance of the Enemy class inputting the coordinates, radius, colour and speed of the enemy. +''' +enemy = Enemy(250, 400, 20, (200, 75, 250), 1) + +# Creating Food +''' +Creating an instance of the food class inputting the coordinates, radius and colour of the food. +''' +food = Food(random.randint(20, DISPLAY_WIDTH - 20), random.randint(20, DISPLAY_HEIGHT - 20), 10, (242, 216, 237)) + +#-------------------------------------------------------------------------------- + +# GAME LOOP +''' +This section of code is the game loop. It runs the game until the user quits the game. +It also checks for user input through key presses and key releases to move the pacman in the desired direction. +First, we have to set run_game to True to run the game. We also have to set the direction of the pacman to False initially. +This is done to prevent the pacman from moving in multiple directions at the same time, and wait for user input. + +''' +run_game = True +is_moving_down = False +is_moving_up = False +is_moving_left = False +is_moving_right = False + +while run_game: + display.fill(black) # Fill the display with black colour + + pacman.draw(display) # Draw Pacman + enemy.draw(display) # Draw the enemy + food.draw(display) # Draw the food + + for event in pygame.event.get(): # Check for events + ''' + Event-driven programming is essential for interactive games because + it allows the game to respond to user inputs (like key presses) and system events (like quitting the game). + This approach ensures smooth gameplay, as actions occur based on events rather than a fixed sequence of commands. + ''' + if event.type == pygame.QUIT: # If the user quits the game, set run_game to False + run_game = False + elif event.type == pygame.KEYDOWN: # If the user presses a key, check which key it is + if event.key == pygame.K_DOWN: # If the key is the down key, set the direction of Pacman to down + is_moving_down = True # Set the direction of the pacman to down + ''' + The following lines of code ensure that Pacman can only move in one direction at a time. If these were + not set to false, the controls would not work as anticipated and Pacman would be attempting to move + in different directions at the same time. + ''' + is_moving_up = False + is_moving_left = False + is_moving_right = False + if event.key == pygame.K_UP: # If the key is the up key, set the direction of Pacman to up + is_moving_up = True # Set the direction of the pacman to up, and so on for the rest of these keys. + is_moving_down = False #As above! + is_moving_left = False + is_moving_right = False + if event.key == pygame.K_LEFT: # If the key is the left key, set the direction of Pacman to left + is_moving_left = True + is_moving_right = False + is_moving_up = False + is_moving_down = False + if event.key == pygame.K_RIGHT: # If the key is the right key, set the direction of Pacman to right + is_moving_right = True + is_moving_left = False + is_moving_up = False + is_moving_down = False + elif event.type == pygame.KEYUP: # If the user releases a key, check which key it is + if event.key == pygame.K_DOWN: # If the key is the down key, set the direction of Pacman to False + is_moving_down = False + if event.key == pygame.K_UP: # If the key is the up key, set the direction of Pacman to False + is_moving_up = False + if event.key == pygame.K_LEFT: # If the key is the left key, set the direction of Pacman to False + is_moving_left = False + if event.key == pygame.K_RIGHT: # If the key is the right key, set the direction of Pacman to False + is_moving_right = False + ''' + The above section unsures that Pacman stops moving when the player releases the key specified. + ''' +#-------------------------------------------------------------------------------- + # IMPLEMENTING MOVEMENT AND COLLISIONS + ''' + The below section of code implements the functions defined in pacman.py, enemy.py and food.py to + move Pacman, move the enemy and check for collisions between Pacman, the enemy and the food. + ''' + + #Pacman + if is_moving_down: + pacman.move_down(DISPLAY_HEIGHT) + if is_moving_up: + pacman.move_up(DISPLAY_HEIGHT) + if is_moving_left: + pacman.move_left(DISPLAY_WIDTH) + if is_moving_right: + pacman.move_right(DISPLAY_WIDTH) + + #Enemy + ''' + This section of code ensures that the enemy follows the food by moving towards it whereever its position is. + ''' + if enemy.get_x() < food.get_x(): # If the enemy is to the left of the food, move right + enemy.move("RIGHT", DISPLAY_WIDTH, DISPLAY_HEIGHT) #Display width and height are passed as arguments to ensure the enemy does not go off the screen + elif enemy.get_x() > food.get_x(): # If the enemy is to the right of the food, move left + enemy.move("LEFT", DISPLAY_WIDTH, DISPLAY_HEIGHT) + if enemy.get_y() < food.get_y(): # If the enemy is above the food, move down + enemy.move("DOWN", DISPLAY_WIDTH, DISPLAY_HEIGHT) + elif enemy.get_y() > food.get_y(): # If the enemy is below the food, move up + enemy.move("UP", DISPLAY_WIDTH, DISPLAY_HEIGHT) + + #Collisions + ''' + This section of code checks for collisions between Pacman, the enemy and the food. + If Pacman collides with the food, Pacman and the food are relocated to a random position on the screen. + This is done by calling the relocate method from the Pacman and Food classes. + We use getters to get the x and y coordinates of the circles and see are they overlapping. + Collision detection is based on the distance formula: (x1 - x2)^2 + (y1 - y2)^2 < (r1 + r2)^2. + This checks if the distance between two objects is less than the sum of their radii, indicating an overlap (i.e., a collision). + ''' + + if (pacman.get_x() - food.get_x())**2 + (pacman.get_y() - food.get_y())**2 < (pacman.get_radius() + food.get_radius())**2: + pacman.relocate(DISPLAY_WIDTH, DISPLAY_HEIGHT) + food.relocate(DISPLAY_WIDTH, DISPLAY_HEIGHT) + if (enemy.get_x() - food.get_x())**2 + (enemy.get_y() - food.get_y())**2 < (enemy.get_radius() + food.get_radius())**2: + enemy.relocate(DISPLAY_WIDTH, DISPLAY_HEIGHT) + food.relocate(DISPLAY_WIDTH, DISPLAY_HEIGHT) + if (enemy.get_x() - pacman.get_x())**2 + (enemy.get_y() - pacman.get_y())**2 < (enemy.get_radius() + pacman.get_radius())**2: + enemy.relocate(DISPLAY_WIDTH, DISPLAY_HEIGHT) + pacman.relocate(DISPLAY_WIDTH, DISPLAY_HEIGHT) + + pygame.display.update() # Update the display so the changes are visible + clock.tick(60) # Set the frame rate to 60 frames per second + +pygame.quit() # Quit the game +quit() # Exit the program +#These are both used so that the game quits and the program also exits when the user closes the game window. + +#-------------------------------------------------------------------------------- +#CODE SUMMARY +''' + +The main.py file is the main file that runs the game. It imports the classes from other files, and then uses these within the main game. +We start by importing the pygame module and the random module, so that all the pygame functionality can be used along with the random number generation. +We then import the classes from the other files (pacman.py, enemy.py and food.py) +The window is set up using DISPLAY_WIDTH and DISPLAY_HEIGHT +A clock object is created to control the frame rate of the game +We create instances of the Pacman, Enemy and Food classes, passing in the required parameters +We set the run_game variable to True to run the game, and set the direction of the pacman to False initially +We then enter the game loop, which runs until the user quits the game. + +''' + +#-------------------------------------------------------------------------------- \ No newline at end of file diff --git a/seeker/snippet/manage_pack_resources.py b/seeker/snippet/manage_pack_resources.py new file mode 100644 index 00000000..5b6d4de9 --- /dev/null +++ b/seeker/snippet/manage_pack_resources.py @@ -0,0 +1,353 @@ +#date: 2025-02-12T16:59:19Z +#url: https://api.github.com/gists/f8d550f7fec40b5ae658b321881f3cd9 +#owner: https://api.github.com/users/cognifloyd + +import os +import pathlib +import time +from collections import defaultdict +from typing import DefaultDict, Dict, TYPE_CHECKING, Union, Optional +from urllib.parse import urlparse + +# noinspection PyPackageRequirements +import yaml + +# noinspection PyPackageRequirements +from st2client.commands.action import ( + LIVEACTION_STATUS_CANCELING, + LIVEACTION_STATUS_ABANDONED, + LIVEACTION_STATUS_CANCELED, + LIVEACTION_STATUS_FAILED, + LIVEACTION_STATUS_TIMED_OUT, + LIVEACTION_STATUS_SUCCEEDED, + LIVEACTION_STATUS_RUNNING, + LIVEACTION_STATUS_DELAYED, + LIVEACTION_STATUS_PAUSED, + LIVEACTION_STATUS_PAUSING, + LIVEACTION_STATUS_SCHEDULED, + LIVEACTION_STATUS_REQUESTED, +) + +# noinspection PyPackageRequirements +from st2client.models import LiveAction + +# noinspection PyPackageRequirements +from urllib3 import disable_warnings + +if TYPE_CHECKING: + from python_runner.python_action_wrapper import ActionService + +# noinspection PyPackageRequirements +from st2client.client import Client +from st2common.config import cfg +from st2common.runners.base_action import Action + +# These are known resources that we can enable/disable +# key is resource_type in pack_resources.yaml +# value is resource_type used in st2client.client.Client.managers +RESOURCE_TYPES_MAP = { + "rules": "Rule", + "policies": "Policy", + "sensors": "Sensor", + "triggers": "Trigger", + "actions": "Action", + "aliases": "ActionAlias", +} + +# Some constants helpful to execute st2 actions +ST2_TERMINAL_STATUSES = [ + LIVEACTION_STATUS_CANCELING, + LIVEACTION_STATUS_ABANDONED, + LIVEACTION_STATUS_CANCELED, + LIVEACTION_STATUS_FAILED, + LIVEACTION_STATUS_TIMED_OUT, +] + +ST2_SUCCESSFUL_STATUSES = [LIVEACTION_STATUS_SUCCEEDED] + +ST2_RUNNING_STATUSES = [ + LIVEACTION_STATUS_RUNNING, + LIVEACTION_STATUS_DELAYED, + LIVEACTION_STATUS_PAUSED, + LIVEACTION_STATUS_PAUSING, + LIVEACTION_STATUS_SCHEDULED, +] + +PENDING_STATUSES = [ + LIVEACTION_STATUS_REQUESTED, + LIVEACTION_STATUS_SCHEDULED, + LIVEACTION_STATUS_RUNNING, + LIVEACTION_STATUS_CANCELING, +] + +RUNNING_STATUSES = [LIVEACTION_STATUS_SCHEDULED, LIVEACTION_STATUS_RUNNING] + +# Max execution time per action by default (in seconds) +MAX_DEFAULT_TIME_WAIT = 300 +# Max time to wait after kicking off action execution (in seconds) +MAX_ACTION_KICK_OFF_TIME = 10 +# Poll interval (in seconds) +ACTION_EXECUTION_POLL_INTERVAL = 2 + + +def make_fake_result(result: dict, final_res: bool) -> dict: + # this is to imitate success or failure for executed actions when final success is + # determined later + if final_res: + result["want_enabled"] = result["enabled_after"] = True + else: + result["want_enabled"] = True + result["enabled_after"] = False + return result + + +class ManagePackResources(Action): + if TYPE_CHECKING: + action_service: ActionService + + def __init__(self, config=None, action_service=None): + super().__init__(config, action_service) + if not config.get("local_test_with"): + try: + webui_base_url = urlparse(cfg.CONF.webui.webui_base_url) + # noinspection PyTypeChecker + self.webui_base_domain: str = webui_base_url.hostname + except Exception as exc: + self.logger.warning( + "Could not parse cfg.CONF.webui.webui_base_url: {}".format(exc) + ) + try: + webui_base_url = urlparse(os.environ.get("ST2_API_URL")) + # noinspection PyTypeChecker + self.webui_base_domain: str = webui_base_url.hostname + except Exception as exc: + self.logger.warning( + "Could not parse env var ST2_API_URL: {}".format(exc) + ) + raise exc + else: + self.webui_base_domain: str = config.get("local_test_with") + disable_warnings() + + self.client = Client() + self.check_mode = False + + def run(self, from_packs: list = None, check_mode=False): + self.check_mode = check_mode + + if len(from_packs) == 1: + packs = {from_packs[0]: self.client.packs.get_by_ref_or_id(from_packs[0])} + else: + packs = {p.ref: p for p in self.client.packs.get_all()} + + results = {} + for pack_name in from_packs: + pack = packs[pack_name] + results[pack_name] = self.resources_in_pack(pack_name, pack) + + success = all( + result.get("want_enabled", True) == result.get("enabled_after", False) + for pack_results in results.values() + for resource_results in pack_results.values() + for result in resource_results.values() + ) + + return {"success": success, "packs": results} + + def resources_in_pack( + self, pack_name, pack + ) -> Dict[str, Dict[str, Dict[str, Union[bool, str]]]]: + + # {resource_type: {resource_name: + # {want_enabled: bool, enabled_before: bool, enabled_after: bool, error_message: str} + # }} + results: DefaultDict[str, Dict[str, Dict[str, Union[bool, str]]]] = defaultdict( + dict + ) + + pack_path = pathlib.Path(pack.path) + resources_file_path = pack_path / "pack_resources.yaml" + if not resources_file_path.exists(): + return results + + with resources_file_path.open("r") as resources_file: + all_resources = yaml.safe_load(resources_file) + resources = all_resources.get(self.webui_base_domain, {}) + action_execution_index = 0 + for resource_type, resource_list in resources.items(): + for resource_name in resource_list: + client_resource_type = RESOURCE_TYPES_MAP.get(resource_type) + if not client_resource_type: + # ignore unknown resource_type + continue + + if client_resource_type == "Action" and isinstance(resource_name, dict): + action_def = dict(resource_name) + resource_name = action_def["ref"] + else: + action_def = None + # we support . and just + pack_prefix = f"{pack_name}." + pack_prefix_len = len(pack_prefix) + enabled = not resource_name.startswith("^") + resource_name = resource_name.lstrip("^") + name = ( + resource_name[pack_prefix_len:] + if resource_name.startswith(pack_prefix) + else resource_name + ) + + if action_def is None: + result = self.manage_resource( + resource_type=client_resource_type, + name=name, + pack=pack_name, + enabled=enabled, + ) + else: + result = self.execute_action( + action_def=action_def, + ) + action_execution_index += 1 + # since we can technically run multiple actions with the same ref, + # make keys unique + resource_name = "{}-{}".format( + action_execution_index, resource_name + ) + results[resource_type][resource_name] = result + return results + + def execute_action(self, action_def: dict) -> Dict[str, Union[bool, str]]: + execution_instance = LiveAction() + execution_instance.action = action_def.get("ref") + if action_def.get("input"): + execution_instance.parameters = action_def.get("input") + try: + # verify response to the client and make sure that the requested action exists and + # was accepted for execution + execution = self.client.liveactions.create(execution_instance) + except Exception as exc: + result = { + "success": False, + "error_message": "{}".format(exc), + } + return make_fake_result(result, False) + self.logger.debug( + "Created action execution {} for: {}".format(execution.id, action_def) + ) + if action_def.get("wait", False): + # wait for the execution to finish or timeout + max_time_wait = action_def.get("timeout", MAX_DEFAULT_TIME_WAIT) + start_time = int(time.time()) + now_time = start_time + while ( + execution.status in PENDING_STATUSES + and now_time - start_time < max_time_wait + ): + time.sleep(ACTION_EXECUTION_POLL_INTERVAL) + execution = self.client.liveactions.get_by_id(execution.id) + self.logger.debug( + "Action execution {} status: {}".format( + execution.id, execution.status + ) + ) + now_time = int(time.time()) + + if execution.status in PENDING_STATUSES: + # if timed out, cancel it and ignore response + self.client.executions.delete_by_id(instance_id=execution.id) + result = { + "success": False, + "error_message": "Action execution {} (execution id: " + "{}) timed out.".format(execution_instance.action, execution.id), + } + elif execution.status in ST2_TERMINAL_STATUSES: + result = { + "success": False, + "error_message": "Action execution {} (execution id: " + "{}) failed.".format(execution_instance.action, execution.id), + } + else: + result = { + "success": True, + "error_message": "Action execution {} (execution id: {}) kicked off " + "and succeeded.".format(execution_instance.action, execution.id), + } + else: + # wait for the action to be requested/scheduled + start_time = int(time.time()) + now_time = start_time + while ( + execution.status not in RUNNING_STATUSES + and execution.status not in ST2_SUCCESSFUL_STATUSES + ) and now_time - start_time < MAX_ACTION_KICK_OFF_TIME: + time.sleep(ACTION_EXECUTION_POLL_INTERVAL) + execution = self.client.liveactions.get_by_id(execution.id) + now_time = int(time.time()) + if execution.status in ST2_TERMINAL_STATUSES: + result = { + "success": False, + "want_enabled": True, + "enabled_after": False, + "error_message": "Action execution {} (execution id: " + "{}) failed with status: " + "{}.".format( + execution_instance.action, execution.id, execution.status + ), + } + return make_fake_result(result, False) + result = { + "success": True, + "error_message": "Action execution {} (execution id: {}) kicked off " + "successfully.".format(execution_instance.action, execution.id), + } + + return make_fake_result(result, True) + + def manage_resource( + self, resource_type: str, name: str, pack: str, enabled: bool + ) -> Dict[str, Optional[Union[bool, str]]]: + # we use self.client.managers instead of self.client. because + # not all resources are available as properties on the client. + + resource = self.client.managers[resource_type].get_by_name(name=name, pack=pack) + if resource is None: + result = { + "want_enabled": enabled, + "enabled_before": None, + "enabled_after": None, + "error_message": f"{resource_type} {pack}.{name} not found.", + } + return result + enabled_before = getattr(resource, "enabled", False) + result = { + "want_enabled": enabled, + "enabled_before": enabled_before, + "enabled_after": None, + "error_message": "", + } + + if self.check_mode: + result["enabled_after"] = enabled + return result + + try: + resource.enabled = result["enabled_after"] = enabled + self.client.managers[resource_type].update(resource) + except Exception as exc: + result["enabled_after"] = enabled_before + result[ + "error_message" + ] = f"Could not update {resource_type} {pack}.{name}: {exc}" + return result + + +if __name__ == "__main__": + # to run against test list of resources under localhost key in the pack_resources.yaml file + # action = ManagePackResources(config={"local_test_with": "localhost"}) + action = ManagePackResources(config={}) + res = action.run(from_packs=["st2gitops"], check_mode=True) + import pprint + + pp = pprint.PrettyPrinter(indent=2, width=200) + pp.pprint(res) diff --git a/seeker/snippet/pacman.py b/seeker/snippet/pacman.py new file mode 100644 index 00000000..a6c03f99 --- /dev/null +++ b/seeker/snippet/pacman.py @@ -0,0 +1,69 @@ +#date: 2025-02-12T17:02:37Z +#url: https://api.github.com/gists/8230fe747a806b0d092da288f3f92073 +#owner: https://api.github.com/users/zoeburke + +#PACMAN.PY +import pygame #Importing the pygame module +import random #Importing the random module +#-------------------------------------------------------------------------------- +class Pacman: #Creating the Pacman class, which takes self, x and y coordinates, radius, colour of pacman and the speed + def __init__(self, x, y, radius, colour, speed): + self._x = x + self._y = y + self._radius = radius + self._colour = colour + self._speed = speed + + def __str__(self): #This is a string representation of the object, which can be called to check the position and colour of the object + return f"Pacman at ({self._x}, {self._y}) with colour {self._colour}" + + def draw(self, display): #This function will draw Pacman as a circle, it takes the parameters of self and display (self having colour, coordinates and radius) + pygame.draw.circle(display, self._colour, (self._x, self._y), self._radius) + + def move_down(self, display_height): #The move down function essentially changes the coordinates based on the speed. So every frame, the coordinates change by the speed specified. + self._y += self._speed + if self._y > display_height - self._radius: #The following two lines of code mean that Pacman reappears at the top when he moves to the bottom. + self._y = 0 + self._radius #This is done to ensure that Pacman does not disappear off the screen. + + def move_up(self, display_height): #The movement functions work in the same way as the move down function, but for different directions. + self._y -= self._speed + if self._y < 0: # Move to bottom if it goes beyond the top + self._y = display_height - self._radius + + def move_left(self, display_width): + self._x -= self._speed + if self._x < 0: # Move to right edge if it goes beyond the left + self._x = display_width - self._radius + + def move_right(self, display_width): + self._x += self._speed + if self._x > display_width: + self._x = 0 + self._radius + + def relocate(self, display_width, display_height): #This function relocates Pacman to a random position on the screen, by setting the x and y coordinates to random integers. + self._x = random.randint(self._radius, display_width - self._radius) + self._y = random.randint(self._radius, display_height - self._radius) + ''' + The functions below are getters, which return the coordinates and radius so that they can be used within the main file. + ''' + def get_x(self): + return self._x + + def get_y(self): + return self._y + + def get_radius(self): + return self._radius +#-------------------------------------------------------------------------------- +#CODE SUMMARY +''' +This file contains the Pacman class, which is used to create a Pacman object within the game. +The Pacman object has attributes such as x and y coordinates, radius, colour and speed. +The class contains methods such as draw, move_down, move_up, move_left, move_right, relocate +and getters for the x and y coordinates and radius. +The draw method is used to draw Pacman as a circle on the screen. +The move methods are used to move Pacman in different directions based on the speed specified. +The relocate method is used to relocate Pacman to a random position on the screen. +The getters are used to get the x and y coordinates and radius of the Pacman object. +''' +#-------------------------------------------------------------------------------- \ No newline at end of file diff --git a/seeker/snippet/practic_basic.py b/seeker/snippet/practic_basic.py new file mode 100644 index 00000000..f2555ee8 --- /dev/null +++ b/seeker/snippet/practic_basic.py @@ -0,0 +1,4184 @@ +#date: 2025-02-12T17:02:21Z +#url: https://api.github.com/gists/e185d6bc9937191a33e4511fd62178a9 +#owner: https://api.github.com/users/Victoria-Abramenko + +##__________________________________ Основы python______________________________________ +# +# print('hello', 'World!', sep=', ') +# from sys import set_asyncgen_hooks +import random +from collections.abc import Callable + +# print('first stroke', end=' - ') +# print('second stroke') + +# name = input('enter your name: ') +# print('hello ', end=' ') +# print(name) + +# name = 'Vika' +# age = 33 +# print(name, age) +# +# name, age = 'Vika', 33 +# print(name, age) + +# name_girl = 'Vika' +# name_man = 'Victor' +# name_girl, name_man = name_man, name_girl +# print(name_girl, name_man) + +# variable = 1 +# print(type(variable)) + +# x = 10 +# y = 5.5 +# my_sum = x + y +# print(my_sum) +# +# x = 9 +# y = 4 +# print(x // y) +# print(x % y) + +# my_float = 1.99999 +# my_int = int(my_float) +# print(my_int) + +# my_float = 1.99999 +# my_int = round(my_float) +# print(my_int) + +# apartment = 81 +# entrance = (apartment - 1) // 20 + 1 +# floor = (apartment - 1) % 20 // 4 + 1 +# print(f'У квартиры {apartment} - подъезд {entrance}, этаж {floor}') + +# x = 10 +# if x > 0: +# print('x +') +# elif x == 0: +# print('x o') +# else: +# print('x -') + +# a = b = c = 90 +# d = 'hello' +# print(type(a), type(c), type(d)) + +# a = -5 % 3 +# print(a) + +# a = 27 ** (1 / 3) +# print(a) + +#функция round(number) округляет к целому числу, Но !!! 5 погранисное округление. +#Округляет в некоторых случаях в большую сторону, иногда в меньшую. + +# a = round(0.5) +# print(a) #0 +# a = round(1.5) +# print(a) #2 +# a = round(10.5) +# print(a) #10 +# a = round(10.500000001) +# print(a) #11 + +# _________________ модуль math ______________________________ +# import math # импортируется весь модуль, а значит необходимо указывать модуль, а зетем вызов функции. +# #ceil(number) округляет к наибольшему целому числу +# a = math.ceil(5.2) +# print(a) #6 +# a = math.ceil(-5.2) +# print(a) #-5 +# #floor(number) округляет к наименьшему целому числу +# a = math.floor(5.2) +# print(a) #5 +# a = math.floor(-5.2) +# print(a) #-6 +# Чтобы не указывать модуль при вызове функций, необходимо просто импортировать функции ceil, floor из модуля math + +# from math import ceil, floor +# a = ceil(5.2) +# b = floor(5.2) +# print(a, b) #6 #5 + +# import math + +# a = math.factorial(6) # вычисляет вакториал числа (1 * 2 * 3 * 4 * 5 * 6 = 720) +# print(a) #720 +# +# a = math.trunc(5.9) #убирает дробную часть аналог int(5.9) = 5 +# print(a) #5 + +# a = math.log2(4) #логарифм основания 2, числа 4 +# print(a)#2.0 +# +# a = math.log10(1000) +# print(a) +# +# a = math.log(27, 3) # другая запись логарифм основания 3, числа 27. +# # Если не указывать основание, натуральный логарифм +# +# print(a)#3.0 + +# a = math.sqrt(49) #Вычисление квадратного корня +# print(a) # 7.0 +# +# a = math.sin(3.14 / 2) # Вычисление синуса +# print(a) # 0.9999996829318346 +# +# a = math.cos(0) # Вычисление косинуса +# print(a) #1 +# +# a = math.pi # константа число Пи +# print(a) #3.141592653589793 +# +# a = math.e # константа e +# print(a) #2.718281828459045 + +#_________________ basic _________________ + +# a = 1.5 +# b = -12.5 +# c = 6 +# print(a, b, c,sep = " | ") #указание разделителя между аргументами результат 1.5 | -12.5 | 6, по умолчанию " " +# +# a = 1.5 +# b = -12.5 +# c = 6 +# print(a, end=" | ")#указание вывода в конце строки, по умолчанию "\n" +# print(b, end=" | ") +# print(c) #результат 1.5 | -12.5 | 6 + +#f-строка +# x = 5.6 +# y = -4.3 +# print("Координаты точки, x = ", x, ", y = ", y, sep="") #Обычный вывод, передача аргументов без разделителя +# print(f"Координаты точки, x = {x}, y = {y}") #Форматированная строка +# #Координаты точки, x = 5.6, y = -4.3 +# #Координаты точки, x = 5.6, y = -4.3 +# +# my_input = input() +# print(my_input, type(my_input)) #Зависит от, того что введет пользователь , например hjhg +# input выводит строку, поэтому даже, если пользователь введет число, на выходе будет тип строка 1234 + +# number = float(input()) #Если пользователь передаст в input дробное число, то при использовании int, будет ошибка +# print(abs(number)) #так как int преобразует только числа, в в дробных числах, помимо цифр есть точка. +# # Например, если пользователь введет -5,4, результат будет 5,4, а в случае number = int(input())возникнет ошибка +# +# +# a = float(input("Введи длину прямоугольника: ")) +# b = float(input("Введи ширину прямоугольника: ")) +# print("Периметр прямоугольника: ", 2 * (a + b)) +# +# #Можно передавать параметры в одну строку, если использовать функцию map +# a, b = map(float, input("Введи длину и ширину через пробел: ").split(" ")) +# print("Периметр прямоугольника: ", 2 * (a + b)) + +# # проверка на четное или нечетное число +# a = 6 +# b = 7 +# print(a % 2 == 0) #True +# print(b % 2 != 0) #True + +# #входит ли в диспазон от 1 до 5 +# x = 3 +# print(x >= 1 and x <= 5)#True +# print(1 <= x <= 5)# сокращенная запись True + +# x = 7 +# print(x % 2 == 0 or x % 3 == 0)#False +# проверка на неравенство +# print(x % 2 != 0 and x % 3 != 0)#True +# print(not(x % 2 == 0 or x % 3 == 0))#True у оператора not самый высокий приоритет, чтобы он не выполнился +# в первую очередь, необходимо условие поместить в скобки + +# print(bool(0))#False +# print(bool(-10))#True +# print(bool(5))#True +# print(bool(""))#False +# print(bool(" "))#True Есть хотя бы один символ, в том числе пробел +# print(bool("0"))#True +# print(bool("gggh"))#True + +# a = "Hi hi hi" +# print(a[len(a) - 1]) #i вывод символа по индексу. Обращение к последнему символу строки +# print(a[-1]) # более упрощенная запись обращения к последнему символу строки + +# print("stroke"[3]) #o по индексу можно обращаться непосредственно в строке + +# Срезы строк stoke[start:stop] последний индекс не включен +# stroke = "python" +# print(stroke[1:3])# yt с 1 и до 3, не включая 3! +# print(stroke[4:])# on с 4 и до конца +# print(stroke[:4])# pyth с начала и до 4, не включая 4! +# str_1 = stroke[:] +# print(str_1,id(stroke), id(str_1))#python 2622090832048 2622090832048 ссылаются на один и тот же объект, +# # эта строка не дублируется +# print(stroke[2:-2])# th -2 предпоследний символ, но он не включается в срез +# print(stroke[4:2])# ничего не выведет, так как интервал не задан +# #stroke[start:stop:step]шаг перебора символов, по умолчанию = 1 +# print(stroke[1:4:2])# yh +# print(stroke[2::3])# tn с 2 до конца с шагом 3 +# print(stroke[::2])# pto с начала до конца с шагом 2 +# print(stroke[::-1])# nohtyp с конца до начала, так как шаг -1 + +# # строки неизменяемый тип +# my_str = "hello" +# # my_str[0] = "H" # приведет к ошибке +# my_str_2 = "H" + my_str[1:] +# print(my_str_2)# "Hello" Это уже новая строка + +# Методы строк объект.метод(аргументы) +# my_str = "I love Python" +# print(my_str.upper()) # I LOVE PYTHON, но это новая строка, содержащая все заглавные буквы +# print(my_str.lower()) # i love python +# print(my_str.count("o")) #2 возвращает количество вхождений подстроки в строку, +# print(my_str.count("o",4))# 1 - есть необязательный параметры start и end начало и конец индекса поиска +# print(my_str.count("o",4, 11))# 0 - параметр не включается в поиск +# print(my_str.find("t"))#9 возвращает индекс первого найденного вхождения подстроки, также есть необязательный параметры +# # start и end начало и конец индекса поиска +# print(my_str.find("tyyyy"))#-1 значит такого вхождения нет +# print(my_str.rfind("ht"))# -1 поиск наоборот справа налево, но сочетание также слева направо? +# print(my_str.rfind("th"))# 9 но сочетанием также слева направо? Просто первым вхождением будет индекс с конца +# print(my_str.index("th"))# 9 Тот же принцип, что и метод find, ищет вхождение, но! +# # print(my_str.index("tyyyy"))# ValueError: substring not found если такого вхождения нет, то выведет ошибку +# print(my_str.replace("love", "like"))#I like Python Заменяет старую подстроку, на новую +# print(my_str.replace("hon",""))#I love Pyt Можно удалить подстроку, если указать пустую подстроку +# print(my_str.replace("o","f", 1))#I lfve Python #необязательный параметр count, определяет +# # максимальное число замен +# print(my_str.isalpha())# False, так как есть пробел, он не буква, а если строка содержит только буквы True +# print("IlovePython".isalpha())# True +# print("12345".isdigit())#True если строка содержит только цифры, и False если другой символ +# print("123.45".isdigit())# False +# print("abc".rjust(6))# abc Выводит строку, необходимой ширины, заполняя ее символом в начале, по умолчанию пробел +# print("abc".rjust(6, "*"))#***abc +# print("abc".ljust(6, "*"))#abc*** заполняя ее символом в конце +# # print("abc".ljust(6, "**"))#ошибка TypeError: The fill character must be exactly one character long +# # в параметре можно указать только 1 символ +# print(my_str.rjust(6))# I love Python, если желаемая длина меньше исхлдной строки, то на выходе будет исходная строка +# print(my_str.split(" "))# ['I', 'love', 'Python'] разбивает строку по казанному разделителю на строки и передает их +# # в виде списка +# print("1, 2 , 3, 4, 5".replace(" ", "").split(","))# ['1', '2', '3', '4', '5'] На полученную новую строку +# # методом,можно применить другой метод. Слева направою Сначала заменяются пробелы, а затем строка делится по разделителю +# # в список с отдельными строками +# print(",".join(["1", "2", "3"]))#"1,2,3" Из списка строк, выводит 1 строку в качестве символа между строками "," +# print("***".join(["1", "2", "3"]))#1***2***3 здесь можно указывать несколько символов +# Также можно применить несколько методов для получения строки из строки, главное понимать, что метод возвращает и какой +#аргумент необходимо передать методу. +# print(", ".join("гений миллиардер филонтроп".split()))#гений, миллиардер, филонтроп join из списка в одну строку, +#вставляя между строками символ ", ", а split разбивает строку в список строк по " ". " " по умолчанию +# print(" gh j \n".strip())# "gh j" удаляет все символы пробела и переноса строки в начале и вконце строки +# print(" gh j \n".rstrip())# " gh j" удаляет все символы пробела и переноса вконце строки, справа +# print(" gh j \n".lstrip())# "gh j \n" удаляет все символы пробела и переноса в начале, слева +# print(my_str)# I love Python исходная строка не изменяется + + +#______________________спецсимволы________________ +#символ \n относится к спецсимволам и программой распознается как 1 символ +# print(len("\n"))#1 #символ переноса строки +# # print("\needs\")# SyntaxError: unterminated string literal (detected at line 274); perhaps you escaped the end quote? +# print("\needs")#eeds с переносом на новую строку +# print("\\")#\ #символ обратного слэша экранирование +# print("\"")#" #символ апострофа(кавычек) +# # print("car "bmw"")#ошибка +# print("car \"bmw\"")#car "bmw" +# print('car "bmw"')#car "bmw" можно и так сделать, но хорошей практикой является именно использование экранирования \ +# print("\ttext")# text #символ табуляции +# #Следует помнить об этих спецсимволах при указании пути файла +# path = "E:\my_project\new_victoria"#E:\my_project +# #ew_victoria сработал перенос символа строки +# print(path) +# path = "E:\my_project\text"#E:\my_project\ text сработал перенос символа табуляции +# print(path) +# path = "E:\\my_project\\new_victoria"#E:\my_project\new_victoria +# print(path) +# #SyntaxWarning: invalid escape sequence '\m' в современной версии языка интерпритатор ругается при таком синтаксе +#rстрока - или сырая строка, она передает все символы, игнорируя спецсимволы +# path = "E:\\my_project\\new_victoria" +# print(path)#E:\my_project\new_victoria +# path = r"E:\\my_project\\new_victoria"# сырая строка +# print(path)#E:\\my_project\\new_victoria + +#______________форматирование строк______________________ +# name = "Вика" +# age = 33 +# # my_str = "Меня зовут " + name + ", мне " + str(age) + " года и я программирую на Python"#сложение строк +# # print(my_str)#Меня зовут Вика, мне 33 года и я программирую на Python +# my_str = "Меня зовут {0}, мне {1} года и я программирую на Python".format(name, age)#использование метода +# # format(index0, index1 и тд.) чаще используют в версия ниже 3.6, так как там еще нет f-строк +# print(my_str)#Меня зовут Вика, мне 33 года и я программирую на Python +# my_str = "Меня зовут {0}, {0}, {0}, мне {1} года и я программирую на Python".format(name, age)# Причем эти +# # переменные можно использовать несколько раз +# print(my_str)#Меня зовут Вика, Вика, Вика, мне 33 года и я программирую на Python +# my_str = "Меня зовут {fio}, мне {old} года и я программирую на Python".format(fio=name, old=age)# а можно указать +# # ключевые слова, и по ним вставлять +# print(my_str)#Меня зовут Вика, мне 33 года и я программирую на Python +# my_str = "Меня зовут {name}, мне {old} года и я программирую на Python".format(fio=name, old=age)#KeyError: 'name' но +# print(my_str)# если указать имя переменной , возникнет ошибка +# my_str = f"Меня зовут {name}, мне {age} года и я программирую на Python"# использование f-строк +# print(my_str)#Меня зовут Вика, мне 33 года и я программирую на Python +# my_str = f"Меня зовут {name.upper()}, мне {age * 2} года и я программирую на Python"# в f-строках можно производить +# # различные операции над переменными +# print(my_str)#Меня зовут ВИКА, мне 66 года и я программирую на Python + +#__________________списки - упорядоченная коллекция _______________________ + +# my_list = ["bmw", "ferrary", "maseratti"] +# print(my_list)#['bmw', 'ferrary', 'maseratti'] # создание списка при помощи квадратных скобок +# # print(type(my_list))# +# # car = my_list[1]# так как список упорядоченный, к его элементам можно обращаться по индексу +# # print(f"Мечтаю о {car}")#Мечтаю о ferrary +# # #car = my_list[5]# list index out of range если обратиться к несуществующему индексу, ошибка выход за диапозон +# # car = my_list[-1]#Обращение к последнему элементу +# # print(f"Мечтаю о {car}")#Мечтаю о maseratti +# # my_list[0] = "hilux"# списки относятся к изменяемым объектам, поэтому можно изменять его элементы +# # print(my_list)#['hilux', 'ferrary', 'maseratti'] +# b = list()# создание списка при помощи функции +# print(b)#[] +# c = list("python")# если в функцию передать строку(перебираемый объект), она вернет список из символов строки +# print(c)#['p', 'y', 't', 'h', 'o', 'n']# она перебирает объекты и формирует из них список + +# функции списков + +# my_list_1 = ['p', 'y', 't', 'h', 'o', 'n', 3.13] +# my_list_2 = [3.14, 5.18, 5, 7.89] +# my_list_3 = ["bmw", "ferrary", "maseratti"] +# my_list_4 = ['p', 'y', 't', 'h', 'o', 'n'] +# print(len(my_list_1))#7 количество элементов в списке +# print(min(my_list_2))#3.14 выводит минимальное значение +# print(max(my_list_2))#7.89 выводит максимальное значение +# # print(min(my_list_1))#TypeError: '<' not supported between instances of 'float' and 'str' +# print(min(my_list_3))#bmw минимальное по длине строки +# print(max(my_list_3))#maseratti максимальное по длине строки +# print(min(my_list_4))#h минимальное по коду числа, порядку элемента в таблице +# print(max(my_list_4))#y максимальное по коду числа, порядку элемента в таблице +# print(sum(my_list_2))#21.21 сумма элементов списка числового +# # print(sum(my_list_3))#TypeError: unsupported operand type(s) for +: 'int' and 'str' +# print(sorted(my_list_2))#[3.14, 5, 5.18, 7.89] Возвращает !!!новый!!! отсортированный список по умолчанию по возрастанию +# print(sorted(my_list_2, reverse=True))#[7.89, 5.18, 5, 3.14] Возвращает !!!новый!!! отсортированный список по убыванию +# print(sorted(my_list_4))# ['h', 'n', 'o', 'p', 't', 'y'] сортирует по коду порядку в алфавите +# print(sorted(my_list_3, reverse=True))#['maseratti', 'ferrary', 'bmw'] сортирует по длине строки +#['bmw', 'ferrary', 'maseratti', 'p', 'y', 't', 'h', 'o', 'n'] новый список с элементами и 1го и 2го списка +# new_list = my_list_3 + 4 #TypeError: can only concatenate list (not "int") to list сложение списка с элементом приведет к ошибке +# # print(new_list) +# new_list = my_list_3 + [4]#['bmw', 'ferrary', 'maseratti', 4] просто сделать из него список с одним элементом +# print(new_list) +# new_list = my_list_3 * 2 +# print(new_list)#['bmw', 'ferrary', 'maseratti', 'bmw', 'ferrary', 'maseratti'] новый список с задублированными элементами +# new_list = ["I"] + ["love"] * 3 + ["python"]# можно использовать одновременно несколько операторов, главное не забывать, +# # какой оператор с чем взаимодействует + со списком, а * с целым числом +# print(new_list)#['I', 'love', 'love', 'love', 'python'] +# оператор in проверяет вхождение элемента в список +# my_list_3 = ["bmw", "ferrari", "maseratti"] +# print("ferrari" in my_list_3)#True +# # оператор del выполняет удаление элемента по его индексу +# del my_list_3[0] +# print(my_list_3)#['ferrari', 'maseratti'] +#срезы, создают новый список +# lst = ["porse", "bmw", "kia", "opel"] +# new_lst = lst[1:3] +# print(new_lst)#['bmw', 'kia'] +# new_lst = lst[1:] +# print(new_lst)#['bmw', 'kia', 'opel'] +# new_lst = lst[:3] +# print(new_lst)#['porse', 'bmw', 'kia'] +# new_lst = lst[:]#создается копия спискаб либо при помощи функции list(lst) +# print(new_lst)#['porse', 'bmw', 'kia', 'opel'] +# new_lst[0] = "lada" +# print(new_lst)#['lada', 'bmw', 'kia', 'opel'] +# print(lst)#['porse', 'bmw', 'kia', 'opel'] +# new_lst = lst[::-1]# копия списка с конца и до начала +# print(new_lst)#['opel', 'kia', 'bmw', 'porse'] +# lst[1:3] = ["mersedes", "toyota"]#при помощи срезов также можно изменить часть списка +# print(lst)#['porse', 'mersedes', 'toyota', 'opel'] изменен сам список, а не создана копия +# lst = [1, 1, 2, 3, 4, 5] +# lst[::2] = [8, 8]# может возникнуть ошибка, если список стал длиннее, а мы передаем меньше элементов, чем входит в срез +# print(lst)#ValueError: attempt to assign sequence of size 2 to extended slice of size 3, +# чтобы избежать таких ошибок лучше указывать начало и конец среза +# lst = [1, 1, 2, 3, 4, 5] +# lst[1:4] = 5, 16, 87 # значения можно указывать и не в списке, а просто через запятую +# print(lst)#[1, 5, 16, 87, 4, 5] +# #сравнение списков, происходит подобно строкам. Проверка проходит по эдементам списка +# print([10, 2] > [9, 2, 1])#True +# print([1, 2, 3] > [1, 3, 2])#False сравнение происходит до тех, пор пока соответствующая пара не выведет True или False +# дальнейшие элементы уже не сравниваются +# но числа со строками сравнивать нельзя, будет ошибка. Нужно. чтобы пара элементов соответствовала по типу данных +# print([1, 2, "abc"] < [1, 2, "cba"])#True +# print([1, 2, 3] < [1, 2, "cba"])#TypeError: '<' not supported between instances of 'int' and 'str' + +# методы списков +# lst = [1, 2, 3, 4, 5] +# print(lst) # [1, 2, 3, 4, 5] +# lst.append(100) # append(element) добавляет элемент в конец списка, меняя сам список +# print(lst) # [1, 2, 3, 4, 5, 100] +# # сам метод append ничего не возвращает None, поэтому его присвоение переменной ничего не даст +# a = lst.append(20) +# print(a) # None +# print(lst) # [1, 2, 3, 4, 5, 100, 20] +# # a = lst.append(20, 20)#TypeError: list.append() takes exactly one argument (2 given) добавляет только 1 элемент, +# # если передать более выскочит ошибка +# lst.insert(2, -100)# insert(ndex, element) этот метод позволяет вставить значение в определенное место по индексу +# print(lst)# [1, 2, -100, 3, 4, 5, 100, 20] подвигая остальные элементы +# lst = [1, 2, 3, 4, 5] +# lst.remove(3)# remove(element) удаляет первый найденный по значению элемент +# print(lst)#[1, 2, 4, 5] +# если удалить несуществующий элемент будет ошибка +# lst.remove(55)#ValueError: list.remove(x): x not in list +#pop()без указания аргумента удаляет последний элемент списка. Удаляет по индексу +# lst = [1, 2, 3, 4, 5] +# # lst.pop() +# # print(lst)#[1, 2, 3, 4] +# lst.pop(-2) +# print(lst)#[1, 2, 3, 5] +# # lst.pop(7)#IndexError: pop index out of range если удалить несуществующий элемент будет ошибка +# #pop возвращает удаляемый элемент списка, поэтому можно присвоить в переменную +# a = lst.pop() +# print(a)#5 +# lst = [1, 2, 3, 4, 5] +# # lst.clear()# очищает весь список +# # print(lst)#[] +# a = lst.copy()#Создает полную копию списка a = lst[:] , a = list(lst) +# print(a, id(lst), id(a))#[1, 2, 3, 4, 5] 2726896510528 2726896362880 +# lst = [1, 2, 2, 3, 5, 5, 0, 5] +# print(lst.count(5))#3 count(element) указывает количество элементов с указанным значением +# print(lst.index(2))#1 указывает первое вхождение(первое найденное значение) элемента с указанным значением +# print(lst.index(5, 6))#7 можно указать стартовый индекс, с которого начать поиск значения +# # print(lst.index(100))#ValueError: 100 is not in list если указать несуществующий элемент будет ошибка +# lst.reverse()# инвертирует порядок элементов в списке +# print(lst)#[5, 0, 5, 5, 3, 2, 2, 1] +# lst = [1, 2, 2, 3, 5, 5, 0, 5] +# # lst.sort()# сортирует текущий список, по умолчанию по возрастанию +# # print(lst)#[0, 1, 2, 2, 3, 5, 5, 5] +# # lst.sort(reverse=True)# по убыванию +# # print(lst)#[5, 5, 5, 3, 2, 2, 1, 0] +# a = lst.sort() +# print(a)#None ничего не возвращает, так как сортирует существующий список +# a = sorted(lst) +# print(a)#[0, 1, 2, 2, 3, 5, 5, 5] возвращает новый отсортированный список + +# lst = [[1, 2, 3], [4, 5, 6]] +# print(lst[1][1])#5 +# lst[0] = [0, 0, 0] # здесь формируется новый список, а затем он присваивается индексу +# print(lst)#[[0, 0, 0], [4, 5, 6]] +# lst[1][:] = [3, 3, 3] # здесь изменяется существующий список, при помощи среза +# print(lst)#[[0, 0, 0], [3, 3, 3]] визуально результат тот же +# lst[1] = [0] * 3 # так как все 3 элемента одинаковые, можно записать иначе +# print(lst)#[[0, 0, 0], [0, 0, 0]] + +#if если условие == True: +# выполняется этот блок кода +#elif иначе проверка этого условия, если условие == True: +# выполняется этот блок кода +#else иначе: +# выполняется этот блок кода +# причем в качестве условия может быть просто переменннная if a: если a пустая или 0, то будет False, если есть +# хоть 1 символ True +# # marks = [3, 2, 4, 3, 5] +# marks = [4, 5, 4, 4, 5] +# # marks = [4, 5, 4, 3, 5] +# if 2 in marks: +# print("Студент отчислен") +# elif not (3 in marks): +# print("Студент сдал сессию на стипендию") +# else: +# print("Студент успешно сдал сессию") + +# a = int(input("Введите число a: ")) +# b = int(input("Введите число b: ")) +# c = int(input("Введите число c: ")) +# if a > b: +# if a > c: +# print("Максимальное из этих трех чисел число a") +# else: +# print("Максимальное из этих трех чисел число c") +# else: +# if b > c: +# print("Максимальное из этих трех чисел число b") +# else: +# print("Максимальное из этих трех чисел число c") + + +# #Тернарный условный оператор +# #значение1 if условие else значение2 +# a = 13 +# b = 4 +# res = a if a > b else b# присваиваем в res a если a > b, иначе приваиваем b +# print(res)#13 +# #Тернарный оператор возвращает зачение, первое если соответствует условие, второе если нет. +# #А обычный условный оператор выполяет блок кода, и ничего не возвращает, +# #Поэтому его нельзя присвоить переменной +# +# #Также в качестве значения мон использовать арифметческие перации и функции +# res = a + 2 if a > b else b + 3 +# print(res)#15 +# a = -2 +# b = -3 +# res = abs(a) if a > b else abs(b) +# print(res)#2 +# +# #также можно работать и строками +# s = "python" +# t = "upper" +# res = s.upper() if t == "upper" else s# если t == "upper" вывести строку со всеми заглавными +# #буквами иначе оставить без изменений +# print(res)#PYTHON +# +# # тернарный оператор не обязательно присваивать переменной, можно ео сразу использовать, +# # например в списках и строках и в функциях +# a = 4 +# b = 7 +# lst = [1, 3, 4, a if a < b else b, 1, 4] +# print(lst)#[1, 3, 4, 4, 1, 4] +# +# strk = "a - " + ("четное" if a % 2 == 0 else "нечетное") + " число" +# print(strk)#a - четное число +# +# #но со строками обязательно нужно в скобках, они показывают начало и конец тернарного оператора +# +# strk = "b - " + "четное" if b % 2 == 0 else "нечетное" + " число" +# print(strk)# не четное число, т.е. "не четное" + " число" +# +# a = 13 +# b = 55 +# x = max(1, 5, a if a > 0 else b, 4, 5) +# print(x)#13 + +# # можно вкладывать один тернарный оператор в другой, но на практике лучше их избегать +# #на примере задачи на максимальное из трех трех чисел +# a = int(input())#2 +# b = int(input())#3 +# c = int(input())#-4 +# res = (a if a > c else c)if a > b else(b if b > c else c) +# print(res)#3 + +# #_________цикл while__________ +# # while до тех пор, пока условие True: +# # выполнять этот код +# my_sum = 0 +# i = 1 +# n = 1000 +# +# while i <= n: +# my_sum += i +# i += 1 +# +# print(my_sum)#500500 +# # однократное выполнение тела цикла называется итерацией + +# # условия можно указывать от обратного, цикл будет работать до тех пор, пока пользователь не введет верные данные +# password_true = "**********" +# password_user = "**********" + "**********"# "**********" "**********"w "**********"h "**********"i "**********"l "**********"e "**********" "**********"p "**********"a "**********"s "**********"s "**********"w "**********"o "**********"r "**********"d "**********"_ "**********"u "**********"s "**********"e "**********"r "**********" "**********"! "**********"= "**********" "**********"p "**********"a "**********"s "**********"s "**********"w "**********"o "**********"r "**********"d "**********"_ "**********"t "**********"r "**********"u "**********"e "**********": "**********" +# password_user = input("Введи пароль: "**********" +# print("Выполнен вход в систему") +# +# # В цикле можно так же указывать дополнительные условия, например вывести только числа кратные трем +# n = 50 +# i = 1 +# while i < n: +# if i % 3 == 0: +# print(i, end=", ") # 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, +# i += 1 + +# # __________break, continue _______ +# # break - досрочное прерывание операции +# # Например, остановить цикл, как только обнаружится первое четное число +# lst = [1, 3, 5, 6, 8, -4, 0] +# i = 0 +# n = 0 +# while i < len(lst): +# n = lst[i] +# if n % 2 == 0: +# break +# i += 1 +# print(n)# мое решение +#2й способ, решение лектора, в качестве значения переменной условие +# lst = [1, 3, 5, 6, 8, -4, 0] +# i = 0 +# flag_find = False +# +# while i < len(lst): +# flag_find = lst[i] % 2 == 0# В результате того или иного числа переменная будет иметь значение True или False +# if flag_find: +# break +# i += 1 +# +# print(lst[i])#6 цикл остановится на 6, так как это четное число +# print(flag_find)#True + +# Альтернатива без break можно указать второе условие, но с break более наглядно что и за чем идет + +# lst = [1, 3, 5, 6, 8, -4, 0] +# i = 0 +# flag_find = False +# while i < len(lst) and lst[i] % 2 != 0: +# i += 1 +# flag_find = i != len(lst) +# print(lst[i])#6 +# print(flag_find)#True + +# # Мое решение +# lst = [1, 3, 5, 6, 8, -4, 0] +# lst = [1, 3, 5, 7, 7, -9, 1] +# i = 0 +# +# while i < len(lst) and lst[i] % 2 != 0: +# i += 1 +# print(lst[i - 1])#6 в первом случае, #1 во втором +# # мой вариант решения не корректен, так как выведет значение в конце цикла независимо от того, четное оно или нет + +# continue - пропуск одной итерации цикла +# используется к примеру в задаче - суммировать все нечетные числа от пользователя, а если 0 остановить посчет. + +# s = 0 +# d = 1 +# while d != 0:# 1 #3 #4 #5 #0 +# d = int(input()) +# if d % 2 == 0: +# continue +# s += d +# print("s = ", s )#1 #4 # #9 + + +# # Также это можно реализовать без continue, но рекомендуется его использовать, так как основная логика +# находится в теле цикла и код выгл\дит более читабельным +# s = 0 +# d = 1 +# while d != 0:# 1 #3 #4 #5 #0 +# d = int(input()) +# if d % 2 != 0: +# s += d +# print("s = ", s ) + +# в цикле while можно также использовать оператор else. Этот код будет работать только в случае +# штатного завершения цикла (без break). В этом главное отличие от кода после цикла, который будет работать в любом случае. +# while условие: +# блок кода +# else: +# блок кода, который выполнится только +# код, который выполнится в любом случае + +# # s = 1/2 + 1/3 + 1/4 + 1/10... + 1/0 завершение +# s = 0 +# i = - 10 +# while i < 100: +# if i == 0: +# break +# s += 1 / i +# i += 1 +# else: +# print("Этот текст не выведется из-за break, но если этого оператора нет выведется")# Этот текст проигнорировался +# print(s)#-2.9289682539682538 +# +# s = 0 +# i = - 10 +# while i < 0: +# if i == 0: +# break +# s += 1 / i +# i += 1 +# else: +# print("Этот текст не выведется из-за break, но если этого оператора нет выведется")# Этот текст не проигнорирован +# print(s)#Этот текст не выведется из-за break, но если этого оператора нет выведется +# #-2.9289682539682538 + +# факториал натурального числа 1 * 2 * 3 ... * n +# в математике факториал обозначается n!, что может сбить меня с толку + +# n = int(input("Введите натуральное число не более 100: "))#6 +# +# if n < 1 or n > 100: +# print("Неверно введено число") +# else: +# p = 1 +# +# for i in range(1, n + 1): +# p *= i +# +# print(f"Факториал числа {n} = {p}")#720 + +# for i in range(1 , 7): +# print("*" * i) +# # * +# # ** +# # *** +# # **** +# # ***** +# # ****** + +# words = ["Python", "дай", "мне", "сил", "пройти", "этот", "курс", "до", "конца"] +# s = "" +# +# for w in words: +# s += " " + w +# print(s.lstrip())#Python дай мне сил пройти этот курс до конца - удалить пробел слева от строки + +#Также удаление пустой строки можно сделать при помощи тернарного оператора и переменной с False +# +# words = ["Python", "дай", "мне", "сил", "пройти", "этот", "курс", "до", "конца"] +# s = "" +# fl_first = True +# for w in words: +# s += ("" if fl_first else " ")+ w +# fl_first = False +# print(s)#Python дай мне сил пройти этот курс до конца +# #но так слишком замудренный код, лучше использовать встроенные функции + +# # это задание можно выполнить в разы проще, не используя цикл +# words = ["Python", "дай", "мне", "сил", "пройти", "этот", "курс", "до", "конца"] +# +# print(" ".join(words))# Python дай мне сил пройти этот курс до конца + +# # в списке все двухзначные числа заменить на ноль +# digs = [4, 3, 100, -53, -30, 1, 34, -8] +# +# for i in range(len(digs)): +# if 10 <= abs(digs[i]) <= 99: +# digs[i] = 0 +# print(digs)#[4, 3, 100, 0, 0, 1, 0, -8] + +# # enumirate возвращает пару индекс и значение в цикле +# digs = [4, 3, 100, -53, -30, 1, 34, -8] +# +# for i, e in enumerate(digs): +# if 10 <= abs(e) <= 99: +# digs[i] = 0 +# print(digs)#[4, 3, 100, 0, 0, 1, 0, -8] + +# # Пример преобразования кириллицы в латиницу (например заголовок страницы, в путь к этой странице) +# lat_letters = ["A", "B", "V", "G", "D", "E", "Zh", +# "Z", "I", "J", "K", "L", "M", "N", "O", "P", +# "R", "S", "T", "U", "F", "H", "C", "Ch", "Sh", +# "Shch", "", "Y", "", "E", "Yu", "Ya"]# словарь для замены +# +# start_index = ord("а")# вспомогательная переменная выводит код буквы +# kir_str = "Пример преобразования кириллицы в латиницу" +# slug = "" #Сюда будет сохраняться преобразованная строка +# +# for i in kir_str.lower(): +# if "а" <= i <= "я": +# slug += lat_letters[ord(i) - start_index]#вычисляем индекс буквы, на которую заменить. +# # В кодовой таблице буквы алфавида по порядку имеют код на 1 больше, +# # чем предыдущая буква +# elif i == "ё":# Если будет е +# slug += "Yo" +# elif i in " !?,.":# Если попадется знак +# slug += "_" +# else: +# slug += i +# +# while slug.count("__"): +# slug = slug.replace("__", "_") +# +# print(slug)#PRIMER_PREOBRAZOVANIYa_KIRILLICY_V_LATINICU + +# итерация коллекций при помощи итератора (функция iter() однократный перебор) +# и функции next() следующий + +# numbers = [3, 5, 6, 10, 43] +# +# it = iter(numbers)# присваиваем итератор +# print(next(it)) +# print(next(it)) +# print(next(it)) +# print(next(it)) +# print(next(it)) +# # 3 +# # 5 +# # 6 +# # 10 +# # 43 +# Если вызвать еще раз, будет ошибка, чтобы заново начать итерацию, +# нужно снова присвоить итератор it = iter(numbers) +# итератор используется как универсальный перебор, так как подходит для любых итерируемых объектов, +# он перебирает не по индексам а по элементам. По такому принципу работает цикл for + +# # _____________ вложенные циклы ____________ +# numbers = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] +# +# for row in numbers: +# print(row, type(row)) +# # [1, 2, 3] +# for column in row: +# print(column, type(column)) +# # 1 +# # 2 +# # 3 +# +# # [1, 2, 3] +# # 1 +# # 2 +# # 3 +# # [4, 5, 6] +# # 4 +# # 5 +# # 6 +# # [7, 8, 9] +# # 7 +# # 8 +# # 9 + +# # сложение двух одинаковых по размеру списков +# +# numbers_1 = [[1, 2, 3], [4, 5, 6]] +# numbers_2 = [[7, 8, 9], [10, 11, 12]] +# numbers_sum = []# список для хранения сложенных соответствующих элементов списков +# +# # при помощи вложенного цикла, складывать соответствующие элементы между собой +# for index, row in enumerate(numbers_1): +# row_list = []# список для хранения сложенных соответствующих элементов строки +# +# for i, column in enumerate(row):# перебираем элементы строки(первого вложенного списка) и суммируем +# # с соответствующими элементами второго списка +# row_list.append(column + numbers_2[index][i])# добавляем в конец списка элемент первого списка +# # + элемент второго(по тем же индексам, что и первого) +# numbers_sum.append(row_list)# добавляет строку(первый вложенный суммированный список), в конечный список) +# print(numbers_sum)# [[8, 10, 12], [14, 16, 18]] + +# # Замена лишних пробелов в списках, при помощи вложенных циклов +# text = ["Даже упав, вновь решайся на взлет", +# "Жизнь твои крылья не зря мастерила.", +# "Помни, что Бог никогда не дает", +# "Ноши, которая нам не по силам."] +# +# for i, elem in enumerate(text):# Перебираем элементы списка (строки) +# while elem.count(' '):# пока есть лишние пробелы в строках +# elem = elem.replace(" ", " ")# заменяем лишние пробелы в строке на нормальные +# +# text[i] = elem # заменяем исправленной строкой в оригинальном списке +# +# print(text) +# # ['Даже упав, вновь решайся на взлет', 'Жизнь твои крылья не зря мастерила.', 'Помни, что Бог никогда не дает', 'Ноши, которая нам не по силам.'] + +# Создать двумерный список, принимая от пользователя два числа m, n. +# Синтаксис функции: map(function, iterable). +# Параметры: +# function — функция, которую нужно применить к каждому элементу итерируемого объекта. +# Iterable — итерируемый объект, элементы которого нужно обработать. + +# # m, n = map(int, input().split())# Принимаем два целочисленных числа от пользователя, указанных через пробел. +# # # разделяем по пробелу (.split() по умолчанию пробел). ПРи помощи функции map применяем int к каждому числу. +# # # эта функция возвращает итератор +# # особенность python +# x, y = [2, 3] +# print(x, y)#2 3 +# x, y = list(map(int, input().split())) +# print(x, y)#2 3 +# # поэтому иногда можно увидеть запись x, y = list(map(int, input().split())), хотя x, y = map(int, input().split()) +# # даст такой же результат + +# m, n = map(int, input().split())#2 3 размерности двумерного списка +# zeros = [] +# +# for i in range(m):# Перебираем элементы списка +# zeros.append([0] * n)# Добавляем вложенный список длинною n +# +# print(zeros)# [[0, 0, 0], [0, 0, 0]] +# +# # чтобы заменить все 0 на 1 +# for x in range(m): +# for y in range(n): +# zeros[x][y] = 1 +# +# print(zeros)# [[1, 1, 1], [1, 1, 1]] + +# преобразование двумерного списка, значение строк, заменить на соответствующее значение столбцов +# # в матиматике это называется траспонирование матрицы +# визуальное представление: [[1, 2, 3, 4], [[1, 5, 9, 13], +# [5, 6, 7, 8], ==>> [2, 6, 10, 14], +# [9, 10, 11, 12], [3, 7, 11, 15], +# [13, 14, 15, 16]] [4, 8, 12, 16]] +# +# # сначала перебираем элементы выше главной диагонали, а затем переприсваиваем им значение +# # +# a = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]] +# +# for i in range(len(a)): +# for j in range(i + 1, len(a)): # перебираем от индекс + 1 до конца +# a[i][j], a[j][i] = a[j][i], a[i][j] # переприсваиваем им значение +# +# print(a)#[[1, 5, 9, 13], [2, 6, 10, 14], [3, 7, 11, 15], [4, 8, 12, 16]] + +# +# # можно отобразить более наглядно +# for i in a: +# for j in i: +# print(j, end="\t") +# print() +# # 1 5 9 13 +# # 2 6 10 14 +# # 3 7 11 15 +# # 4 8 12 16 + + +# # треугольник Паскаля. +# # по краям 1, а далее сумма предыдущих соседних строк +# # 1 +# # 1 1 1+1 +# # 1 2 1 2 => 1+2 2+1 +# # 1 3 3 1 3 3 => 1+3 3+3 3+1 +# # 1 4 6 4 1 4 6 4 ... +# # 1 5 10 10 5 1 +# +# # этот треугольник можно представить как набор вложенных списков +# # [[1], i = (0, 6), j = (0, i) +# # [1, 1], | --> +# # [1, 2, 1], v +# # [1, 3, 3, 1], +# # [1, 4, 6, 4, 1], +# # [1, 5, 10, 10, 5, 1]] +# +# # алгоритм решения - сначала создать список с 1 - [1] * (i + 1) (i - это индекс, а длина + 1) +# # проверка крайних значений j != 0 and j != i: +# # вычисляем промежуточные значения row[j] = lst[i - 1][j - 1] + lst[i - 1][j] +# +# n = 7 # указанная губина треугольника Паскаля, (количество строк) +# lst_p = [] +# +# for i in range(n): +# row = [1] * (i + 1) +# +# for j in range(i + 1):# включительно до i +# if j != 0 and j != i: +# row[j] = lst_p[i - 1][j - 1] + lst_p[i - 1][j]# вычисляем значение +# +# lst_p.append(row)# добаляем эту строку в коллекцию +# +# print(lst_p)# [[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1], [1, 5, 10, 10, 5, 1], [1, 6, 15, 20, 15, 6, 1]] +# +# # можно сделать вывод более наглядным +# +# for r in lst_p: +# print(r) +# # [1] +# # [1, 1] +# # [1, 2, 1] +# # [1, 3, 3, 1] +# # [1, 4, 6, 4, 1] +# # [1, 5, 10, 10, 5, 1] +# # [1, 6, 15, 20, 15, 6, 1] + +# # __________ генератор списков __________ +# # [x ** 2 что сделать с перебираемой переменной for x in range(n) перебор чисел от 0 до n - 1, так как не включая n] +# они работают быстрее чем циклы for, поэтому где возможно, лучше использовать их +# n = 7 +# +# a = [x ** 2 for x in range(n)] +# +# print(a)# [0, 1, 4, 9, 16, 25, 36] +# +# b = [ x % 2 == 0 for x in range(n)]# если в качестве действия над переменной указать условие, то получится +# # список из булевых значений +# +# print(b)#[True, False, True, False, True, False, True] +# +# numbers_input = input("Введите числа через пробел: ")#1 2 3 4 5 +# +# numbers_list = [int(x) for x in numbers_input.split()] разбили строку по пробелу, затем каждое значение преобразовали +# в int и внесли его в список +# print(numbers_list)#[1, 2, 3, 4, 5] + +# # также можно указать условие отбора переменных в генераторе +# a = [x for x in range(-10, 5) if x < 0 ]# условие, если x отрицательный, тогда вносим в список +# print(a)#[-10, -9, -8, -7, -6, -5, -4, -3, -2, -1] + +# # даже составные условия +# a = [x for x in range(-10, 7) if x % 2 == 0 and x % 3 == 0 ]# условие, если x четное и кратное трем число +# print(a)#[-6, 0, 6] + +# # в генераторах списка также можно использовать тернарный оператор +# +# d = [1, 3, 4, -5, -7, 5, -6, 2, 1] +# a = ["четное" if x % 2 == 0 else "нечетное" for x in d] +# print(a)#['нечетное', 'нечетное', 'четное', 'нечетное', 'нечетное', 'нечетное', 'четное', 'четное', 'нечетное'] + +# # Для читабельности можно переносить на несколько строк, например если есть еще условие +# d = [1, 3, 4, -5, -7, 5, -6, 2, 1] +# a = ["четное" if x % 2 == 0 else "нечетное" +# for x in d +# if x > 0] +# print(a)#['нечетное', 'нечетное', 'четное', 'нечетное', 'четное', 'нечетное'] + +# Вложенные генераторы +#[<способ формирования значение> +# for <переменная_1> in <итерируемый объект> if <условие> +# for <переменная_1> in <итерируемый объект> if <условие> +# ... for <переменная_n> in <итерируемый объект> if <условие>] +# a = [(i, j) +# for i in range(3)# внешний цикл +# for j in range(4)# этот цикл вложен в верхний(i = 0, j = 0, j = 1, j = 2, j = 3) +# ] +# print(a)#[(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3)] +# # можно прописывать дополнительные условия +# a = [(i, j) +# for i in range(3) if i % 3 == 0 +# for j in range(4) if j % 2 == 0 +# ] +# print(a)# [(0, 0), (0, 2)] + +# # создать таблицу умножения +# a = [f"{i}*{j} = {i * j}"# не придумала как сделать перенос строки, никак это список, только перебирая эленменты +# for i in range(2, 4) +# for j in range(1, 11) +# ] +# print(a) # ['2*1 = 2', '2*2 = 4', '2*3 = 6', '2*4 = 8', '2*5 = 10', '2*6 = 12', '2*7 = 14', '2*8 = 16', '2*9 = 18'... + +# # +# # из двумерного списка сделать обычный список +# +# numbers = [[1, 2, 3, 4], +# [5, 6, 7, 8], +# [9, 10, 11, 12]] +# +# new_list = [x +# for row in numbers +# for x in row +# ] +# +# print(new_list)# [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] +# + +# # также еще один генератор можно указать вместо действия над переменной, +# # то есть один генератор вложен в другой +# m, n = 3, 4 +# +# lst = [[a for a in range(m)] for b in range(n)]# сначала отрабатывает правый генератор списков, b = 0, +# # затем левый a = 0, 1, 2, затем b = 1 и т.д. Получается двумерный список. +# +# print(lst)# [[0, 1, 2], [0, 1, 2], [0, 1, 2], [0, 1, 2]] +# + +# # возведение в квадрат всех элементов двумерного списка +# +# numbers = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] +# +# lst = [[x ** 2 for x in row] for row in numbers] +# +# print(lst)#на выходе двумерный список [[1, 4, 9], [16, 25, 36], [49, 64, 81]] +# +# lst_2 = [x ** 2 +# for row in numbers +# for x in row +# ] +# print(lst_2)# на выход уже одномерный список [1, 4, 9, 16, 25, 36, 49, 64, 81] +# + +# # поменять значение строк и столбцов в двумерном списке. Транспонирование марицы +# +# numbers_1 = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] +# +# numbers_2 = [[row[i] for row in numbers_1] for i in range(len(numbers_1[0]))] +# +# print(numbers_2)# [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]] +# +# # также генератор списка можно помещать в качестве итерируемого объекта +# +# g = [y ** 2 for y in [x + 1 for x in range(5)]] +# +# # сначала при помощи генератора мы создаем список от 1 до 5(так как x + 1) +# +# # затем по этому списку проходим следующим генератором и возводим каждое число во вторую степень +# +# print(g) #[1, 4, 9, 16, 25] +# +# ___________________ словари __________________ +# в качестве ключа могут быть любые неизменяемые типы данных. Строки, числа, булевые значение, в качесиве значения любые +# my_dict = {"house" : "дом", "car" : "машина", "tree" : "дерево", +# "road" : "дорога", "river" : "река"} +# print(my_dict["road"])# дорога обратиться к элементу можно по значению ключа +# +# # можно создать словарь при помощи функции dict(key=value, key1=value1 ...), но ключи должны быть строками, +# # но записываются без кавычек. Имена ключей по тем же правилам, что и переменные +# a = dict(один="дома", два="сапога-пара") +# print(a) + +# # эта функция используется, например, когда из списка нужно сделать словарь +# lst = [[2, "неудовдетворительно"], [3, "удовдетворительно"], [4, "хорошо"], [5, "отлично"]] +# d = dict(lst)# в таком случае ключ не обязательно строка +# print(d)#{2: 'неудовдетворительно', 3: 'удовдетворительно', 4: 'хорошо', 5: 'отлично'} +# +# my_dict = {"house" : "дом", "car" : "машина", "tree" : "дерево", +# "road" : "дорога", "river" : "река"} +# +# my_dict["coffee"] = "кофе"# если такого ключа нет в словаре - добавить его, если есть, заменит его значение +# print(my_dict)# {'house': 'дом', 'car': 'машина', 'tree': 'дерево', 'road': 'дорога', 'river': 'река', 'coffee': 'кофе'} +# +# print(len(my_dict))# 6 колмичество пар ключ:значение длина словаря +# del my_dict["tree"] # удаление элемента по ключу +# print(my_dict) # {'house': 'дом', 'car': 'машина', 'road': 'дорога', 'river': 'река', 'coffee': 'кофе'} +# print("coffee" in my_dict)#True Проверка на наличие ключа в словаре, не значение!!! Если нужно проверить, что такого +# # ключа нет"coffee" not in my_dict + +# ______ методы словаря ____________ + +# lst = ["+7", "ghj", "jhj", "fgh"] +# a = dict.fromkeys(lst)# Создать словарь, используя элементы списка в качестве ключей +# print(a)# {'+7': None, 'ghj': None, 'jhj': None, 'fgh': None} пока без значения + +# a = dict.fromkeys(lst, "просто")# можно указать значение по умолчанию +# # print(a)# {'+7': 'просто', 'ghj': 'просто', 'jhj': 'просто', 'fgh': 'просто'} +# +# a.clear()# очищает словарь +# print(a)#{} + +# d = {True : 1, False : "Ложь", "list" : [1, 2, 3], 5 : "5"} + +# d2 = d.copy()# Создать копию словаря 1й способ +# print(d2)# {True: 1, False: 'Ложь', 'list': [1, 2, 3], 5: '5'} +# +# d3 = dict(d)# Создать копию словаря 2й способ +# print(d3)# {True: 1, False: 'Ложь', 'list': [1, 2, 3], 5: '5'} +# +# print(d.get("list"))# [1, 2, 3] Получить значение по ключу, в отличии от d['key'] в случае отсутствия ключа выведет None, +# # а не выдаст ошибку, +# print(d.get("key", "Такого ключа нет"))# Такого ключа нет - причем в аргументах функции можно указать, какое значение вывести в случае отсутствия ключа + +# print(d.setdefault("list"))# вывод значения по существующему ключу +# print(d.setdefault("кофе", "Дим"))#Дим, а если ключа нет, то внесет его в словарь со значением по умолчанию +# print(d)# {True: 1, False: 'Ложь', 'list': [1, 2, 3], 5: '5', 'кофе': 'Дим'} добавился ключ кофе + +# print(d.pop(5))#5 Удаляет заданный ключ и выводит содержимое +# print(d)# True: 1, False: 'Ложь', 'list': [1, 2, 3], 'кофе': 'Дим'} # ключ удален +# при удалении несуществующего ключа, выведет ошибку, чтобы избежать этого, можно указать что +# вывести в случае его отсутствия +# print(d.pop("Гадя", "нет такого имени"))#ет такого имени + +# print(d.popitem())#(5, '5') удаляет последнее значение с ключом (версия python ниже 3.7 список был +# # неупорядоченной коллекцией, поэтому удалялось случайное значение) + +# print(d.keys())# dict_keys([True, False, 'list', 5]) возвращает список ключей +# # цикл for также проходит по ключам словаря +# for k in d: +# print(k) +# # True +# # False +# # list +# # 5 + +# print(d.values())# dict_values([1, 'Ложь', [1, 2, 3], '5']) Выведет список значений +# for v in d.values(): +# print(v) +# 1 +# Ложь +# [1, 2, 3] +# 5 + +# # можно сразу получать и значение и ключ +# for x in d.items():# x принимает и коюч и значение в виде кортежа +# print(x) +# # (True, 1) +# # (False, 'Ложь') +# # ('list', [1, 2, 3]) +# # (5, '5') + +# # print(d.items())#dict_items([(True, 1), (False, 'Ложь'), ('list', [1, 2, 3]), (5, '5')]) список с кортежами +# # x, y = (1, 2) # на подобии такого присвоения можно присвоить сразу двум переменным кортеж +# for key, value in d.items(): +# print(key, end='-') +# print(value) +# # True-1 +# # False-Ложь +# # list-[1, 2, 3] +# # 5-5 + +# d = {True : 1, False : "Ложь", "list" : [1, 2, 3], 5 : "5"} +# d2 = {'house': 'дом', 'car': 'машина', 'road': 'дорога', 'river': 'река', 'coffee': 'кофе'} +# # Добавить в один словарь значения другого +# d.update(d2) +# print(d)# E{True: 1, False: 'Ложь', 'list': [1, 2, 3], 5: '5', 'house': 'дом', 'car': 'машина', 'road': 'дорога', +# # 'river': 'река', 'coffee': 'кофе'} +# # если будут одинаковые ключи. то перезапишется значение на новое +# +# # объединить словари 2й способ +# d3 = {**d, **d2} +# print(d3)#{True: 1, False: 'Ложь', 'list': [1, 2, 3], 5: '5', 'house': 'дом', 'car': 'машина', 'road': 'дорога', +# # 'river': 'река', 'coffee': 'кофе'} + +# # объединить словари 3й способ python > 3.9 +# d3 = d | d2 +# print(d3)# {True: 1, False: 'Ложь', 'list': [1, 2, 3], 5: '5', 'house': 'дом', 'car': 'машина', 'road': 'дорога', +# # 'river': 'река', 'coffee': 'кофе'} + +# # _________________ кортежи ________________ +# # упорядоченная, но неизменяемая коллекция +# a = (1, 2) +# b = 3, 4 +# print(a, b)# (1, 2) (3, 4) + +# # можно создать кортеж и с 1 элементом, но нужно оставить запятую, иначе воспримет как число в скобках +# a = (1) +# b = (2,) +# print(a,b)#1 (2,) + +# создать пустой кортеж +# a = () +# b = tuple() +# print(a, b)# () () +# если передавать в итерируемый объект, создастся кортеж с этими элементами +# b = tuple("python") +# print(b)# ('p', 'y', 't', 'h', 'o', 'n') +# a = a + (1, 2, 3) +# print(a)# (1, 2, 3) Создается новый кортеж сложением двух, а не изменяется старый +# b = ("yooou",) * 6 +# print(b)# 'yooou', 'yooou', 'yooou', 'yooou', 'yooou', 'yooou') Создается новый кортеж + +# # кортеж можно распаковать в отдельные переменные +# x, y, z = (1, 2, 3) +# print(x, y)#1 2 3 + +## списками также можно +# x, y, z = ["Я", "люблю", "python"] +# print(x, y, z)#Я люблю python + +# # эта операция доступно с любым итерируемым объектом, даже строками +# x, y, z = "mba" +# print(x, y, z)#m b a + +# a = (1, "121", "zara") +# print(len(a))#3 возвращает длину - количество элементов кортежа +# print(a[0])#1 Чтобы обратиться к элементу, также используется индекс +# print(a[1:2])# так же можно получать срезы +# но при срезе a[:] не будет создаваться его копия, а переменная будет ссылаться на этот кортеж +# b = a[:] +# print(id(a), id(b))#2152799795328 2152799795328 +# кортеж неизменяемый тип данных, поэтому его можно использовать в качестве ключа в словаре, они меньше памяти занимают, +# чем списки +# a1 = [1, 2, 3, "four", True] +# a2 = (1, 2, 3, "four", True) +# print(a1.__sizeof__())#88 +# print(a2.__sizeof__())#64 + +# # Но изменяемые типы данных внутри кортежа, менять можно +# b = (1, 2, [3, 4], 7) +# b[2].append(5) +# b[2].append(6) +# print(b)# (1, 2, [3, 4, 5, 6], 7) + +# b = (1, 2, [3, 4, 5, 6], 7) +# print(b.count(7))#1 Количество элементов с указанным значением +# print(b.index(7))#3 Выводит индекс 1го попавшегося элемента с указанным значением +# в параметрах можно указать начиная и заканчивая каким индексом проводить проверку +# b = (1, 2, 7, [3, 4, 5, 6], 7, 7) +# print(b.index(7, 3, 5))#4 начиная со второго до 5 не включая его +# Также можно использовать оператор in для проверки вхождения +# print(7 in b)# True + +# ___________________________ множества __________________ +# неупорядоченная коллекция уникальных элементов + +# a = {1, 2, "python", 6} +# print(type(a))# + +# a = {1, 2, "python", 6, 2, "python"} +# print(a)# {1, 2, 'python', 6} только уникальные элементы, дубли отбрасывает автоматически + +# # в множествах можно использовать только неизменяемые типы данных +# a = {1, 2, "python", 6, [1, 2, 3]} +# print(a)# TypeError: unhashable type: 'list' + +# a = {1, 2, "python", 6, (1, 2, 3)}# можно использовать кортеж, но внутри также должны быть неизменяемые объекты +# print(a)# {'python', 1, 2, 6, (1, 2, 3)} + +# a = set()# создание пустого множества +# print(type(a))# +# a = {}# создаст пустой словарь +# print(type(a))# + +# s = set([1, 3, 5, 7, 1, 7]) # передать итерируемый объект, создать множество с этими элементами +# s1 = set("hello world") +# s2 = set(range(9)) +# print(s)# {1, 3, 5, 7} +# print(s1)# {'o', 'w', 'd', 'e', 'l', 'h', 'r', ' '} +# print(s2)# {0, 1, 2, 3, 4, 5, 6, 7, 8} +# обратиться к элементу по индексу невозможно, так как множество неупорядоченная коллекция + +# используется если необходимо получить список уникальных элементов +# lst1 = ["Moscow", "Krasnodar", "Sochi", "Stavropol", "Moscow", "Krasnar", "Sochi", "Stavropol"] +# lst2 = list(set(lst1)) +# print(lst2)# ['Krasnodar', 'Moscow', 'Stavropol', 'Sochi'] + +# s = set([1, 3, 5, 7, 1, 7]) +# print(len(s))#4 + +# s = {'Krasnodar', 'Moscow', 'Stavropol', 'Sochi'} +# print("Moscow" in s)# True + +# s = set() +# s.add("python")# добавить элемент в множество +# print(s)# {'python'} +# # добавить несколько элементов, передается итерируемый объект +# s.update(["I", "love", "coding", "on"]) +# print(s)#{'on', 'python', 'love', 'I', 'coding'} +# s.discard("on")# удалить указанный элемент, ошибку не выдаст, если указать несуществующий элемент, в отличии от remove +# print(s)# {'python', 'I', 'love', 'coding'} +# # s.remove(4)#KeyError: 4 +# # print(s) +# print(s.pop())# "python" удаляет произвольный объект и возвращает удаленный элемент +# print(s)# {'I', 'love', 'coding'} +# s.clear()# удаляется все элементы множества +# print(s)# set() + +# ________________ операции над множествами ______________ +# set_a = {1, 2, 3, 4, 5} +# set_b = {4, 5, 6, 7, 8, 9} + +# set_c = set_a & set_b# результат пересечения двух множеств +# print(set_c)# {4, 5} выделены общие элементы для обоих множеств в новое множество +# set_c = set_a.intersection(set_b)# тоже самое - результат пересечения двух множеств +# print(set_c)# {4, 5} +# set_a = set_a & set_b#{4, 5} # присвоит новое значение множеству set_a +# set_a &= set_b#{4, 5} # короткая запись +# set_a.intersection_update(set_b)#{4, 5} # присвоит новое значение множеству set_a, 2й способ + +# set_c = set_a | set_b# объединение двух множеств. Образуется новое множество, содержащее элементы обоих множеств +# print(set_c)# {1, 2, 3, 4, 5, 6, 7, 8, 9} +# set_a |= set_b# {1, 2, 3, 4, 5, 6, 7, 8, 9} присвоит новое значение множеству set_a короткая запись +# set_a.union(set_b)# {1, 2, 3, 4, 5, 6, 7, 8, 9} при помощи метода новое множество, содержащее элементы обоих множеств + +# вычетание одного множества из другого, из первого множества(из которого вычетается) остаются те элементы, которые +# не входят во второе множество +# set_c = set_a - set_b +# print(set_c)# {1, 2, 3} +# set_c = set_b - set_a +# print(set_c)# {8, 9, 6, 7} +# # set_a -= set_b# присвоит новое значение множеству set_a короткая запись + +# set_c = set_a ^ set_b# симметричная разность - на выходе получаем новое множество с уникальными элементами из первого и второго множества +# print(set_c)# {1, 2, 3, 6, 7, 8, 9} нет тех элементов, которые были в обоих списках + +# set_a = {1, 2, 3, 4} +# set_b = {4, 3, 2, 1} +# print(set_a == set_b)#True и длина и значения элементов одинаковые +# print(set_a > set_b)#False +# print(set_a < set_b)#False + +# set_a = {1, 2, 3, 4} +# set_b = {2, 1} +# print(set_a > set_b)#True так как set_b входит в set_a + +# set_a = {1, 2, 3, 4} +# set_b = {2, 1, 5} +# print(set_a > set_b)#False так как set_b не входит в set_a + +#________________________ генератор множеств и словарей ______________ +# по подобию генератора списков +# s = { x ** 2 for x in range(2, 6)} просто значения, значит на выходе множество +# print(s)#{16, 9, 4, 25} +# d = {x: x ** 2 for x in range(2, 6)}# здесь задаем ключ x, значит на выходе будет словарь +# print(d)#{2: 4, 3: 9, 4: 16, 5: 25} + +# lst = [-2, -1, 0, 1, 2, "3", "4", 5.3] +# # set_numbers = {int(x) for x in lst} +# # print(set_numbers)#{0, 1, 2, 3, 4, 5, -1, -2} +# +# # это же можно было сделать и при помощи цикла, но это работает медленнее чем генератор списка +# set_numbers = set() +# for x in lst: +# set_numbers.add(int(x)) +# print(set_numbers)# {0, 1, 2, 3, 4, 5, -1, -2} + +# my_dict = {"неуд" : 2, "уд" : 3, "хор" : "4", "отл" : "5"} +# new_dict = { key.upper(): int(value) for key, value in my_dict.items()}# ключи сделать заглавными, а значения целым числом +# print(new_dict)# {'НЕУД': 2, 'УД': 3, 'ХОР': 4, 'ОТЛ': 5} +# +# # также в генератор можно добавить условие +# lst = [-2, -1, 0, 1, 2, "3", "4", 5.3] +# my_dict = {int(x) for x in lst if int(x) > 0} +# print(my_dict)#{1, 2, 3, 4, 5} + +# my_dict = {"безнадежно" : 0, "убого" : 1, "неудовлетворительно" : 2, "удовлетворительно" : 3, "хорошо" : "4", +# "отлично" : "5"} +# # поменять местами ключ и значение, и внести в словарь оценку только от 2 до 5 включительно +# new_dict = {int(value): key for key, value in my_dict.items() if 2 <= int(value) <= 5} +# print(new_dict)# {2: 'неудовлетворительно', 3: 'удовлетворительно', 4: 'хорошо', 5: 'отлично'} + +# _______________________ функции _____________________ +# def имя функции (передаваемые аргументы): +# бок кода => тело функции +# чтобы вызвать функцию необходимо прописать имя функции и оператор вызова функции () - function(), после ее объявления +# +# def send_mail():# создание функции +# text = "Какой-то текст сообщения" +# print(text)# имитация отправки текста сообщения +# +# +# send_mail()# вызов этой функции +# send_mail()# вызов этой функции +# # Какой-то текст сообщения +# # Какой-то текст сообщения +# # по pep8 между функцией и основной программой необходимо отделить двумя строками, в pycharm есть горячая клавиша, +# # которая настроит код по этому стандарту alt + ctrl + l (у меня не сработало, другое alt + shift + enter, +# но нужно выделить фрагмент) + +# В функцию можно передавать параметры + +# def send_mail(from_name): # определение внутри функции называется параметром +# text = f"Какой-то текст сообщения - с уважением, {from_name}" +# print(text) # имитация отправки текста сообщения +# +# +# send_mail("Виктория") # передаваемое значение при вызове функции называется аргументом Если у функции указан параметры, +# # то при вызове этой функции необходимо передать аргументы, тоже количество, что и указана параметров, иначе возникнет +# # ошибка. Их порядок также имеет значение + +# return возвращает результат работы функций. Может быть только один в функции, так как после этого оператора функция +# завершает свою работу, но через запятую можно вывести несколько значений - на выходе коллекция, например, кортеж + +# вычисление квадратного корня из числа, если оно положительное + +# def get_sqrt(x): +# res = None if x < 0 else x ** 0.5 # эта переменная существует только в теле этой функции +# +# +# a = get_sqrt(49) +# +# print(a) # None, так как мы не указали оператор return функция никакого значения не возвращает + +# def get_sqrt(x): +# res = None if x < 0 else x ** 0.5 +# return res # указали, что именно вернуть +# +# +# a = get_sqrt(49) +# +# print(a) # 7.0 + +# def get_sqrt(x): +# res = None if x < 0 else x ** 0.5 +# return res, x # указали, что именно вернуть +# +# +# s = get_sqrt(49) +# a, b = get_sqrt(49) +# +# print(s) # (7.0, 49) +# print(a, b) # 7.0 49 + +# # в return можно также передавать тернарный оператор +# def get_max_2(a, b): +# return a if a > b else b +# +# +# x = int(input()) +# y = int(input()) +# +# print(get_max_2(x, y)) +# +# def get_max_2(a, b): +# return a if a > b else b +# +# +# x = int(input()) # 21 +# y = int(input()) # 5 +# z = int(input()) # 2 +# +# print(get_max_2(x, get_max_2(y, z))) # 5 # вызов функции внутри функции. Сначала срарвнятся y и z, а затем наибольшее +# # из них сравнится с x + +# # можно даже вынести это отдельной функцией +# +# def get_max_2(a, b): +# return a if a > b else b +# +# +# def get_max_3(a, b, c): +# return get_max_2(a, get_max_2(b, c)) +# +# x = int(input()) # 1 +# y = int(input()) # 5 +# z = int(input()) # 2 +# +# print(get_max_3(x, y, z)) # 5 + +# # функции можно использовать в разных частях программы, например в условиях, когда выбор функции зависит от условия +# condiition = input() # периметр +# +# if condiition == "периметр": # сработает это условие, значит функция будет вычислять периметр +# def get_resault(a, b): +# return 2 * (a + b) +# if condiition == "площадь": +# def get_resault(a, b): +# return a * b +# +# x = float(input()) # 2 +# y = float(input()) # 3.9 +# +# print(get_resault(x, y)) # 11.8 + +# # или в цикле, например вывести только четные числа +# +# def even(x): +# return x % 2 == 0 +# +# for i in range(17): +# if even(i): # если четное - true +# print(i, end=", ") # 0, 2, 4, 6, 8, 10, 12, 14, 16, + +# ___________________________________ алгоритм Евклида _________________________________ +# для нахождения общего максимального делителя двух натуральных чисел. Наибольший Общий Делитель - НОД +# Принцип алгоритма: Сначала из наибольшего числа вычитаем меньшее. Получившееся значение записать в переменную +# с большим значением. В следующей итерации также из получившихся чисел, находим большее и из него вычитаем меньшее. +# Результат также записать в переменную с большим значением. До тех пор, пока в обеих переменных не получится +# одинаковое значение + +# def get_nod(a, b): # вычисляет НОД по алгоритму Евклида +# while a != b: # до тех пор, пока числа не равны +# if a > b: # Проверяем на большое число. Если больше a +# a -= b # из a вычитаем b +# else: # Если b больше a +# b -= a # то из b вычитаем a +# return a # Когда числа будут равны, возвращаем это значение +# +# +# a = 18 +# b = 24 +# +# print(get_nod(a, b)) # 6 + +# Алгоритм Евклида есть быстрое воплощение при помощи остатка от деления. Наибольшее число делим на наименьшее, +# и записываем в переменную с наибольшим числом этот остаток. Затем опять сравниваем и наибольшее делим на меньшее до +# тех пор, пока остаток от деления не станет равен 0. Значит это наименьшее число и будет нод. + +# def get_nod(a, b): # вычисляет НОД по алгоритму Евклида +# if a < b: # Проверяем, если a меньше b, то +# a, b = b, a # поменяем их значения, чтобы a всегда было набольшим числом для удобства +# while b != 0: # до тех пор, пока b не равно 0 +# a, b = b, a % b # a присваиваем значение b, в b присваиваем значение от деления +# return a # Когда числа будут равны, возвращаем это значение +# +# +# a = 18 +# b = 24 +# +# print(get_nod(a, b)) # 6 +# +# import time +# +# # для проверки работы функций используется специальная функция тестирования - asset +# def test_nod(func): # создаем функцию проверки +# # тест №1 +# a = 28 +# b = 35 +# res = func(a, b) +# if res == 7: +# print("тест 1 завершен успешно") +# else: +# print("тест 1 Что-то пошло не так") +# +# # тест №2 +# a = 2 +# b = 100000000 +# start_time = time.time() # Засекаем начало времени +# res = func(a, b) # запускаем функцию +# end_time = time.time() # засекаем конец времени +# work_time = end_time - start_time # вычисляем время работы функции +# if res == 2 and work_time < 1: +# print("тест 2 завершен успешно") +# else: +# print("тест 2 Что-то пошло не так") + +# при вызове медленного варианта решения +# test_nod(get_nod) # вызов функции проверки +# # тест 1 завершен успешно +# # тест 2 Что-то пошло не так +# при вызове быстрого варианта решения +# тест 1 завершен успешно +# тест 2 завершен успешно + + +# # Для описания того, что делает функция используется многострочный комментарий. Другой программист через функции help +# # может посмотреть это описание +# +# def nothing(): +# """ +# эта функция ничего не делает +# :return: и ничего не возвращает +# """ +# pass +# +# help(nothing) +# # nothing() +# # эта функция ничего не делает +# # :return: и ничего не возвращает + +# # именованные аргументы. +# def get_v(a, b, c): +# print(f"a = {a}, b = {b}, c = {c}") +# return a * b * c + +# # v = get_v(c=4, a=3, b=2) # значения аргументам присваиваются явно +# # print(v) +# # a = 3, b = 2, c = 4 +# # 24 +# +# # можно комбинировать, но позиционные должны быть расположены вначале, а затем уже именованные +# v = get_v(4, c=3, b=2) # значения аргументам присваиваются явно +# print(v) +# # a = 4, b = 2, c = 3 +# # 24 + +# # В передаваемых параметрах можно указывать значение по умолчанию. +# def get_v(a, b, c, do=True): # параметры со значением по умолчанию называют формальными, а без значения фактическими +# if do: +# print(f"a = {a}, b = {b}, c = {c}") +# return a * b * c +# +# +# v = get_v(4, c=3, b=2) +# print(v) +# # a = 4, b = 2, c = 3 +# # 24 +# v = get_v(4, c=3, b=2,do=False) # меняем значение по умолчанию +# print(v) # 24 + +# # Благодаря фактическим параметрам можно задавать поведение функции, например, функция сравнивающая строки с учетом или +# # не учитывая регистр или лишних пробелов +# def cmp_str(str_1, str_2, reg=False, trim=False): +# if reg: +# str_1 = str_1.lower() +# str_2 = str_2.lower() +# if trim: +# str_1 = str_1.strip() +# str_2 = str_2.strip() +# return str_1 == str_2 +# +# str_1 = "python" +# str_2 = " python " +# res_1 = cmp_str(str_1, str_2, False, True) # не учитывать пробелы +# print(res_1) # True +# +# str_1 = "PythoN" +# str_2 = "python" +# res_1 = cmp_str(str_1, str_2,True) # не учитывать регистр +# print(res_1) # True +# +# str_1 = "PythoN" +# str_2 = " python " +# res_1 = cmp_str(str_1, str_2,True, True) # не учитывать регистр и пробелы +# print(res_1) # True + +# # Но есть нюанс, если в функцию в качестве параметра передать изменяемый объект (например список - создается ссылка на +# # список, и изменяя его, мы также меняем и его значение по умолчанию) +# def add_value(value, lst=[]): # Создается ссылка на список, пока он пустой +# lst.append(value) +# return lst +# +# l = add_value(1) # [1] изменяется список, но ссылка на тот же список не меняется +# l = add_value(2) # [1, 2] поэтому при повторном вызове, список не пустой, и в него добавляется еще одно значение +# print(l) # [1, 2] + +# # Чтобы создавать пустой список, при неуказанном параметре нужно задать неизменяемый тип None, а внутри функции уже +# # присвоить пустой список +# def add_value(value, lst=None): # Создается ссылка на список, пока он пустой +# if lst == None: +# lst = [] +# lst.append(value) +# return lst +# + +# l = add_value(1) # [1] +# print(l) # [1] +# l = add_value(1, l) # [1, 1] +# print(l) # [1, 1] +# l = add_value(2) # [2] +# print(l) # [2] + + +# # Функции с произвольным числом аргументов *args **kwargs +# # _______ *args ________ +# def os_path(*args): # * - оператор упаковки аргументов +# return args +# +# +# file_path = os_path("E:", "\\my_project", "\\python", "\\practic_basic.py") +# +# print(file_path) # ('E:', '\\my_project', '\\python', '\\practic_basic.py') кортеж +# +# # и дальше с ним уже можно работать +# def os_path(*args): # * - оператор упаковки аргументов +# path = "\\".join(args) +# return path +# +# +# # file_path = os_path("E:", "\\my_project", "\\python", "\\practic_basic.py") +# +# # print(file_path) # (E:\\my_project\\python\\practic_basic.py строка +# +# # *args это фактические аргументы, если передавать в функцию формальный параметр, возникнет ошибка, +# file_path = os_path("E:", "\\my_project", "\\python", "\\practic_basic.py", sep="**") +# print(file_path) # TypeError: os_path() got an unexpected keyword argument 'sep' +# # чтобы этого избежать, его необходимо прописать в аргументах. +# def os_path(*args, sep=""): # * - оператор упаковки аргументов +# path = sep.join(args) +# return path +# +# +# file_path = os_path("E:", "\\my_project", "\\python", "\\practic_basic.py", sep="**") +# print(file_path) # E:**\my_project**\python**\practic_basic.py + +# # ________ **kwargs _________ +# # Чтобы передать функции произвольное число именованных аргумантов, используется **kwargs +# def get(**kwargs): +# return kwargs +# +# +# s = get(lower=True, trim=False) +# print(s) # {'lower': True, 'trim': False} словарь, в качестве ключей имя аргумента + +# # если необходимо использоват определенный параметр в функции, его следует прописать, причем перед **kwargs +# def get(*args, sep="", **kwargs): +# path = sep.join(args) +# return path +# +# +# file_path = get("E:", "\\my_project", "\\python", "\\practic_basic.py", lower=True, trim=False) # не возникнет ошибки, +# # хотя не передаем аргумент разделителя, так как есть указанный по умолчанию +# print(file_path) #E:\my_project\python\practic_basic.py +# +# # чтобы учесть именованные параметры, которые могут быть и не указаны, можно использовать проверку +# def get(*args, sep="", **kwargs): +# if "trim" in kwargs and kwargs["trim"]: +# args = [x.strip() for x in args] +# +# path = sep.join(args) +# return path +# +# +# file_path = get(" E:", "\\my_project ", "\\python ", " \\practic_basic.py", lower=True, trim=False) +# print(file_path) # E:\my_project \python \practic_basic.py +# file_path = get(" E:", "\\my_project ", "\\python ", " \\practic_basic.py", lower=True, trim=True) +# print(file_path) # E:\my_project\python\practic_basic.py + +# ___________________________ * ** операторы упаковки и распаковки ____________________________________ +# переданные аргументы в функции упаковывает в кортеж * - () и в словарь ** - {} +# можно распаковывать при работе с коллекциями +# x, *y = (1, 2, 3, 4) +# print(x) # 1 +# print(y) # [2, 3, 4] + +# # и другими итерируемыми объектами +# x, *y, z = "hello python" +# print(x) # h +# print(y) # ['e', 'l', 'l', 'o', ' ', 'p', 'y', 't', 'h', 'o'] +# print(z) # n + +# # но переупаковывать уже упакованное выдаст ошибку +# *x = 1, 2, 3 # так как здесь подразумевается кортеж +# print(x)# SyntaxError: starred assignment target must be in a list or tuple выдаст ошибку +# +# a = [1, 2, 3] +# a = (a, ) # создаст кортеж из 1 элемента - списка +# print(a) # ([1, 2, 3],) +# +# a = [1, 2, 3] +# a = (*a, ) # уже распакует элементы списка в кортеж +# print(a) # (1, 2, 3) + +# # еще пример применения распаковки +# d = -5, 5 # кортеж +# for i in range(*d): # если в range передать кортеж, будет ошибка, так как функция ожидает значения, а не коллекцию +# print(i, end=", ") # -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, + +# d = -5, 5 +# lst = [*range(*d)] # пример формирования списка +# print(lst) # [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4] + +# d = 0, 6 +# a = [7, 8, 9, 10] +# b = (True, True, False) +# lst = [*range(*d), *a, *b] +# print(lst) # [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, True, True, False] + +# # распаковка словаря +# my_dict = {"безнадежно" : 0, "убого" : 1, "неудовлетворительно" : 2, "удовлетворительно" : 3, "хорошо" : "4", +# "отлично" : "5"} +# +# print(*my_dict) # безнадежно убого неудовлетворительно удовлетворительно хорошо отлично - распаковка по ключам +# print(*my_dict.values()) # 0 1 2 3 4 5 - распаковка по значениям +# print(*my_dict.items()) # 'безнадежно', 0) ('убого', 1) ('неудовлетворительно', 2) ('удовлетворительно', 3) +# # ('хорошо', '4') ('отлично', '5') - распаковка по ключам и значениям в виде кортежей +# +# # распокавать в виде словаря ** +# d1 = {"правда" : True, "неправда" : False} +# d2 = {"безнадежно" : 0, "убого" : 1, "неудовлетворительно" : 2, "удовлетворительно" : 3, "хорошо" : "4", +# "отлично" : "5"} +# +# d3 = {**d1, **d2} +# print(d3) # {'правда': True, 'неправда': False, 'безнадежно': 0, 'убого': 1, 'неудовлетворительно': 2, +# # 'удовлетворительно': 3, 'хорошо': '4', 'отлично': '5'} + + + +## ___________________________________ Рекурсия __________________________ + +# рекурсивная функция - функция, которая вызывает саму себя + +# в рекурсии обязательно должны быть: +# условие выхода, уменьшение элемента, return +# +# def recursive(value): +# print(value, end=", ") +# if value < 10: +# recursive(value + 1) +# +# recursive(1) # 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + +# но если вывести значение по завершении функции, выводиться будут предыдущие значения функций (стек количество +# (глубина рекурсии) вызовов функций) + +# +# def recursive(value): +# print(value, end=", ") +# if value < 10: +# recursive(value + 1) +# print(value, end="*") +# +# recursive(1) # 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10*9*8*7*6*5*4*3*2*1* + +# найти сумму чисел в списке. +# def my_sum(a_list:list) -> int:#в функцию передать список, элементы класса int +# if not a_list:# если список пустой, условие выхода из рекурсии +# return 0# вернуть 0, так как сумма = 0 +# if len(a_list) == 1:# если в списке всего один элемент +# return a_list[0]# вернуть этот элемент +# return a_list[0] + my_sum(a_list[1:])# 1й элемент + вызов функции, укороченной на 1 элемент +# +# инверсия строки +# def my_reverse(value: str) -> str: +# if not value: +# return '' +# if len(value) == 1: +# return value +# if len(value) == 2: +# return f"value[1] + value[0]" +# return my_reverse(value[1:] + value[0]) +# +# возведение в степень +# def my_pow(x:int, y:int) -> int: +# if y == 0: +# return 1 +# if y == 1: +# return x +# if y == 2: +# return x * x +# return x * my_pow(x, y - 1) + +# if __name__ == '__main__': +# # assert my_sum([]) == 0 # тестовые значения для проверки +# # assert my_sum([1]) == 1 +# # assert my_sum([-1]) == -1 +# # assert my_sum([1, 2]) == 3 +# # assert my_sum([1, 2, 3]) == 6 +# +# # assert my_reverse('') == '' # тестовые значения для проверки +# # assert my_reverse('a') == 'a' +# # assert my_reverse('ab') == 'ba' +# # assert my_reverse('abc') == 'cba' +# +# assert my_pow(2, 0) == 1 # тестовые значения для проверки +# assert my_pow(2, 1) == 2 +# assert my_pow(2, 2) == 4 +# assert my_pow(2, 3) == 8 +# assert my_pow(6, 4) == 1296 + +# # вычисление факториала (n! математическое обозначение факториала) +# def factorial(n): +# if n <= 0: +# return 1 +# else: +# return n * factorial(n-1) +# +# +# print(factorial(5)) # 120 + +# чаще рекурсия используется для обхода каталогов и файлов + +# d = {"C:" : {"Program Files" : {"MPC-HC" : ["Authors.txt", "Changelog.txt"]}, +# "AMD" : {"amdkmpfd" : ["amdkmpfd.cbz", "amdkmpfd.ibz", "amdkmpfd.sbz"]} +# } +# } +# +# def get_file(dictionary, deep=0): +# for i in dictionary: +# print(" "*deep, i) +# if type(dictionary[i]) == dict: +# get_file(dictionary[i], deep + 1) +# else: +# print(" " * (deep + 1), " ".join(dictionary[i])) +# +# get_file(d) +# +# # C: +# # Program Files +# # MPC - HC +# # Authors.txt Changelog.txt +# # AMD +# # amdkmpfd +# # amdkmpfd.cbz +# # amdkmpfd.ibz +# # amdkmpfd.sbz + +# _________________________ анонимные (lambda) функции __________________________________ +# # lambda параметр1, параметр2 : команда +# print(lambda a, b: a + b) # at 0x000002D1DE72F240> +# # Чтобы вызвать функцию еее можно присвоить переменной +# s = lambda a, b: a + b # функция автоматически возвращает значение, поэтому оператор return не нужен +# print(s(1 ,2)) # 3 +# # ее можно использовать в любой конструкции python +# a = [1, 3, "dfdf", lambda:print("лямбда"), 3, True] +# print(a[3]) # at 0x000002932409F240> хранит ссылку на эту функцию +# # чтобы вызвать функцию необходимо прописать круглые скобки +# a[3]() # лямбда + +# # Пример использования лямбда функции. +# # Перебор чисел списка, если фильтр None, то все элементы остаются, а если указан фильтр, то отфильтровать +# # по указанному критерию +# +# def get_lst(lst, filter=None): +# if filter is None: +# return lst +# +# new_lst = [] +# for i in lst: +# if filter(i): +# new_lst.append(i) +# +# return new_lst +# +# a = [5, 6, -10, 63, 7] +# +# r = get_lst(a) +# print(r) # [5, 6, -10, 63, 7] без фильтра получим тотже список +# +# r = get_lst(a, lambda c: c % 2 == 0) # фильтр по четному числу +# print(r) # [6, -10] + +# в Python существуют две конструкции: «is None» и «== None». Оператор «==» сравнивает значения двух переменных, в то +# время как оператор «is» сравнивает, являются ли две переменные одним и тем же объектом. На практике чаще всего для +# проверки на None используют «is None», так как это более эффективно и проверяет, если переменная привязана к +# объекту None. + +# в лямбда функции можно выполнять только 1 команду, +# ее нельзя объявлять в несколько строк, +# нельзя внутрии нее использовать оператор присваивания, даже a += 1 вызовет ошибку. lambda a: a + 1, так сработает + +# ____________________ области видимости переменных _______________________ +# глобальные переменные доступны в любой области программы, после их объявления (Пространство имен всей программы) +# функции создают свое пространство имен. И в них создаются локальные переменный. Они существуют только внутри функции + +# width, height = 600, 200 # width, height глобальные переменные +# +# def my_number(lst): # lst, n, x локальные переменные +# for x in lst: +# n = x + 1 +# print(n) +# +# my_number([1, 2, 3]) +# print(lst) # NameError: name 'lst' is not defined. Did you mean: 'list'? ошибка +# print(x) # NameError: name 'x' is not defined +# print(n) # NameError: name 'n' is not defined +# # а глобальную переменную можно без проблем использовать в функции +# width, height = 600, 200 # width, height глобальные переменные +# +# def my_number(lst): # lst, n, x локальные переменные +# print(width, height) +# for x in lst: +# n = x + 1 +# print(n) +# +# my_number([1, 2, 3]) +# # 600 200 +# # 2 +# # 3 +# # 4 + +# width, height = 600, 200 # width, height глобальные переменные +# # +# def my_number(lst): +# height = 3500 # при присваивании нового значения внутри функции, глобальная переменная не изменяется, +# for x in lst: # а создается новая с таким же именем +# n = x + 1 + height #+3500 сначала поиск такой переменной происходит локально, если есть используется ее значение, +# print(n) # если такой нет, то поиск осуществляется глобально +# +# my_number([1, 2, 3]) +# print(height) # 200 значение глобальной переменной +# # 3502 +# # 3503 +# # 3504 +# # 200 + +# # ключевое слово global указывает, что в функции работать необходимо с глобальной переменной, тогда изменения сохранятся +# width, height = 600, 200 # width, height глобальные переменные +# # +# def my_number(lst): +# global height +# height = 3500 # при присваивании нового значения внутри функции, глобальная переменная изменяется, а не создает новую +# for x in lst: +# n = x + 1 +# print(n) +# +# my_number([1, 2, 3]) +# print(height) # 3500 значение глобальной переменной +# # 2 +# # 3 +# # 4 +# # 3500 + +# x = 0 # глобальная переменная +# +# +# def outer(): +# x = 1 # локальная переменная +# def inner(): +# x = 2 # локальная переменная(вложенная функция) +# print("inner: ", x) # 2 +# inner() +# print("outer: ", x) # 1 +# outer() +# print("global: ", x) # 0 +# # inner: 2 +# # outer: 1 +# # global: 0 + +# # ключевое nonlocal слово позволяет работать с переменной внешней оббласти видимости +# x = 0 # глобальная переменная +# +# +# def outer(): +# x = 1 # локальная переменная +# def inner(): +# nonlocal x # будет изменять ч из внешней функции outer +# x = 2 # локальная переменная(вложенная функция) +# print("inner: ", x) # 2 +# inner() +# print("outer: ", x) # 2 +# outer() +# print("global: ", x) # 0 +# # inner: 2 +# # outer: 2 # значение изменилось, так как использовалось ключевое слово nonlocal +# # global: 0 +# +# # ключевое слово nonlocal можно использовать только для локальных областей имен (например для вложенных функций), а для +# # глобальных областей используется ключевое слово global + +# __________________ замыкания ____________________ +# def say_name (name): +# def say_hello(): +# print(f"Привет, {name}") +# say_hello() +# +# say_name("Vika") # Привет, Vika + +# # можно не вызывать внутреннюю функцию, а просто вернуть ее +# def say_name (name): +# def say_hello(): +# print(f"Привет, {name}") +# return say_hello +# +# f = say_name("Vika") # чтобы к ней можно было обратиться, сохраняем ее в переменную +# f() # Привет, Vika. А затем вызываем +# +# # на внутреннюю функцию ссылается глобальная переменная, поэтому она не удаляется автоматическим сборщиком мусора, +# # и продолжает существовать даже после завершения основной функции. Внешнее окружение также продолжает существовать, +# # поэтому функция может обращаться к name. Это и есть замыкание. Мы как бы держим все внутренние окружения - они по +# # цепочке подтягивают друг друга. Причем каждый вызов функции со своим аргументом создаст свое локальное окружение +# f2 = say_name("python") +# f2() # Привет, python + +# # где можно использовать замыкания, например для создания счетчика +# def counter(start=0): +# def step(): +# nonlocal start # чтобы изменять именно переменную из внешнего окружения, а не создавать новую с таким же именем +# start += 1 +# return start +# +# return step # вернуть ссылку на функцию, а не ее вызов +# +# s1 = counter(10) +# s2 = counter() +# # оба счетчика работают независимо друг от друга, благодаря замыканию +# print(s1(), s2()) # 11 1 +# print(s1(), s2()) # 12 2 +# print(s1(), s2()) # 13 3 +# print(s1(), s2()) # 14 4 +# +# # пример удаления пробелов и символов +# def strip_string(string_chars=" "):# по умолчанию просто пробел +# def do_strip(string): +# return string.strip(string_chars) # удаление этих символов в начале и в конце строки +# return do_strip +# +# strip1 = strip_string() # ссылка на внутреннюю функцию, с параметром " " для внешней функции +# strip2 = strip_string(" !,.?") # ссылка на внутреннюю функцию с параметром " !,.?" для внешней функции +# # здесь уже передаем аргументы для внутренней функции +# print(strip1(" hello, python!!!... ")) # hello, python!!!... +# print(strip2(" hello, python!!!... ")) # hello, python + +# __________________________ декораторы функций ___________________________ +# def decorator_func(func): +# def wrapper(): +# print("-------- что-то делаем до вызова функции --------") +# func() # вызываем функцию +# print("-------- что-то делаем после вызова функции --------") +# +# return wrapper # возвращает ссылку на внутреннюю функцию +# +# +# def some_func(): +# print("Вывод функции some_func") +# +# some_func() # Вывод функции some_func # обыкновенный вызов функции +# # вызов функции через другую функцию(декоратор) +# +# f = decorator_func(some_func) # передаем функцию some_func в decorator_func +# f() +# -------- что-то делаем до вызова функции -------- +# Вывод функции some_func +# -------- что-то делаем после вызова функции -------- + +# # декоратор расширяет функционал сторонней функции +# # но обычно при декорации не присваивают новой переменной, а присваивают функции(перезаписывают ее) +# def decorator_func(func): +# def wrapper(): +# print("-------- что-то делаем до вызова функции --------") +# func() # вызываем функцию +# print("-------- что-то делаем после вызова функции --------") +# +# return wrapper # возвращает ссылку на внутреннюю функцию +# +# +# def some_func(): +# print("Вывод функции some_func") +# +# some_func = decorator_func(some_func) # перезаписываем функцию some_func +# some_func() +# # -------- что-то делаем до вызова функции -------- +# # Вывод функции some_func +# # -------- что-то делаем после вызова функции -------- + +# но если передать в функцию параметр выведется ошибка, так как у внутренней функции нет параметров +# def decorator_func(func): +# def wrapper(): # нет аргументов +# print("-------- что-то делаем до вызова функции --------") +# func() # вызываем функцию +# print("-------- что-то делаем после вызова функции --------") +# +# return wrapper # возвращает ссылку на внутреннюю функцию +# +# +# def some_func(title): +# print("Вывод функции some_func " + title) +# +# some_func = decorator_func(some_func) # перезаписываем функцию some_func +# some_func("some text") # TypeError: decorator_func..wrapper() takes 0 positional arguments but 1 was given + +# # для решения этой проблемы внутренней функции *args, **kwargs +# def decorator_func(func): +# def wrapper(*args, **kwargs): # нет аргументов +# print("-------- что-то делаем до вызова функции --------") +# func(*args, **kwargs) # вызываем функцию +# print("-------- что-то делаем после вызова функции --------") +# +# return wrapper # возвращает ссылку на внутреннюю функцию +# +# +# def some_func(title): +# print("Вывод функции some_func " + title) +# +# some_func = decorator_func(some_func) # перезаписываем функцию some_func +# some_func("some text") # не возникнет ошибки даже в случае, если не будет аргументов, или будут именованные аргументы +# # -------- что-то делаем до вызова функции -------- +# # Вывод функции some_func some text +# # -------- что-то делаем после вызова функции -------- + +# # если добавить в функцию some_func return, ничего не выведется, так как внутренняя функция wrapper ничего не возвращает +# def decorator_func(func): +# def wrapper(*args, **kwargs): # нет аргументов +# print("-------- что-то делаем до вызова функции --------") +# func(*args, **kwargs) # вызываем функцию +# print("-------- что-то делаем после вызова функции --------") +# +# return wrapper # возвращает ссылку на внутреннюю функцию, но результат func не возвращает +# +# +# def some_func(title): +# print("Вывод функции some_func " + title) +# return f"возврат функции some_func - title: {title}" +# +# some_func = decorator_func(some_func) # перезаписываем функцию some_func +# res = some_func("some text") +# print(res) # None +# # -------- что-то делаем до вызова функции -------- +# # Вывод функции some_func some text +# # -------- что-то делаем после вызова функции -------- # после вывода ничего не вывелось - нет return +# None + + +# # чтобы это исправить и сделать декоратор более универсальным - присвоить результат переменной и вернуть его +# def decorator_func(func): +# def wrapper(*args, **kwargs): # нет аргументов +# print("-------- что-то делаем до вызова функции --------") +# res = func(*args, **kwargs) # присваиваем результат переменной +# print("-------- что-то делаем после вызова функции --------") +# return res # возвращает результат функции +# +# return wrapper # возвращает ссылку на внутреннюю функцию, и результат func +# +# +# def some_func(title): +# print("Вывод функции some_func " + title) +# return f"возврат функции some_func - title: {title}" +# +# some_func = decorator_func(some_func) # перезаписываем функцию some_func +# res = some_func("some text") +# print(res) +# # -------- что-то делаем до вызова функции -------- +# # Вывод функции some_func some text +# # -------- что-то делаем после вызова функции -------- +# # возврат функции some_func - title: some text + +# пример использования декоратора - тестирование скорости работы функции - на примере алгоритмов Евклида +# import time +# +# +# def test_time(func): +# def wrapper(*args, **kwargs): # произвольное число аргументов +# start = time.time() +# res = func(*args, **kwargs) # присваиваем результат переменной +# end = time.time() +# time_out = end - start +# print(f"Время работы функции - {time_out} сек") +# +# return res # возвращает результат функции +# +# return wrapper # возвращает ссылку на внутреннюю функцию, и результат func +# +# def get_node_long(a, b): # длинный алгоритм Евклида для нахождения наибольшего общего делителя +# while a != b: +# if a > b: +# a -= b +# else: +# b -= a +# +# return a +# +# def get_node_short(a, b): # короткий алгоритм Евклида для нахождения наибольшего общего делителя +# if a < b: +# a, b = b, a +# while b: +# a, b = b, a % b +# +# return a +# +# get_node_long = test_time(get_node_long) +# res = get_node_long(2, 10000000) +# get_node_short = test_time(get_node_short) +# res2 = get_node_short(2, 10000000) +# print(res, res2) +# # Время работы функции - 1.420173168182373 сек +# # Время работы функции - 6.9141387939453125e-06 сек у меня почему-то быстрый отработал медленнее +# # 2 2 + +# # но в программировании декораторы прописывают для удобства иначе +# import time +# +# +# def test_time(func): +# def wrapper(*args, **kwargs): # произвольное число аргументов +# start = time.time() +# res = func(*args, **kwargs) # присваиваем результат переменной +# end = time.time() +# time_out = end - start +# print(f"Время работы функции - {time_out} сек") +# +# return res # возвращает результат функции +# +# return wrapper # возвращает ссылку на внутреннюю функцию, и результат func +# +# @test_time +# def get_node_long(a, b): # длинный алгоритм Евклида для нахождения наибольшего общего делителя +# while a != b: +# if a > b: +# a -= b +# else: +# b -= a +# +# return a +# +# @test_time +# def get_node_short(a, b): # короткий алгоритм Евклида для нахождения наибольшего общего делителя +# if a < b: +# a, b = b, a +# while b: +# a, b = b, a % b +# +# return a +# +# +# res = get_node_long(2, 10000000) +# +# res2 = get_node_short(2, 10000000) +# print(res, res2) +# # Время работы функции - 0.7530386447906494 сек +# # Время работы функции - 8.58306884765625e-06 сек +# # 2 2 + +# _______________________________ декораторы функций с параметрами ______________________________________ +# вычисление производной функции = функция (с передаваемым параметром + указанный параметр с малым значением) - +# - обычная функция(с передаваемым параметром) / параметр(с малым значением) +# import math +# +# +# def func_decorator(func): +# def wrapper(x, *args, **kwargs): # передаем 1 параметр + универсальные +# dx = 0.0001 # задаем малое значение для вычисления производной +# res = (func(x + dx, *args, *kwargs) - func(x, *args, *kwargs)) / dx # , *args, *kwargs на случай переданных +# # дополнительных аргументов +# return res +# return wrapper +# +# @func_decorator +# def sin_dx(x): # функция вычисления синуса в точке x +# return math.sin(x) +# +# df = sin_dx(math.pi / 3) # в качестве аргумента передаем значение число Пи / 3 +# print(df) # 0.4999566978958203 + +# но чтобы параметр dx был настраиваемым (его можно было передавать в декоратор), необходимо модифицировать декоратор +# вложить его еще в одну функцию, которая и будет принимать этот параметр +# import math +# +# def df_decorator(dx=0.001): +# def func_decorator(func): +# def wrapper(x, *args, **kwargs): # передаем 1 параметр + универсальные +# res = (func(x + dx, *args, *kwargs) - func(x, *args, *kwargs)) / dx # , *args, *kwargs на случай переданных +# # дополнительных аргументов +# return res +# return wrapper +# return func_decorator +# +# @df_decorator(dx=0.00001) +# def sin_dx(x): # функция вычисления синуса в точке x +# return math.sin(x) +# +# df = sin_dx(math.pi / 3) # в качестве аргумента передаем значение число Пи / 3 +# print(df) # 0.499995669867026 + +# # при помощи .__name__ можно посмотреть фактическое имя функции +# import math +# +# def df_decorator(dx=0.001): +# def func_decorator(func): +# def wrapper(x, *args, **kwargs): # передаем 1 параметр + универсальные +# res = (func(x + dx, *args, *kwargs) - func(x, *args, *kwargs)) / dx # , *args, *kwargs на случай переданных +# # дополнительных аргументов +# return res +# return wrapper +# return func_decorator +# +# @df_decorator(dx=0.00001) +# def sin_dx(x): # функция вычисления синуса в точке x +# return math.sin(x) +# +# df = sin_dx(math.pi / 3) # в качестве аргумента передаем значение число Пи / 3 +# print(df) # 0.499995669867026 +# print(sin_dx.__name__) # wrapper, так как в декораторе возвращается ссылка на объект функции wrapper + +# # чтобы функция сохранила свое имя это можно указать явно +# import math +# +# def df_decorator(dx=0.001): +# def func_decorator(func): +# def wrapper(x, *args, **kwargs): # передаем 1 параметр + универсальные +# res = (func(x + dx, *args, *kwargs) - func(x, *args, *kwargs)) / dx # , *args, *kwargs на случай переданных +# # дополнительных аргументов +# return res +# wrapper.__name__ = func.__name__ # Явно указываем у ссылки wrapper имя той функции, которую передаем +# return wrapper +# return func_decorator +# +# @df_decorator(dx=0.00001) +# def sin_dx(x): # функция вычисления синуса в точке x +# return math.sin(x) +# +# df = sin_dx(math.pi / 3) # в качестве аргумента передаем значение число Пи / 3 +# print(df) # 0.499995669867026 +# print(sin_dx.__name__) # sin_dx, так как в декораторе явно указали имя +# +# # чтобы функция сохранила свое описание(оставляют для других разработчиков) используется .__doc__ +# import math +# +# def df_decorator(dx=0.001): +# """Декоратор для вычисления производной функции""" +# def func_decorator(func): +# def wrapper(x, *args, **kwargs): # передаем 1 параметр + универсальные +# res = (func(x + dx, *args, *kwargs) - func(x, *args, *kwargs)) / dx # , *args, *kwargs на случай переданных +# # дополнительных аргументов +# return res +# wrapper.__name__ = func.__name__ # Явно указываем у ссылки wrapper имя той функции, которую передаем +# return wrapper +# return func_decorator +# +# @df_decorator(dx=0.00001) +# def sin_dx(x): +# """функция вычисления синуса в точке x""" # описание функции +# return math.sin(x) +# +# df = sin_dx(math.pi / 3) # в качестве аргумента передаем значение число Пи / 3 +# print(df) # 0.499995669867026 +# print(sin_dx.__name__) # sin_dx, так как в декораторе явно указали имя +# print(sin_dx.__doc__) # None так как описание в wrapper нет. Его также необходимо явно указать + +# import math +# +# def df_decorator(dx=0.001): +# """Декоратор для вычисления производной функции""" +# def func_decorator(func): +# def wrapper(x, *args, **kwargs): # передаем 1 параметр + универсальные +# res = (func(x + dx, *args, *kwargs) - func(x, *args, *kwargs)) / dx # , *args, *kwargs на случай переданных +# # дополнительных аргументов +# return res +# wrapper.__name__ = func.__name__ # Явно указываем у ссылки wrapper имя той функции, которую передаем +# wrapper.__doc__ = func.__doc__ # Явно указываем у ссылки wrapper описание той функции, которую передаем +# return wrapper +# return func_decorator +# +# @df_decorator(dx=0.00001) +# def sin_dx(x): +# """функция вычисления синуса в точке x""" # описание функции +# return math.sin(x) +# +# df = sin_dx(math.pi / 3) # в качестве аргумента передаем значение число Пи / 3 +# print(df) # 0.499995669867026 +# print(sin_dx.__name__) # sin_dx, так как в декораторе явно указали имя +# print(sin_dx.__doc__) # функция вычисления синуса в точке x # так как явно указали какое описание должно быть + +# # прописывать описание и имя функции в декораторах, считается хорошим тоном, поэтому для этого уже есть специальная +# # встроенная функция wraps в модуле functools +# from functools import wraps +# import math +# +# def df_decorator(dx=0.001): +# """Декоратор для вычисления производной функции""" +# def func_decorator(func): +# @wraps(func) # для сохранения имени и описания функции в wrapper +# def wrapper(x, *args, **kwargs): +# res = (func(x + dx, *args, *kwargs) - func(x, *args, *kwargs)) / dx +# return res +# +# return wrapper +# return func_decorator +# +# @df_decorator(dx=0.00001) +# def sin_dx(x): +# """функция вычисления синуса в точке x""" # описание функции +# return math.sin(x) +# +# df = sin_dx(math.pi / 3) +# print(df) # 0.499995669867026 +# print(sin_dx.__name__) # sin_dx, так как использовали встроенную @wraps(имя функции) +# print(sin_dx.__doc__) # функция вычисления синуса в точке x, так как использовали встроенную @wraps(имя функции) + +# ______________________ импорт стандартных модулей _________________________ +# import импортирует документ с расширением.py +# при использовании записи import math необходимо прописывать имя модуля перед использованием встроенного метода +# import math +# sinus = math.sin(5) # название модуля(math).вызов метода(нахождение синуса от числа) +# print(sinus) # -0.9589242746631385 +# так импортируется весь модуль со всеми его функциями + +# # при использовании записи from math import sin достаточно прописать имя самой функции +# так импортируется определенная функция этого модуля +# from math import sin +# sinus = sin(5) # название модуля(math).вызов метода(нахождение синуса от числа) +# print(sinus) # -0.9589242746631385 + +# import math +# +# n = math.ceil(1.8) # округлениe к наибольшему целому числу +# print(n) # 2 + +# # python позволяет задавать импортируемым модулям и функциям псевдоним +# import math as mt +# num_pi = mt.pi +# print(num_pi) # 3.141592653589793 + +# from time import time as t +# start = t() +# print(start) # 1737882985.2651734 +# end = t() +# print(end) # 1737882985.2715108 + +# # 2й способ все импортировать из библиотеки +# from math import * # чтобы посмотреть содержимое библиотеки crtl + LMB(левая кнопка мышки) по названию библиотеки +# s = factorial(6) +# print(s) # 720 +# но такой импорт крайне не рекомендуется делать, так как при импорте нескольких модулей может возникать конфликт из-за +# одинаковых имен функций +# также не рекомендуется импортировать вот так +# impor time, math +# по стандартам pep8 каждый нужно записывать с новой строки +# import time +# import math +# все импорты располагаются в самом начале + +# _______________ импорт своего модуля ___________________ +# import my_module +# +# # чтобы обратиться к элементам модуля нужно указать имя модуля.функцию или переменную, к которой хочешь обратиться +# my_module.my_func("Вика") +# # Привет Вика - Это код из модуля my_module +# +# from my_module import my_func +# my_func("Вика") +# # Привет Вика - Это код из модуля my_module + +# но если в модуле будет свой импорт, необходимо описать иерархию пространства имен +# import my_module +# +# a = my_module.math.factorial(5) # сначала имя модуля.имя импортируемого в нем модуля.а потом имя функции +# print(a) # 120 + +# import my_module # если в модуле прописать from math +# +# a = my_module.factorial_func(5) # сначала имя модуля. а потом имя функции +# print(a) # 120 + +import new_folder.my_module # если модуль будет находиться в подкаталоге (в другой папке), то необходимо прописать сначала имя папки, +# а затем уже имя модуля + +# # 2й вариант можно прописать путь к этой папке во встроенном модуле sys добавив в path необходимый путь +# import sys +# sys.path.append("E:\\my_project\\python\\new_folder") # здесь он найдет my_module и импортирует его +# import my_module +# +# a = my_module.factorial_func(5) # сначала имя модуля. а потом имя функции +# print(a) # 120 +# Но чаще используется первый способ + +# import my_module +# my_module так как сработал print из my_module, здесь у __name__ имя уже будет my_module + + +# # модуль импортируется 1 раз, поэтому и выполняется 1 раз +# import my_module +# import my_module +# # my_module выполнение 1 раз +# # +# # если необходимо импортировать библиотеку повторно есть встроенный модуль (с версии python 3.4) +# import my_module +# import importlib +# +# importlib.reload(my_module) +# # my_module +# # my_module сработал оба раза + +#_________________ установка сторонних модулей ________________ + +# NumPy - для работы с многомерными массивами +# Matplotlib - для отображения графиков +# Pygame - для игр 2д графики +# Flask - простой фреймворк, чаще для информационных сайтов +# Django - продвинутый фреймворк для сложных сайтов +# +# в терминале pip list - выведет все установленные модули для текущего интерпретатора python +# PS E:\my_project\python> pip list +# Package Version +# ------- ------- +# pip 24.3.1 +# PS E:\my_project\python> у меня еще ничего не установлено +# для установки в терминале pip install название пакета, если необходимо определенную версию, то после названия +# добавить ==1.1.2 +# pip install flask==1.1.2 + +# для того чтобы записать все библиотеки с версиями, для переноса на другой проект существует специальная команда +# pip freeze name.txt это создаст в рабочей директории текстовый документ с установленными пакетами + +# затем все эти модули можно установить пакетной установкой +# pip install -r name.txt + +# package - специальным образом организованный подкаталог с набором модулей (как правило, решающих сходные задачи) +# RMB - new - python package - задать имя - enter +# автоматически создастся каталог с python файлом с именем __init__.py +# для корректной работы всех модулей кодировка всех файлов должна быть UTF-8 + +# пакеты импортируются также как модули. В названии не должно быть пробелов +import courses_catalog + +# Process finished with exit code 0 Программа отработала без ошибок, но ничего не вывела +# print(dir(courses_catalog)) # эта команда выводит что содержится в этом пространстве имен(переменные, функции) +# # ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'name'] +# # name наша созданная переменная, остальные служебные, то есть при импорте пакета, автоматически импортируется все из +# # файла __init__.py +# # чтобы отобразить остальные файлы, их необходимо импортировать в __init__.py +# # Тогда при запуске команда dir, появятся имена других файлов +# import courses_catalog +# +# print(dir(courses_catalog)) +# # ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', +# # 'courses_catalog', 'css', 'html', 'java', 'name', 'python'] +# +# # и тогда можно вызвать функции из этих файлов +# import courses_catalog +# +# courses_catalog.python.func_python() +# # тут курс по Python +# courses_catalog.css.func_css() +# # тут курс по CSS +# courses_catalog.html.func_html() +# # тут курс по HTML +# courses_catalog.java.func_java() +# # тут курс по Java + +# Если импортировать функцию в инит, то имя файла прописывать не нужно(по принципу модулей impor и from ... import +# import courses_catalog +# +# courses_catalog.func_python() +# # тут курс по Python +# courses_catalog.func_css() +# # тут курс по CSS +# courses_catalog.func_html() +# # тут курс по HTML +# courses_catalog.func_java() +# # тут курс по Java + +# import courses_catalog +# +# courses_catalog.func_python() +# # тут курс по Python + +# # можно создать подкаталог - например, документация к языкам программирования +# import courses_catalog +# +# # print(courses_catalog.python_doc.python) # А тут типа документация по python +# print(courses_catalog.java_doc.java) # Типа тут документация по java: тут курс по Java + +# _________________ работа с файлами __________________ +# # open(file=путь к файлу, mode=режим доступа к файлу(чтение/запись), encoding=кодировка файла) +# # open открывает файл по-умолчанию на чтение +# # если файл находится в том же каталоге, что и исполняемый файл, можно просто написать его имя с расширением - это +# # относительный путь +# # file = open("text.txt") +# # # или прописать путь полностью - абсолютный путь +# # file = open("E:\\my_project\\python\\text.txt") +# # но путь лучше прописывать обратным слэшем (так как тот вариант будет работать только на windows) +# file = open("E:/my_project/python/text.txt") # будет работать и на линукс +# # если файл находится в разных директориях от исполняемого, то обращаются к родительскому каталогу ../ +# #read() выведет все, что есть в файле +# print(file.read()) # Какой-то текст просто для проверки работоспособности РєРѕРґР°. + + +# # в windows по умолчанию читается в кодировке windows251, поэтому необходимо явно указывать кодировку +# file = open("E:/my_project/python/text.txt", encoding="utf-8") # +# # print(file.read()) # Какой-то текст просто для проверки работоспособности кода. +# print(file.read(5)) # Какой # можно указать сколько символов прочитать +# print(file.read(5)) # -то т # выведет следующие 5 символов. Так как запоминает файловую позицию. +# # иногда при прочитывании файла в начале и вконце файла могут содержаться невидимые символы #EFEF EOF(end of file), +# # поэтому количество символов может выводиться меньше. +# # чтобы изменить файловую позицию есть команда seek() +# file.seek(0) # обнуляем файловую позицию +# print(file.read(5)) # Какой # снова читает только 5 символов, и опять с начала, так как обнулили файловую позицию +# # tell показывает текущую файловую позицию +# print(file.tell()) # 10 номер байта (символ 2 байта), а не значение +# file = open("E:/my_project/python/text.txt", encoding="utf-8") +# # # чтобы прочитать строку метод readline() +# # print(file.readline()) # Какой-то текст просто для проверки работоспособности кода. Также запоминает позицию в файле, +# # # при повторном вызове отобразит уже следующую строку +# # # чтобы прочитать файл построчно, можно использовать цикл for +# # for line in file: +# # print(line, end="") +# # # Строка 1 -Какой-то текст просто для проверки работоспособности кода. +# # # Строка 2 -Какой-то текст просто для проверки работоспособности кода. +# # # Строка 3 -Какой-то текст просто для проверки работоспособности кода. +# # чтобы отобразить все строки файла, есть метод readlines возвращает список со строками +# print(file.readlines()) # при работе с огромными файлами может возникнуть ошибка +# # ['Строка 1 -Какой-то текст просто для проверки работоспособности кода.\n', +# # 'Строка 2 -Какой-то текст просто для проверки работоспособности кода.\n', +# # 'Строка 3 -Какой-то текст просто для проверки работоспособности кода.'] + +# после работы с файлом его нужно закрыть +# file.close()# так как это освобождает память и позволяет не потерять записанные данные + +# # ___________ исключение FileNotFoundError ________________ +# # обработка исключний делается для того, чтобы программа продолжала работать, +# # даже в случае ошибки для этого ипользуются операторы try, except, finally +# # try: +# # блок операторов критического кода (те, которые могут привести к исключениям(ошибкам)) +# # except: +# # блок операторов обработки иключения (обрабатывает исключения) +# # finally: +# # блок операторов всегда исполняемых, вне зависимости от возникновения исключения +# try: +# file = open("text.txt", encoding="utf-8") +# print(file.readlines()) +# file.close() +# # после возникновения ошибки последующий код из блока try выполняться не будет, программа +# # перейдет к блоку except +# except FileNotFoundError: +# print("Невозможно открыть файл") +# # ['Строка 1 -Какой-то текст просто для проверки работоспособности кода.\n', +# # 'Строка 2 -Какой-то текст просто для проверки работоспособности кода.\n', +# # 'Строка 3 -Какой-то текст просто для проверки работоспособности кода.'] + + +# # но если ошибка возникнет, например при чтении файла(это уже другое исключение), то код +# # закрытия файла не сработает, поэтому внутри также следует прописать эту контрукцию +# try: +# file = open("text.txt", encoding="utf-8") +# try: +# print(file.readlines()) +# # код в блоке finnaly выполнится в любом случае +# finally: +# file.close() +# except FileNotFoundError: +# print("Невозможно открыть файл") +# # если не указывать конкретную ошибку, то будут обрабатываться любые ошибки, +# # поэтому такое иключение стоит указывать после всех конкретных +# except: +# print("Возникла ошибка при работе с файлом") +# # так как внутренний блок не обрабатывает ошибки, их обработает внешний +# # ['Строка 1 -Какой-то текст просто для проверки работоспособности кода.\n', +# # 'Строка 2 -Какой-то текст просто для проверки работоспособности кода.\n', +# # 'Строка 3 -Какой-то текст просто для проверки работоспособности кода.'] + + + +# # эту конструкцию можно заменить файловым менеджером контекста +# try: +# with open("text.txt", encoding="utf-8") as file: # если откроется то +# # выполнится блок кода ниже +# print(file.readlines()) +# # он автоматически закрывает файл, поэтому его часто используют +# except FileNotFoundError: +# print("Невозможно открыть файл") +# except: +# print("Возникла ошибка при работе с файлом") +# # а при возникновении ошибки, выполнится внешний обработчик исключений +# # чтобы проверить, действительно ли файл закрылся, можно использовать closed +# finally: +# print(file.closed) # True +# # ['Строка 1 -Какой-то текст просто для проверки работоспособности кода.\n', 'Строка 2 -Какой-то текст просто для проверки работоспособности кода.\n', 'Строка 3 -Какой-то текст просто для проверки работоспособности кода.'] +# # True + +# # __________________________ Запись в файл __________________________ +# # для того, чтобы что-то записать в файл, его необходимо открыть в режиме записи "w" +# file = open("out.txt", "w") # если такого файла нет, то программа создаст его +# file.write("Какой-то записанный через программу текст") # записать в файл строку +# file.close() # После того, как записали, документ обязательно нужно закрыть +# +# # при открытии файла на запись, все содеримое в нем уничтожается, поэтому при повторном открытии +# # и записи другой строки, она просто перезапишется, а не добавится +# file = open("out.txt", "w") +# file.write("Теперь в файле будет записана эта строка, вместо той") +# file.close() + +# во избежание возможных ошибок, код стоит также поместить в конструкцию обработки исключений +# try: +# with open("out.txt", "w") as file: +# file.write("Теперь в файле будет записана эта строка, вместо той") +# except FileNotFoundError: +# print("файл не найден") +# except: +# print("Произошла какая-то ошибка") +# # строка запишется в файл + +# # file использует файловую позицию, поэтому строки записываются одна за другой, не с новой строки +# try: +# with open("out.txt", "w") as file: +# file.write("Строка 1") +# file.write("Строка 2") +# file.write("Строка 3") +# except: +# print("Произошла ошибка при работе с файлом") +# # # строка запишется в файл +# +# # чтобы записать с новой строки дотаточно использовать символ новой строки \n +# try: +# with open("out.txt", "w") as file: +# file.write("Строка 1\n") +# file.write("Строка 2\n") +# file.write("Строка 3") +# except: +# print("Произошла ошибка при работе с файлом") +# # # строка запишется в файл +# +# # а если нужно дозаписать в файл какую-то информацию, нужно открыть в режиме "a" append добавить +# try: +# with open("out.txt", "a") as file: +# file.write("Добавленная Строка 1\n") +# file.write("Добавленная Строка 2\n") +# file.write("Добавленная Строка 3") +# except: +# print("Произошла ошибка при работе с файлом") +# # # строка запишется в файл +# +# # но если открыть файл в формате записи или добавления то попытка его прочитать приведет к ошибке +# try: +# with open("out.txt", "a") as file: +# r = file.readlines() +# print(r) +# +# except: +# print("Произошла ошибка при работе с файлом") +# # Произошла ошибка при работе с файлом +# # +# # # Чтобы и записывать и читать файл используется реим a+ +# # +# try: +# with open("out.txt", "a+") as file: +# r = file.readlines() +# print(r) +# +# except: +# print("Произошла ошибка при работе с файлом") +# # [] + +# # но в таком режиме файловая позиция находится вконце, поэтому и вывелся пустой список, +# # чтобы прочитать все эти строки, позицию нужно вернуть на начало +# try: +# with open("out.txt", "a+") as file: +# file.seek(0) # это файловая позиция для чтения +# r = file.readlines() +# print(r) +# +# except: +# print("Произошла ошибка при работе с файлом") +# # ['Строка 1\n', 'Строка 2\n', 'Строка 3Добавленная Строка 1\n', 'Добавленная Строка 2\n', 'Добавленная Строка 3'] +# +# # # для изменения файловой позиции для записи используется отдельная независимая позиция +# try: +# with open("out.txt", "a+") as file: +# file.seek(0) # это файловая позиция для чтения +# file.write("Эта строка запишется в конец, не смотря на то что обнулена позиция") +# file.seek(0) +# r = file.readlines() +# print(r) +# +# except: +# print("Произошла ошибка при работе с файлом") +# # ['Строка 1\n', 'Строка 2\n', 'Строка 3Добавленная Строка 1\n', 'Добавленная Строка 2\n', +# # 'Добавленная Строка 3Эта строка запишется в конец, не смотря на то что обнулена позицияЭта строка запишется в конец, +# # не смотря на то что обнулена позицияЭта строка запишется в конец, не смотря на то что обнулена позиция'] +# +# # # специальный метод для записи сразу нескольких строк writelines([]) +# try: +# with open("out.txt", "a+") as file: +# file.seek(0) +# file.writelines(["запишется ", "сразу", "несколько", "строк"]) +# file.seek(0) +# r = file.readlines() +# print(r) +# +# except: +# print("Произошла ошибка при работе с файлом") +# # ['Строка 1\n', 'Строка 2\n', 'Строка 3Добавленная Строка 1\n', 'Добавленная Строка 2\n', 'Добавленная Строка 3Эта строка запишется в конец, не смотря на то что обнулена позицияЭта строка запишется в конец, не смотря на то что обнулена позицияЭта строка запишется в конец, не смотря на то что обнулена позицияЭта строка запишется в конец, не смотря на то что обнулена позициязапишется сразунесколькострокЭта строка запишется в конец, не смотря на то что обнулена позиция'] +# # ['Строка 1\n', 'Строка 2\n', 'Строка 3Добавленная Строка 1\n', 'Добавленная Строка 2\n', 'Добавленная Строка 3Эта строка запишется в конец, не смотря на то что обнулена позицияЭта строка запишется в конец, не смотря на то что обнулена позицияЭта строка запишется в конец, не смотря на то что обнулена позицияЭта строка запишется в конец, не смотря на то что обнулена позициязапишется сразунесколькострокЭта строка запишется в конец, не смотря на то что обнулена позициязапишется сразунесколькострок'] + + +# +# # ____________________ бинарный тип записи _______________________ +# # данные запиываются без какой-либо обработки "wb" библиотеки pickle +# import pickle +# +# books = [ +# ("Евгений Онегин", "Пушкин А.С.", 200), +# ("Муму", "Тургенев И.С.", 250), +# ("Мастер и Маргарита", "Булгаков М.А.", 500) +# ] +# file = open("out.bin", "wb") +# # dump(данные, файл) #загрузить данные в файл +# pickle.dump(books, file) +# file.close() +# # произошла запись +# +# # чтобы прочитать файл в бинарном режиме rb +# import pickle +# +# file = open("out.bin", "rb") +# # load(файл)#прочитать данные в файле +# bs = pickle.load(file) +# file.close() +# print(bs) +# [('Евгений Онегин', 'Пушкин А.С.', 200), ('Муму', 'Тургенев И.С.', 250), ('Мастер и Маргарита', 'Булгаков М.А.', 500)] +# +# # если необходимо передать несколько данных +# import pickle +# +# book1 = ["Евгений Онегин", "Пушкин А.С.", 200] +# book2 = ["Муму", "Тургенев И.С.", 250] +# book3 = ["Мастер и Маргарита", "Булгаков М.А.", 500] +# +# try: +# with open("out.bin", "wb") as file: +# pickle.dump(book1, file) +# pickle.dump(book2, file) +# pickle.dump(book3, file) +# except: +# print("Произошла ошибка при работе с файлом") +# # [('Евгений Онегин', 'Пушкин А.С.', 200), ('Муму', 'Тургенев И.С.', 250), ('Мастер и Маргарита', 'Булгаков М.А.', 500)] + +# # # если необходимо прочитать несколько данных +# import pickle +# +# try: +# with open("out.bin", "rb") as file: +# b1 = pickle.load(file) +# b2 = pickle.load(file) +# b3 = pickle.load(file) +# except: +# print("Произошла ошибка при работе с файлом") +# print(b1, b2, b3, sep="\n") +# # ['Евгений Онегин', 'Пушкин А.С.', 200] +# # ['Евгений Онегин', 'Пушкин А.С.', 200] +# # ['Муму', 'Тургенев И.С.', 250] +# # ['Мастер и Маргарита', 'Булгаков М.А.', 500] + + +# #________________________ выражения генераторы ________________________________ +# # генераторов кортежей не существует (они же неизменяемые), поэтому генератор в круглых скобках это просто генератор, +# # который не привязан к какой-либо коллекции <формирование значения> for <переменная> in <итерируемый объект> +# a = (x ** 2 for x in range(6)) +# print(a) # at 0x00000280339EA9B0> +# # генератор также является итератором, поэтому его значения можно перебирать, например при помощи next() +# print(next(a)) # 0 +# print(next(a)) # 1 +# print(next(a)) # 4 +# print(next(a)) # 9 +# print(next(a)) # 16 +# print(next(a)) # 25 +# print(next(a)) # StopIteration так как значений больше нет сработает исключение + +# # генератор - итерируемый объект, поэтому его также можно перебрать при помощи цикла for +# gen = (x ** 2 for x in range(6)) +# +# for i in gen: +# print(i) +# # # 0 +# # # 1 +# # # 4 +# # # 9 +# # # 16 +# # # 25 +# +# # но если генератор перебрать еще раз, ничего не будет, так как перебираются значение генератора только 1 раз +# for i in gen: +# print(i) # пустая строка + +# # функции, которые работают с итераторами(итерируемыми объектами) также можно использовать для генераторов +# gen = (x ** 2 for x in range(6)) +# +# gen_list = list(gen) # создает список из итерируемых объектов +# gen_max = max(gen) # выводит максимальное число из сгенерированных, но !!! перебрать генератор можно 1 раз, +# # а мы уже вызвали функцию list(), поэтому выдаст ошибку +# print(gen_list) # +# print(gen_max) # ValueError: max() iterable argument is empty передается пустой объект + +# # но если ее вызвать отдельно +# gen = (x ** 2 for x in range(6)) +# +# gen_max = max(gen) +# print(gen_max) # 25 # так отработает + +# # генератор можно прописывать непосредственно в функции +# print(min(x ** 2 for x in range(6))) # 0 + +# генераторы не хранят значения, а генерируют их по необходимости, их используют для экономии памяти +# lst = list(range(10000000000)) # MemoryError ошибка нехватка памяти +# lst1 = list(x for x in range(10000000000)) # отработает без ошибки, так как не хранятся в памяти, они формируются +# # по мере перебора генератора +# for i in lst1: +# print(i, end=", ") +# if i > 50: +# break +# на винде 11 завис, у моего компа все равно не хватает памяти + +# # len() с генератором также вызовет ошибку, так как он генерируется по мере необходимости, его длина не известна, +# по этой же причине нельзя обращаться к генератору по индексам и т.д. +# a = (x for x in range(2, 11)) +# len(a) # TypeError: object of type 'generator' has no len() + +# чтобы из генератора создать список, используется функция list(), так как если прописать генератор внутри списка, +# в качестве значения будет ссылка на генератор (не генератор списков ! там все отработает как надо) +# a = (x for x in range(5)) +# b = list(a) +# print(b) # [0, 1, 2, 3, 4] +# +# b = [(x for x in range(5))] +# print(b) # [ at 0x000002AC50C95A80>] + +#_____________________________ функция генератор _________________________________ +# # оператор yield +# def get_list(): +# for x in [1, 2, 3, 4]: +# return x # поскольку после return функция прекращает работу, она не пройдет весь цикл +# +# a = get_list() +# print(a) # 1 + +# def get_list(): +# for x in [1, 2, 3, 4]: +# yield x # если вместо return прописать yield, то вернется генератор +# +# a = get_list() +# print(a) # ] + +# # чтобы вывести его значение, можно использовать next() +# def get_list(): +# for x in [1, 2, 3, 4]: +# yield x # если вместо return прописать yield, то вернется генератор +# +# a = get_list() +# print(next(a)) # 1 +# print(next(a)) # 2 +# print(next(a)) # 3 +# print(next(a)) # 4 + +# # например, функция для вычисления среднего арифметического из сгенерированных чисел +# def get_middle(): +# for i in range(1, 10): # числа от 1 до 9 +# a = range(i, 11) # от значения i до 10 +# yield sum(a) / len(a) +# +# a = get_middle() +# +# print(list(a)) # [5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5] + +# # найти в файле индексы встречающегося слова +# def find_word(link_file, word): +# g_index = 0 # глобальный индекс будет определять смещение индекса в соответствии со строкой +# for line in link_file: # читаем файл построчно +# indx = 0 # сначала поиск с 0 индекса +# while (indx != -1): # если не встретиться ни одного слова indx = -1 +# indx = line.find(word, indx) # слово, которое искать, и индекс, с которого начинать поиск +# if indx > -1: +# yield g_index + indx +# indx += 1 # чтобы искать в этой же строке, но начиная с этого индекса +# g_index += len(line) # увеличивает индекс на длину строки +# +# try: +# with open("text.txt", encoding="utf-8") as file: +# a = find_word(file, "строка") +# print(list(a)) +# +# except: +# print("Возникла ошибка при работе с файлом") +# # [0, 69, 138] +# # не особо догнала смысл этой программы + +# ___________________________ функция map ____________________________ +# например, когда необходимо преобразовать строки в целое число map(ссылка на функцию, итерируемый объект) +# lst = ["1", "2", "3", "4", "5"] +# b = map(int, lst) +# print(b) # возвращает итератор, который можно перебирать +# +# for x in b: +# print(x, end=" | ") # 1 | 2 | 3 | 4 | 5 | # каждый элемент преобразован в целое число +# +# # или поместить в список +# c = list(b) +# print(c) # [] скорее всего map тоже функция генератор, поэтому обратившись к этому элементу снова, он уже будет пустым + +# # поэтому надо прописать функцию отдельно +# lst = ["1", "2", "3", "4", "5"] +# b = map(int, lst) +# +# c = list(b) +# print(c) # [1, 2, 3, 4, 5] + +# # эквивалентный функции map() генератор +# lst = ["1", "2", "3", "4", "5"] +# b = (int(x) for x in lst) +# print(list(b)) # [1, 2, 3, 4, 5] + +# # в функцию можно передать ссылку на любую функцию, которая принимает 1 параметр и возвращает какое-то значение +# lst = ["ярославль", "краснодар", "сочи", "москва", "пермь"] +# a = map(str.upper, lst) +# print(list(a)) # ['ЯРОСЛАВЛЬ', 'КРАСНОДАР', 'СОЧИ', 'МОСКВА', 'ПЕРМЬ'] + +# # также можно использовать свои функции +# def symbols(a): +# return f"** {a} **" +# +# +# lst = ["p", "y", "t", "h", "o", "n"] +# b = map(symbols, lst) +# print(list(b)) # ['** p **', '** y **', '** t **', '** h **', '** o **', '** n **'] + +# # но для описания простых функций используется lambda +# lst = ["p", "y", "t", "h", "o", "n"] +# b = map(lambda a: f"** {a} **", lst) +# print(list(b)) # ['** p **', '** y **', '** t **', '** h **', '** o **', '** n **'] + +# # или например, чтобы записать слова задом наперед +# lst = ["ярославль", "краснодар", "сочи", "москва", "пермь"] +# b = map(lambda a: a[::-1], lst) +# print(list(b)) # ['ьлвалсоря', 'радонсарк', 'ичос', 'авксом', 'ьмреп'] + +# # также map часто используется для получения чисел введеных пользователем в одну строку, например через пробел +# a = map(int, input().split()) # получаем введеные пользователем значения и преобразуем в целое число +# print(list(a)) # затем преобразуем их в список +# # 3 55 7 8 1 вводили +# # [3, 55, 7, 8, 1] вывод + +# # преобразовать к списку можно также в 1 строке +# a = list(map(int, input().split())) # получаем введеные пользователем значения и преобразуем в целое число +# print(a) +# # 3 5 7 9 0 # ввод +# # [3, 5, 7, 9, 0] # вывод + +#_________________ функция filter ____________________ +# filter(функция, итерируемый объект) отбирает из итерируемого объекта элементы по условию (если переданная функция +# возвращает True) +# a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] +# +# b = filter(lambda x: x % 2 == 0, a) +# # print(b) # также возвращает итератор +# print(list(b)) # [2, 4, 6, 8, 10] + +# # проверка на простое число, тяжело записать в виде в лямбда функции, в вункции также можно и свои прописывать +# def simple_numb(x): +# d = x - 1 +# if d < 0: +# return False +# +# while d > 1: +# if x % d == 0: +# return False +# d -= 1 +# +# return True +# +# +# a = [-1, 3, -5, 9, 11, 20, 74, -74] +# b = filter(simple_numb, a) +# print(tuple(b)) # (3, 11) передаем к кортеж +# +# # Простое число в математике — это натуральное число больше 1, у которого есть всего два делителя: единица и само число. +# # Например, 2, 3, 5, 7, 11, 13, 17 + +# tpl = ("Шереметьево", "Шереметьево-2", "Сколково", "Краснодар-1") +# +# b = filter(str.isalpha, tpl) # проверка строки на отсутствие символов и цифр, только буквы +# print(list(b)) # ['Шереметьево', 'Сколково'] + +# # поскольку filter возвращает итерируемый объект, ее также можно вложить в функцию filter +# # например первый фильтр отбирает только простые числа, а второй из них отбирает только четные +# def is_simple(x): +# d = x - 1 +# if d < 0: +# return False +# +# while d > 1: +# if x % d == 0: +# return False +# d -= 1 +# +# return True +# +# a = [-1, 2, 3, -5, 9, 11, 20, 74, -74, 7] +# b = filter(lambda x: x % 2 == 0, filter(is_simple, a)) +# print(list(b)) # [2] + +# # но на практике создают более уточняющие условия, чтобы не использовать вложения, например теперь нечетные числа +# def is_simple(x): +# d = x - 1 +# if d < 0 or x % 2 == 0: # добавили еще и сравнение на четность +# return False +# +# while d > 1: +# if x % d == 0: +# return False +# d -= 1 +# +# return True +# +# a = [-1, 2, 3, -5, 9, 11, 20, 74, -74, 7] +# b = filter(is_simple, a) +# print(list(b)) # [3, 11, 7] + +# #________________ функция zip ___________________ +# # для итерируемых объектов выполняет перебор соответствующих элементов до конца короткой коллекции 1й элемент с +# # 1м другой коллекции, 2й со 2рым и т.д. +# a = (1, 2, 3, 4) +# b = [5, 6, 7, 8, 9, 10] +# c = "python" +# d = zip(a, b, c) # может работать с разными итерируемыми объектами +# # print(d) # на выходе также итерируемый объект +# print(tuple(d)) # ((1, 5, 'p'), (2, 6, 'y'), (3, 7, 't'), (4, 8, 'h')) + +# # можно сразу распаковывать элементы из кортежа +# a = (1, 2, 3, 4) +# b = [5, 6, 7, 8, 9, 10] +# c = "python" +# d = zip(a, b, c) # может работать с разными итерируемыми объектами +# +# for v1, v2, v3 in d: +# print(v1, v2, v3) +# # 1 5 p +# # 2 6 y +# # 3 7 t +# # 4 8 h + +# # можно сразу распаковать в переменные, но необходимо, чтобы их количество соответствовало, иначе ошибка +# a = (1, 2, 3, 4) +# b = [5, 6, 7, 8, 9, 10] +# c = "python" +# v1, v2, v3, v4 = zip(a, b, c) # по количеству элементов в самой короткой коллекции +# print(v1, v2, v3, v4) # (1, 5, 'p') (2, 6, 'y') (3, 7, 't') (4, 8, 'h') + +# # можно распаковать первое значение, а остальное поместить во вторую переменную при помощи оператора распаковки * +# a = (1, 2, 3, 4) +# b = [5, 6, 7, 8, 9, 10] +# c = "python" +# v1, *v2 = zip(a, b, c) +# print(v1, v2) # (1, 5, 'p') [(2, 6, 'y'), (3, 7, 't'), (4, 8, 'h')] + +# # можно поместить в список и распаковать его, тогда на выходе получим сразу 4 кортежа +# a = (1, 2, 3, 4) +# b = [5, 6, 7, 8, 9, 10] +# c = "python" +# d = zip(a, b, c) +# lz = list(d) +# print(*lz) # (1, 5, 'p') (2, 6, 'y') (3, 7, 't') (4, 8, 'h') # распаковка списка на отдельные элементы (здесь кортежи) + + +# # иногда на практике используется двойной прием распаковки +# a = (1, 2, 3, 4) +# b = [5, 6, 7, 8, 9, 10] +# c = "python" +# d = zip(a, b, c) +# v1, v2, v3 = zip(*d) # (1, 5, 'p') (2, 6, 'y') (3, 7, 't') (4, 8, 'h') +# print(v1, v2, v3, sep="\n") +# # (1, 2, 3, 4) +# # (5, 6, 7, 8) +# # ('p', 'y', 't', 'h') + +#_________________________ сортировка через sort ________________________ +# list.sort() - для сортировки элементов списка +# sorted() - для сортировки итерируемого объекта +# при помощи метода .sort() кортеж изменить нельзя, так как он неизменяемый тип +# однако при помощи функции sorted() можно, так как она возвращает новый отсортированный список, а не изменяет старый +# но элементы должны быть сравнимы между собой (число и строку сравнить нельзя - приведет к ошибке) +# d = (1, 3, 5, 2, 6, 4, 7) +# print(sorted(d)) # [1, 2, 3, 4, 5, 6, 7] + +# # по умолчанию сортировка по возрастанию, чтобы изменить, используется параметр reverse = True +# d = (1, 3 , 5, 2, 6, 4, 7) +# print(sorted(d, reverse=True)) # [7, 6, 5, 4, 3, 2, 1] + +# # Отсортировать можно даже словарь, по умолчанию вывод ключей словаря +# d = {'один': 1, 'три': 3, 'семь': 7, 'четыре': 4} +# print(sorted(d)) # ['один', 'семь', 'три', 'четыре'] +# +# # чтобы отсортировать значения, дополнительно необходимо прописать метод .values() +# d = {'один': 1, 'три': 3, 'семь': 7, 'четыре': 4} +# print(sorted(d.values())) # [1, 3, 4, 7] + +# # можно вывести и ключ и значение, сортировка будет производиться по ключам. При помощи метода items(). +# # На выходе список с кортежами (ключ: значение) +# d = {'один': 1, 'три': 3, 'семь': 7, 'четыре': 4} +# print(sorted(d.items())) # [('один', 1), ('семь', 7), ('три', 3), ('четыре', 4)] + +# # затем из него можно снова сделать словарь, уже отсортированный по ключам +# d = {'один': 1, 'семь': 7, 'четыре': 4, 'три': 3} +# s = dict(sorted(d.items())) +# print(s) # {'один': 1, 'семь': 7, 'три': 3, 'четыре': 4} + +# __________________________________ аргумент key для управления сортировкой ________________________________________ +# этот аргумент 5есть и у .sort() и у sorted() + +# # например, можно отсортировать элементы по ключу четности и нечетности, ключи будут располагаться по возрастанию, +# # а элементы, в том порядке в котором они были в списке, они не будут отсортированы +# # key=имя функции, в которой будет произведено какое-то действие над текущим значением +# def is_odd(x): +# return x % 2 # остаток от деления на 2 (если 0 это 0, остальное 1) + + +# d = [1, 3, 5, 2, -3, 6, 4, 7, - 10] +# a = sorted(d, key=is_odd) +# print(a) # [2, 6, 4, -10, 1, 3, 5, -3, 7] сначала идут четные (x % 2 == 0), затем нечетные, но последовательность +# # элементов такая, какая была в начальном списке +# +# # для простых функций используется лямбда функция +# d = [1, 3, 5, 2, -3, 6, 4, 7, - 10] +# a = sorted(d, key=lambda x: x % 2) +# print(a) # [2, 6, 4, -10, 1, 3, 5, -3, 7] + +# # чтобы значения также выставить по возрастанию, нужно ключ key немного модифицировать - четным числам присвоим 0 + +# # прибавим значение самого элемента, а не четным 100, и прибавим значение самого элемента. Для нашего примера +# # этого достаточно +# def is_odd(x): +# return x if x % 2== 0 else 100 + x # остаток от деления на 2 (если 0 это 0, остальное 1) +# +# +# d = [1, 3, 5, 2, -3, 6, 4, 7, - 10] +# a = sorted(d, key=is_odd) +# print(a) # [-10, 2, 4, 6, -3, 1, 3, 5, 7] # теперь элементы отсортированы и по возрастанию и по четности + +# # можно использовать встроенные функции, например для сортировки по длине строки +# lst = ["python", "Java", "C++", "C#", "C", "Php"] +# lst.sort(key=len) +# print(lst) # ['C', 'C#', 'C++', 'Php', 'Java', 'python'] отсортированы по длине строки, а не по коду символа, как +# # по умолчанию + +# # или отсортировать по последнему символу строк - главное понять суть его работы и можно экспериментировать с разными +# его настройками +# lst = ["python", "Java", "C++", "C#", "C", "Php"] +# lst.sort(key=lambda x: x[-1]) +# print(lst) # ['C#', 'C++', 'C', 'Java', 'python', 'Php'] + +# # отсортировать товары по цене из кортежа +# tpl = ( +# ("Ошейник", 250), +# ("Мячик", 150), +# ("Корм", 2500), +# ("Лакомство", 180), +# ("Пеленки", 400), +# ) +# lst = sorted(tpl, key=lambda x: x[-1]) # сортировка по цене +# lst2 = sorted(tpl, key=lambda x: x[0]) # сортировка по товарам +# print(lst) # [('Мячик', 150), ('Лакомство', 180), ('Ошейник', 250), ('Пеленки', 400), ('Корм', 2500)] +# print(lst2) # [('Корм', 2500), ('Лакомство', 180), ('Мячик', 150), ('Ошейник', 250), ('Пеленки', 400)] + +# #____________________________ функция isinstance _____________________________ +# # isinstance(объект, тип данных) +# # True - если объект соответствует указанному типу +# # False - если не соответствует +# +# # a = 5 +# # print(isinstance(a, int)) # True +# +# # но у этой функции есть нюансы при работе с булевыми значениями +# b = True +# print(isinstance(b, bool)) # True # тут отработает корректно +# print(isinstance(b, int)) # True # хотя это не целое число (так как тип bool наследуется от int) +# +# # чтобы этого избежать нужно сделать строгую проверку +# print(type(b) == int) # False +# # другой вариант записи +# print(type(b) is int) # False +# +# # или сделать проверку сразу по нескольким типам +# print(type(b) in (bool, float, str)) # True так как тип bool +# +# # разница isinstance и type. isinstance делает проверку с учетом иерархии наследования типов. Ее используют для проверки +# # принадлежит классу + +# # Например, нам нужно сложить все вещественные значения из кортежа +# data = (4.5, 9.4, 5, "jjj", [True, False], True, -11) +# +# s = 0 # переменная для вычисления суммы +# for x in data: # перебираем элементы кортежа +# if isinstance(x, float): +# s += x +# +# print(s) # 13.9 + +# # вместо цикла можно также использовать функцию filer, она и быстрее работает и короче код +# data = (4.5, 9.4, 5, "jjj", [True, False], True, -11) +# s = sum(filter(lambda x: isinstance(x, float), data)) +# print(s) # 13.9 +# +# # но сумма натуральных чисел, выдаст неверный ответ +# data = (4.5, 9.4, 5, "jjj", [True, False], True, -11) # булевое значение True было воспринято, как целочисленное значение 1 +# s = sum(filter(lambda x: isinstance(x, int), data)) +# print(s) # -5 неверное значение + +# # чтобы это исправить нужно сделать строгую проверку +# data = (4.5, 9.4, 5, "jjj", [True, False], True, -11) # булевое значение True было воспринято, как целочисленное значение 1 +# s = sum(filter(lambda x: type(x) is int, data)) +# print(s) # -6 верное значение + +# # можно при помощи функции isinstance сделать проверку сразу на несколько типов +# a = 1.5 +# print(isinstance(a, (int, float))) #True в кортеже проверить или целое или вещественное число +# это эквивалентно записи +# print(isinstance(a, int) or isinstance(a, float)) # True +# +# #___________________________ функция all() и any() _______________________________ +# # all() если все элементы итерируемого объекта имеют значение True, она вернет True +# a = [True, True, True, True] +# print(all(a)) # True + +# # Если хотя бы 1 элемент False, она вернет False +# a = [True, False, True, True] +# print(all(a)) # False + +# a = [0, 1, 2.5, [], (1, 2), "", {}, "python"] +# print(all(a)) # False, так как есть 0 и пустые строки и коллекции +# +# # если их убрать +# a = [1, 2.5, (1, 2), "python"] +# print(all(a)) # True + +# # как сымитировать эту функцию самостоятельно +# a = [0, 1, 2.5, [], (1, 2), "", {}, "python"] +# res = True +# for x in a: +# res = res and bool(x) +# print(res) # False +# +# # any() работает аналогичным образом, но вернет True, если встретиться хотя бы 1 значение True +# a = [0, 1, 2.5, [], (1, 2), "", {}, "python"] +# print(any(a)) # True +# +# # # как сымитировать эту функцию самостоятельно +# a = [0, 1, 2.5, [], (1, 2), "", {}, "python"] +# res = False +# for x in a: +# res = res or bool(x) +# print(res) # True + +# для чего используется all() +# # например, можно сымитировать игру крестики нолики. Если в строке все три х выйгрыш +# # первые 3 элемента, это 1 строка, следующие вторая и т.д. +# # представим в виде списка +# game = ['x', '0', '0', +# '0', 'x', '0', +# 'x', 'x', 'x'] +# +# row_1 = all(map(lambda x: x == 'x', game[:3])) # срез первые 3 элемента - 1 строка +# row_2 = all(map(lambda x: x == 'x', game[3:6])) +# row_3 = all(map(lambda x: x == 'x', game[6:])) +# print(row_1) # False +# print(row_2) # False +# print(row_3) # True + +# # в python не должен повторяться один и тот же код, поэтому функцию лучше вынести отдельно +# def true_x(x): +# return x == 'x' +# game = ['x', '0', '0', +# '0', 'x', '0', +# 'x', 'x', 'x'] +# +# row_1 = all(map(true_x, game[:3])) # срез первые 3 элемента - 1 строка +# row_2 = all(map(true_x, game[3:6])) +# row_3 = all(map(true_x, game[6:])) +# print(row_1, row_2, row_3, sep='\n') +# # False +# # False +# # True + +# # можно сделать и по столбцам +# def true_x(x): +# return x == 'x' +# game = ['x', '0', '0', +# '0', 'x', '0', +# 'x', 'x', 'x'] +# +# col_1 = all(map(true_x, game[::3])) # срез с 0 каждый 3 элемент - 1 столбец +# col_2 = all(map(true_x, game[1::3])) # срез с 1 каждый 3 элемент - 2 столбец +# col_3 = all(map(true_x, game[2::3])) # срез с 0 каждый 3 элемент - 3 столбец +# print(col_1, col_2, col_3, sep='\n') +# # False +# # False +# # False + +# # интереса ради хочу самостоятельно сделать проверку по диагонали +# def true_x(x): +# return x == 'x' +# game = ['x', '0', '0', +# '0', 'x', '0', +# 'x', 'x', 'x'] +# # +# diag_1 = all(map(true_x, game[::4])) # срез с 0 каждый 4 элемент - 1 диагональ +# diag_2 = all(map(true_x, game[2::2])) # срез с 2 каждый 2 элемент - 2 диагональ +# +# print(diag_1, diag_2, sep='\n') +# # True +# # False кажись получилось))) + +# # для чего используется any() +# # например, в игре сапер поле 10 на 10. Заполним 0 +# n = 10 +# p = [0] * (n * n) # 10 на 10 - список из 0 +# p[5] = '*' # изменим одно значение на мину +# p2 = [0] * (n * n) +# +# lose = any(map(lambda x: x == '*', p)) +# print(lose) # True пользователь проиграл если наступил на это поле +# lose = any(map(lambda x: x == '*', p2)) +# print(lose) # False а если пользователь наступил на это поле, то не проиграл + +# #_______________________ системы счисления ____________________________ + +# # Также числа можно записывать через степень десятки (экспоненциальная форма записи чисел) +# ^ - здесь в качестве символа обозначающего степень +# # 500 = 5e2, 5e2 = 5 * 10^2, т.е. 5 * 100, а 0.01 = 1e-2, т.е. 1 * 10^-1 = 1 * 0.01 +# # формат записи экспоненциального числа <число>e<целая степень десятки> используют для записи длинных значений +# a = 5e6 +# b = 4e-4 +# на выходе получается вещественное число +# print(a) # 5000000.0 +# print(b) # 0.0004 +# # поэкспериментировала, в python по умолчанию отображаются не так много знаков после запятой +# c = 2e-5 +# print(c) # 2e-05 уже отобразил такую запись + +#____ Десятичная _____ +# числа от 0 до 9 +# 123 = 1 * 10^2 + 2 * 10^1 + 3 * 10^0, т.е. 100 + 20 + 3 + + +# # ____ двоичная ____ +# # числа от 0 до 1 (их еще называю битами) +# # эта система помогает визуализировать включен 1 или выключен бит +# # вместо десяти здесь двойки/ перевод двоичного представления числа в десятичное +# # 1101 = 1 * 2^3 + 1 * 2^2 + 0 * 2^1 + 1 * 2^0 = 1 * 8 + 1 * 4 + 0 * 2 + 1 * 1 = 8 + 4 + 0 + 1 = 13 +# # чтобы в python передать число в двоичной системе 0b<двоичное число>, если отрицательное -0b<двоичное число> +# a = 0b1101 +# b = -0b1111 +# print(a) # 13 +# print(b) # -15 +# # чтобы из обычного (десятичного) числа получить двоичное в python есть функция bin() +# a = 345 +# b = bin(a) +# print(b) # 0b101011001 + +# # ____ шестнадцатиричная ____ +# # числа от 0 до 9, а затем A, B, C, D, E, F (10, 11, 12, 13, 14, 15) +# # 1A = 1 * 16^1 + A * 16^0 = 1 * 16 + 10 * 1 = 26 +# # для удобного представления байтовых данных +# # чтобы в python передать число в двоичной системе 0x<шестнадцатиричное число>, если отрицательное -0x<шестнадцатиричное +# # число> +# a = 0x3d5a +# print(a) # 15706 # на выходе целое число + +# # ____ восьмиричная ____ +# # числа от 0 до 7 +# # 14 = 1 * 8^1 + 4 * 8^0 = 8 + 4 = 12 +# # чтобы в python передать число в двоичной системе 0o<двоичное число>, если отрицательное -0o<двоичное число> +# a = 0o54 +# print(a) # 44 + +# #_______________ битовые операции и, или, не, xor ___________ +# # ____ ~ инвертирует биты (не) +# a = 121 +# b = bin(a) +# print(b) # 0b1111001 +# print(~a) # -122 +# самый крайний бит знаковый(если число положительное он равен 0000...00000, если инвертировать, то равен 1111...1111, +# т.е. получается -1) +# # при битовой инверсии число не только становится отрицательным, но и уменьшается на 1, причем отрицательные тоже +# d = 0 +# print(~d) # -1 +# d = -10 +# print(~d) # 9 + +# # ____ битовая операция и &, по тому же принципу, что истина ложь при сравнении (только True c True даст True) +# a = 5 +# b = 4 +# res = a & b +# print(res) # 4 +# # 00000101 -> 5 +# # 00000100 -> 4 +# # 00000100 -> res +# # используется для проверки включен ли определенный бит в числе, создается вспомогательная переменная, с 1 в том месте, +# # где хотим проверить включение и сравниваем их +# a = 5 +# b = 4 +# if a & b == b: # 00000100 *(в битах нумерация с конца, также начинается с нуля +# print("Включен второй бит") # Включен второй бит +# else: +# print("Второй бит выключен ") + +# # либо для того, чтобы выключить определенный бит (2й и 0й) +# a = 13 # 00001101 +# b = 5 # 00000101 +# a = a & ~b # инверсия b 11111010, у операции ~ больший приоритет, поэтому сначала выполняется инверсия, затем сравнение +# print(a) # 8 +# # 00001101 +# # 11111010 +# # 00001000 -> 8 + +# # ____ битовая операция или | (по тому же принципу, что истина ложь при сравнении (только False c False даст False) +# # используют, чтобы включить определенные биты переменной +# a = 8 # 00001000 +# b = 5 # 00000101 +# a = a | b +# print(a) # 13 +# # 00001000 +# # 00000101 +# # 00001101 -> 13 + +# # битовые операторы сравнения также можно записывать в короткой записи +# a = 8 # 00001000 +# b = 5 # 00000101 +# a |= b +# print(a) # 13 + +# #____ ^ xor исключающее или +# # в ней, как противоположные значения +# # 0 0 -> 0 +# # 1 1 -> 0 +# # 1 0 -> 1 +# # 0 1 -> 1 +# a = 9 # 00001001 +# b = 1 # 00000001 +# a = a ^ b +# print(a) # 8 -> 00001000 +# # она работает без потерь, если ее снова применить, то получим изначальное число +# a = 9 # 00001001 +# b = 1 # 00000001 +# a = a ^ b +# a = a ^ b +# print(a) # 9 +# по такому принципу создается пароль zip + +# # оператор смещения бит вправо >> и влево << +# x = 160 # 10100000 +# x = x >> 1 +# print(x) # 80 -> 01010000, то есть такая операция делит число на 2^1 (целочисленное деление - поэтому если сильно +# сдвинуть, так что последняя единичка отброситься получится целое число у которого отбросили дробную частть) +# # а сдвиг влево равен операции умножения +# x = 50 +# x = x << 2 +# print(x) # 200 т.е. умножить на 2^2 + +# # __________________ модуль random ________________________ +# # Для начала необходимо импортировать этот стандартный модуль +# import random + +# # функция random возвращает случайное число от 0 до 1 +# a = random.random() +# print(a) # #по равномерному закону(т.е. каждое число имеет равные шансы появиться) +# # при каждом запуске программы будет новое число +# # 0.4984128111957935 +# # 0.44295315046185024 +# # 0.8492116064454878 + +# # uniform(a, b) похожая функция - также возвращает случайное число от a до b +# import random + +# a = random.uniform(1, 6) +# print(a) +# # также при каждом запуске программы будет новое число +# # 3.2933339364872296 +# # 4.196949779881457 +# # 3.7975230233750716 + +# # для целочисленной генерации используется функция randint() +# import random + +# a = random.randint(-3, 6) +# print(a) +# # 2 +# # 1 +# # 3 +# # 4 + +# randrange(start, stop, step) в указанном диапазоне с указанным шагом +# import random +# +# a = random.randrange(-8, 8, 2) +# print(a) +# # 4 +# # -6 + +# если требуется Гауссовское распределение (то есть чаще будут попадаться значения, которые ближе к среднему значению, а +# чем дальше от него, тем реже) +# например, для колебаний цен на нефть +# используется функция gauss(mu, sigma) mu - математическое ожидание(среднее значение), sigma - среднеквадратическое +# отклонение (меру разброса относительно среднего значения) +# import random +# +# a = random.gauss(250, 21) # колебание цены дим кофе в зависимости от количества баллов +# print(a) +# # 272.6725916170897 +# # 237.11012978774957 + +# # для выбора случайного элемента из коллекции используется функция choice() +# import random +# +# lst = [2, 5, 3, 9, -10] +# a = random.choice(lst) +# print(a) +# # -10 +# # 9 + +# # функция shuffle() позволяет перемешивать элементы списка (работает только с изменяемыми типами данных, так как меняет +# # оригинал) +# import random + +# lst = [2, 5, 3, 9, -10, 1, 5, 3] +# random.shuffle(lst) +# print(lst) # каждый вызов будет заново перемешивать +# # [5, 1, -10, 2, 3, 3, 5, 9] +# # [2, 3, 1, -10, 3, 5, 5, 9] + +# # функция sample(список, количество элементов) возвращает новый список из случайно выбранных неповторяющихся элементов переданного списка +# import random +# +# lst = [2, 5, 3, 9, -10, 1, 5, 3] +# a = random.sample(lst, 4) +# print(a) +# # [2, 3, 3, 1] Если элементы одинаковые в самом списке, то повторяться будут +# # [3, 3, 5, 1] + +# # можно сгенерировать одинаковые последовательности +# # при помощи генератора списков создадим список из 20 элементов, а в качестве значений передадим случайные +# # сгенерированные значения от 0 до 10 +# import random +# +# lst = [random.randint(0, 10) for i in range(21)] +# print(lst) +# # [1, 9, 7, 2, 0, 9, 0, 7, 1, 2, 8, 8, 2, 9, 5, 3, 7, 10, 1, 10, 6] +# # [5, 1, 5, 10, 8, 1, 5, 0, 6, 1, 7, 8, 3, 2, 2, 6, 10, 5, 2, 6, 8] + +# # чтобы сгенерировалось 1 раз, а не при каждом запуске по новой, нужно зафиксировать зерно генератора seed() +# import random +# +# random.seed(123) # указать некое начальное значение генератора +# lst = [random.randint(0, 10) for i in range(21)] +# print(lst) +# # [0, 4, 1, 6, 4, 1, 0, 6, 8, 8, 5, 5, 0, 2, 2, 5, 8, 5, 3, 2, 0] +# # [0, 4, 1, 6, 4, 1, 0, 6, 8, 8, 5, 5, 0, 2, 2, 5, 8, 5, 3, 2, 0] +# # сохранится тот же сгенерированный результат + +# #_________________ аннотация типов ____________________ +# # в python динамическая типизация. Тип переменной зависит от значения. +# # если мы хотим явно указать тип используется аннотация (аннотирование) +# a:int # явное объявление типа переменной. Это и есть аннотация типа, но у нее чисто информативный характер, на ход +# # выполнение программы не повлияет (если передать неверный тип) +# a = 9 # int +# b = "hello" # stroke +# c = [1, 3, 8] # list +# d = 2.5 # float +# +# a = 5.5 # среда разработки подчеркивает, при наведении в подсказке написано, что ожидается тип int, а мы передаем float +# print(a) # 5.5 при этом программа отработает без ошибок + +# # аннотация типов применяется для удобства, чтобы программист наглядно мог понять какие данные нужно передать +# int, str, bool, float, None, bytes +# # можно совместить аннотацию с присвоением значения +# a:int = 4 +# print(a) # 4 + +# # чаще применяется в функциях +# def mul2(x: int): +# return x * 2 +# +# +# print(mul2(5)) # 10 +# # у функции появляется атрибут annotations +# print(mul2.__annotations__) # {'x': } словарь + +# # можно совмещать аннотации с указанием значения по умолчанию +# def mul2(x: int, y: int = 25): +# return x * 2 + y +# +# +# print(mul2(5)) # 35 (5 * 2 + 25) + +# # в функциях еще указывается аннотация к выводимому значению -> тип +# def mul2(x: int, y: int = 25) -> int: +# return x * 2 + y +# +# +# print(mul2(5)) # 35 (5 * 2 + 25) +# print(mul2.__annotations__) # {'x': , 'y': , 'return': } + +# # если функция ничего не возвращает, указывается аннотация None +# def show_x(x:int) -> None: +# print(x) + +# если нужно указать аннотацию с несколькими типами используется модуль typing +# from typing import Union, Optional, Any, Final +# Union объединяет типы +# a:Union[int, float] = 2 + +# начиная с версии python 3.10 можно записывать по новому синтаксису +# a: int | float = 2 + +# # поскольку Union это объект мы можем присвоить его переменной (алеас), но так пропадает наглядность и простота кода +# ann_type = Union[int, float] +# a: ann_type = 2 + +from typing import Union, Optional, Any, Final + +# # Optional 1 тип данных + None == Union[int, None] +# def show_x(x:int, descr: Optional[str]=None) -> None: +# if descr: +# print(f'{descr} {x}') +# else: +# print(x) +# +# print(show_x(5, "x = ")) +# # x = 5 +# # None + +# # Any +# a:Any = "Любой тип данных" # это значит что сюда можно передавать абсолютно любой тип + +# Final появился python 3.10 служит для пометки констант +# p:Final = 3.14 # подсказка для программиста, что это значение не должно меняться + +# #________________________________ аннотации коллекций _____________________________________ +# # list, tuple, dict, set +# можно указывать аннотации только к коллекциям list, tuple, dict, set +# а можно аннотировать и их значения [тип] + +# lst: list[int] = [1, 3, 5] # аннотация не только к коллекции, но и к ее содержимому с версии python 3.9 и выше +# # для более ранних версий используется другой синтаксис +# from typing import List, Tuple, Dict, Set +# lst: List[int] = [1, 3, 5] + +# # у кортежа типы указываются для каждого элемента (а не один общий как у списка), так как кортежи чаще используют +# # для компановки данных. с версии python 3.9 и выше +# addr : tuple[str, int, str] = ("Новороссийская", 240, "a") +# # если для всех элементов 1 тип, записывается так +# tpl : tuple[float,...] = (1.5, 2.8, 3.9) + +# # для более ранних версий используется другой синтаксис +# from typing import List, Tuple, Dict, Set +# addr : Tuple[str, int, str] = ("Новороссийская", 240, "a") + +# # у словаря для значений тип указывается общий для ключей, и общий для значений +# с версии python 3.9 и выше +# d : dict[str, int] = {"one": 1, "two": 2} + +# # для ранних версий используется другой синтаксис +# from typing import List, Tuple, Dict, Set +# d : Dict[str, int] = {"one": 1, "two": 2} + +# # для множеств с версии python 3.9 и выше +# persons : set[str] = {"John", "James"} +# # для ранних версий используется другой синтаксис +# from typing import List, Tuple, Dict, Set +# persons : Set[str] = {"John", "James"} + +# # аннотации для коллекций также можно прописывать непосредственно в функциях +# def get_positives(collection:list[int]) -> list[int]: +# return list(filter(lambda x: x > 0, collection)) +# +# +# a = [2, 7, -9, 8 -4, 0, -7, 6, 5] +# b = get_positives(a) +# print(b) # [2, 7, 4, 6, 5] + +# # если несколько типов +# # с версии python 3.9 и выше +# def get_positives(collection:list[int | float]) -> list[int | float]: +# return list(filter(lambda x: x > 0, collection)) +# +# +# a = [2, 7, -9, 8.6 -4, 0, -7, 6.8, 5] +# b = get_positives(a) +# print(b) # [2, 7, 4.6, 6.8, 5] + +# # если несколько типов +# # для ранних версий используется другой синтаксис +# from typing import List, Union +# def get_positives(collection:List[Union[int, float]]) -> List[Union[int, float]]: +# return list(filter(lambda x: x > 0, collection)) +# +# +# a = [2, 7, -9, 8.6 -4, 0, -7, 6.8, 5] +# b = get_positives(a) +# print(b) # [2, 7, 4.6, 6.8, 5] + +# # callable тип используется для вызываемых объектов, например функций +# # Callable [[тип параметров функции], тип выводимого значения] +# from typing import Callable, List +# +# +# def get_digites(fun:Callable[[int], bool], lst: List[int]=None) -> List[int]: +# if lst is None: +# return [] +# else: +# return list(filter(fun, lst)) +# +# # a = get_digites(lambda x: x > 0) +# # print(a) # [] +# # b = get_digites(lambda x: x > 0, [1, 5, -4, 7, -8, 8]) +# # print(b) # [1, 5, 7, 8] +# +# def even(x:int): +# return bool(x % 2 == 0) +# +# +# c = get_digites(even, [1, 5, -4, 7, -8, 8]) +# print(c) # [-4, -8, 8] + +# если функция не принимает параметры и не возвращает ничего, то Callable[[], None] + +# # _____________ аннотация на уровне классов __________________ +# # object общий класс, от которого наследуются остальные int, str... +# x: object = "stroke 1" + +# # Поэтому при аннотации тип any совместим с любым, а тип object не совместим ни с каким +# К Any можно привести любой тип, а вот к object нельзя привести никакой +# from typing import Any +# a: Any = None +# b: str = "ffffuuuu" +# b = a # не высветит никакого предупреждения. Так как Any - это любой тип + +# # но ! +# from typing import Any +# a: object = None +# b: str = "ffffuuuu" +# # b = a # Появляется предупреждение, ожидается str, а получаем объект +# # если наоборот объекту присвоить строку, никаких предупреждений не будет +# a = b # предупреждений нет + +# class Class1:pass +# class Class2(Class1):pass # Второй класс наследуется от первого +# # тогда в аннотации типа предупреждения не возникнет +# a: Class1 +# a = Class2() # не высвечивается предупреждения, при аннотировании Class1, так как Class2 наследуется от Class1, +# # но если убрать наследование, то появится предупреждение +# class Class1:pass +# class Class2:pass # Второй класс наследуется от первого +# # тогда в аннотации типа предупреждения не возникнет +# a: Class1 +# a = Class2() # появилось предупреждение - ожидается Class1, а получаем Class2 + +# при помощи модуля mypy можно проверять корректность аннотаций +# в терминале mypy name.py +# mypy practic_basic.py + +# a: Any = None +# b: str = "ffffuuuu" +# b = a +# # Success: no issues found in 1 source file + +# a: object = None +# b: str = "ffffuuuu" +# b = a +# practic_basic.py:3945: error: Incompatible types in assignment (expression has type "object", variable has type "str") [assignment] +# Found 1 error in 1 file (checked 1 source file) + +# class Geom: pass +# class Point2d(Geom): pass +# +# def factory_object(cls_obj : Geom) -> Geom: # ссылка на класс (а не на объект класса) +# return cls_obj() # функция просто возвращает объект класса +# # код подсвечивается, так как аннотация Geom подразумевает что переменная cls_obj будет ссылаться не на сам класс, +# # а на объекты класса + +# # чтобы это исправить используется Type из модуля typing +# from typing import Type +# class Geom: pass +# class Point2d(Geom): pass +# +# def factory_object(cls_obj : Type[Geom]) -> Geom: # тогда никаких предупреждений не будет +# return cls_obj() +# # # так как параметр cls_obj в таком случае будет ссылаться на класс Geom +# +# # geom = factory_object(Geom) +# # point = factory_object(Point2d) +# # # никаких предупреждений +# +# # если прописать аннотацию для них, то уже возникнет предупреждение +# geom : Geom = factory_object(Geom) # здесь не будет предупреждения +# point : Point2d = factory_object(Point2d) # а вот здесь предупреждение возникнет, так как ожидается Geom +# +# # чтобы избегать таких проблем используются общие типы TypeVar из модуля typing +# from typing import Type, TypeVar +# +# class Geom: pass +# class Point2d(Geom): pass +# +# t = TypeVar("t", bound=Geom) # Создаем переменную, в которой указываем имя переменной, именованный аргумент bound +# # указываем, что допустимы все типы, которые связаны с базовым типом Geom +# +# def factory_object(cls_obj : Type[t]) -> t: # затем меняем на этот тип +# return cls_obj() +# +# +# geom = factory_object(Geom) +# point = factory_object(Point2d) # тогда предупреждения не будет + +# t = TypeVar("t") # если не указывать ограничений можно подставлять любой тип +# t = TypeVar("t", int, float) # или указать типы через запятую + +# # аннотация типов внутри класса +# from __future__ import annotations +# class Geom: pass +# +# class Point2d(Geom): +# x: int +# y: int +# +# def __init__(self, x:int, y:int) -> None: # функция инициализации, она ничего не возвращает +# self.x = x +# self.y = y +# +# # def copy(self) -> Point2d:# функция создает копию # аннотация выдает ошибку, так внутри прописывать нельзя +# # return Point2d(self.x, self.y) +# +# # def copy(self) -> 'Point2d':# либо заключить в строку - считается устаревшим +# # return Point2d(self.x, self.y) +# +# def copy(self) -> Point2d: # импортировать annotations из модуля __future__ python 3/7 > +# return Point2d(self.x, self.y) +# +# p = Point2d(10, 20) + +#_________________ конструкция match/case ___________________ +# python 3.10 > +# анализирует переменные по шаблонам, для найденного совпадения выполняется блок кода +# в match должен быть хотя бы 1 блок case +# cmd = "top" + +# match cmd: # переменная +# case "top": # шаблон 1 +# print("Вверх") +# case "down": +# print("Вниз") +# case "left": +# print("Влево") +# case "right": +# print("Вправо") +# case _: +# print("Другое") +# +# print("Проверка завершена") +# # Вверх +# # Проверка завершена + +# # если необходимо в case прописать сразу несколько констант испозуется вертикальная черта | +# cmd = "top" +# +# match cmd: # переменная +# case "top" | "down": # если переменная примет одно из этих значений (или) +# print("Вверх - Вниз") +# case "left" | "right": +# print("Влево - Вправо") +# case _: +# print("Другое") +# +# print("Проверка завершена") +# # Вверх - Вниз +# # Проверка завершена + +# # match/case в python более гибкий чем switch/case в C +# cmd = "top" +# +# match cmd: +# case command: # создается переменная, которая ссылается на то же значение, что и переменная cmd. +# # этот шаблон не проверяет, поэтому будет срабатывать всегда +# print(f"Команда: {command}") +# # Команда: top + +# # поэтому возникнет синтаксическая ошибка если написать еще 1 case +# cmd = "top" +# +# match cmd: +# case command: # создается переменная, которая ссылается на то же значение, что и переменная cmd. +# # этот шаблон не проверяет, поэтому будет срабатывать всегда +# print(f"Команда: {command}") +# case "top": +# print("Будет ошибка") +# # SyntaxError: name capture 'command' makes remaining patterns unreachable + +# # такой блок нужно ставить в конце +# cmd = "top" +# +# match cmd: +# case "top": +# print("этот код отработает") +# case command: # создается переменная, которая ссылается на то же значение, что и переменная cmd. +# # этот шаблон не проверяет, поэтому будет срабатывать всегда +# print(f"Команда: {command}") +# # этот код отработает + +# БЛОК DEFAULT - case _: - он отработает тогда, когда другие блоки не отработают (как if-else) +# cmd = "top" +# +# match cmd: +# case "top": +# print("этот код отработает") +# case _: # это называется wildcard +# print("Другое") + +# # также в блоке case можно проводить проверку на тип +# cmd = "top" +# +# match cmd: +# case int(): +# print("это целочисление значение") +# case float(): +# print("это вещественное значение") +# case str(): +# print("Это строка") +# # Это строка + +# # если необходимо помимо проверки еще и создать переменную, используется as +# cmd = "top" +# # +# match cmd: +# case int(): +# print("это целочисление значение") +# case float(): +# print("это вещественное значение") +# case str() as command: # если это строка, тогда создается переменная +# print(f"Это строка {command}") +# # Это строка top + +# # # 2й способ, но лучше использовать 1й, он нагляднее +# cmd = "top" +# # +# match cmd: +# case int(): +# print("это целочисление значение") +# case float(): +# print("это вещественное значение") +# case str(command): # если это строка, тогда создается переменная +# print(f"Это строка {command}") +# # # Это строка top + +# # НО!!! Осторожнее с булевым типом, так как int наследуется от него +# cmd = True +# # +# match cmd: +# case int(): +# print("это целочисление значение") +# case float(): +# print("это вещественное значение") +# case bool(): # если это строка, тогда создается переменная +# print(f"Это булевое") +# # 10 # это целочисление значение +# # True # это целочисление значение + +# #Чтобы этого не происходило сначала следует указывать bool +# cmd = 10 +# # +# match cmd: +# case bool(): # если это строка, тогда создается переменная +# print(f"Это булевое") +# case int(): +# print("это целочисление значение") +# case float(): +# print("это вещественное значение") +# # True #Это булевое +# #10 #это целочисление значение + +# # с float таких проблем не возникает +# cmd = True +# # +# match cmd: +# case float(): +# print("это вещественное значение") +# case bool(): # если это строка, тогда создается переменная +# print(f"Это булевое") +# case int(): +# print("это целочисление значение") +# #11.5 #это вещественное значение +# # True # Это булевое + +# # также в case можно указать дополнительные условия +# cmd = 5 +# # +# match cmd: +# case float(): +# print("это вещественное значение") +# case bool(): # если это строка, тогда создается переменная +# print(f"Это булевое") +# case int() as numb if 0 <= numb <= 9: # оператор if (guard - защитник) +# print("это целочисление значение от 0 до 9") +# # это целочисление значение от 0 до 9 + +# конструкция match/case Работает по принципу if/elif/else более наглядный при грамотном использовании \ No newline at end of file diff --git a/seeker/snippet/query.java b/seeker/snippet/query.java deleted file mode 100644 index 74d66c21..00000000 --- a/seeker/snippet/query.java +++ /dev/null @@ -1,13 +0,0 @@ -//date: 2025-02-10T16:48:52Z -//url: https://api.github.com/gists/aa30de16571f3024edb4a30dda028a13 -//owner: https://api.github.com/users/bastide - - /** - * Calcule le nombre d'articles commandés par un client - * @param clientCode la clé du client - */ - // Attention : SUM peut renvoyer NULL si on ne trouve pas d'enregistrement - // On utilise COALESCE pour renvoyer 0 dans ce cas - // http://www.h2database.com/html/functions.html#coalesce - @Query("SELECT COALESCE(SUM(l.quantite), 0) FROM Ligne l WHERE l.commande.client.code = :clientCode") - int nombreArticlesCommandesPar(String clientCode); diff --git a/seeker/snippet/replace_network_id.sh b/seeker/snippet/replace_network_id.sh deleted file mode 100644 index 42359156..00000000 --- a/seeker/snippet/replace_network_id.sh +++ /dev/null @@ -1,17 +0,0 @@ -#date: 2025-02-10T16:47:10Z -#url: https://api.github.com/gists/a3fc0471885909f9e61f21de5cdef98d -#owner: https://api.github.com/users/vanviethieuanh - -#!/bin/bash -# This bash script replace all OLD_NETWORK_ID with NEW_NETWORK_ID of all containers -# You might want to run this script with sudo -# Remember to restart docker after run this script. - -OLD_NETWORK_ID="your_old_network_id" -NEW_NETWORK_ID="your_new_network_id" - -# Iterate through each container's config.v2.json file -find /$DOCKER_HOME/containers/*/config.v2.json -type f | while read config_file; do - # Replace OLD_NETWORK_ID with NEW_NETWORK_ID in each file - sed -i "s/$OLD_NETWORK_ID/$NEW_NETWORK_ID/g" "$config_file" -done diff --git a/seeker/snippet/sample_pipeline.py b/seeker/snippet/sample_pipeline.py new file mode 100644 index 00000000..eab38dd5 --- /dev/null +++ b/seeker/snippet/sample_pipeline.py @@ -0,0 +1,56 @@ +#date: 2025-02-12T17:10:57Z +#url: https://api.github.com/gists/3672eb69bbeeceaccc246d60af852531 +#owner: https://api.github.com/users/tejashah88 + +# Copied from https://github.com/tejashah88/blueos-oakd-extension/blob/5e8a4bdcd46e6bc60e3f3c501464d8046789abe6/src/oakd_pipeline.py + +# Create pipeline +pipeline = dai.Pipeline() + +camRgb = pipeline.create(dai.node.ColorCamera) +camRgb.setBoardSocket(dai.CameraBoardSocket.CAM_A) +camRgb.setResolution(dai.ColorCameraProperties.SensorResolution.THE_1080_P) + +videoEnc = pipeline.create(dai.node.VideoEncoder) +rgbEncOut = pipeline.create(dai.node.XLinkOut) +rgbEncOut.setStreamName('rgb') +videoEnc.setDefaultProfilePreset(25, dai.VideoEncoderProperties.Profile.H264_MAIN) +camRgb.video.link(videoEnc.input) +videoEnc.bitstream.link(rgbEncOut.input) + +# Create left/right mono cameras for Stereo depth +monoLeft = pipeline.create(dai.node.MonoCamera) +monoLeft.setResolution(dai.MonoCameraProperties.SensorResolution.THE_400_P) +monoLeft.setCamera('left') + +monoRight = pipeline.create(dai.node.MonoCamera) +monoRight.setResolution(dai.MonoCameraProperties.SensorResolution.THE_400_P) +monoRight.setCamera('right') + +# Create a node that will produce the depth map +depth = pipeline.create(dai.node.StereoDepth) +depth.setDefaultProfilePreset(dai.node.StereoDepth.PresetMode.HIGH_DENSITY) +depth.initialConfig.setMedianFilter(dai.MedianFilter.KERNEL_7x7) +depth.setLeftRightCheck(True) +depth.setExtendedDisparity(True) +# NOTE: Subpixel disparity is of UINT16 format, which is unsupported by VideoEncoder +depth.setSubpixel(False) +monoLeft.out.link(depth.left) +monoRight.out.link(depth.right) + +# Colormap +colormap = pipeline.create(dai.node.ImageManip) +colormap.initialConfig.setColormap(dai.Colormap.TURBO, depth.initialConfig.getMaxDisparity()) +colormap.initialConfig.setFrameType(dai.ImgFrame.Type.NV12) + +videoEnc = pipeline.create(dai.node.VideoEncoder) +# Depth resolution/FPS will be the same as mono resolution/FPS +videoEnc.setDefaultProfilePreset(monoLeft.getFps(), dai.VideoEncoderProperties.Profile.H264_HIGH) + +# Link +depth.disparity.link(colormap.inputImage) +colormap.out.link(videoEnc.input) + +xout = pipeline.create(dai.node.XLinkOut) +xout.setStreamName('depth') +videoEnc.bitstream.link(xout.input) \ No newline at end of file diff --git a/seeker/snippet/segmentio_consumer_lag.go b/seeker/snippet/segmentio_consumer_lag.go new file mode 100644 index 00000000..51d3ab92 --- /dev/null +++ b/seeker/snippet/segmentio_consumer_lag.go @@ -0,0 +1,145 @@ +//date: 2025-02-12T17:11:26Z +//url: https://api.github.com/gists/ab235f7a34bc1589e5840b11ea8c4fe6 +//owner: https://api.github.com/users/MrLis + +package main + +import ( + "context" + "crypto/tls" + "crypto/x509" + "errors" + "fmt" + "math" + "time" + + "github.com/samber/lo" + "github.com/segmentio/kafka-go" +) + +var ( + Brokers = []string{"localhost:9092"} +) + +const ( + Cert = `-----BEGIN CERTIFICATE----- +... +-----END CERTIFICATE-----` + Key = `-----BEGIN RSA PRIVATE KEY----- +... +-----END RSA PRIVATE KEY-----` + Ca = `-----BEGIN CERTIFICATE----- +... +-----END CERTIFICATE-----` +) + +func main() { + + lags, err := getConsumerLag(context.Background()) + if err != nil { + fmt.Println(err) + } + + for k, v := range lags { + fmt.Printf("Topic: %s, ConsumerGroup: %s, Lag: %f\n", k.Topic, k.ConsumerGroup, v) + } +} + +type TopicConsumerGroup struct { + Topic string + ConsumerGroup string +} + +func getConsumerLag(ctx context.Context) (map[TopicConsumerGroup]float64, error) { + res := make(map[TopicConsumerGroup]float64, 0) + + cert, err := tls.X509KeyPair([]byte(Cert), []byte(Key)) + if err != nil { + return res, fmt.Errorf("failed to parse kafka cert: %w", err) + } + certPool := x509.NewCertPool() + if !certPool.AppendCertsFromPEM([]byte(Ca)) { + return res, errors.New("failed to parse kafka ca") + } + client := &kafka.Client{ + Addr: kafka.TCP(Brokers...), + Timeout: 60 * time.Second, + Transport: &kafka.Transport{ + TLS: &tls.Config{ + Certificates: []tls.Certificate{cert}, + RootCAs: certPool, + }, + }, + } + + // get list of topics + metadata, err := client.Metadata(ctx, &kafka.MetadataRequest{}) + if err != nil { + return res, fmt.Errorf("failed to request metadata: %w", err) + } + allTopics := metadata.Topics + + // get list of consumer groups + listGroupResp, err := client.ListGroups(ctx, &kafka.ListGroupsRequest{}) + if err != nil { + return res, fmt.Errorf("failed to request group list: %w", err) + } + + for _, group := range listGroupResp.Groups { + // get offsets for each group + commitedOffsetResp, err := client.OffsetFetch(ctx, &kafka.OffsetFetchRequest{ + GroupID: group.GroupID, + Topics: lo.SliceToMap(allTopics, func(topic kafka.Topic) (string, []int) { + return topic.Name, lo.Map(topic.Partitions, func(p kafka.Partition, _ int) int { + return p.ID + }) + }), + }) + if err != nil { + return res, fmt.Errorf("failed to request commited offsets: %w", err) + } + + // get last offsets for each topic + listOffsetsResponse, err := client.ListOffsets(ctx, &kafka.ListOffsetsRequest{ + Topics: lo.SliceToMap(allTopics, func(topic kafka.Topic) (string, []kafka.OffsetRequest) { + return topic.Name, lo.Map(topic.Partitions, func(p kafka.Partition, _ int) kafka.OffsetRequest { + return kafka.LastOffsetOf(p.ID) + }) + }), + }) + if err != nil { + return res, fmt.Errorf("failed to request last offsets: %w", err) + } + + // compute consumer lag + for topic, partitionOffsets := range listOffsetsResponse.Topics { + + // go through all partitions in topic and compute lag + for _, partition := range partitionOffsets { + lastOffset := float64(partition.LastOffset) + commitedOffset := math.NaN() + commitedOffsets, ok := commitedOffsetResp.Topics[topic] + if ok { + for _, offset := range commitedOffsets { + if offset.Partition == partition.Partition { + if offset.CommittedOffset != -1 { + commitedOffset = float64(offset.CommittedOffset) + } + } + } + } + + tc := TopicConsumerGroup{ + Topic: topic, + ConsumerGroup: group.GroupID, + } + if _, ok := res[tc]; !ok { + res[tc] = 0 + } + res[tc] = res[tc] + lastOffset - commitedOffset + } + } + } + + return res, nil +} diff --git a/seeker/snippet/snake_game.py b/seeker/snippet/snake_game.py new file mode 100644 index 00000000..5ec2186d --- /dev/null +++ b/seeker/snippet/snake_game.py @@ -0,0 +1,189 @@ +#date: 2025-02-12T17:07:50Z +#url: https://api.github.com/gists/52d3290c8716c36a91348c6ac81b4bca +#owner: https://api.github.com/users/mr-ki-wissen-2go + +# Simple Snake Game in Python 3 for Beginners +# By @TokyoEdTech + +import turtle +import time +import random + +delay = 0.1 + +# Score +score = 0 +high_score = 0 + +# Set up the screen +wn = turtle.Screen() +wn.title("Snake Game by @TokyoEdTech") +wn.bgcolor("green") +wn.setup(width=600, height=600) +wn.tracer(0) # Turns off the screen updates + +# Snake head +head = turtle.Turtle() +head.speed(0) +head.shape("square") +head.color("black") +head.penup() +head.goto(0,0) +head.direction = "stop" + +# Snake food +food = turtle.Turtle() +food.speed(0) +food.shape("circle") +food.color("red") +food.penup() +food.goto(0,100) + +segments = [] + +# Pen +pen = turtle.Turtle() +pen.speed(0) +pen.shape("square") +pen.color("white") +pen.penup() +pen.hideturtle() +pen.goto(0, 260) +pen.write("Score: 0 High Score: 0", align="center", font=("Courier", 24, "normal")) + +# Functions +def go_up(): + if head.direction != "down": + head.direction = "up" + +def go_down(): + if head.direction != "up": + head.direction = "down" + +def go_left(): + if head.direction != "right": + head.direction = "left" + +def go_right(): + if head.direction != "left": + head.direction = "right" + +def move(): + if head.direction == "up": + y = head.ycor() + head.sety(y + 20) + + if head.direction == "down": + y = head.ycor() + head.sety(y - 20) + + if head.direction == "left": + x = head.xcor() + head.setx(x - 20) + + if head.direction == "right": + x = head.xcor() + head.setx(x + 20) + +# Keyboard bindings +wn.listen() +wn.onkeypress(go_up, "w") +wn.onkeypress(go_down, "s") +wn.onkeypress(go_left, "a") +wn.onkeypress(go_right, "d") + +# Main game loop +while True: + wn.update() + + # Check for a collision with the border + if head.xcor()>290 or head.xcor()<-290 or head.ycor()>290 or head.ycor()<-290: + time.sleep(1) + head.goto(0,0) + head.direction = "stop" + + # Hide the segments + for segment in segments: + segment.goto(1000, 1000) + + # Clear the segments list + segments.clear() + + # Reset the score + score = 0 + + # Reset the delay + delay = 0.1 + + pen.clear() + pen.write("Score: {} High Score: {}".format(score, high_score), align="center", font=("Courier", 24, "normal")) + + + # Check for a collision with the food + if head.distance(food) < 20: + # Move the food to a random spot + x = random.randint(-290, 290) + y = random.randint(-290, 290) + food.goto(x,y) + + # Add a segment + new_segment = turtle.Turtle() + new_segment.speed(0) + new_segment.shape("square") + new_segment.color("grey") + new_segment.penup() + segments.append(new_segment) + + # Shorten the delay + delay -= 0.001 + + # Increase the score + score += 10 + + if score > high_score: + high_score = score + + pen.clear() + pen.write("Score: {} High Score: {}".format(score, high_score), align="center", font=("Courier", 24, "normal")) + + # Move the end segments first in reverse order + for index in range(len(segments)-1, 0, -1): + x = segments[index-1].xcor() + y = segments[index-1].ycor() + segments[index].goto(x, y) + + # Move segment 0 to where the head is + if len(segments) > 0: + x = head.xcor() + y = head.ycor() + segments[0].goto(x,y) + + move() + + # Check for head collision with the body segments + for segment in segments: + if segment.distance(head) < 20: + time.sleep(1) + head.goto(0,0) + head.direction = "stop" + + # Hide the segments + for segment in segments: + segment.goto(1000, 1000) + + # Clear the segments list + segments.clear() + + # Reset the score + score = 0 + + # Reset the delay + delay = 0.1 + + # Update the score display + pen.clear() + pen.write("Score: {} High Score: {}".format(score, high_score), align="center", font=("Courier", 24, "normal")) + + time.sleep(delay) + +wn.mainloop() \ No newline at end of file diff --git a/seeker/snippet/terraform-module-mover.sh b/seeker/snippet/terraform-module-mover.sh deleted file mode 100644 index 94cf0361..00000000 --- a/seeker/snippet/terraform-module-mover.sh +++ /dev/null @@ -1,12 +0,0 @@ -#date: 2025-02-10T16:44:19Z -#url: https://api.github.com/gists/da829a6592c22efe81fec84d0f99b452 -#owner: https://api.github.com/users/andreiio - -#!/bin/bash -# Generates terraform "moved" blocks for files based on terraform state -export OLD_MODULE="old_module_name" -export NEW_MODULE="" #LEAVE EMPTY to move to root module or enter "module.new_module." if you want to move to another module - -terraform state list | -grep module.${OLD_MODULE} | cut -d. -f 3- | sed 's/\"/\\\"/g' | -xargs -I {} sh -c 'echo "moved {" && echo " from = module.${OLD_MODULE}.{}" && echo " to = ${NEW_MODULE}{}" && echo "}"' | sed 's/\]/\"]/g' | sed 's/\[/\["/g' | tr -d '\r' > moved-blocks.tf \ No newline at end of file diff --git a/seeker/snippet/testzep.py b/seeker/snippet/testzep.py deleted file mode 100644 index 45d75872..00000000 --- a/seeker/snippet/testzep.py +++ /dev/null @@ -1,59 +0,0 @@ -#date: 2025-02-10T17:01:47Z -#url: https://api.github.com/gists/32c4936c56e46dd5ccccf9aa99e248e5 -#owner: https://api.github.com/users/boat-builder - - -user = "testuser1" -agent = "berlin-ecom1" -user_session_id = "60d86e48-b48f-4b9c-909f-5c248bd7ea73" -agent_session_id = "207a4a3a-a5be-4dc1-9b42-2c5ddfa6d5c6" - - -async def main(): - resp = await zep.user.add(user_id=user) - resp = await zep.user.add(user_id=agent) - resp = await zep.memory.add_session(user_id=user, session_id=user_session_id) - resp = await zep.memory.add_session(user_id=agent, session_id=agent_session_id) - - resp = await zep.memory.add( - session_id=user_session_id, - messages=[ - Message( - role_type="user", - content="Your suggestion contains schlage product. But we don't sell anything other than sargent products.", - ), - ], - ) - print("user message added", resp) - resp = await zep.memory.add( - session_id=agent_session_id, - messages=[ - Message( - role_type="assistant", - content="latest SEO knowledge in ecommerce is to create product pages over category and blog/article pages. Product pages ranks better", - ) - ], - ) - print("agent message added", resp) - fact_response = await zep.user.get_facts(user_id=user) - print("user facts", fact_response) - fact_response = await zep.user.get_facts(user_id=agent) - print("agent facts", fact_response) - r = await zep.graph.search( - user_id=user, - query="I just found three toics to create a page for SEO. Which one should I pick and what page should I make? \n1. Schlage hardware and doors\n2. Sargent door locks\n3. Van Du Prin door locks", - limit=4, - scope="edges", - ) - print("user search", r) - r = await zep.graph.search( - user_id=agent, - query="I just found three toics to create a page for SEO. Which one should I pick and what page should I make? \n1. Schlage hardware and doors\n2. Sargent door locks\n3. Van Du Prin door locks", - limit=4, - scope="edges", - ) - print("agent search", r) - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/seeker/snippet/wol b/seeker/snippet/wol deleted file mode 100644 index 4244a667..00000000 --- a/seeker/snippet/wol +++ /dev/null @@ -1,44 +0,0 @@ -#date: 2025-02-10T17:04:55Z -#url: https://api.github.com/gists/57624c73c7592ceb984bee36d5985a1b -#owner: https://api.github.com/users/prossel - -#!/usr/bin/env python3 - -# chmod +x wol -# mv wol /usr/local/bin/ -# Usage: wol - -import socket -import struct -import sys - -def wake_on_lan(macaddress): - # Check MAC address format and try to compensate. - if len(macaddress) == 12: - pass - elif len(macaddress) == 12 + 5: - sep = macaddress[2] - macaddress = macaddress.replace(sep, '') - else: - raise ValueError('Incorrect MAC address format') - - # Pad the synchronization stream. - data = ''.join(['FFFFFFFFFFFF', macaddress * 20]) - send_data = b'' - - # Split up the hex values and pack. - for i in range(0, len(data), 2): - send_data = b''.join([send_data, struct.pack('B', int(data[i: i + 2], 16))]) - - # Broadcast it to the LAN. - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) - sock.sendto(send_data, ('', 7)) - -if __name__ == "__main__": - if len(sys.argv) != 2: - print("Usage: wol ") - sys.exit(1) - - mac_address = sys.argv[1] - wake_on_lan(mac_address)