
tknp = """
def binary_search(a, target):
    l, r = 0, len(a) - 1
    while l <= r:
        mid = (l + r) // 2
        if a[mid] == target: return mid
        if a[mid] < target: l = mid + 1
        else: r = mid - 1
    return -1
"""

lam_tron_so = """
def lam_tron_so(so_dau_vao):
  # Sử dụng f-string với định dạng :.2f
  # .2f nghĩa là format số float (f) với 2 chữ số sau dấu thập phân (.)
  return f"{so_dau_vao:.2f}"
"""
#Tên hàm: doc_file
doc_file = """
def doc_file(duong_dan_file):
    try:
        with open(duong_dan_file, 'r', encoding='utf-8') as file:
            noi_dung = file.read()
        return noi_dung
    except FileNotFoundError:
        return "Lỗi: Không tìm thấy file tại đường dẫn đã cho."
    except Exception as e:
        return f"Lỗi không xác định khi đọc file: {e}"
"""
#Tên hàm: tim_bcnn
tim_bcnn = """
def tim_ucln(a, b):
    # Hàm UCLN (dựa trên thuật toán Euclid) được nhúng để sử dụng
    a = abs(a)
    b = abs(b)
    while b:
        a, b = b, a % b
    return a

def tim_bcnn(a, b):
    if a == 0 or b == 0:
        # BCNN của bất kỳ số nào với 0 là 0
        return 0
    
    # Tính UCLN
    ucln = tim_ucln(a, b)
    
    # Tính BCNN theo công thức
    # Lấy giá trị tuyệt đối của tích và chia cho UCLN
    bcnn = abs(a * b) // ucln
    
    return bcnn
"""
#Tên hàm: tim_vi_tri

tim_vi_tri = """
def tim_vi_tri(ma_tran, N):
    # Lặp qua từng hàng (row_index)
    for i, hang in enumerate(ma_tran):
        try:
            # Tìm vị trí cột (col_index) của N trong hàng hiện tại
            j = hang.index(N)
            return i, j  # Trả về (hàng, cột) ngay khi tìm thấy
        except ValueError:
            # Nếu N không có trong hàng hiện tại, tiếp tục sang hàng kế tiếp
            continue
    
    # Nếu vòng lặp kết thúc mà không tìm thấy
    return -1, -1
"""

thuat_toan_tham_lam = """
def thuat_toan_tham_lam(jobs):
    jobs.sort(key=lambda x: x[1])
    
    selected_jobs = []
    end_time = 0 # Thời gian kết thúc của công việc được chọn gần nhất
    
    for start, finish in jobs:
        # Nếu thời gian bắt đầu của công việc hiện tại (start)
        # Lớn hơn hoặc bằng thời gian kết thúc của công việc đã chọn trước đó (end_time)
        if start >= end_time:
            # Chọn công việc này
            selected_jobs.append((start, finish))
            # Cập nhật thời gian kết thúc mới
            end_time = finish
            
    return selected_jobs
"""
#Tên hàm: giai_bai_que_tinh
giai_bai_que_tinh = """
def giai_bai_que_tinh(n):
    n = int(n)
    
    # 1. Tính MAX S: Tổng bình phương các số từ 1 đến n
    # Công thức: n*(n+1)*(2n+1)/6
    max_s = (n * (n + 1) * (2 * n + 1)) // 6
    
    # 2. Tính MIN S: Tổng tích của dãy tăng dần nhân dãy giảm dần
    # Công thức rút gọn: n*(n+1)*(n+2)/6
    min_s = (n * (n + 1) * (n + 2)) // 6
    
    return f"{max_s} {min_s}"
"""    
#Tên hàm: tim_ucln
ucln = """
def ucln(a, b):
    # Xử lý trường hợp số âm hoặc số không hợp lệ nếu cần, 
    # nhưng thường UCLN được định nghĩa cho số dương. 
    # Ta sẽ làm việc với giá trị tuyệt đối để đảm bảo thuật toán hoạt động.
    a = abs(a)
    b = abs(b)

    # Thuật toán Euclid
    while b:
        # Gán a thành b, và b thành phần dư của a chia b
        a, b = b, a % b
        
    # Khi b = 0, giá trị cuối cùng của a chính là UCLN
    return a
"""
sapxep = """
def quicksort(a):
    if len(a) <= 1: return a
    pivot = a[len(a)//2]
    left  = [x for x in a if x < pivot]
    mid   = [x for x in a if x == pivot]
    right = [x for x in a if x > pivot]
    return quicksort(left) + mid + quicksort(right)
"""

snt = """
def eratosthenes(n):
    isprime = [True]*(n+1)
    isprime[0] = isprime[1] = False
    for i in range(2, int(n**0.5)+1):
        if isprime[i]:
            for j in range(i*i, n+1, i):
                isprime[j] = False
    return [i for i in range(n+1) if isprime[i]]
"""

bfs = """
from collections import deque

def bfs_shortest(grid, start, end):
    rows, cols = len(grid), len(grid[0])
    q = deque([(start[0], start[1], 0)])
    visited = set([start])

    while q:
        r, c, d = q.popleft()
        if (r, c) == end: return d
        
        for dr, dc in [(1,0),(-1,0),(0,1),(0,-1)]:
            nr, nc = r + dr, c + dc
            if 0 <= nr < rows and 0 <= nc < cols and (nr,nc) not in visited and grid[nr][nc] == 0:
                visited.add((nr,nc))
                q.append((nr,nc,d+1))
    return -1
"""

loang = """
def count_oil_spills(matrix):
    """
    Đếm số lượng vùng dầu loang độc lập trong ma trận, 
    sử dụng thuật toán DFS với 8 hướng kết nối.
    """
    if not matrix or not matrix[0]:
        return 0

    rows = len(matrix)
    cols = len(matrix[0])
    count = 0

    # 8 hướng di chuyển: (lên, xuống, trái, phải, chéo trên trái/phải, chéo dưới trái/phải)
    directions = [
        (-1, 0), (1, 0), (0, -1), (0, 1), 
        (-1, -1), (-1, 1), (1, -1), (1, 1)
    ]

    def is_valid(r, c):
        """Kiểm tra xem (r, c) có nằm trong ma trận hay không."""
        return 0 <= r < rows and 0 <= c < cols

    def dfs(r, c):
        """
        Thực hiện tìm kiếm theo chiều sâu, đánh dấu tất cả các ô dầu loang 
        kết nối với (r, c) là đã được thăm (bằng cách đổi thành 0).
        """
        # Đánh dấu ô hiện tại là đã thăm
        matrix[r][c] = 0

        # Thăm các ô kề theo 8 hướng
        for dr, dc in directions:
            new_r, new_c = r + dr, c + dc
            
            # Nếu ô mới hợp lệ và là dầu loang (1)
            if is_valid(new_r, new_c) and matrix[new_r][new_c] == 1:
                dfs(new_r, new_c)

    # Duyệt qua toàn bộ ma trận
    for r in range(rows):
        for c in range(cols):
            # Nếu tìm thấy một ô dầu loang chưa được thăm (giá trị là 1)
            if matrix[r][c] == 1:
                count += 1      # Tăng số lượng vùng dầu loang
                dfs(r, c)       # Bắt đầu loang để đánh dấu toàn bộ vùng này

    return count

# Dữ liệu đầu vào của bạn
matrix_input = [
    [1,1,1,0],
    [0,0,0,1],
    [1,1,0,0],
    [0,0,0,0],
    [1,1,1,0]
]

# Lưu ý: Hàm sẽ thay đổi ma trận gốc. Nếu muốn giữ ma trận gốc, bạn nên copy nó trước khi gọi hàm.
# matrix_copy = [row[:] for row in matrix_input]

result = count_oil_spills(matrix_input)
print(f"Số lượng vùng dầu loang độc lập là: {result}")

"""
#Tên hàm: tinh_tong_1_den_n
tinh_tong_1_den_n = """
def tinh_tong_1_den_n(n):
    # Công thức Gauss: n * (n + 1) / 2
    # Sử dụng phép chia lấy nguyên (//) để kết quả là số nguyên (int)
    return (n * (n + 1)) // 2
"""
#Tên hàm: tim_mode
tim_mode = """
from collections import Counter
def tim_mode(danh_sach_so):
    if not danh_sach_so:
        return None # Trả về None nếu danh sách rỗng

    # 1. Đếm tần suất sử dụng Counter
    tan_suat = Counter(danh_sach_so)
    
    # 2. Tìm phần tử có tần suất cao nhất
    # most_common(1) trả về list chứa 1 tuple: [(phần tử, số lần xuất hiện)]
    # [0] để lấy tuple đầu tiên, [0] tiếp theo để lấy phần tử (số)
    mode = tan_suat.most_common(1)[0][0]
    
    return mode
"""
dp = """
def longest_increasing_subsequence(a):
    n = len(a)
    dp = [1]*n
    for i in range(n):
        for j in range(i):
            if a[j] < a[i]:
                dp[i] = max(dp[i], dp[j] + 1)
    return max(dp)
"""

matran = """
def read_matrix_from_file(path):
    matrix = []
    with open(path, "r") as f:
        for line in f:
            nums = list(map(int, line.strip().split()))
            matrix.append(nums)
    return matrix
"""
allcmd = """
def allcmd():
    return "tknp, lam_tron_so, doc_file, tim_bcnn, tim_vi_tri, thuat_toan_tham_lam, giai_bai_que_tinh, ucln, sapxep, snt, bfs, loang, tinh_tong_1_den_n, tim_mode, dp, matran"
"""
__all__ = [
    "allcmd",
    "tknp",
    "lam_tron_so",
    "doc_file",
    "tim_bcnn",
    "tim_vi_tri",
    "thuat_toan_tham_lam",
    "giai_bai_que_tinh",
    "ucln",
    "sapxep",
    "snt",
    "bfs",
    "loang",
    "tinh_tong_1_den_n",
    "tim_mode",
    "dp",
    "matran"
]
