diff --git a/README-zh_CN.md b/README-zh_CN.md
index ea24bef71..dfc934d56 100644
--- a/README-zh_CN.md
+++ b/README-zh_CN.md
@@ -3616,5 +3616,3 @@ where c.Customer_ID in (Select Customer_ID from cat_food);
* [Cloud Slack bot](scenarios/cloud_slack_bot.md)
* [Writing Jenkins Scripts](scenarios/jenkins_scripts.md)
* [Writing Jenkins Pipelines](scenarios/jenkins_pipelines.md)
-
-
\ No newline at end of file
diff --git a/README.md b/README.md
index dfe483f3d..f996f96bf 100644
--- a/README.md
+++ b/README.md
@@ -109,6 +109,7 @@
 KubePrep |
 Linux Master |
+  System Design Hero |
diff --git a/coding/python/binary_search.py b/coding/python/binary_search.py
index d1937e6e9..7a66c848a 100644
--- a/coding/python/binary_search.py
+++ b/coding/python/binary_search.py
@@ -1,28 +1,42 @@
#!/usr/bin/env python
import random
-from typing import List
+from typing import List, Optional
-def binary_search(arr: List[int], lb: int, ub: int, target: int) -> int:
+def binary_search(arr: List[int], lb: int, ub: int, target: int) -> Optional[int]:
"""
A Binary Search Example which has O(log n) time complexity.
"""
- if lb <= ub:
- mid: int = lb + (ub - lb) // 2
+ while lb <= ub:
+ mid = lb + (ub - lb) // 2
if arr[mid] == target:
return mid
elif arr[mid] < target:
- return binary_search(arr, mid + 1, ub, target)
+ lb = mid + 1
else:
- return binary_search(arr, lb, mid - 1, target)
- else:
- return -1
+ ub = mid - 1
+ return -1
+
+
+def generate_random_list(size: int = 10, lower: int = 1, upper: int = 50) -> List[int]:
+ return sorted(random.randint(lower, upper) for _ in range(size))
+
+
+def find_target_in_list(target: int, lst: List[int]) -> int:
+ return binary_search(lst, 0, len(lst) - 1, target)
+
+
+def main():
+ """
+ Executes the binary search algorithm with a randomly generated list.
+ Time Complexity: O(log n)
+ """
+ rand_num_li = generate_random_list()
+ target = random.randint(1, 50)
+ index = find_target_in_list(target, rand_num_li)
+ print(f"List: {rand_num_li}\nTarget: {target}\nIndex: {index}")
if __name__ == '__main__':
- rand_num_li: List[int] = sorted([random.randint(1, 50) for _ in range(10)])
- target: int = random.randint(1, 50)
- print("List: {}\nTarget: {}\nIndex: {}".format(
- rand_num_li, target,
- binary_search(rand_num_li, 0, len(rand_num_li) - 1, target)))
+ main()
diff --git a/coding/python/merge_sort.py b/coding/python/merge_sort.py
new file mode 100644
index 000000000..a92ca6bc9
--- /dev/null
+++ b/coding/python/merge_sort.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+
+import random
+from typing import List
+
+
+def merge_sort(arr: List[int]) -> List[int]:
+ if len(arr) <= 1:
+ return arr
+ mid = len(arr) // 2
+ left = merge_sort(arr[:mid])
+ right = merge_sort(arr[mid:])
+ return merge(left, right)
+
+
+def merge(left: List[int], right: List[int]) -> List[int]:
+ merged = []
+ i = j = 0
+ while i < len(left) and j < len(right):
+ if left[i] <= right[j]:
+ merged.append(left[i])
+ i += 1
+ else:
+ merged.append(right[j])
+ j += 1
+ merged.extend(left[i:])
+ merged.extend(right[j:])
+ return merged
+
+
+def generate_random_list(size: int = 10, lower: int = 1, upper: int = 100) -> List[int]:
+ return [random.randint(lower, upper) for _ in range(size)]
+
+
+def main():
+ """
+ Executes the merge sort algorithm with a randomly generated list.
+ Time Complexity: O(n log n)
+ """
+ rand_num_li = generate_random_list()
+ print(f"Unsorted List: {rand_num_li}")
+ sorted_list = merge_sort(rand_num_li)
+ print(f"Sorted List: {sorted_list}")
+
+
+if __name__ == '__main__':
+ main()
diff --git a/images/apps/system_design_hero.png b/images/apps/system_design_hero.png
new file mode 100644
index 000000000..fa8c5552d
Binary files /dev/null and b/images/apps/system_design_hero.png differ
diff --git a/scripts/aws s3 event triggering/s3-lambda/s3-lambda.py b/scripts/aws s3 event triggering/s3-lambda/s3-lambda.py
index 0fab7aa84..b28ced2db 100644
--- a/scripts/aws s3 event triggering/s3-lambda/s3-lambda.py
+++ b/scripts/aws s3 event triggering/s3-lambda/s3-lambda.py
@@ -1,38 +1,38 @@
import boto3
import json
-def lambda_handler(event, context):
- # i want to know that event thing
- print(event)
+def lambda_handler(event, context):
+ # i want to know that event thing
+ print(event)
- # extract relevant information from the s3 event trigger
- bucket_name=event['Records'][0]['s3']['bucket']['name']
- object_key=event['Records'][0]['s3']['object']['key']
+ # extract relevant information from the s3 event trigger
+ bucket_name = event['Records'][0]['s3']['bucket']['name']
+ object_key = event['Records'][0]['s3']['object']['key']
- # perform desired operations with the upload file
- print(f"File '{object_key}' was uploaded to bucket '{bucket_name}'")
+ # perform desired operations with the uploaded file
+ print(f"File '{object_key}' was uploaded to bucket '{bucket_name}'")
- # example: send a notification via sns
- sns_client=boto3.client('sns')
- topic_arn='arn:aws:sns:us-east-1::s3-lambda-sns'
- sns_client.publish(
- TopicArn=topic_arn,
- Subject='s3 object created !!',
- Message=f"File '{object_key}' was uploaded to bucket '{bucket_name}"
- )
+ # example: send a notification via SNS
+ sns_client = boto3.client('sns')
+ topic_arn = 'arn:aws:sns:us-east-1::s3-lambda-sns'
+ sns_client.publish(
+ TopicArn=topic_arn,
+ Subject='s3 object created !!',
+ Message=f"File '{object_key}' was uploaded to bucket '{bucket_name}'"
+ )
- # Example: Trigger another Lambda function
- # lambda_client = boto3.client('lambda')
- # target_function_name = 'my-another-lambda-function'
- # lambda_client.invoke(
- # FunctionName=target_function_name,
- # InvocationType='Event',
- # Payload=json.dumps({'bucket_name': bucket_name, 'object_key': object_key})
- # )
- # in case of queuing and other objective similar to the netflix flow of triggering
+ # Example: Trigger another Lambda function
+ # lambda_client = boto3.client('lambda')
+ # target_function_name = 'my-another-lambda-function'
+ # lambda_client.invoke(
+ # FunctionName=target_function_name,
+ # InvocationType='Event',
+ # Payload=json.dumps({'bucket_name': bucket_name, 'object_key': object_key})
+ # )
+ # in case of queuing and other objectives similar to the Netflix flow of triggering
- return {
- 'statusCode': 200,
- 'body': json.dumps("Lambda function executed successfully !!")
- }
+ return {
+ 'statusCode': 200,
+ 'body': json.dumps("Lambda function executed successfully !!")
+ }
diff --git a/scripts/question_utils.py b/scripts/question_utils.py
index 765ad91cb..a51fc3304 100644
--- a/scripts/question_utils.py
+++ b/scripts/question_utils.py
@@ -7,66 +7,50 @@
from typing import List
import re
-p = pathlib.Path(__file__).parent.parent.joinpath("README.md")
-
-
-def get_file_list():
- file_list = ""
- with open(p, "rb") as f:
- for line in f.readlines():
- file_list += line.rstrip().decode()
- return file_list
-
-
-def get_question_list(file_list: List[str]) -> list:
- file_list = re.findall("(.*?) ", file_list)
- questions_list = []
- for i in file_list:
- q = re.findall(r"(.*?)", i)[0]
- questions_list.append(q)
- return questions_list
-
-
-def get_answered_questions(question_list: List[str]) -> list:
- t = []
- question_list = re.findall("(.*?) ", question_list)
- for i in question_list:
- q = re.findall(r"(.*?)", i)
- if q and q[0] == "":
- continue
- a = re.findall(r"(.*?)", i)
- if a and a[0] == "":
- continue
- else:
- t.append(q[0])
- return t
-
-
-def get_answers_count() -> List:
- """
- Return [answer_questions,all_questions] ,PASS complete. FAIL incomplete.
- >>> get_answers_count()
- [463, 463]
- """
- ans_questions = get_answered_questions(get_file_list())
- len_ans_questions = len(ans_questions)
- all_questions = get_question_list(get_file_list())
- len_all_questions = len(all_questions)
- return [len_ans_questions, len_all_questions]
+README_PATH = pathlib.Path(__file__).parent.parent / "README.md"
+EXERCISES_PATH = pathlib.Path(__file__).parent.parent / "exercises"
+
+DETAILS_PATTERN = re.compile(r"(.*?) ", re.DOTALL)
+SUMMARY_PATTERN = re.compile(r"(.*?)", re.DOTALL)
+B_PATTERN = re.compile(r"(.*?)", re.DOTALL)
+
+
+def get_file_content() -> str:
+ with README_PATH.open("r", encoding="utf-8") as f:
+ return f.read()
+
+
+def get_question_list(file_content: str) -> List[str]:
+ details = DETAILS_PATTERN.findall(file_content)
+ return [SUMMARY_PATTERN.search(detail).group(1) for detail in details if SUMMARY_PATTERN.search(detail)]
+
+
+def get_answered_questions(file_content: str) -> List[str]:
+ details = DETAILS_PATTERN.findall(file_content)
+ answered = []
+ for detail in details:
+ summary_match = SUMMARY_PATTERN.search(detail)
+ b_match = B_PATTERN.search(detail)
+ if summary_match and b_match and summary_match.group(1).strip() and b_match.group(1).strip():
+ answered.append(summary_match.group(1))
+ return answered
+
+
+def get_answers_count() -> List[int]:
+ file_content = get_file_content()
+ answered = get_answered_questions(file_content)
+ all_questions = get_question_list(file_content)
+ return [len(answered), len(all_questions)]
def get_challenges_count() -> int:
- challenges_path = (
- pathlib.Path(__file__).parent.parent.joinpath("exercises").glob("*.md")
- )
- return len(list(challenges_path))
+ return len(list(EXERCISES_PATH.glob("*.md")))
-# WIP WAITING FEEDBACK
-def get_random_question(question_list: List[str], with_answer=False):
+def get_random_question(question_list: List[str], with_answer: bool = False) -> str:
if with_answer:
- return choice(get_answered_questions(question_list))
- return choice(get_question_list(question_list))
+ return choice(get_answered_questions(get_file_content()))
+ return choice(get_question_list(get_file_content()))
"""Use this question_list. Unless you have already opened/worked/need the file, then don't or
@@ -74,7 +58,7 @@ def get_random_question(question_list: List[str], with_answer=False):
eg:
#my_dir/main.py
from scripts import question_utils
-print(question_utils.get_answered_questions(question_utils.question_list)
+print(question_utils.get_answered_questions(question_utils.get_question_list(question_utils.get_file_content()))
>> 123
# noqa: E501
"""
@@ -83,7 +67,3 @@ def get_random_question(question_list: List[str], with_answer=False):
import doctest
doctest.testmod()
- # print(get_question_list(get_file_list()))
- # print(get_answered_questions(get_file_list()))
- # print(get_random_question(get_file_list(),True))
- # print(get_random_question(get_file_list(),False))
diff --git a/scripts/run_ci.sh b/scripts/run_ci.sh
index 29e7b96c1..98dfbbbdc 100755
--- a/scripts/run_ci.sh
+++ b/scripts/run_ci.sh
@@ -2,14 +2,18 @@
set -euo pipefail
-PROJECT_DIR="$(dirname $(readlink -f ${BASH_SOURCE[0]}))/.."
+PROJECT_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")/.."
-MD_FILES=$(find ${PROJECT_DIR} -name "*.md" -not -path "${PROJECT_DIR}/tests/*")
-
-for file in ${MD_FILES[@]}; do
- python ${PROJECT_DIR}/tests/syntax_lint.py ${file} > /dev/null
+# Use the `-print0` option to handle spaces safely, and while-read loop:
+find "${PROJECT_DIR}" \
+ -name "*.md" \
+ -not -path "${PROJECT_DIR}/tests/*" \
+ -print0 |
+while IFS= read -r -d '' file
+do
+ python "${PROJECT_DIR}/tests/syntax_lint.py" "${file}" > /dev/null
done
echo "- Syntax lint tests on MD files passed successfully"
-flake8 --max-line-length=100 . && echo "- PEP8 Passed"
\ No newline at end of file
+flake8 --max-line-length=100 . && echo "- PEP8 Passed"
diff --git a/topics/ansible/README.md b/topics/ansible/README.md
index e8f85ef86..315f5c8b5 100644
--- a/topics/ansible/README.md
+++ b/topics/ansible/README.md
@@ -421,10 +421,6 @@ def cap(self, string):
What are callback plugins? What can you achieve by using callback plugins?
-
-What is Ansible Collections?
-
-
What is the difference between `include_task` and `import_task`?
@@ -530,6 +526,16 @@ It's used to rapidy develop and test Ansbile roles. Molecule can be used to tes
What are collections in Ansible?
+Ansible Collections are a way to package and distribute modules, roles, plugins, and documentation in a structured format. They help organize and distribute automation code efficiently, especially for complex environments.
+
+
+
+Why Use Ansible Collections?
+
+ - Modular and reusable components
+ - Simplifies management of custom and third-party modules
+ - Provides a standardized way to distribute automation content
+ - Helps in version control and dependency management
diff --git a/topics/argo/README.md b/topics/argo/README.md
index ccafea056..8655cd86a 100644
--- a/topics/argo/README.md
+++ b/topics/argo/README.md
@@ -308,7 +308,9 @@ So instead of creating multiple separate applications, you have the root applica
* Cluster Preparation: You would like to deploy multiple applications at once to bootstrap a Kubernetes cluster
-TODO: add more :)
+* Multiple environments: If deploying many versions of the same application, but with minor changes. For example, several test deployments to test different features
+
+* Multiple clusters: when the same application needs to be deployed across multiple K8s clusters connected to ArgoCD
@@ -507,4 +509,4 @@ It's an Analysis resource that fetches response status from Prometheus (monitori
`kubectl argo rollouts get rollout SOME-APP --watch`
-
\ No newline at end of file
+
diff --git a/topics/linux/README.md b/topics/linux/README.md
index ebde22e0f..91696aae7 100644
--- a/topics/linux/README.md
+++ b/topics/linux/README.md
@@ -2249,6 +2249,14 @@ $OLDPWD
How to count the number of lines in a file? What about words?
+
+For these we can use `wc` command.
+
+1. To count the number of lines in file
+```wc -l```
+
+2. To count the number of words in file
+```wc -w```