From 8668211fb8c20db131a4cb85f179a945fdd5bcc3 Mon Sep 17 00:00:00 2001 From: Nataliia Volkova Date: Wed, 19 Nov 2025 12:51:34 +0000 Subject: [PATCH 1/8] 01 Implement shell tools (cat, ls, wc) in JS with mode --- implement-shell-tools/cat/cat.js | 33 +++++++++++++++++++ implement-shell-tools/ls/ls.js | 56 ++++++++++++++++++++++++++++++++ implement-shell-tools/wc/wc.js | 38 ++++++++++++++++++++++ 3 files changed, 127 insertions(+) create mode 100644 implement-shell-tools/cat/cat.js create mode 100644 implement-shell-tools/ls/ls.js create mode 100644 implement-shell-tools/wc/wc.js diff --git a/implement-shell-tools/cat/cat.js b/implement-shell-tools/cat/cat.js new file mode 100644 index 000000000..331be0929 --- /dev/null +++ b/implement-shell-tools/cat/cat.js @@ -0,0 +1,33 @@ +import process from "node:process"; +import { promises as fs } from "node:fs"; + +const arrArgv = process.argv.slice(2); + +const numberLines = arrArgv.includes("-n"); +const numberNonemptyLines = arrArgv.includes("-b"); + +const nonFlagArrArgv = arrArgv.filter((arr) => !arr.startsWith("-")); + +let number = 1; + +for (let file of nonFlagArrArgv) { + const content = await fs.readFile(file, "utf-8"); + + const linedText = content.split("\n"); + + const numbered = linedText.map((line) => { + if (numberNonemptyLines) { + if (line.trim() === "") { + return line; + } else { + return `${String(number++).padStart(3)} ${line}`; + } + } + if (numberLines) { + return `${String(number++).padStart(3)} ${line}`; + } + + return line; + }); + console.log(numbered.join("\n")); +} diff --git a/implement-shell-tools/ls/ls.js b/implement-shell-tools/ls/ls.js new file mode 100644 index 000000000..47414da60 --- /dev/null +++ b/implement-shell-tools/ls/ls.js @@ -0,0 +1,56 @@ +import process from "node:process"; +import { promises as fs } from "node:fs"; +import path from "node:path"; + +const arrArgv = process.argv.slice(2); + +const longFormat = arrArgv.includes("-l"); +const showHidden = arrArgv.includes("-a"); + +const paths = arrArgv.filter((argv) => !argv.startsWith("-")); +if (paths.length === 0) path = "[.]"; + +for (let listFile of paths) { + const status = await fs.stat(listFile); + + if (status.isFile()) { + const permissions = (status.mode & 0o777).toString(8); + const sizeFile = status.size; + const owner = status.uid; + const group = status.gid; + const timeMod = status.mtime.toLocaleString(); + + if (longFormat) { + console.log( + `${permissions}, ${owner}, ${group}, ${sizeFile}, ${timeMod}, ${listFile}` + ); + } else { + console.log(listFile); + } + } else { + let files = await fs.readdir(listFile, { withFileTypes: true }); + + if (!showHidden) { + files = files.filter((file) => !file.name.startsWith(".")); + } + + for (let file of files) { + const wholePath = path.join(listFile, file.name); + const statusFile = await fs.stat(wholePath); + + const permissions = (statusFile.mode & 0o777).toString(8); + const sizeFile = statusFile.size; + const owner = statusFile.uid; + const group = statusFile.gid; + const timeMod = statusFile.mtime.toLocaleString(); + + if (longFormat) { + console.log( + `${permissions}, ${owner}, ${group}, ${sizeFile}, ${timeMod}, ${file.name}` + ); + } else { + console.log(file.name); + } + } + } +} diff --git a/implement-shell-tools/wc/wc.js b/implement-shell-tools/wc/wc.js new file mode 100644 index 000000000..2648d62d3 --- /dev/null +++ b/implement-shell-tools/wc/wc.js @@ -0,0 +1,38 @@ +import process from "node:process"; +import { promises as fs } from "node:fs"; + +const arrArgv = process.argv.slice(2); + +const lines = arrArgv.includes("-l"); +const words = arrArgv.includes("-w"); +const bytes = arrArgv.includes("-c"); + +const noFlags = !lines && !words && !bytes; + +const paths = arrArgv.filter((argv) => !argv.startsWith("-")); + +for (let path of paths) { + const context = await fs.readFile(path, "utf-8"); + + const countLines = context.split(/\r?\n/).length; + const countWords = context.split(/\s+/).length; + const countBytes = Buffer.byteLength(context, "utf-8"); + + let startInput = ""; + + if (noFlags || lines) { + startInput += `${countLines} `; + } + + if (noFlags || words) { + startInput += `${countWords} `; + } + + if (noFlags || bytes) { + startInput += `${countBytes} `; + } + + startInput += path; + + console.log(startInput); +} From 061be3093946f3ce3eb7f41b56fcd9b1fcb40f38 Mon Sep 17 00:00:00 2001 From: Nataliia Volkova Date: Sat, 20 Dec 2025 19:05:36 +0000 Subject: [PATCH 2/8] python script allocation laptop --- allocate_laptop.py | 91 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 allocate_laptop.py diff --git a/allocate_laptop.py b/allocate_laptop.py new file mode 100644 index 000000000..3a842d9dc --- /dev/null +++ b/allocate_laptop.py @@ -0,0 +1,91 @@ +from dataclasses import dataclass +from enum import Enum +from typing import List, Dict, Tuple, Optional + +class OperatingSystem(Enum): + MACOS = "macOS" + ARCH = "Arch Linux" + UBUNTU = "Ubuntu" + +@dataclass(frozen=True) +class Person: + name: str + age: int + # Sorted in order of preference, most preferred is first. + preferred_operating_systems: List[OperatingSystem] + + +@dataclass(frozen=True) +class Laptop: + id: int + manufacturer: str + model: str + screen_size_in_inches: float + operating_system: OperatingSystem + +def norm_os_values(value: str) -> OperatingSystem: + value = value.strip().lower() + if value == "ubuntu": + return OperatingSystem.UBUNTU + if value == "arch linux": + return OperatingSystem.ARCH + if value == "macos": + return OperatingSystem.MACOS + raise ValueError(f"Unknown OS: {value}") + + +people = [ + Person(name="Imran", age=22, preferred_operating_systems=[norm_os_values("Ubuntu"), norm_os_values("Arch Linux")]), + Person(name="Eliza", age=34, preferred_operating_systems=[norm_os_values("Arch Linux"), norm_os_values("macOS"), norm_os_values("Ubuntu")]), + Person(name="Ira", age=21, preferred_operating_systems=[norm_os_values("Ubuntu"), norm_os_values("Arch Linux")]), + Person(name="Anna", age=34, preferred_operating_systems=[norm_os_values("Ubuntu"), norm_os_values("macOS")]), + Person(name="Nahimn", age=42, preferred_operating_systems=[norm_os_values("Ubuntu"), norm_os_values("Arch Linux")]) +] + +laptops = [ + Laptop(id=1, manufacturer="Dell", model="XPS", screen_size_in_inches=13, operating_system=norm_os_values("Arch Linux")), + Laptop(id=2, manufacturer="Dell", model="XPS", screen_size_in_inches=15, operating_system=norm_os_values("Ubuntu")), + Laptop(id=3, manufacturer="Dell", model="XPS", screen_size_in_inches=15, operating_system=norm_os_values("ubuntu")), + Laptop(id=4, manufacturer="Apple", model="macBook", screen_size_in_inches=13, operating_system=norm_os_values("macOS")), +] + + +def allocate_laptops(people: List[Person], laptops: List[Laptop]) -> Dict[Tuple[str, int], int]: + sadness_table: Dict[Tuple[str, int], int] = {} + for person in people: + for laptop in laptops: + if laptop.operating_system in person.preferred_operating_systems: + index = person.preferred_operating_systems.index(laptop.operating_system) + sadness = index + else: + sadness = 100 + sadness_table[(person.name, laptop.id)] = sadness + return sadness_table + + +sadness_table = allocate_laptops(people, laptops) + +allocation_list: List[Tuple[str, Optional[int], int]] = [] +allocated_laptops: set[int] = set() +allocated_persons: set[str] = set() +total_happiness: int = 0 + +for (person_name, laptop_id), sadness in sorted(sadness_table.items(), key=lambda value: value[1]): + if laptop_id in allocated_laptops: + continue + if person_name in allocated_persons: + continue + allocation_list.append((person_name, laptop_id, sadness)) + allocated_laptops.add(laptop_id) + allocated_persons.add(person_name) + total_happiness += sadness + print(f"{person_name} got laptop {laptop_id}") + + +for person in people: + if person.name not in allocated_persons: + print(f"{person.name} did not get laptop") +print(f"Total happiness: {total_happiness}") + +print(allocation_list) + From eb8a06bf350ae74baa648f28503fcb8d96fd7747 Mon Sep 17 00:00:00 2001 From: Nataliia Volkova Date: Sat, 20 Dec 2025 19:34:52 +0000 Subject: [PATCH 3/8] Inheritens --- inherit.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 inherit.py diff --git a/inherit.py b/inherit.py new file mode 100644 index 000000000..f0675ef48 --- /dev/null +++ b/inherit.py @@ -0,0 +1,39 @@ +from typing import List + +class Parent: + def __init__(self, first_name: str, last_name: str): + self.first_name = first_name + self.last_name = last_name + + def get_name(self) -> str: + return f"{self.first_name} {self.last_name}" + + +class Child(Parent): + def __init__(self, first_name: str, last_name: str): + super().__init__(first_name, last_name) + self.previous_last_names: List [str]= [] + + def change_last_name(self, last_name: str) -> None: + self.previous_last_names.append(self.last_name) + self.last_name = last_name + + def get_full_name(self) -> str: + suffix: str = "" + if len(self.previous_last_names) > 0: + suffix = f" (née {self.previous_last_names[0]})" + return f"{self.first_name} {self.last_name}{suffix}" + +person1 = Child("Elizaveta", "Alekseeva") +print(person1.get_name()) +print(person1.get_full_name()) +person1.change_last_name("Tyurina") +print(person1.get_name()) +print(person1.get_full_name()) + +person2 = Parent("Elizaveta", "Alekseeva") +print(person2.get_name()) +# print(person2.get_full_name()) // this method dose not belong to Parent class +# person2.change_last_name("Tyurina") // this method dose not belong to Parent class +print(person2.get_name()) +# print(person2.get_full_name()) // this method dose not belong to Parent class \ No newline at end of file From 5f5269349384c9237e7e7f2e90ab0da308ca5340 Mon Sep 17 00:00:00 2001 From: Nataliia Volkova Date: Sat, 20 Dec 2025 19:46:34 +0000 Subject: [PATCH 4/8] enum exer. --- enums.py | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 enums.py diff --git a/enums.py b/enums.py new file mode 100644 index 000000000..2a776b917 --- /dev/null +++ b/enums.py @@ -0,0 +1,105 @@ +from dataclasses import dataclass +from enum import Enum +from typing import List, Dict +import sys + + + + +class OperatingSystem(Enum): + MACOS = "macOS" + ARCH = "Arch Linux" + UBUNTU = "Ubuntu" + +@dataclass(frozen=True) +class Person: + name: str + age: int + preferred_operating_system: OperatingSystem + + +@dataclass(frozen=True) +class Laptop: + id: int + manufacturer: str + model: str + screen_size_in_inches: float + operating_system: OperatingSystem + + +def count_laptops(laptops: List[Laptop]) -> Dict[OperatingSystem, int]: + number_eachOS_laptops: Dict[OperatingSystem, int] = { + OperatingSystem.MACOS: 0, + OperatingSystem.ARCH: 0, + OperatingSystem.UBUNTU: 0} + for laptop in laptops: + number_eachOS_laptops[laptop.operating_system] +=1 + return number_eachOS_laptops + + +def count_possible_laptops(laptops: List[Laptop], person: Person) -> int: + possible_laptops: List[Laptop] =[] + for laptop in laptops: + if laptop.operating_system == person.preferred_operating_system: + possible_laptops.append(laptop) + number_possible_laptops = len(possible_laptops) + return number_possible_laptops + +def chose_alternative_laptops(laptops: List[Laptop], person: Person) -> Dict[OperatingSystem, int]: + number_possible_laptops = count_possible_laptops(laptops, person) + number_eachOS_laptops = count_laptops(laptops) + preferred_os = person.preferred_operating_system + alternative_laptops: Dict[OperatingSystem, int] = {} + for eachOS, count in number_eachOS_laptops.items(): + if eachOS == preferred_os: + continue + if count > number_possible_laptops: + alternative_laptops[eachOS] = count + if len(alternative_laptops) != 0: + print(f"There is an operating system that has more laptops available.If you’re willing to accept them, there is a list: {alternative_laptops}.") + return alternative_laptops + else: + print("There is not an operating system that has more laptops available.") + return alternative_laptops + +while True: + user_name = input("Type your name: ").strip() + if len(user_name) < 3: + print(f"Error, {user_name} is not valid. Try again, length should be more than 3 characters.") + continue + break + +while True: + user_age = input("Type your age: ").strip() + try: + user_age_int = int(user_age) + if user_age_int < 18: + raise ValueError + break + except ValueError: + print("Invalid age, try again! Borrowing allowed from 18 years old.") + +available_os = [os.value for os in OperatingSystem] +print("Available OSs are: ", ",".join(available_os)) +user_operating_system = input("Type operating system: ").strip() +if user_operating_system not in available_os: + print(f"Error, {user_operating_system} is not in available list\n" + f"Available OSs are: {','.join(available_os)}", file=sys.stderr) + sys.exit(1) + +preferred_operating_system = OperatingSystem(user_operating_system) + +user = Person(name=user_name, age=user_age_int, preferred_operating_system=preferred_operating_system) + + +laptops = [ + Laptop(id=1, manufacturer="Dell", model="XPS", screen_size_in_inches=13, operating_system=OperatingSystem.ARCH), + Laptop(id=2, manufacturer="Dell", model="XPS", screen_size_in_inches=15, operating_system=OperatingSystem.UBUNTU), + Laptop(id=3, manufacturer="Dell", model="XPS", screen_size_in_inches=15, operating_system=OperatingSystem.UBUNTU), + Laptop(id=4, manufacturer="Apple", model="macBook", screen_size_in_inches=13, operating_system=OperatingSystem.MACOS), +] + + +possible_laptops = count_possible_laptops(laptops, user) +print(f"Possible laptops for {user_name}: {possible_laptops}") +alternative_laptops = chose_alternative_laptops(laptops, user) From 762ed73eb70c096c6440e28efe0b2da64785e3ba Mon Sep 17 00:00:00 2001 From: Nataliia Volkova Date: Sat, 20 Dec 2025 19:54:53 +0000 Subject: [PATCH 5/8] typy guide refactoring --- type_guide_refact.py | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 type_guide_refact.py diff --git a/type_guide_refact.py b/type_guide_refact.py new file mode 100644 index 000000000..f1ee15eb3 --- /dev/null +++ b/type_guide_refact.py @@ -0,0 +1,42 @@ +from dataclasses import dataclass +from typing import List + +@dataclass(frozen=True) +class Person: + name: str + age: int + preferred_operating_systems: List[str] + + +@dataclass(frozen=True) +class Laptop: + id: int + manufacturer: str + model: str + screen_size_in_inches: float + operating_system: str + + +def find_possible_laptops(laptops: List[Laptop], person: Person) -> List[Laptop]: + possible_laptops: list[Laptop] = [] + for laptop in laptops: + if laptop.operating_system in person.preferred_operating_systems: + possible_laptops.append(laptop) + return possible_laptops + + +people = [ + Person(name="Imran", age=22, preferred_operating_systems=["Ubuntu"]), + Person(name="Eliza", age=34, preferred_operating_systems=["Arch Linux"]), +] + +laptops = [ + Laptop(id=1, manufacturer="Dell", model="XPS", screen_size_in_inches=13, operating_system="Arch Linux"), + Laptop(id=2, manufacturer="Dell", model="XPS", screen_size_in_inches=15, operating_system="Ubuntu"), + Laptop(id=3, manufacturer="Dell", model="XPS", screen_size_in_inches=15, operating_system="ubuntu"), + Laptop(id=4, manufacturer="Apple", model="macBook", screen_size_in_inches=13, operating_system="macOS"), +] + +for person in people: + possible_laptops = find_possible_laptops(laptops, person) + print(f"Possible laptops for {person.name}: {possible_laptops}") \ No newline at end of file From 7e620980463ddd41f65aee94eda46bde028448b0 Mon Sep 17 00:00:00 2001 From: Nataliia Volkova Date: Sat, 20 Dec 2025 20:02:10 +0000 Subject: [PATCH 6/8] generics --- familytree.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 familytree.py diff --git a/familytree.py b/familytree.py new file mode 100644 index 000000000..2e2579d69 --- /dev/null +++ b/familytree.py @@ -0,0 +1,20 @@ +from dataclasses import dataclass +from typing import List + +@dataclass(frozen=True) +class Person: + name: str + children: List["Person"] + age: int + +fatma = Person(name="Fatma", children=[], age=17) +aisha = Person(name="Aisha", children=[], age=25) + +imran = Person(name="Imran", children=[fatma, aisha], age=51) + +def print_family_tree(person: Person) -> None: + print(person.name, f"({person.age})") + for child in person.children: + print(f"- {child.name} ({child.age})") + +print_family_tree(imran) \ No newline at end of file From 63309c281205879e3f03a707142d687b2409805c Mon Sep 17 00:00:00 2001 From: Nataliia Volkova Date: Sat, 20 Dec 2025 20:10:41 +0000 Subject: [PATCH 7/8] dataclasses --- dataclasses_ex.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 dataclasses_ex.py diff --git a/dataclasses_ex.py b/dataclasses_ex.py new file mode 100644 index 000000000..0114071a2 --- /dev/null +++ b/dataclasses_ex.py @@ -0,0 +1,24 @@ +from datetime import date +from dataclasses import dataclass + +@dataclass(frozen=True) +class Person: + name: str + preferred_operating_system: str + birth_date: date + + def is_adult(self) -> bool: + today = date.today() + age = today.year - self.birth_date.year + + if (today.month, today.day) < (self.birth_date.month, self.birth_date.day): + age -=1 + + return age >= 18 + +imran = Person("Imran", "Ubuntu", date(2000, 9, 12)) + +print(imran.is_adult()) + + + From 12748b0a1a43cc43c99e8510e5e6e356c54c735e Mon Sep 17 00:00:00 2001 From: Nataliia Volkova Date: Sat, 20 Dec 2025 20:54:09 +0000 Subject: [PATCH 8/8] types_banc_account_exer --- typesExer.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 typesExer.py diff --git a/typesExer.py b/typesExer.py new file mode 100644 index 000000000..9ba857ef1 --- /dev/null +++ b/typesExer.py @@ -0,0 +1,33 @@ +from typing import Union, Dict + + +def open_account(balances: Dict[str, int], name: str, amount: Union[str, float]): + balances[name] = int(float(amount) *100) + +def sum_balances(accounts: Dict[str, int]): + total = 0 + for name, pence in accounts.items(): + print(f"{name} had balance {pence}") + total += pence + return total + +def format_pence_as_pound(total_pence: int) -> str: + if total_pence < 100: + return f"{total_pence}p" + pounds = total_pence // 100 + pence = total_pence % 100 + return f"£{pounds}.{pence:02d}" + +balances = { + "Sima": 700, + "Linn": 545, + "Georg": 831, +} + +open_account(balances, "Tobi", 9.13) +open_account(balances, "Olya", 7.13) + +total_pence = sum_balances(balances) +total_pound = format_pence_as_pound(total_pence) + +print(f"The bank accounts total {total_pound}") \ No newline at end of file