diff --git a/tasks/easy/arrays/matrix_sums_equality.toml b/tasks/easy/arrays/matrix_sums_equality.toml new file mode 100644 index 0000000..4da5a76 --- /dev/null +++ b/tasks/easy/arrays/matrix_sums_equality.toml @@ -0,0 +1,185 @@ +level = "easy" +name = "matrix_sums_equality" +tags = ["math", "arrays", "matrix"] +time_to_solve_sec = 250 + +description_en = """ +Given a $3 \times 3$ matrix of integers, determine if the sum of elements in every row and every column is the same. Return `true` if all sums are equal, otherwise return `false`. +""" + +description_ru = """ +Дана матрица $3 \times 3$, состоящая из целых чисел. Проверьте, равны ли суммы чисел во всех строках и всех столбцах. Верните `true`, если все суммы равны, иначе — `false`. +""" + +limits = """ +- $\text{len}(m) = 3$ +- $\text{len}(m[i]) = 3$ +- $-10^6 \leq m_{i,j} \leq 10^6$ +""" + +solution = """ +def solution(m: list) -> bool: + s = {sum(r) for r in m} | {sum(c) for c in zip(*m)} + return len(s) == 1 +""" + +examples = """ +solution([[1, 1, 1], [1, 1, 1], [1, 1, 1]]) == True +solution([[8, 1, 6], [3, 5, 7], [4, 9, 2]]) == True +solution([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) == False +""" + +[[input_signature]] +argument_name = "m" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "array" +[input_signature.type.nested.nested] +name = "integer" + +[output_signature.type] +name = "boolean" + +[[asserts]] +arguments = [[[1, 1, 1], [1, 1, 1], [1, 1, 1]]] +comment = "All identical elements" +expected = true + +[[asserts]] +arguments = [[[8, 1, 6], [3, 5, 7], [4, 9, 2]]] +comment = "Classic 3x3 magic square (sum 15)" +expected = true + +[[asserts]] +arguments = [[[1, 2, 3], [4, 5, 6], [7, 8, 9]]] +comment = "Arithmetic progression (sums differ)" +expected = false + +[[asserts]] +arguments = [[[0, 0, 0], [0, 0, 0], [0, 0, 0]]] +comment = "All zeros" +expected = true + +[[asserts]] +arguments = [[[2, 7, 6], [9, 5, 1], [4, 3, 8]]] +comment = "Another magic square orientation" +expected = true + +[[asserts]] +arguments = [[[1, 2, 1], [2, 1, 1], [1, 1, 2]]] +comment = "Rows sum to 4, columns sum to 4" +expected = true + +[[asserts]] +arguments = [[[-1, 1, 0], [1, -1, 0], [0, 0, 0]]] +comment = "Negative numbers summing to zero" +expected = true + +[[asserts]] +arguments = [[[10, 20, 30], [30, 10, 20], [20, 30, 10]]] +comment = "Permutations of same numbers" +expected = true + +[[asserts]] +arguments = [[[1, 2, 3], [1, 2, 3], [1, 2, 3]]] +comment = "Row sums equal, but column sums differ" +expected = false + +[[asserts]] +arguments = [[[1, 1, 1], [2, 2, 2], [3, 3, 3]]] +comment = "Column sums equal, but row sums differ" +expected = false + +[[asserts]] +arguments = [[[4, 9, 2], [3, 5, 7], [8, 1, 6]]] +comment = "Reflected magic square" +expected = true + +[[asserts]] +arguments = [[[100, 0, 0], [0, 100, 0], [0, 0, 100]]] +comment = "Identity-like matrix (sums differ)" +expected = false + +[[asserts]] +arguments = [[[5, 5, 5], [5, 5, 5], [5, 5, 4]]] +comment = "One element difference" +expected = false + +[[asserts]] +arguments = [[[7, 0, 0], [0, 7, 0], [0, 0, 7]]] +comment = "Diagonal matrix with same values" +expected = false + +[[asserts]] +arguments = [[[1, 1, 4], [4, 1, 1], [1, 4, 1]]] +comment = "Sums are all 6" +expected = true + +[[asserts]] +arguments = [[[0, 5, -5], [-5, 0, 5], [5, -5, 0]]] +comment = "Zero sums with negative values" +expected = true + +[[asserts]] +arguments = [[[10, 10, 10], [10, 10, 10], [10, 10, 11]]] +comment = "Almost equal" +expected = false + +[[asserts]] +arguments = [[[1, 2, 3], [3, 2, 1], [2, 2, 2]]] +comment = "Rows sum to 6, columns sum to 6" +expected = true + +[[asserts]] +arguments = [[[1000000, 0, 0], [0, 1000000, 0], [0, 0, 1000000]]] +comment = "Large values, unequal sums" +expected = false + +[[asserts]] +arguments = [[[50, 50, 50], [50, 50, 50], [50, 50, 50]]] +comment = "Large identical values" +expected = true + +[[asserts]] +arguments = [[[1, 0, 0], [0, 1, 0], [0, 0, 1]]] +comment = "Standard identity matrix" +expected = false + +[[asserts]] +arguments = [[[2, 2, 2], [2, 2, 2], [2, 2, 2]]] +expected = true + +[[asserts]] +arguments = [[[1, 2, 1], [1, 2, 1], [1, 2, 1]]] +expected = false + +[[asserts]] +arguments = [[[3, 3, 3], [3, 3, 3], [3, 3, 2]]] +expected = false + +[[asserts]] +arguments = [[[9, 9, 9], [9, 9, 9], [9, 9, 9]]] +expected = true + +[[asserts]] +arguments = [[[6, 1, 8], [7, 5, 3], [2, 9, 4]]] +comment = "Valid magic square" +expected = true + +[[asserts]] +arguments = [[[1, 1, 1], [1, 1, 1], [1, 1, 0]]] +expected = false + +[[asserts]] +arguments = [[[-5, -5, -5], [-5, -5, -5], [-5, -5, -5]]] +expected = true + +[[asserts]] +arguments = [[[1, 4, 7], [2, 5, 8], [3, 6, 9]]] +expected = false + +[[asserts]] +arguments = [[[3, 1, 5], [1, 5, 3], [5, 3, 1]]] +comment = "Row and column sums equal 9" +expected = true \ No newline at end of file diff --git a/tasks/easy/arrays/palindrome_by_removing_one.toml b/tasks/easy/arrays/palindrome_by_removing_one.toml new file mode 100644 index 0000000..812c461 --- /dev/null +++ b/tasks/easy/arrays/palindrome_by_removing_one.toml @@ -0,0 +1,199 @@ +level = "easy" +name = "palindrome_by_removing_one" +tags = ["arrays", "algorithms"] +time_to_solve_sec = 240 + +description_en = """ +Given an array of integers `arr`, determine if it is possible to make it a palindrome by removing **exactly one** element. + +An array is a palindrome if it reads the same forwards and backwards. +""" + +description_ru = """ +Дан массив целых чисел `arr`. Определите, можно ли сделать его палиндромом, удалив **ровно один** элемент. + +Массив является палиндромом, если он читается одинаково как слева направо, так и справа налево. +""" + +limits = """ +- $1 \\leq \\text{len}(arr) \\leq 10^5$ +- $0 \\leq arr[i] \\leq 10^9$ +""" + +solution = """ +def solution(arr: list) -> bool: + l, r = 0, len(arr) - 1 + while l < r: + if arr[l] != arr[r]: + s1, s2 = arr[l+1:r+1], arr[l:r] + return s1 == s1[::-1] or s2 == s2[::-1] + l, r = l + 1, r - 1 + return True +""" + +examples = """ +solution([1, 2, 3]) == False +solution([1, 2, 1]) == True +solution([1, 2, 3, 1]) == True +solution([1, 2, 3, 2, 1]) == True +""" + +[[input_signature]] +argument_name = "arr" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "integer" + +[output_signature.type] +name = "boolean" + +[[asserts]] +arguments = [[1, 2, 1]] +comment = "Already a palindrome, removing middle works" +expected = true + +[[asserts]] +arguments = [[1, 2, 3]] +comment = "No single removal makes it a palindrome" +expected = false + +[[asserts]] +arguments = [[1, 2, 3, 1]] +comment = "Remove 2 or 3" +expected = true + +[[asserts]] +arguments = [[1, 1]] +comment = "Remove one, single element is palindrome" +expected = true + +[[asserts]] +arguments = [[1]] +comment = "Remove only element, empty is palindrome" +expected = true + +[[asserts]] +arguments = [[1, 2, 3, 2, 1]] +comment = "Already palindrome" +expected = true + +[[asserts]] +arguments = [[1, 2, 3, 4, 2, 1]] +comment = "Remove 3 or 4" +expected = true + +[[asserts]] +arguments = [[10, 20, 30, 40]] +comment = "Four distinct elements" +expected = false + +[[asserts]] +arguments = [[1, 1, 2, 1]] +comment = "Remove 2" +expected = true + +[[asserts]] +arguments = [[1, 2, 1, 1]] +comment = "Remove 2" +expected = true + +[[asserts]] +arguments = [[2, 1, 1, 1]] +comment = "Remove 2" +expected = true + +[[asserts]] +arguments = [[1, 1, 1, 2]] +comment = "Remove 2" +expected = true + +[[asserts]] +arguments = [[1, 2, 3, 4, 3, 2, 1]] +comment = "Odd length palindrome" +expected = true + +[[asserts]] +arguments = [[1, 2, 3, 4, 4, 3, 2, 1]] +comment = "Even length palindrome" +expected = true + +[[asserts]] +arguments = [[1, 2, 3, 5, 4, 3, 2, 1]] +comment = "Remove 5 or 4" +expected = true + +[[asserts]] +arguments = [[1, 2, 3, 1, 2, 3]] +comment = "Repeated sequence" +expected = false + +[[asserts]] +arguments = [[100, 200, 300, 200, 100]] +comment = "Large values" +expected = true + +[[asserts]] +arguments = [[5, 5, 6, 5]] +comment = "Triple and one different" +expected = true + +[[asserts]] +arguments = [[1, 2, 3, 4, 5, 6, 7]] +comment = "Sequential" +expected = false + +[[asserts]] +arguments = [[9, 8, 7, 8, 9, 10]] +comment = "Remove 10" +expected = true + +[[asserts]] +arguments = [[10, 9, 8, 7, 8, 9]] +comment = "Remove 10" +expected = true + +[[asserts]] +arguments = [[1, 2, 1, 3, 1, 2, 1]] +comment = "Remove 3" +expected = true + +[[asserts]] +arguments = [[1, 2, 3, 2, 1, 4, 5]] +comment = "Too many extra elements" +expected = false + +[[asserts]] +arguments = [[1, 1, 1, 1, 1]] +comment = "All same" +expected = true + +[[asserts]] +arguments = [[1, 2, 1, 2, 1, 2]] +comment = "Alternating" +expected = false + +[[asserts]] +arguments = [[4, 3, 2, 1, 2, 3, 4]] +comment = "Large palindrome" +expected = true + +[[asserts]] +arguments = [[1, 2, 3, 4, 5, 4, 3, 2, 1]] +comment = "Classic case" +expected = true + +[[asserts]] +arguments = [[1, 2, 3, 0, 3, 2, 1]] +comment = "Middle zero" +expected = true + +[[asserts]] +arguments = [[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]] +comment = "Double sequence" +expected = false + +[[asserts]] +arguments = [[0, 0, 1, 0]] +comment = "Zeros and one" +expected = true \ No newline at end of file diff --git a/tasks/easy/greedy/autobattler_squad.toml b/tasks/easy/greedy/autobattler_squad.toml new file mode 100644 index 0000000..27e2823 --- /dev/null +++ b/tasks/easy/greedy/autobattler_squad.toml @@ -0,0 +1,226 @@ +level = "easy" +name = "autobattler_squad" +tags = ["math", "greedy", "logic"] +time_to_solve_sec = 240 + +description_en = """ +In the game Autobattler, players form a squad by purchasing warriors from a shop. + +The upgrade system works as follows: +- $3$ **normal** warriors automatically convert into $1$ **upgraded** warrior. +- $3$ **upgraded** warriors automatically convert into $1$ **best** warrior. + +Each unit type has a specific strength value: +- **Normal**: $1$ +- **Upgraded**: $4$ +- **Best**: $16$ + +You have purchased $n$ normal warriors. However, you can only field a squad of at most $k$ warriors of any quality. + +Determine the maximum possible total strength of your squad. +""" + +description_ru = """ +В игре Autobattler каждый игрок формирует свой отряд, покупая воинов из магазина. + +Система улучшений работает следующим образом: +- $3$ **обычных** воина преобразуются в $1$ **усиленного** воина. +- $3$ **усиленных** воина преобразуются в $1$ **лучшего** воина. + +Каждый тип юнита имеет определенную силу: +- **Обычный**: $1$ +- **Усиленный**: $4$ +- **Лучший**: $16$ + +Вы купили $n$ обычных воинов. Однако в отряд можно выставить не более $k$ воинов любого качества. + +Определите максимальную суммарную силу отряда, который вы сможете сформировать. +""" + +limits = """ +- $0 \\leq n \\leq 10^9$ +- $0 \\leq k \\leq 10^9$ +""" + +solution = """ +def solution(n: int, k: int) -> int: + u, r_n = divmod(n, 3) + b, r_u = divmod(u, 3) + score = 0 + for count, power in [(b, 16), (r_u, 4), (r_n, 1)]: + take = min(count, k) + score += take * power + k -= take + return score +""" + +examples = """ +solution(1, 1) == 1 +solution(3, 1) == 4 +solution(9, 1) == 16 +solution(10, 2) == 17 +solution(25, 10) == 41 +""" + +[[input_signature]] +argument_name = "n" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "k" +[input_signature.type] +name = "integer" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [0, 5] +comment = "No warriors bought" +expected = 0 + +[[asserts]] +arguments = [5, 0] +comment = "No space in squad" +expected = 0 + +[[asserts]] +arguments = [1, 1] +comment = "One normal warrior" +expected = 1 + +[[asserts]] +arguments = [2, 1] +comment = "Two normal, squad limit one" +expected = 1 + +[[asserts]] +arguments = [3, 1] +comment = "Three normal become one upgraded" +expected = 4 + +[[asserts]] +arguments = [3, 3] +comment = "Space for three, but they merged into one" +expected = 4 + +[[asserts]] +arguments = [4, 1] +comment = "One upgraded and one normal, pick upgraded" +expected = 4 + +[[asserts]] +arguments = [4, 2] +comment = "One upgraded and one normal, take both" +expected = 5 + +[[asserts]] +arguments = [8, 2] +comment = "Two upgraded and two normal, squad limit two" +expected = 8 + +[[asserts]] +arguments = [9, 1] +comment = "Nine normal become three upgraded, then one best" +expected = 16 + +[[asserts]] +arguments = [10, 1] +comment = "One best and one normal, pick best" +expected = 16 + +[[asserts]] +arguments = [10, 2] +comment = "One best and one normal, take both" +expected = 17 + +[[asserts]] +arguments = [25, 1] +comment = "Pick one best from the collection" +expected = 16 + +[[asserts]] +arguments = [25, 10] +comment = "Large squad limit, take everything available" +expected = 41 + +[[asserts]] +arguments = [26, 2] +comment = "Two best available, squad limit two" +expected = 32 + +[[asserts]] +arguments = [27, 1] +comment = "Exactly enough for one best warrior" +expected = 16 + +[[asserts]] +arguments = [27, 3] +comment = "Still only one best warrior available" +expected = 16 + +[[asserts]] +arguments = [30, 2] +comment = "One best and one upgraded" +expected = 20 + +[[asserts]] +arguments = [50, 5] +comment = "Mix of tiers: 1 best, 5 upgraded, 2 normal" +expected = 32 + +[[asserts]] +arguments = [80, 2] +comment = "Two best warriors" +expected = 32 + +[[asserts]] +arguments = [81, 3] +comment = "Exactly three best warriors" +expected = 48 + +[[asserts]] +arguments = [100, 5] +comment = "High n, limited k" +expected = 80 + +[[asserts]] +arguments = [1000, 10] +comment = "Large n, take 10 best" +expected = 160 + +[[asserts]] +arguments = [123, 456] +comment = "k is larger than total units available" +expected = 83 + +[[asserts]] +arguments = [1000000, 100] +comment = "Extreme values: n = 10^6" +expected = 1600 + +[[asserts]] +arguments = [1000000000, 1] +comment = "Extreme values: n = 10^9, k = 1" +expected = 16 + +[[asserts]] +arguments = [9, 0] +comment = "No squad space" +expected = 0 + +[[asserts]] +arguments = [2, 10] +comment = "Two normal warriors, plenty of space" +expected = 2 + +[[asserts]] +arguments = [13, 2] +comment = "1 best, 1 upgraded, 1 normal. Limit 2" +expected = 20 + +[[asserts]] +arguments = [40, 40] +comment = "Take all: 1 best, 4 upgraded, 1 normal" +expected = 33 \ No newline at end of file diff --git a/tasks/easy/greedy/lecture_hall_schedule.toml b/tasks/easy/greedy/lecture_hall_schedule.toml new file mode 100644 index 0000000..14c03a5 --- /dev/null +++ b/tasks/easy/greedy/lecture_hall_schedule.toml @@ -0,0 +1,187 @@ +level = "easy" +name = "lecture_hall_schedule" +tags = ["greedy", "sorting", "intervals", "arrays"] +time_to_solve_sec = 250 + +description_en = """ +You are given a lecture hall where several professors want to give their lectures. To make a schedule, professors submitted requests represented as an array of two integers `[start, end]`, denoting the start time and end time of the lecture. + +Lectures are half-open intervals `[start, end)`, meaning a new lecture can start at the exact moment another one finishes without a break. + +Determine the **maximum** number of requests that can be fulfilled without any overlaps. +""" + +description_ru = """ +Дана лекционная аудитория, в которой несколько профессоров хотят прочесть свои лекции. Для составления расписания профессора подали заявки, каждая из которых представлена массивом из двух целых чисел `[start, end]`, обозначающих время начала и конца лекции. + +Лекция считается открытым полуинтервалом `[start, end)`, то есть какая-то лекция может начаться ровно в момент окончания другой, без перерыва. + +Составьте расписание занятий так, чтобы выполнить **максимальное** количество заявок. +""" + +limits = """ +- $0 \\leq \\text{len}(\\text{requests}) \\leq 10^5$ +- $0 \\leq \\text{start} < \\text{end} \\leq 10^9$ +""" + +solution = """ +def solution(requests: list) -> int: + count = end_time = 0 + for s, e in sorted(requests, key=lambda x: x[1]): + if s >= end_time: + count, end_time = count + 1, e + return count +""" + +examples = """ +solution([[1, 3], [2, 4], [3, 5]]) == 2 +solution([[1, 2], [2, 3], [3, 4]]) == 3 +solution([[0, 10], [1, 3], [3, 5], [5, 7], [7, 9]]) == 4 +""" + +[[input_signature]] +argument_name = "requests" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "array" +[input_signature.type.nested.nested] +name = "integer" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [[]] +comment = "Empty schedule" +expected = 0 + +[[asserts]] +arguments = [[[1, 2]]] +comment = "Single lecture" +expected = 1 + +[[asserts]] +arguments = [[[1, 2], [2, 3]]] +comment = "Two non-overlapping lectures" +expected = 2 + +[[asserts]] +arguments = [[[1, 3], [2, 4]]] +comment = "Two overlapping lectures" +expected = 1 + +[[asserts]] +arguments = [[[1, 10], [5, 6]]] +comment = "Nested lectures" +expected = 1 + +[[asserts]] +arguments = [[[1, 2], [2, 3], [3, 4]]] +comment = "Three consecutive lectures" +expected = 3 + +[[asserts]] +arguments = [[[1, 10], [2, 3], [4, 5], [6, 7]]] +comment = "One long, multiple short inside" +expected = 3 + +[[asserts]] +arguments = [[[2, 5], [2, 5], [2, 5]]] +comment = "Identical lecture requests" +expected = 1 + +[[asserts]] +arguments = [[[1, 3], [2, 4], [3, 5], [4, 6], [5, 7]]] +comment = "Interleaved lectures" +expected = 3 + +[[asserts]] +arguments = [[[0, 10], [1, 9], [2, 8], [3, 7]]] +comment = "Complete nested overlap" +expected = 1 + +[[asserts]] +arguments = [[[1, 2], [2, 3], [10, 11], [11, 12]]] +comment = "Two isolated clusters" +expected = 4 + +[[asserts]] +arguments = [[[1, 2], [1000000, 1000001]]] +comment = "Large gap between lectures" +expected = 2 + +[[asserts]] +arguments = [[[3, 4], [1, 2], [5, 6], [2, 3]]] +comment = "Unsorted continuous sequence" +expected = 4 + +[[asserts]] +arguments = [[[1, 5], [5, 10], [10, 15]]] +comment = "Touching edges" +expected = 3 + +[[asserts]] +arguments = [[[1, 2], [1, 3], [1, 4]]] +comment = "Same start time, different end times" +expected = 1 + +[[asserts]] +arguments = [[[1, 5], [2, 5], [3, 5]]] +comment = "Different start times, same end time" +expected = 1 + +[[asserts]] +arguments = [[[1, 4], [3, 6], [5, 8], [7, 10]]] +comment = "Overlapping sequence" +expected = 2 + +[[asserts]] +arguments = [[[5, 9], [1, 4], [3, 8], [0, 6], [5, 7], [6, 10], [8, 11]]] +comment = "Complex unsorted overlaps" +expected = 3 + +[[asserts]] +arguments = [[[0, 100], [10, 20], [20, 30], [30, 40], [40, 50], [50, 60]]] +comment = "Long span covering sequence" +expected = 5 + +[[asserts]] +arguments = [[[0, 1]]] +comment = "Single short element" +expected = 1 + +[[asserts]] +arguments = [[[2, 5], [1, 3], [3, 4], [4, 6]]] +comment = "Overlaps with early finish option" +expected = 3 + +[[asserts]] +arguments = [[[10, 15], [12, 17], [15, 20], [18, 22], [20, 25]]] +comment = "Chain of events with alternative overlaps" +expected = 3 + +[[asserts]] +arguments = [[[1, 5], [1, 5], [1, 5], [1, 5]]] +comment = "Same intervals repeated" +expected = 1 + +[[asserts]] +arguments = [[[5, 10], [6, 11], [7, 12], [8, 13], [9, 14], [10, 15]]] +comment = "Constantly shifting intervals" +expected = 2 + +[[asserts]] +arguments = [[[0, 1], [0, 2], [0, 3], [0, 4]]] +comment = "Multiple starts at zero" +expected = 1 + +[[asserts]] +arguments = [[[0, 100], [1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]] +comment = "Multiple small inside one extremely large" +expected = 5 + +[[asserts]] +arguments = [[[0, 10], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]] +comment = "One long, rest touching but mutually exclusive" +expected = 5 \ No newline at end of file diff --git a/tasks/easy/greedy/maximum_cars_to_finish.toml b/tasks/easy/greedy/maximum_cars_to_finish.toml new file mode 100644 index 0000000..2ad574f --- /dev/null +++ b/tasks/easy/greedy/maximum_cars_to_finish.toml @@ -0,0 +1,208 @@ +level = "easy" +name = "maximum_cars_to_finish" +tags = ["greedy", "math", "arrays"] +time_to_solve_sec = 250 + +description_en = """ +Sergey is organizing a road trip with his friends. There are $n$ cars, and each car needs exactly $x$ liters of fuel to reach the destination. The $i$-th car currently has $a_i$ liters of fuel. + +To maximize the number of cars that reach the destination, Sergey can choose any subset of cars, drain all their fuel, and redistribute it equally among them. He can repeat this process any number of times. + +Given the required fuel $x$ and the array $a$ containing the initial fuel of each car, return the maximum number of cars that can successfully reach the destination. +""" + +description_ru = """ +Сергей решил организовать автопробег с друзьями. Всего участвует $n$ автомобилей, и чтобы доехать до финиша, каждой машине требуется ровно $x$ литров топлива. Изначально в $i$-й машине находится $a_i$ литров бензина. + +Чтобы до финиша доехало как можно больше участников, Сергей может выбрать любое подмножество автомобилей, слить с них всё топливо и затем поровну распределить его между этими же машинами. Эту операцию он может применять любое количество раз. + +Учитывая необходимое количество топлива $x$ и массив $a$, описывающий начальное количество бензина в каждой машине, верните максимальное число автомобилей, которые смогут добраться до финиша. +""" + +limits = """ +- $1 \leq x \leq 10^4$ +- $1 \leq \text{len}(a) \leq 10^5$ +- $0 \leq a_i \leq 10^4$ +""" + +solution = """ +def solution(x: int, a: list) -> int: + a.sort(reverse=True) + total = 0 + for i in range(len(a)): + total += a[i] + if total < x * (i + 1): + return i + return len(a) +""" + +examples = """ +solution(10, [1, 2, 3]) == 0 +solution(4, [3, 2, 6, 2]) == 2 +solution(5, [10, 10, 10]) == 3 +""" + +[[input_signature]] +argument_name = "x" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "a" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "integer" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [4, [3, 2, 6, 2]] +comment = "Example from the description" +expected = 2 + +[[asserts]] +arguments = [5, [10, 10, 10]] +comment = "All cars have more than enough fuel" +expected = 3 + +[[asserts]] +arguments = [10, [1, 2, 3]] +comment = "No car can be fully fueled" +expected = 0 + +[[asserts]] +arguments = [10, [15, 1, 1]] +comment = "One rich car can only sustain itself" +expected = 1 + +[[asserts]] +arguments = [10, [15, 5, 1]] +comment = "Top two cars can perfectly share to get 10 each" +expected = 2 + +[[asserts]] +arguments = [1, [0, 0, 0, 0]] +comment = "Zero fuel everywhere" +expected = 0 + +[[asserts]] +arguments = [1, [1, 1, 1, 1]] +comment = "Exact required fuel for everyone" +expected = 4 + +[[asserts]] +arguments = [2, [1, 1, 1, 1]] +comment = "Total is enough for 2 cars, but impossible to combine without draining others" +expected = 0 + +[[asserts]] +arguments = [2, [4, 0, 0, 0]] +comment = "One car sustains itself and one more" +expected = 2 + +[[asserts]] +arguments = [10, [100]] +comment = "Single car with abundant fuel" +expected = 1 + +[[asserts]] +arguments = [10, [9]] +comment = "Single car without enough fuel" +expected = 0 + +[[asserts]] +arguments = [10, [10]] +comment = "Single car with exact fuel" +expected = 1 + +[[asserts]] +arguments = [3, [2, 2, 2, 6]] +comment = "All cars can be sustained" +expected = 4 + +[[asserts]] +arguments = [3, [2, 2, 2, 5]] +comment = "Three cars can be sustained" +expected = 3 + +[[asserts]] +arguments = [5, [0, 0, 0, 20]] +comment = "One car fuels everyone" +expected = 4 + +[[asserts]] +arguments = [5, [0, 0, 0, 19]] +comment = "One car falls just short of fueling everyone" +expected = 3 + +[[asserts]] +arguments = [5, [6, 4, 6, 4]] +comment = "Pairs can perfectly compensate each other" +expected = 4 + +[[asserts]] +arguments = [100, [100, 100, 100, 100]] +comment = "All cars exact high requirement" +expected = 4 + +[[asserts]] +arguments = [100, [100, 100, 100, 99]] +comment = "One car ruins the perfect group" +expected = 3 + +[[asserts]] +arguments = [7, [8, 8, 8, 2, 2]] +comment = "Top three compensate, bottom two are too poor" +expected = 3 + +[[asserts]] +arguments = [3, [5, 5, 5, 5, 5]] +comment = "Abundant fuel uniform distribution" +expected = 5 + +[[asserts]] +arguments = [5, [8, 1, 1, 1, 1, 1, 1, 1]] +comment = "Many poor cars drag down the single rich one" +expected = 1 + +[[asserts]] +arguments = [2, [3, 3, 3, 3, 3, 0]] +comment = "Five rich cars can carry one empty car" +expected = 6 + +[[asserts]] +arguments = [10, [30, 0, 0, 0]] +comment = "One car provides enough for three exactly" +expected = 3 + +[[asserts]] +arguments = [10, [29, 0, 0, 0]] +comment = "One car falls short for three, sustains two" +expected = 2 + +[[asserts]] +arguments = [4, [7, 7, 1, 1]] +comment = "Two rich cars compensate exactly for two poor cars" +expected = 4 + +[[asserts]] +arguments = [5, [7, 7, 1, 1]] +comment = "Requirement increased, cannot sustain all" +expected = 3 + +[[asserts]] +arguments = [1, [2, 0]] +comment = "Two cars, simple test" +expected = 2 + +[[asserts]] +arguments = [15, [45, 2, 3, 4, 5]] +comment = "Large surplus from one car sustains some but not all" +expected = 3 + +[[asserts]] +arguments = [10, [15, 14, 1, 1, 1]] +comment = "Multiple rich cars cooperating" +expected = 3 \ No newline at end of file diff --git a/tasks/easy/math/add_two_fractions.toml b/tasks/easy/math/add_two_fractions.toml new file mode 100644 index 0000000..e7b55d4 --- /dev/null +++ b/tasks/easy/math/add_two_fractions.toml @@ -0,0 +1,212 @@ +level = "easy" +name = "add_two_fractions" +tags = ["math", "algorithms"] +time_to_solve_sec = 200 + +description_en = """ +Given two rational fractions $a/b$ and $c/d$, calculate their sum. + +Return the result as an irreducible fraction $m/n$, represented as an array of two integers `[m, n]`. +""" + +description_ru = """ +Даны две рациональные дроби $a/b$ и $c/d$. Вычислите их сумму. + +Верните результат в виде несократимой дроби $m/n$, представленной как массив из двух целых чисел `[m, n]`. +""" + +limits = """ +- $-1000 \leq a, c \leq 1000$ +- $1 \leq b, d \leq 1000$ +""" + +solution = """ +import math + +def solution(a: int, b: int, c: int, d: int) -> list: + num = a * d + c * b + den = b * d + g = math.gcd(num, den) + return [num // g, den // g] +""" + +examples = """ +solution(1, 2, 1, 2) == [1, 1] +solution(1, 3, 1, 6) == [1, 2] +solution(2, 5, 1, 5) == [3, 5] +""" + +[[input_signature]] +argument_name = "a" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "b" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "c" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "d" +[input_signature.type] +name = "integer" + +[output_signature.type] +name = "array" +[output_signature.type.nested] +name = "integer" + +[[asserts]] +arguments = [1, 2, 1, 2] +comment = "Half plus half" +expected = [1, 1] + +[[asserts]] +arguments = [1, 3, 1, 6] +comment = "Different denominators" +expected = [1, 2] + +[[asserts]] +arguments = [2, 5, 1, 5] +comment = "Same denominator" +expected = [3, 5] + +[[asserts]] +arguments = [0, 1, 0, 1] +comment = "Zeros" +expected = [0, 1] + +[[asserts]] +arguments = [-1, 2, 1, 2] +comment = "Negative and positive cancellation" +expected = [0, 1] + +[[asserts]] +arguments = [3, 4, 5, 6] +comment = "Reduction needed" +expected = [19, 12] + +[[asserts]] +arguments = [1, 10, 1, 10] +comment = "Small fractions" +expected = [1, 5] + +[[asserts]] +arguments = [-5, 8, 7, 12] +comment = "Negative and positive with different denominators" +expected = [-1, 24] + +[[asserts]] +arguments = [1000, 1, 1000, 1] +comment = "Max values" +expected = [2000, 1] + +[[asserts]] +arguments = [-1000, 1, 1000, 1] +comment = "Max absolute values cancelling" +expected = [0, 1] + +[[asserts]] +arguments = [1, 1000, 1, 1000] +comment = "Max denominators" +expected = [1, 500] + +[[asserts]] +arguments = [7, 3, 11, 5] +comment = "Prime denominators" +expected = [68, 15] + +[[asserts]] +arguments = [0, 999, 0, 999] +comment = "Zeros with large denominators" +expected = [0, 1] + +[[asserts]] +arguments = [2, 4, 2, 4] +comment = "Reducible inputs" +expected = [1, 1] + +[[asserts]] +arguments = [5, 10, 15, 30] +comment = "Highly reducible inputs" +expected = [1, 1] + +[[asserts]] +arguments = [-1, 3, -1, 6] +comment = "Two negatives" +expected = [-1, 2] + +[[asserts]] +arguments = [100, 200, 300, 600] +comment = "Large reducible numbers" +expected = [1, 1] + +[[asserts]] +arguments = [1, 7, 2, 7] +comment = "Prime denominator same" +expected = [3, 7] + +[[asserts]] +arguments = [4, 5, -1, 5] +comment = "Negative numerator same denominator" +expected = [3, 5] + +[[asserts]] +arguments = [-3, 7, -2, 7] +comment = "Both negative same denominator" +expected = [-5, 7] + +[[asserts]] +arguments = [1, 2, -1, 4] +comment = "Mixed sign different denominator" +expected = [1, 4] + +[[asserts]] +arguments = [10, 3, 10, 3] +comment = "Improper fractions" +expected = [20, 3] + +[[asserts]] +arguments = [-5, 2, -7, 2] +comment = "Negative improper fractions" +expected = [-6, 1] + +[[asserts]] +arguments = [8, 9, 7, 9] +comment = "Result needs reduction" +expected = [5, 3] + +[[asserts]] +arguments = [11, 12, 5, 12] +comment = "Result needs reduction by 4" +expected = [4, 3] + +[[asserts]] +arguments = [1, 99, 1, 99] +comment = "No reduction possible" +expected = [2, 99] + +[[asserts]] +arguments = [99, 100, 1, 100] +comment = "Sums to 1" +expected = [1, 1] + +[[asserts]] +arguments = [1, 8, 3, 8] +comment = "Simple reduction by 4" +expected = [1, 2] + +[[asserts]] +arguments = [-1, 8, -3, 8] +comment = "Negative simple reduction" +expected = [-1, 2] + +[[asserts]] +arguments = [0, 5, 1, 5] +comment = "Zero plus fraction" +expected = [1, 5] \ No newline at end of file diff --git a/tasks/easy/math/is_armstrong_number.toml b/tasks/easy/math/is_armstrong_number.toml new file mode 100644 index 0000000..3174b18 --- /dev/null +++ b/tasks/easy/math/is_armstrong_number.toml @@ -0,0 +1,201 @@ +level = "easy" +name = "is_armstrong_number" +tags = ["math", "numbers"] +time_to_solve_sec = 250 + +description_en = """ +An Armstrong number (or Narcissistic number) is a number that is the sum of its own digits each raised to the power of the number of digits. + +For example, $153$ is an Armstrong number because it has $3$ digits and $1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153$. + +Given an integer $n$, return `true` if it is an Armstrong number, and `false` otherwise. +""" + +description_ru = """ +Число Армстронга — это натуральное число, которое равно сумме своих цифр, возведенных в степень, равную количеству его цифр. + +Например, $153$ является числом Армстронга, так как оно состоит из $3$ цифр и $1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153$. + +Дано целое число $n$. Верните `true`, если оно является числом Армстронга, и `false` в противном случае. +""" + +limits = """ +- $0 \\leq n \\leq 10^9$ +""" + +solution = """ +def solution(n: int) -> bool: + s = str(n) + p = len(s) + return sum(int(d)**p for d in s) == n +""" + +examples = """ +solution(0) == True +solution(10) == False +solution(153) == True +solution(1634) == True +""" + +[[input_signature]] +argument_name = "n" +[input_signature.type] +name = "integer" + +[output_signature.type] +name = "boolean" + +[[asserts]] +arguments = [0] +comment = "Single digit (0^1 = 0)" +expected = true + +[[asserts]] +arguments = [5] +comment = "Single digit (5^1 = 5)" +expected = true + +[[asserts]] +arguments = [9] +comment = "Single digit (9^1 = 9)" +expected = true + +[[asserts]] +arguments = [10] +comment = "Two digits (1^2 + 0^2 = 1)" +expected = false + +[[asserts]] +arguments = [153] +comment = "Classic 3-digit Armstrong number" +expected = true + +[[asserts]] +arguments = [154] +comment = "Not an Armstrong number" +expected = false + +[[asserts]] +arguments = [370] +comment = "3-digit: 3^3 + 7^3 + 0^3 = 370" +expected = true + +[[asserts]] +arguments = [371] +comment = "3-digit: 3^3 + 7^3 + 1^3 = 371" +expected = true + +[[asserts]] +arguments = [407] +comment = "3-digit: 4^3 + 0^3 + 7^3 = 407" +expected = true + +[[asserts]] +arguments = [408] +comment = "Not an Armstrong number" +expected = false + +[[asserts]] +arguments = [1000] +comment = "Power of 10 is not Armstrong (except 1 and 0)" +expected = false + +[[asserts]] +arguments = [1634] +comment = "4-digit: 1^4 + 6^4 + 3^4 + 4^4 = 1634" +expected = true + +[[asserts]] +arguments = [8208] +comment = "4-digit Armstrong number" +expected = true + +[[asserts]] +arguments = [9474] +comment = "4-digit Armstrong number" +expected = true + +[[asserts]] +arguments = [9475] +comment = "Close but not Armstrong" +expected = false + +[[asserts]] +arguments = [54748] +comment = "5-digit Armstrong number" +expected = true + +[[asserts]] +arguments = [92727] +comment = "5-digit Armstrong number" +expected = true + +[[asserts]] +arguments = [93084] +comment = "5-digit Armstrong number" +expected = true + +[[asserts]] +arguments = [548834] +comment = "6-digit Armstrong number" +expected = true + +[[asserts]] +arguments = [1741725] +comment = "7-digit Armstrong number" +expected = true + +[[asserts]] +arguments = [4210818] +comment = "7-digit Armstrong number" +expected = true + +[[asserts]] +arguments = [9800817] +comment = "7-digit Armstrong number" +expected = true + +[[asserts]] +arguments = [9926315] +comment = "7-digit Armstrong number" +expected = true + +[[asserts]] +arguments = [24678050] +comment = "8-digit Armstrong number" +expected = true + +[[asserts]] +arguments = [24678051] +comment = "8-digit Armstrong number" +expected = true + +[[asserts]] +arguments = [88593477] +comment = "8-digit Armstrong number" +expected = true + +[[asserts]] +arguments = [146511208] +comment = "9-digit Armstrong number" +expected = true + +[[asserts]] +arguments = [472335975] +comment = "9-digit Armstrong number" +expected = true + +[[asserts]] +arguments = [534494836] +comment = "9-digit Armstrong number" +expected = true + +[[asserts]] +arguments = [912985153] +comment = "9-digit Armstrong number" +expected = true + +[[asserts]] +arguments = [999999999] +comment = "Large non-Armstrong number" +expected = false \ No newline at end of file diff --git a/tasks/easy/strings/five_letter_palindromes.toml b/tasks/easy/strings/five_letter_palindromes.toml new file mode 100644 index 0000000..3036f4b --- /dev/null +++ b/tasks/easy/strings/five_letter_palindromes.toml @@ -0,0 +1,175 @@ +level = "easy" +name = "five_letter_palindromes" +tags = ["strings", "filtering"] +time_to_solve_sec = 240 + +description_en = """ +Given a string `text`, find all palindrome words of exactly $5$ characters. + +A word consists only of English letters. Ignore all punctuation marks, digits, and character cases. +Return a list of unique found palindromes in lowercase, sorted alphabetically. +""" + +description_ru = """ +В заданной строке `text` найдите все слова-палиндромы длиной ровно $5$ символов. + +Слово состоит только из английских букв. Игнорируйте любые знаки препинания, цифры и регистр символов. +Верните список найденных уникальных палиндромов в нижнем регистре, отсортированный по алфавиту. +""" + +limits = """ +- $0 \\leq \\text{len}(\\text{text}) \\leq 10^5$ +""" + +solution = """ +def solution(text: str) -> list: + words = "".join(c if c.isalpha() else " " for c in text).lower().split() + return sorted(list({w for w in words if len(w) == 5 and w == w[::-1]})) +""" + +examples = """ +solution("No palindromes here!") == [] +solution("Civic duty is good.") == ["civic"] +solution("Madam, see a kayak and radar.") == ["kayak", "madam", "radar"] +solution("Level? Stats! Rotor. Tenet.") == ["level", "rotor", "stats", "tenet"] +""" + +[[input_signature]] +argument_name = "text" +[input_signature.type] +name = "string" + +[output_signature.type] +name = "array" +[output_signature.type.nested] +name = "string" + +[[asserts]] +arguments = [""] +comment = "Empty string" +expected = [] + +[[asserts]] +arguments = [" "] +comment = "Only whitespaces" +expected = [] + +[[asserts]] +arguments = ["hello world"] +comment = "No palindromes at all" +expected = [] + +[[asserts]] +arguments = ["apple banana cherry"] +comment = "Five-letter words, but not palindromes" +expected = [] + +[[asserts]] +arguments = ["madam"] +comment = "One exact lowercase palindrome" +expected = ["madam"] + +[[asserts]] +arguments = ["KAYAK"] +comment = "One exact uppercase palindrome" +expected = ["kayak"] + +[[asserts]] +arguments = ["mAdAm"] +comment = "Mixed case palindrome" +expected = ["madam"] + +[[asserts]] +arguments = ["wow mom dad"] +comment = "Palindromes, but shorter than 5 characters" +expected = [] + +[[asserts]] +arguments = ["racecar repaper"] +comment = "Palindromes, but longer than 5 characters" +expected = [] + +[[asserts]] +arguments = ["civic duty is a good thing"] +comment = "Sentence with one valid palindrome" +expected = ["civic"] + +[[asserts]] +arguments = ["Level rotor stats tenet"] +comment = "Multiple valid palindromes without punctuation" +expected = ["level", "rotor", "stats", "tenet"] + +[[asserts]] +arguments = ["Madam, I see a kayak and a radar."] +comment = "Multiple valid palindromes with punctuation" +expected = ["kayak", "madam", "radar"] + +[[asserts]] +arguments = ["stats stats STATS stats!"] +comment = "Duplicate valid palindromes" +expected = ["stats"] + +[[asserts]] +arguments = ["12345 54345 12321"] +comment = "Numbers should be ignored" +expected = [] + +[[asserts]] +arguments = ["abcde1edcba"] +comment = "Numbers acting as word separators" +expected = ["abcde", "edcba"] + +[[asserts]] +arguments = ["-radar- *civic* 'kayak'"] +comment = "Words wrapped in punctuation" +expected = ["civic", "kayak", "radar"] + +[[asserts]] +arguments = ["\t\nlevel\r\n"] +comment = "Whitespace and escape characters" +expected = ["level"] + +[[asserts]] +arguments = ["A man, a plan, a canal, Panama!"] +comment = "Complex sentence with no 5-letter palindromes" +expected = [] + +[[asserts]] +arguments = ["Alula is a bird, right?"] +comment = "Valid palindrome at the beginning" +expected = ["alula"] + +[[asserts]] +arguments = ["Did you see the minim?"] +comment = "Valid palindrome at the end" +expected = ["minim"] + +[[asserts]] +arguments = ["solos kayak solos radar"] +comment = "Repeated multiple palindromes" +expected = ["kayak", "radar", "solos"] + +[[asserts]] +arguments = ["tenet rotor stats level madam civic kayak solos alula minim"] +comment = "Many 5-letter palindromes to sort" +expected = ["alula", "civic", "kayak", "level", "madam", "minim", "rotor", "solos", "stats", "tenet"] + +[[asserts]] +arguments = ["refer to the manual"] +comment = "Valid palindrome in text" +expected = ["refer"] + +[[asserts]] +arguments = ["abcdcba abcba a"] +comment = "Mixed length palindromes" +expected = ["abcba"] + +[[asserts]] +arguments = ["noon deed peep"] +comment = "Even length palindromes only" +expected = [] + +[[asserts]] +arguments = ["This is a test string containing exactly zero matching words."] +comment = "Long string with no matches" +expected = [] \ No newline at end of file diff --git a/tasks/hard/algo/knight_phone_dialer.toml b/tasks/hard/algo/knight_phone_dialer.toml new file mode 100644 index 0000000..e00e3d6 --- /dev/null +++ b/tasks/hard/algo/knight_phone_dialer.toml @@ -0,0 +1,259 @@ +level = "hard" +name = "knight_phone_dialer" +tags = ["graphs", "algorithms", "bfs"] +time_to_solve_sec = 900 + +description_en = """ +You are using a standard push-button phone with the following keypad layout: + +$$ +\\begin{array}{|c|c|c|} +\\hline +\\color{red}{\\mathbf{1}} & 2 & 3 \\\\ +\\hline +4 & 5 & 6 \\\\ +\\hline +7 & 8 & 9 \\\\ +\\hline +~ & 0 & ~ \\\\ +\\hline +\\end{array} +$$ + +A chess knight moves in an $L$-shape: two squares in one cardinal direction and then one square perpendicularly. + +Given a string `digits` representing a phone number, calculate the **minimum total number of knight moves** required to dial the sequence. + +Rules: +1. You start at the first digit of the sequence ($0$ moves to reach it). +2. To move from one digit to the next, you must use the minimum number of knight moves. +3. If two consecutive digits are the same, the distance between them is $0$. +4. If it is impossible to reach the next digit (e.g., the digit $5$ which has no knight moves), return $-1$. +5. An empty string or a single-digit string requires $0$ moves. +""" + +description_ru = """ +Вы пользуетесь кнопочным телефоном со следующей раскладкой: + +$$ +\\begin{array}{|c|c|c|} +\\hline +\\color{red}{\\mathbf{1}} & 2 & 3 \\\\ +\\hline +4 & 5 & 6 \\\\ +\\hline +7 & 8 & 9 \\\\ +\\hline +~ & 0 & ~ \\\\ +\\hline +\\end{array} +$$ + +Шахматный конь ходит буквой «Г»: на две клетки в одном направлении и на одну в перпендикулярном. + +Дана строка `digits`, представляющая номер телефона. Найдите **минимальное суммарное количество ходов коня**, необходимых для набора этой последовательности. + +Правила: +1. Вы начинаете с первой цифры последовательности ($0$ ходов, чтобы «добраться» до неё). +2. Чтобы перейти от одной цифры к следующей, нужно использовать минимальное количество ходов коня. +3. Если две идущие подряд цифры одинаковы, расстояние между ними равно $0$. +4. Если невозможно достичь следующей цифры (например, цифра $5$, у которой нет ходов), верните $-1$. +5. Пустая строка или строка из одной цифры требуют $0$ ходов. +""" + +limits = """ +- $0 \\leq \\text{len}(digits) \\leq 50$ +- $digits[i] \\in \\{0, 1, 2, 3, 4, 5, 6, 7, 8, 9\\}$ +""" + +solution = """ +def solution(digits: str) -> int: + if len(digits) < 2: return 0 + adj = {0:[4,6], 1:[6,8], 2:[7,9], 3:[4,8], 4:[0,3,9], 5:[], 6:[0,1,7], 7:[2,6], 8:[1,3], 9:[2,4]} + memo = {} + def get_dist(s, e): + if s == e: return 0 + if (s, e) in memo: return memo[(s, e)] + q, v = [(s, 0)], {s} + for curr, d in q: + if curr == e: + memo[(s, e)] = d + return d + for nxt in adj[curr]: + if nxt not in v: + v.add(nxt) + q.append((nxt, d + 1)) + return -1 + total = 0 + for i in range(len(digits) - 1): + step = get_dist(int(digits[i]), int(digits[i+1])) + if step == -1: return -1 + total += step + return total +""" + +examples = """ +solution("5") == 0 +solution("16") == 1 +solution("123") == 6 +solution("4061") == 3 +solution("5111") == -1 +""" + +[[input_signature]] +argument_name = "digits" +[input_signature.type] +name = "string" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [""] +comment = "Empty string" +expected = 0 + +[[asserts]] +arguments = ["5"] +comment = "Single digit (isolated)" +expected = 0 + +[[asserts]] +arguments = ["1"] +comment = "Single digit" +expected = 0 + +[[asserts]] +arguments = ["16"] +comment = "Single direct move" +expected = 1 + +[[asserts]] +arguments = ["161"] +comment = "Back and forth direct moves" +expected = 2 + +[[asserts]] +arguments = ["12"] +comment = "Distance from 1 to 2 is 3 moves" +expected = 3 + +[[asserts]] +arguments = ["123"] +comment = "Two jumps of 3 moves each" +expected = 6 + +[[asserts]] +arguments = ["406"] +comment = "4-0 is 1, 0-6 is 1" +expected = 2 + +[[asserts]] +arguments = ["51"] +comment = "Impossible to move from 5" +expected = -1 + +[[asserts]] +arguments = ["15"] +comment = "Impossible to reach 5" +expected = -1 + +[[asserts]] +arguments = ["111"] +comment = "Identical digits" +expected = 0 + +[[asserts]] +arguments = ["0438"] +comment = "Sequence of direct moves: 0-4(1), 4-3(1), 3-8(1)" +expected = 3 + +[[asserts]] +arguments = ["13"] +comment = "1 to 3 requires 2 moves (1-8-3 or 1-6-4-3 is 3? No, 1-8-3 is 2)" +expected = 2 + +[[asserts]] +arguments = ["28"] +comment = "2 to 8 requires 2 moves (2-7-6-1-8 is long, 2-9-4-3-8 is long, 2-7-0-6-1-8... wait 2-7 is 1, 7-6 is 1, 6-1 is 1, 1-8 is 1. Direct is 2-7-6-1-8 is 4. No, 2-9-4-3-8 is 4. Shortest is 2-7-6-1-8? Actually 2-7(1), 7-2(0), 2-9(1), 9-4(1), 4-3(1), 3-8(1). It is 2: 2-7-6-1-8 is not it. 2-7(1)-6(1) is 2. 6-1(1)-8(1) is 2. Total 2 is impossible. 2-7-6-1-8 is 4." +expected = 4 + +[[asserts]] +arguments = ["0618349270"] +comment = "Circular path around the keypad" +expected = 9 + +[[asserts]] +arguments = ["55555"] +comment = "Staying on 5 is allowed" +expected = 0 + +[[asserts]] +arguments = ["17"] +comment = "1 to 7 via 6 (1-6, 6-7)" +expected = 2 + +[[asserts]] +arguments = ["91"] +comment = "9 to 1 via 4 and 0? No, 9-4-3-8-1 (4) or 9-2-7-6-1 (4)" +expected = 4 + +[[asserts]] +arguments = ["80"] +comment = "8-1-6-0 (3 moves) or 8-3-4-0 (3 moves)" +expected = 3 + +[[asserts]] +arguments = ["222"] +comment = "Repeating digits" +expected = 0 + +[[asserts]] +arguments = ["160492761"] +comment = "Long sequence of distance 1 moves" +expected = 8 + +[[asserts]] +arguments = ["37"] +comment = "3-4-9-2-7 (4 moves) or 3-8-1-6-7 (4 moves)" +expected = 4 + +[[asserts]] +arguments = ["42"] +comment = "4-9-2 (2 moves) or 4-3-8-1-6-7-2 (long)" +expected = 2 + +[[asserts]] +arguments = ["004466"] +comment = "Moves mixed with repeats" +expected = 2 + +[[asserts]] +arguments = ["73"] +comment = "7-2-9-4-3 (4 moves) or 7-6-1-8-3 (4 moves)" +expected = 4 + +[[asserts]] +arguments = ["54"] +comment = "Starting at 5 to move away" +expected = -1 + +[[asserts]] +arguments = ["1379"] +comment = "1-3(2), 3-7(4), 7-9(2)" +expected = 8 + +[[asserts]] +arguments = ["82"] +comment = "8-1-6-7-2 (4) or 8-3-4-9-2 (4)" +expected = 4 + +[[asserts]] +arguments = ["02"] +comment = "0-4-9-2 (3 moves)" +expected = 3 + +[[asserts]] +arguments = ["62"] +comment = "6-7-2 (2 moves)" +expected = 2 \ No newline at end of file diff --git a/tasks/hard/bitmasks/min_team_combinations.toml b/tasks/hard/bitmasks/min_team_combinations.toml new file mode 100644 index 0000000..54be526 --- /dev/null +++ b/tasks/hard/bitmasks/min_team_combinations.toml @@ -0,0 +1,200 @@ +level = "hard" +name = "min_team_combinations" +tags = ["bitmask", "brute_force", "algo"] +time_to_solve_sec = 500 + +description_en = """ +You are given an array of integers `people`, where each integer represents the skill set of a person as a bitmask (the $i$-th bit is $1$ if they have the $i$-th skill, and $0$ otherwise). You are also given an integer `target_skills` representing all the skills required for a project as a bitmask. + +Find the minimum number of people needed to form a team that covers all required skills. If it is impossible to cover all required skills, return `-1`. + +*Note:* The number of people is small enough that you can iterate through all possible combinations (subsets) of people, but iterating through all permutations will be too slow. +""" + +description_ru = """ +Дан массив целых чисел `people`, где каждое число представляет набор навыков человека в виде битовой маски ($i$-й бит равен $1$, если у человека есть $i$-й навык, и $0$ в противном случае). Также дано целое число `target_skills`, представляющее все необходимые для проекта навыки в виде битовой маски. + +Найдите минимальное количество людей, необходимое для формирования команды, которая закроет все требуемые навыки. Если это сделать невозможно, верните `-1`. + +*Примечание:* Количество людей достаточно мало, чтобы перебрать все возможные комбинации (подмножества) людей, однако перебор всех перестановок будет слишком медленным. +""" + +limits = """ +- $1 \leq \text{len}(\text{people}) \leq 15$ +- $0 \leq \text{people}[i] \leq 65535$ +- $1 \leq \text{target\_skills} \leq 65535$ +""" + +solution = """ +def solution(people: list[int], target_skills: int) -> int: + n = len(people) + ans = float('inf') + for i in range(1 << n): + mask = 0 + cnt = 0 + for j in range(n): + if (i >> j) & 1: + mask |= people[j] + cnt += 1 + if (mask & target_skills) == target_skills: + if cnt < ans: + ans = cnt + return ans if ans != float('inf') else -1 +""" + +examples = """ +solution([1], 3) == -1 +solution([3], 3) == 1 +solution([1, 2], 3) == 2 +solution([1, 2, 4, 8], 15) == 4 +""" + +[[input_signature]] +argument_name = "people" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "integer" + +[[input_signature]] +argument_name = "target_skills" +[input_signature.type] +name = "integer" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [[3], 3] +comment = "Single person has all skills" +expected = 1 + +[[asserts]] +arguments = [[1], 3] +comment = "Impossible to form team" +expected = -1 + +[[asserts]] +arguments = [[1, 2], 3] +comment = "Two people needed" +expected = 2 + +[[asserts]] +arguments = [[1, 2, 3], 3] +comment = "Optimal person available" +expected = 1 + +[[asserts]] +arguments = [[1, 2, 4, 8], 15] +comment = "Four distinct skills" +expected = 4 + +[[asserts]] +arguments = [[15, 1, 2, 4, 8], 15] +comment = "Best combination is one person" +expected = 1 + +[[asserts]] +arguments = [[3, 6, 12, 9], 15] +comment = "Pairs of overlapping skills" +expected = 2 + +[[asserts]] +arguments = [[10, 5], 15] +comment = "Perfect complementary skills" +expected = 2 + +[[asserts]] +arguments = [[1, 2, 4, 8, 16, 32], 63] +comment = "Sequential bits needed" +expected = 6 + +[[asserts]] +arguments = [[63], 63] +comment = "Exact match for 6 bits" +expected = 1 + +[[asserts]] +arguments = [[31, 31, 31], 63] +comment = "Multiple people missing the same skill" +expected = -1 + +[[asserts]] +arguments = [[1, 2, 4], 7] +comment = "Simple powers of 2" +expected = 3 + +[[asserts]] +arguments = [[3, 5, 6], 7] +comment = "Overlapping minimal pairs" +expected = 2 + +[[asserts]] +arguments = [[7, 7, 7], 7] +comment = "Redundant complete sets" +expected = 1 + +[[asserts]] +arguments = [[0, 0, 0, 7], 7] +comment = "Ignore zeros" +expected = 1 + +[[asserts]] +arguments = [[15, 16], 7] +comment = "Person has more skills than required" +expected = 1 + +[[asserts]] +arguments = [[8, 16, 32, 64], 120] +comment = "Higher bits exactly matched" +expected = 4 + +[[asserts]] +arguments = [[24, 48, 96], 120] +comment = "Two sets cover 4 bits" +expected = 2 + +[[asserts]] +arguments = [[17, 34, 68], 119] +comment = "Disjoint odd positions" +expected = 3 + +[[asserts]] +arguments = [[255], 255] +comment = "All 8 bits by 1" +expected = 1 + +[[asserts]] +arguments = [[15, 240], 255] +comment = "Halves of 8 bits" +expected = 2 + +[[asserts]] +arguments = [[3, 12, 48, 192], 255] +comment = "Quarter splits of 8 bits" +expected = 4 + +[[asserts]] +arguments = [[2, 4, 8, 16], 31] +comment = "Missing the lowest bit" +expected = -1 + +[[asserts]] +arguments = [[1, 4, 16, 64, 256], 341] +comment = "Alternating bits pattern" +expected = 5 + +[[asserts]] +arguments = [[1, 2, 3, 4, 5, 6, 7], 7] +comment = "Many options, best is 1" +expected = 1 + +[[asserts]] +arguments = [[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384], 32767] +comment = "Worst case full spread up to 15 bits" +expected = 15 + +[[asserts]] +arguments = [[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384], 65535] +comment = "Max elements but impossible to cover target" +expected = -1 \ No newline at end of file diff --git a/tasks/hard/graphs/is_bipartite_graph.toml b/tasks/hard/graphs/is_bipartite_graph.toml new file mode 100644 index 0000000..6b4c118 --- /dev/null +++ b/tasks/hard/graphs/is_bipartite_graph.toml @@ -0,0 +1,208 @@ +level = "hard" +name = "is_bipartite_graph" +tags = ["graphs", "bfs", "dfs"] +time_to_solve_sec = 600 + +description_en = """ +You are given an undirected graph represented as an adjacency list, where `graph[i]` is a list of nodes connected to node `i`. + +Return `True` if and only if it is bipartite. + +A graph is bipartite if its nodes can be partitioned into two independent sets such that every edge connects a node in one set to a node in the other. The graph may not be connected. +""" + +description_ru = """ +Вам дан неориентированный граф, представленный в виде списка смежности, где `graph[i]` — это список вершин, соединенных с вершиной `i`. + +Верните `True`, если граф является двудольным. + +Граф является двудольным, если его вершины можно разбить на два независимых множества так, что каждое ребро соединяет вершину из одного множества с вершиной из другого. Граф может быть несвязным. +""" + +limits = """ +- $1 \leq \text{len}(\text{graph}) \leq 100$ +- $0 \leq \text{graph}[i][j] < \text{len}(\text{graph})$ +- $i \neq \text{graph}[i][j]$ +""" + +solution = """ +def solution(graph: list[list[int]]) -> bool: + color = {} + for i in range(len(graph)): + if i not in color: + color[i] = 0 + q = [i] + while q: + u = q.pop() + for v in graph[u]: + if v not in color: + color[v] = color[u] ^ 1 + q.append(v) + elif color[v] == color[u]: + return False + return True +""" + +examples = """ +solution([[]]) == True +solution([[1], [0]]) == True +solution([[1, 2], [0, 2], [0, 1]]) == False +solution([[1, 3], [0, 2], [1, 3], [0, 2]]) == True +""" + +[[input_signature]] +argument_name = "graph" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "array" +[input_signature.type.nested.nested] +name = "integer" + +[output_signature.type] +name = "boolean" + +[[asserts]] +arguments = [[[]]] +comment = "Single isolated node" +expected = true + +[[asserts]] +arguments = [[[], []]] +comment = "Two disconnected nodes" +expected = true + +[[asserts]] +arguments = [[[[1], [0]]]] +comment = "Two connected nodes" +expected = true + +[[asserts]] +arguments = [[[[1, 2], [0, 2], [0, 1]]]] +comment = "Triangle (Not bipartite)" +expected = false + +[[asserts]] +arguments = [[[[1, 3], [0, 2], [1, 3], [0, 2]]]] +comment = "Cycle of 4" +expected = true + +[[asserts]] +arguments = [[[[1, 2, 3], [0, 2], [0, 1, 3], [0, 2]]]] +comment = "Cycle of 4 with a chord (contains triangle)" +expected = false + +[[asserts]] +arguments = [[[[1], [0, 2], [1]]]] +comment = "Path of 3" +expected = true + +[[asserts]] +arguments = [[[[1], [0, 2], [1, 3], [2]]]] +comment = "Path of 4" +expected = true + +[[asserts]] +arguments = [[[[1, 3], [0, 2], [1, 3], [0, 2], []]]] +comment = "Cycle of 4 + isolated node" +expected = true + +[[asserts]] +arguments = [[[[1, 4], [0, 2], [1, 3], [2, 4], [0, 3]]]] +comment = "Cycle of 5 (Not bipartite)" +expected = false + +[[asserts]] +arguments = [[[[1, 5], [0, 2], [1, 3], [2, 4], [3, 5], [0, 4]]]] +comment = "Cycle of 6" +expected = true + +[[asserts]] +arguments = [[[[1, 2, 3], [0], [0], [0]]]] +comment = "Star graph with 4 nodes" +expected = true + +[[asserts]] +arguments = [[[[1, 2, 3, 4], [0], [0], [0], [0]]]] +comment = "Star graph with 5 nodes" +expected = true + +[[asserts]] +arguments = [[[[1, 2], [0, 3], [0, 3], [1, 2]]]] +comment = "Bipartite graph with overlapping edges" +expected = true + +[[asserts]] +arguments = [[[[3, 4, 5], [3, 4, 5], [3, 4, 5], [0, 1, 2], [0, 1, 2], [0, 1, 2]]]] +comment = "Complete bipartite graph K_3,3" +expected = true + +[[asserts]] +arguments = [[[[1, 2, 3, 4], [0, 2, 3, 4], [0, 1, 3, 4], [0, 1, 2, 4], [0, 1, 2, 3]]]] +comment = "Complete graph K_5" +expected = false + +[[asserts]] +arguments = [[[[1], [0, 2], [1, 3], [2, 4], [3, 5], [4, 6], [5, 7], [6]]]] +comment = "Path of 8" +expected = true + +[[asserts]] +arguments = [[[[1], [0, 2], [1, 3], [2, 4], [3, 5], [4, 6], [5, 7], [6, 0]]]] +comment = "Cycle of 8" +expected = true + +[[asserts]] +arguments = [[[[1, 2], [0, 2], [0, 1, 3, 4], [2, 4], [2, 3]]]] +comment = "Two triangles joined at an edge" +expected = false + +[[asserts]] +arguments = [[[[ ], [ ], [ ], [ ]]]] +comment = "Four isolated nodes" +expected = true + +[[asserts]] +arguments = [[[[1], [0], [3], [2]]]] +comment = "Two disjoint edges" +expected = true + +[[asserts]] +arguments = [[[[1], [0, 2], [1], [4, 5], [3, 5], [3, 4]]]] +comment = "Path of 3 + disconnected triangle" +expected = false + +[[asserts]] +arguments = [[[[1, 2, 3], [0, 2], [0, 1], [0]]]] +comment = "Triangle with an attached node" +expected = false + +[[asserts]] +arguments = [[[[3], [2], [1], [0]]]] +comment = "Two disjoint edges crossing over indices" +expected = true + +[[asserts]] +arguments = [[[[1, 2], [0], [0]]]] +comment = "V shape" +expected = true + +[[asserts]] +arguments = [[[[1], [0], [3], [2], [5], [4]]]] +comment = "Three disjoint edges" +expected = true + +[[asserts]] +arguments = [[[[1], [0, 2], [1, 3], [2, 4], [3, 5], [4, 6], [5, 0]]]] +comment = "Cycle of 7" +expected = false + +[[asserts]] +arguments = [[[[2, 3], [3, 4], [0], [0, 1], [1]]]] +comment = "Path of length 5" +expected = true + +[[asserts]] +arguments = [[[[1], [0], [3, 5], [2, 4], [3, 5], [2, 4]]]] +comment = "Two separate bipartite components" +expected = true \ No newline at end of file diff --git a/tasks/hard/graphs/minimum_tree_cover.toml b/tasks/hard/graphs/minimum_tree_cover.toml new file mode 100644 index 0000000..e7b7679 --- /dev/null +++ b/tasks/hard/graphs/minimum_tree_cover.toml @@ -0,0 +1,231 @@ +level = "hard" +name = "minimum_tree_cover" +tags = ["graphs", "trees", "dp"] +time_to_solve_sec = 900 + +description_en = """ +Given an undirected tree with `n` vertices labeled from $0$ to $n - 1$ and an array of `edges`, find the minimum number of vertices needed to cover all edges. + +A vertex is considered to cover all of its directly connected (incident) edges. +""" + +description_ru = """ +Дано неориентированное дерево с `n` вершинами, пронумерованными от $0$ до $n - 1$, и массив `edges`. Найдите минимальное количество вершин, необходимое для покрытия всех ребер. + +Вершина считается покрывающей все свои непосредственно подключенные (инцидентные) ребра. +""" + +limits = """ +- $1 \leq n \leq 10^5$ +- $\text{len}(\text{edges}) = n - 1$ +- $0 \leq \text{edges}[i][0], \text{edges}[i][1] < n$ +""" + +solution = """ +def solution(n: int, edges: list) -> int: + if n <= 1: + return 0 + + adj = [[] for _ in range(n)] + for u, v in edges: + adj[u].append(v) + adj[v].append(u) + + order = [] + parent = [-1] * n + q = [0] + + while q: + u = q.pop(0) + order.append(u) + for v in adj[u]: + if v != parent[u]: + parent[v] = u + q.append(v) + + inc = [1] * n + exc = [0] * n + + for u in reversed(order): + for v in adj[u]: + if v != parent[u]: + inc[u] += min(inc[v], exc[v]) + exc[u] += inc[v] + + return min(inc[0], exc[0]) +""" + +examples = """ +solution(1, []) == 0 +solution(2, [[0, 1]]) == 1 +solution(3, [[0, 1], [0, 2]]) == 1 +solution(4, [[0, 1], [1, 2], [2, 3]]) == 2 +solution(5, [[0, 1], [1, 2], [2, 3], [3, 4]]) == 2 +""" + +[[input_signature]] +argument_name = "n" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "edges" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "array" +[input_signature.type.nested.nested] +name = "integer" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [1, []] +comment = "Single vertex, no edges" +expected = 0 + +[[asserts]] +arguments = [2, [[0, 1]]] +comment = "Two vertices, one edge" +expected = 1 + +[[asserts]] +arguments = [3, [[0, 1], [1, 2]]] +comment = "Three vertices path" +expected = 1 + +[[asserts]] +arguments = [4, [[0, 1], [0, 2], [0, 3]]] +comment = "Star graph with 4 vertices" +expected = 1 + +[[asserts]] +arguments = [4, [[0, 1], [1, 2], [2, 3]]] +comment = "Four vertices path" +expected = 2 + +[[asserts]] +arguments = [5, [[0, 1], [0, 2], [0, 3], [0, 4]]] +comment = "Star graph with 5 vertices" +expected = 1 + +[[asserts]] +arguments = [5, [[0, 1], [1, 2], [2, 3], [3, 4]]] +comment = "Five vertices path" +expected = 2 + +[[asserts]] +arguments = [7, [[0, 1], [0, 2], [1, 3], [1, 4], [2, 5], [2, 6]]] +comment = "Complete binary tree depth 2" +expected = 2 + +[[asserts]] +arguments = [6, [[0, 1], [0, 2], [0, 3], [3, 4], [4, 5]]] +comment = "Y-shaped tree" +expected = 2 + +[[asserts]] +arguments = [7, [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6]]] +comment = "Seven vertices path" +expected = 3 + +[[asserts]] +arguments = [8, [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7]]] +comment = "Eight vertices path" +expected = 4 + +[[asserts]] +arguments = [9, [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8]]] +comment = "Nine vertices path" +expected = 4 + +[[asserts]] +arguments = [10, [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8], [8, 9]]] +comment = "Ten vertices path" +expected = 5 + +[[asserts]] +arguments = [11, [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8], [8, 9], [9, 10]]] +comment = "Eleven vertices path" +expected = 5 + +[[asserts]] +arguments = [12, [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8], [8, 9], [9, 10], [10, 11]]] +comment = "Twelve vertices path" +expected = 6 + +[[asserts]] +arguments = [13, [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8], [8, 9], [9, 10], [10, 11], [11, 12]]] +comment = "Thirteen vertices path" +expected = 6 + +[[asserts]] +arguments = [14, [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 7], [7, 8], [8, 9], [9, 10], [10, 11], [11, 12], [12, 13]]] +comment = "Fourteen vertices path" +expected = 7 + +[[asserts]] +arguments = [8, [[0, 1], [0, 2], [0, 3], [0, 4], [1, 5], [1, 6], [1, 7]]] +comment = "Two connected stars" +expected = 2 + +[[asserts]] +arguments = [9, [[0, 2], [2, 1], [0, 3], [0, 4], [1, 5], [1, 6], [1, 7], [1, 8]]] +comment = "Two stars connected by a middle vertex" +expected = 2 + +[[asserts]] +arguments = [7, [[0, 1], [0, 2], [0, 3], [1, 4], [2, 5], [3, 6]]] +comment = "Subdivided star graph" +expected = 3 + +[[asserts]] +arguments = [9, [[0, 1], [0, 2], [0, 3], [0, 4], [1, 5], [2, 6], [3, 7], [4, 8]]] +comment = "Larger subdivided star graph" +expected = 4 + +[[asserts]] +arguments = [6, [[0, 1], [0, 2], [0, 3], [1, 4], [2, 5]]] +comment = "Asymmetrical subdivided star" +expected = 3 + +[[asserts]] +arguments = [10, [[0, 1], [1, 2], [2, 3], [3, 4], [0, 5], [1, 6], [2, 7], [3, 8], [4, 9]]] +comment = "Caterpillar graph" +expected = 5 + +[[asserts]] +arguments = [15, [[0, 1], [0, 2], [1, 3], [1, 4], [2, 5], [2, 6], [3, 7], [3, 8], [4, 9], [4, 10], [5, 11], [5, 12], [6, 13], [6, 14]]] +comment = "Complete binary tree depth 3" +expected = 5 + +[[asserts]] +arguments = [6, [[0, 1], [1, 2], [2, 3], [0, 4], [2, 5]]] +comment = "Comb graph" +expected = 2 + +[[asserts]] +arguments = [11, [[0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [1, 6], [2, 7], [3, 8], [4, 9], [5, 10]]] +comment = "Star where every leaf has exactly one leaf" +expected = 5 + +[[asserts]] +arguments = [15, [[0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [0, 6], [0, 7], [0, 8], [0, 9], [0, 10], [0, 11], [0, 12], [0, 13], [0, 14]]] +comment = "Large star graph" +expected = 1 + +[[asserts]] +arguments = [10, [[0, 1], [1, 2], [1, 3], [3, 4], [3, 5], [0, 6], [6, 7], [7, 8], [8, 9]]] +comment = "Random irregular tree" +expected = 4 + +[[asserts]] +arguments = [8, [[0, 1], [0, 2], [1, 3], [1, 4], [2, 5], [2, 6], [6, 7]]] +comment = "Another random irregular tree" +expected = 3 + +[[asserts]] +arguments = [3, [[1, 0], [2, 0]]] +comment = "Star graph with zero at center, unordered" +expected = 1 \ No newline at end of file diff --git a/tasks/medium/dp/triangular_coins.toml b/tasks/medium/dp/triangular_coins.toml new file mode 100644 index 0000000..4f8cb6f --- /dev/null +++ b/tasks/medium/dp/triangular_coins.toml @@ -0,0 +1,195 @@ +level = "medium" +name = "triangular_coins" +tags = ["math", "dp", "algorithms"] +time_to_solve_sec = 400 + +description_en = """ +You have $5$ different types of coins, each with a value equal to one of the first $5$ triangular numbers: $1$, $3$, $6$, $10$, and $15$. All coin types are available in unlimited quantities. + +Your task is to determine the minimum number of coins sufficient to make a sum of exactly $n$. +""" + +description_ru = """ +У вас есть $5$ различных типов монет, каждый из которых имеет значение, равное одному из первых $5$ треугольных чисел: $1$, $3$, $6$, $10$ и $15$. Все типы монет имеются в неограниченном количестве. + +Ваша задача — определить, какого минимального количества монет достаточно, чтобы набрать сумму ровно $n$. +""" + +limits = """ +- $0 \\leq n \\leq 10^4$ +""" + +solution = """ +def solution(n: int) -> int: + dp = [0] + [n] * n + for i in range(1, n + 1): + for c in [1, 3, 6, 10, 15]: + if i >= c: + dp[i] = min(dp[i], dp[i - c] + 1) + return dp[n] +""" + +examples = """ +solution(0) == 0 +solution(2) == 2 +solution(12) == 2 +solution(100) == 7 +""" + +[[input_signature]] +argument_name = "n" +[input_signature.type] +name = "integer" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [0] +comment = "Zero sum needs zero coins" +expected = 0 + +[[asserts]] +arguments = [1] +comment = "Exact match for coin 1" +expected = 1 + +[[asserts]] +arguments = [2] +comment = "Two coins of 1" +expected = 2 + +[[asserts]] +arguments = [3] +comment = "Exact match for coin 3" +expected = 1 + +[[asserts]] +arguments = [4] +comment = "Coin 3 and coin 1" +expected = 2 + +[[asserts]] +arguments = [5] +comment = "One 3 and two 1s" +expected = 3 + +[[asserts]] +arguments = [6] +comment = "Exact match for coin 6" +expected = 1 + +[[asserts]] +arguments = [10] +comment = "Exact match for coin 10" +expected = 1 + +[[asserts]] +arguments = [12] +comment = "Greedy fails here (uses two 6s instead of 10+1+1)" +expected = 2 + +[[asserts]] +arguments = [15] +comment = "Exact match for coin 15" +expected = 1 + +[[asserts]] +arguments = [18] +comment = "One 15 and one 3" +expected = 2 + +[[asserts]] +arguments = [20] +comment = "Two 10s (greedy would incorrectly pick 15+3+1+1)" +expected = 2 + +[[asserts]] +arguments = [23] +comment = "Two 10s and one 3" +expected = 3 + +[[asserts]] +arguments = [24] +comment = "Coins 15, 6, and 3" +expected = 3 + +[[asserts]] +arguments = [28] +comment = "Coins 15, 10, and 3" +expected = 3 + +[[asserts]] +arguments = [29] +comment = "Requires 4 coins" +expected = 4 + +[[asserts]] +arguments = [30] +comment = "Two 15s" +expected = 2 + +[[asserts]] +arguments = [35] +comment = "One 15 and two 10s" +expected = 3 + +[[asserts]] +arguments = [40] +comment = "Two 15s and one 10" +expected = 3 + +[[asserts]] +arguments = [42] +comment = "Two 15s and two 6s" +expected = 4 + +[[asserts]] +arguments = [50] +comment = "Two 15s and two 10s" +expected = 4 + +[[asserts]] +arguments = [60] +comment = "Four 15s" +expected = 4 + +[[asserts]] +arguments = [99] +comment = "Six 15s and one 6 and one 3" +expected = 8 + +[[asserts]] +arguments = [100] +comment = "Six 15s and one 10" +expected = 7 + +[[asserts]] +arguments = [150] +comment = "Ten 15s" +expected = 10 + +[[asserts]] +arguments = [999] +comment = "Large number with remainder 9" +expected = 68 + +[[asserts]] +arguments = [1000] +comment = "Large number with remainder 10" +expected = 67 + +[[asserts]] +arguments = [4995] +comment = "Multiple of 15" +expected = 333 + +[[asserts]] +arguments = [9999] +comment = "Maximum bound close value" +expected = 668 + +[[asserts]] +arguments = [10000] +comment = "Maximum constraint limit" +expected = 667 \ No newline at end of file diff --git a/tasks/medium/games/checker_to_king.toml b/tasks/medium/games/checker_to_king.toml new file mode 100644 index 0000000..d31c105 --- /dev/null +++ b/tasks/medium/games/checker_to_king.toml @@ -0,0 +1,181 @@ +level = "medium" +name = "checker_to_king" +tags = ["math", "dynamic_programming", "games"] +time_to_solve_sec = 400 + +description_en = """ +On an $8 \\times 8$ chessboard, there is a single white checker. It can move diagonally forward (one step up-left or up-right). + +Given its starting column `x` (from $1$ to $8$, counting from the left) and row `y` (from $1$ to $8$, counting from the bottom), return the number of ways it can reach the last row ($y = 8$) to become a king. The checker cannot move outside the board limits. +""" + +description_ru = """ +На шахматной доске $8 \\times 8$ стоит одна белая шашка. Она может двигаться по диагонали вперед (на одну клетку влево-вверх или вправо-вверх). + +По заданному начальному столбцу `x` (от $1$ до $8$, считая слева) и строке `y` (от $1$ до $8$, считая снизу), верните количество способов, которыми она может дойти до последней строки ($y = 8$) и стать дамкой. Шашка не может выходить за пределы доски. +""" + +limits = """ +- $1 \\leq x \\leq 8$ +- $1 \\leq y \\leq 8$ +""" + +solution = """ +def solution(x: int, y: int) -> int: + dp = [[0] * 10 for _ in range(9)] + dp[y][x] = 1 + for r in range(y + 1, 9): + for c in range(1, 9): + dp[r][c] = dp[r-1][c-1] + dp[r-1][c+1] + return sum(dp[8]) +""" + +examples = """ +solution(1, 8) == 1 +solution(1, 7) == 1 +solution(2, 7) == 2 +solution(4, 1) == 103 +""" + +[[input_signature]] +argument_name = "x" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "y" +[input_signature.type] +name = "integer" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [1, 8] +comment = "Already a king on the left edge" +expected = 1 + +[[asserts]] +arguments = [4, 8] +comment = "Already a king in the middle" +expected = 1 + +[[asserts]] +arguments = [8, 8] +comment = "Already a king on the right edge" +expected = 1 + +[[asserts]] +arguments = [1, 7] +comment = "One step away on the left edge" +expected = 1 + +[[asserts]] +arguments = [2, 7] +comment = "One step away, can go left or right" +expected = 2 + +[[asserts]] +arguments = [5, 7] +comment = "One step away in the middle" +expected = 2 + +[[asserts]] +arguments = [8, 7] +comment = "One step away on the right edge" +expected = 1 + +[[asserts]] +arguments = [1, 6] +comment = "Two steps from the left edge" +expected = 2 + +[[asserts]] +arguments = [2, 6] +comment = "Two steps away" +expected = 3 + +[[asserts]] +arguments = [4, 6] +comment = "Two steps away in the middle" +expected = 4 + +[[asserts]] +arguments = [7, 6] +comment = "Two steps away near right edge" +expected = 3 + +[[asserts]] +arguments = [2, 5] +comment = "Three steps away" +expected = 6 + +[[asserts]] +arguments = [5, 5] +comment = "Three steps away in the middle" +expected = 8 + +[[asserts]] +arguments = [8, 5] +comment = "Three steps away on right edge" +expected = 3 + +[[asserts]] +arguments = [3, 4] +comment = "Four steps away" +expected = 14 + +[[asserts]] +arguments = [4, 4] +comment = "Four steps away in the middle" +expected = 15 + +[[asserts]] +arguments = [7, 4] +comment = "Four steps away near right edge" +expected = 10 + +[[asserts]] +arguments = [2, 3] +comment = "Five steps away" +expected = 20 + +[[asserts]] +arguments = [5, 3] +comment = "Five steps away in the middle" +expected = 29 + +[[asserts]] +arguments = [3, 2] +comment = "Six steps away" +expected = 49 + +[[asserts]] +arguments = [6, 2] +comment = "Six steps away, mirrored" +expected = 49 + +[[asserts]] +arguments = [1, 1] +comment = "Full board distance, left edge" +expected = 35 + +[[asserts]] +arguments = [2, 1] +comment = "Full board distance" +expected = 69 + +[[asserts]] +arguments = [4, 1] +comment = "Full board distance, inner column" +expected = 103 + +[[asserts]] +arguments = [5, 1] +comment = "Full board distance, inner column mirrored" +expected = 103 + +[[asserts]] +arguments = [8, 1] +comment = "Full board distance, right edge" +expected = 35 \ No newline at end of file diff --git a/tasks/medium/graphs/lowest_common_ancestor.toml b/tasks/medium/graphs/lowest_common_ancestor.toml new file mode 100644 index 0000000..2b700d5 --- /dev/null +++ b/tasks/medium/graphs/lowest_common_ancestor.toml @@ -0,0 +1,227 @@ +level = "medium" +name = "lowest_common_ancestor" +tags = ["trees", "graphs", "algorithms"] +time_to_solve_sec = 400 + +description_en = """ +You are given a tree of $n$ nodes represented by a `parent` array, where `parent[i]` is the parent of node $i$. The root of the tree has `parent[root] = -1`. + +Given two nodes $u$ and $v$, return their Lowest Common Ancestor (LCA). The LCA is the deepest node that is an ancestor of both $u$ and $v$. +""" + +description_ru = """ +Вам дано дерево из $n$ узлов, представленное массивом `parent`, где `parent[i]` — родитель узла $i$. Корень дерева имеет `parent[root] = -1`. + +Учитывая два узла $u$ и $v$, верните их наименьшего общего предка (LCA). LCA — это самый глубокий узел, который является предком как для $u$, так и для $v$. +""" + +limits = """ +- $1 \leq \text{len}(\text{parent}) \leq 1000$ +- $-1 \leq \text{parent}[i] < \text{len}(\text{parent})$ +- $0 \leq u < \text{len}(\text{parent})$ +- $0 \leq v < \text{len}(\text{parent})$ +""" + +solution = """ +def solution(parent: list, u: int, v: int) -> int: + ancestors = set() + while u != -1: + ancestors.add(u) + u = parent[u] + while v != -1: + if v in ancestors: + return v + v = parent[v] + return -1 +""" + +examples = """ +solution([-1, 0, 0], 1, 2) == 0 +solution([-1, 0, 1, 2], 3, 1) == 1 +solution([-1, 0, 0, 1, 1, 2], 3, 4) == 1 +""" + +[[input_signature]] +argument_name = "parent" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "integer" + +[[input_signature]] +argument_name = "u" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "v" +[input_signature.type] +name = "integer" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [[-1], 0, 0] +comment = "Single node tree" +expected = 0 + +[[asserts]] +arguments = [[-1, 0], 1, 1] +comment = "Same node, two nodes tree" +expected = 1 + +[[asserts]] +arguments = [[-1, 0], 0, 1] +comment = "Root and child" +expected = 0 + +[[asserts]] +arguments = [[-1, 0, 0], 1, 2] +comment = "Siblings, root is parent" +expected = 0 + +[[asserts]] +arguments = [[-1, 0, 0], 1, 0] +comment = "Node and its parent" +expected = 0 + +[[asserts]] +arguments = [[-1, 0, 0, 1, 1, 2, 2], 3, 4] +comment = "Deep siblings" +expected = 1 + +[[asserts]] +arguments = [[-1, 0, 0, 1, 1, 2, 2], 5, 6] +comment = "Deep siblings on the right" +expected = 2 + +[[asserts]] +arguments = [[-1, 0, 0, 1, 1, 2, 2], 3, 5] +comment = "Nodes on different branches" +expected = 0 + +[[asserts]] +arguments = [[-1, 0, 0, 1, 1, 2, 2], 4, 6] +comment = "Different branches, level 2" +expected = 0 + +[[asserts]] +arguments = [[-1, 0, 0, 1, 1, 2, 2], 1, 3] +comment = "Ancestor and descendant" +expected = 1 + +[[asserts]] +arguments = [[-1, 0, 0, 1, 1, 2, 2], 2, 6] +comment = "Ancestor and descendant right side" +expected = 2 + +[[asserts]] +arguments = [[-1, 0, 0, 1, 1, 2, 2], 0, 5] +comment = "Root and leaf" +expected = 0 + +[[asserts]] +arguments = [[-1, 0, 0, 1, 1, 2, 2], 4, 2] +comment = "Leaf and uncle" +expected = 0 + +[[asserts]] +arguments = [[-1, 0, 1, 2, 3, 4], 3, 4] +comment = "Line graph, parent and child" +expected = 3 + +[[asserts]] +arguments = [[-1, 0, 1, 2, 3, 4], 0, 4] +comment = "Line graph, root and leaf" +expected = 0 + +[[asserts]] +arguments = [[-1, 0, 1, 2, 3, 4], 1, 4] +comment = "Line graph, intermediate node and leaf" +expected = 1 + +[[asserts]] +arguments = [[-1, 0, 1, 2, 3, 4], 2, 2] +comment = "Line graph, same node" +expected = 2 + +[[asserts]] +arguments = [[-1, 0, 1, 2, 3, 4], 4, 1] +comment = "Line graph, reverse order parameters" +expected = 1 + +[[asserts]] +arguments = [[-1, 0, 0, 0, 0, 0, 0], 1, 2] +comment = "Star graph, leaf siblings" +expected = 0 + +[[asserts]] +arguments = [[-1, 0, 0, 0, 0, 0, 0], 3, 6] +comment = "Star graph, distant siblings" +expected = 0 + +[[asserts]] +arguments = [[-1, 0, 0, 0, 0, 0, 0], 4, 5] +comment = "Star graph, adjacent siblings" +expected = 0 + +[[asserts]] +arguments = [[-1, 0, 0, 0, 0, 0, 0], 0, 3] +comment = "Star graph, root and leaf" +expected = 0 + +[[asserts]] +arguments = [[1, 2, 3, -1, 3, 4], 0, 5] +comment = "Root is not at index 0" +expected = 3 + +[[asserts]] +arguments = [[1, 2, 3, -1, 3, 4], 1, 2] +comment = "Root not at 0, path components" +expected = 2 + +[[asserts]] +arguments = [[1, 2, 3, -1, 3, 4], 5, 3] +comment = "Root not at 0, leaf and root" +expected = 3 + +[[asserts]] +arguments = [[1, 2, 3, -1, 3, 4], 0, 4] +comment = "Root not at 0, across branches" +expected = 3 + +[[asserts]] +arguments = [[-1, 0, 1, 1, 0, 4, 4, 6], 2, 3] +comment = "Complex tree, simple LCA" +expected = 1 + +[[asserts]] +arguments = [[-1, 0, 1, 1, 0, 4, 4, 6], 5, 6] +comment = "Complex tree, mid-level LCA" +expected = 4 + +[[asserts]] +arguments = [[-1, 0, 1, 1, 0, 4, 4, 6], 5, 7] +comment = "Complex tree, different depths" +expected = 4 + +[[asserts]] +arguments = [[-1, 0, 1, 1, 0, 4, 4, 6], 2, 7] +comment = "Complex tree, cross branches to root" +expected = 0 + +[[asserts]] +arguments = [[-1, 0, 1, 1, 0, 4, 4, 6], 3, 5] +comment = "Complex tree, opposite sides" +expected = 0 + +[[asserts]] +arguments = [[-1, 0, 1, 1, 0, 4, 4, 6], 6, 7] +comment = "Complex tree, direct line" +expected = 6 + +[[asserts]] +arguments = [[-1, 0, 1, 1, 0, 4, 4, 6], 1, 4] +comment = "Complex tree, high level nodes" +expected = 0 \ No newline at end of file diff --git a/tasks/medium/graphs/shortest_path_length.toml b/tasks/medium/graphs/shortest_path_length.toml new file mode 100644 index 0000000..d9c24f0 --- /dev/null +++ b/tasks/medium/graphs/shortest_path_length.toml @@ -0,0 +1,216 @@ +level = "medium" +name = "shortest_path_length" +tags = ["graphs", "bfs", "algorithms"] +time_to_solve_sec = 400 + +description_en = """ +You are given an unweighted, undirected graph with $n$ nodes numbered from $0$ to $n - 1$. You are also given an array `edges`, where $\\text{edges}[i] = [u_i, v_i]$ represents a bidirectional edge between node $u_i$ and node $v_i$. + +Find the length of the shortest path between the `start` node and the `end` node. The length of a path is the number of edges in it. + +If there is no valid path between `start` and `end`, return `-1`. +""" + +description_ru = """ +Вам дан невзвешенный неориентированный граф с $n$ вершинами, пронумерованными от $0$ до $n - 1$. Также дан массив `edges`, где $\\text{edges}[i] = [u_i, v_i]$ представляет собой двунаправленное ребро между вершиной $u_i$ и вершиной $v_i$. + +Найдите длину кратчайшего пути между вершиной `start` и вершиной `end`. Длина пути — это количество рёбер в нём. + +Если пути между `start` и `end` не существует, верните `-1`. +""" + +limits = """ +- $1 \\leq n \\leq 1000$ +- $0 \\leq \\text{len}(\\text{edges}) \\leq 2000$ +- $0 \\leq u_i, v_i < n$ +- $0 \\leq \\text{start}, \\text{end} < n$ +- $u_i \\neq v_i$ +""" + +solution = """ +def solution(n: int, edges: list, start: int, end: int) -> int: + g = [[] for _ in range(n)] + for u, v in edges: + g[u].append(v) + g[v].append(u) + + dist = [-1] * n + dist[start] = 0 + q = [start] + + for u in q: + for v in g[u]: + if dist[v] == -1: + dist[v] = dist[u] + 1 + q.append(v) + + return dist[end] +""" + +examples = """ +solution(4, [[0, 1], [2, 3]], 0, 3) == -1 +solution(3, [[0, 1], [1, 2], [0, 2]], 0, 2) == 1 +solution(5, [[0, 1], [1, 2], [2, 3], [3, 4]], 0, 4) == 4 +""" + +[[input_signature]] +argument_name = "n" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "edges" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "array" +[input_signature.type.nested.nested] +name = "integer" + +[[input_signature]] +argument_name = "start" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "end" +[input_signature.type] +name = "integer" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [5, [[0, 1], [1, 2], [2, 3], [3, 4]], 0, 4] +comment = "Line graph from one end to another" +expected = 4 + +[[asserts]] +arguments = [3, [[0, 1], [1, 2], [0, 2]], 0, 2] +comment = "Triangle graph, direct connection available" +expected = 1 + +[[asserts]] +arguments = [4, [[0, 1], [2, 3]], 0, 3] +comment = "Disconnected components" +expected = -1 + +[[asserts]] +arguments = [1, [], 0, 0] +comment = "Single node, start equals end" +expected = 0 + +[[asserts]] +arguments = [3, [[0, 1], [1, 2]], 1, 1] +comment = "Start equals end with existing edges" +expected = 0 + +[[asserts]] +arguments = [2, [[0, 1]], 0, 1] +comment = "Two nodes, directly connected" +expected = 1 + +[[asserts]] +arguments = [2, [[0, 1]], 1, 0] +comment = "Two nodes, backwards" +expected = 1 + +[[asserts]] +arguments = [5, [[0, 1], [2, 3], [3, 4]], 0, 4] +comment = "Larger disconnected graph" +expected = -1 + +[[asserts]] +arguments = [4, [[0, 1], [1, 2], [2, 3], [3, 0]], 0, 2] +comment = "Cycle graph of 4" +expected = 2 + +[[asserts]] +arguments = [5, [[0, 1], [0, 2], [0, 3], [0, 4]], 1, 4] +comment = "Star graph, path goes through center" +expected = 2 + +[[asserts]] +arguments = [4, [[0, 1], [0, 2], [0, 3], [1, 2], [1, 3], [2, 3]], 0, 3] +comment = "Complete graph" +expected = 1 + +[[asserts]] +arguments = [4, [[0, 1], [1, 2], [2, 3], [0, 3]], 0, 3] +comment = "Multiple paths, picking the shortest" +expected = 1 + +[[asserts]] +arguments = [5, [[0, 1], [1, 2], [2, 4], [0, 3], [3, 4]], 0, 4] +comment = "Two paths of different lengths" +expected = 2 + +[[asserts]] +arguments = [7, [[0, 1], [0, 2], [1, 3], [1, 4], [2, 5], [2, 6]], 3, 6] +comment = "Tree, finding distance between two leaves" +expected = 4 + +[[asserts]] +arguments = [5, [[0, 1], [1, 2], [1, 3], [3, 4]], 0, 2] +comment = "Graph with a dead end" +expected = 2 + +[[asserts]] +arguments = [6, [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 0]], 0, 3] +comment = "Hexagon cycle, maximum distance" +expected = 3 + +[[asserts]] +arguments = [6, [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 0]], 0, 4] +comment = "Hexagon cycle, shorter path backwards" +expected = 2 + +[[asserts]] +arguments = [4, [[1, 2], [2, 3]], 0, 3] +comment = "Start node is completely isolated" +expected = -1 + +[[asserts]] +arguments = [4, [[0, 1], [2, 3]], 0, 2] +comment = "Start and end in different edges" +expected = -1 + +[[asserts]] +arguments = [6, [[0, 1], [0, 2], [1, 3], [2, 3], [3, 4], [3, 5], [4, 5]], 0, 5] +comment = "Path with multiple triangles" +expected = 3 + +[[asserts]] +arguments = [6, [[0, 3], [0, 4], [0, 5], [1, 3], [1, 4], [1, 5], [2, 3], [2, 4], [2, 5]], 0, 2] +comment = "Complete bipartite graph K_3,3" +expected = 2 + +[[asserts]] +arguments = [9, [[0, 1], [1, 2], [3, 4], [4, 5], [6, 7], [7, 8], [0, 3], [3, 6], [1, 4], [4, 7], [2, 5], [5, 8]], 0, 8] +comment = "3x3 Grid, corner to corner" +expected = 4 + +[[asserts]] +arguments = [9, [[0, 1], [1, 2], [3, 4], [4, 5], [6, 7], [7, 8], [0, 3], [3, 6], [1, 4], [4, 7], [2, 5], [5, 8]], 0, 4] +comment = "3x3 Grid, corner to center" +expected = 2 + +[[asserts]] +arguments = [6, [[0, 1], [1, 2], [2, 3], [0, 4], [4, 5], [5, 3]], 0, 3] +comment = "Two independent paths of length 3" +expected = 3 + +[[asserts]] +arguments = [5, [[0, 1], [1, 2], [2, 3], [3, 4], [2, 4]], 0, 4] +comment = "Path with a shortcut" +expected = 3 + +[[asserts]] +arguments = [5, [[0, 1], [1, 2], [2, 3], [3, 4]], 2, 4] +comment = "Line graph, start in the middle" +expected = 2 + +[[asserts]] +arguments = [4, [], 0, 3] +comment = "Empty edges" +expected = -1 \ No newline at end of file diff --git a/tasks/medium/greedy/maximize_product.toml b/tasks/medium/greedy/maximize_product.toml new file mode 100644 index 0000000..1618234 --- /dev/null +++ b/tasks/medium/greedy/maximize_product.toml @@ -0,0 +1,192 @@ +level = "medium" +name = "maximize_product" +tags = ["math", "strings", "greedy"] +time_to_solve_sec = 400 + +description_en = """ +You are given two strings `x` and `y` of the same length, consisting of digits from `1` to `9`. + +You can perform the following operation any number of times: swap the $i$-th digit of `x` with the $i$-th digit of `y`. + +Return the maximum possible product of the integers represented by `x` and `y` after performing any number of swaps. +""" + +description_ru = """ +Вам даны две строки `x` и `y` одинаковой длины, состоящие из цифр от `1` до `9`. + +Вы можете выполнять следующую операцию любое количество раз: менять местами $i$-ю цифру в `x` и $i$-ю цифру в `y`. + +Верните максимально возможное произведение чисел `x` и `y`, которого можно достичь с помощью этих операций. +""" + +limits = """ +- $1 \\leq \\text{len}(x) = \\text{len}(y) \\leq 100$ +- $x_i, y_i \\in \\{1, 2, \\dots, 9\\}$ +""" + +solution = """ +def solution(x: str, y: str) -> int: + rx, ry, diff = "", "", False + for a, b in zip(x, y): + if a == b: + rx += a; ry += b + elif not diff: + rx += max(a, b); ry += min(a, b); diff = True + else: + rx += min(a, b); ry += max(a, b) + return int(rx) * int(ry) +""" + +examples = """ +solution("1", "9") == 9 +solution("73", "31") == 2343 +solution("123", "321") == 39483 +""" + +[[input_signature]] +argument_name = "x" +[input_signature.type] +name = "string" + +[[input_signature]] +argument_name = "y" +[input_signature.type] +name = "string" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = ["1", "2"] +comment = "Single digit" +expected = 2 + +[[asserts]] +arguments = ["9", "9"] +comment = "Single identical digits" +expected = 81 + +[[asserts]] +arguments = ["73", "31"] +comment = "Two digits with swap" +expected = 2343 + +[[asserts]] +arguments = ["12", "21"] +comment = "Simple palindrome pair" +expected = 252 + +[[asserts]] +arguments = ["11", "99"] +comment = "Max and min combinations" +expected = 1729 + +[[asserts]] +arguments = ["99", "11"] +comment = "Reversed max and min" +expected = 1729 + +[[asserts]] +arguments = ["123", "123"] +comment = "Identical three digits" +expected = 15129 + +[[asserts]] +arguments = ["321", "123"] +comment = "Three digits swap logic" +expected = 39483 + +[[asserts]] +arguments = ["456", "654"] +comment = "Consecutive numbers" +expected = 298224 + +[[asserts]] +arguments = ["111", "999"] +comment = "Ones and Nines" +expected = 181289 + +[[asserts]] +arguments = ["1234", "4321"] +comment = "Four digits progression" +expected = 5630814 + +[[asserts]] +arguments = ["9876", "6789"] +comment = "Four digits large progression" +expected = 67346864 + +[[asserts]] +arguments = ["1111", "2222"] +comment = "Repeated digits four" +expected = 2579642 + +[[asserts]] +arguments = ["5555", "5555"] +comment = "Identical repetitive sequence" +expected = 30858025 + +[[asserts]] +arguments = ["1919", "9191"] +comment = "Alternating digits" +expected = 18212889 + +[[asserts]] +arguments = ["2468", "8642"] +comment = "Even digits progression" +expected = 22523256 + +[[asserts]] +arguments = ["1357", "7531"] +comment = "Odd digits progression" +expected = 11414367 + +[[asserts]] +arguments = ["2323", "3232"] +comment = "Alternating small digits" +expected = 7516926 + +[[asserts]] +arguments = ["1212", "2121"] +comment = "Alternating 1 and 2" +expected = 2579642 + +[[asserts]] +arguments = ["9999", "1111"] +comment = "Four nines and ones" +expected = 18212889 + +[[asserts]] +arguments = ["11111", "99999"] +comment = "Five digits extremes" +expected = 1822128889 + +[[asserts]] +arguments = ["54321", "12345"] +comment = "Five digits countdown vs countup" +expected = 750544745 + +[[asserts]] +arguments = ["13579", "97531"] +comment = "Five odd digits" +expected = 1644181449 + +[[asserts]] +arguments = ["24681", "18642"] +comment = "Mixed digits length 5" +expected = 460343162 + +[[asserts]] +arguments = ["98765", "56789"] +comment = "Large overlapping strings" +expected = 5688717585 + +[[asserts]] +arguments = ["111111", "222222"] +comment = "Six digits repetitions" +expected = 25802406442 + +[[asserts]] +arguments = ["999999", "111111"] +comment = "Six digits nines and ones" +expected = 182221288889 \ No newline at end of file diff --git a/tasks/medium/greedy/minimum_refuels.toml b/tasks/medium/greedy/minimum_refuels.toml new file mode 100644 index 0000000..af21dd6 --- /dev/null +++ b/tasks/medium/greedy/minimum_refuels.toml @@ -0,0 +1,205 @@ +level = "medium" +name = "minimum_refuels" +tags = ["greedy", "math", "algorithms"] +time_to_solve_sec = 400 + +description_en = """ +Andrey is driving from point A to point B. The distance between these points is `n` kilometers. With a full tank, the car can travel `k` kilometers. + +You are given an array `stations` containing the coordinates of gas stations relative to point A. The coordinates are strictly sorted in ascending order. + +Determine the minimum number of refuels Andrey needs to make to reach point B successfully. + +He starts with a full tank at point A. If it is impossible to reach point B, return `-1`. +""" + +description_ru = """ +Андрей едет из пункта A в пункт B на автомобиле. Расстояние между этими пунктами равно `n` километров. С полным баком автомобиль способен проехать `k` километров. + +Дана карта в виде массива `stations` с координатами бензоколонок относительно пункта A, отсортированными строго по возрастанию. + +Определите минимальное число заправок, которые придется сделать Андрею, чтобы успешно достичь пункта B. + +При выезде из пункта A бак был полон. Если достичь пункта B невозможно, верните `-1`. +""" + +limits = """ +- $1 \\leq n \\leq 10^5$ +- $1 \\leq k \\leq 10^5$ +- $0 \\leq \\text{len}(\\text{stations}) \\leq 10^4$ +- $0 < \\text{stations}[i] < n$ +""" + +solution = """ +def solution(n: int, k: int, stations: list) -> int: + stops = [0] + stations + [n] + refuels, current = 0, 0 + for i in range(len(stops) - 1): + if stops[i+1] - stops[i] > k: + return -1 + if current + k < stops[i+1]: + refuels += 1 + current = stops[i] + return refuels +""" + +examples = """ +solution(10, 5, []) == -1 +solution(5, 10, [1, 2, 3]) == 0 +solution(10, 3, [2, 5, 7]) == 3 +""" + +[[input_signature]] +argument_name = "n" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "k" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "stations" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "integer" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [10, 3, [2, 5, 7]] +comment = "Basic scenario with multiple stops" +expected = 3 + +[[asserts]] +arguments = [10, 2, [3, 5, 7]] +comment = "Impossible to reach first station" +expected = -1 + +[[asserts]] +arguments = [10, 2, [2, 5, 7]] +comment = "Impossible distance between two stations" +expected = -1 + +[[asserts]] +arguments = [10, 2, [2, 4, 6]] +comment = "Impossible distance at the end" +expected = -1 + +[[asserts]] +arguments = [5, 10, [1, 2, 3]] +comment = "No refuels needed with enough capacity" +expected = 0 + +[[asserts]] +arguments = [5, 5, []] +comment = "No stations, exact reach" +expected = 0 + +[[asserts]] +arguments = [10, 5, []] +comment = "No stations, impossible" +expected = -1 + +[[asserts]] +arguments = [10, 5, [5]] +comment = "Exact reach with one refuel" +expected = 1 + +[[asserts]] +arguments = [10, 2, [1, 3, 5, 7, 9]] +comment = "Multiple small jumps" +expected = 5 + +[[asserts]] +arguments = [10, 2, [2, 4, 6, 8]] +comment = "Refuel at every station" +expected = 4 + +[[asserts]] +arguments = [20, 6, [4, 8, 12, 16]] +comment = "Skip some capacity to reach next station" +expected = 4 + +[[asserts]] +arguments = [100, 10, [10, 20, 30, 40, 50, 60, 70, 80, 90]] +comment = "Long sequence, exact bounds" +expected = 9 + +[[asserts]] +arguments = [100, 11, [10, 20, 30, 40, 50, 60, 70, 80, 90]] +comment = "Long sequence, slightly larger capacity" +expected = 9 + +[[asserts]] +arguments = [100, 50, [49, 50, 51]] +comment = "Refuel in the middle optimally" +expected = 1 + +[[asserts]] +arguments = [100, 50, [49, 51]] +comment = "Suboptimal middle stations requiring more refuels" +expected = 2 + +[[asserts]] +arguments = [15, 5, [3, 4, 7, 8, 12, 14]] +comment = "Irregularly spaced stations" +expected = 3 + +[[asserts]] +arguments = [20, 10, [5, 15]] +comment = "Must refuel at exact limits relative to position" +expected = 2 + +[[asserts]] +arguments = [20, 10, [10]] +comment = "Single optimal midpoint" +expected = 1 + +[[asserts]] +arguments = [20, 10, [9, 11]] +comment = "Two stations around midpoint" +expected = 2 + +[[asserts]] +arguments = [30, 10, [10, 20]] +comment = "Two exact boundary refuels" +expected = 2 + +[[asserts]] +arguments = [10, 10, [1, 2, 3]] +comment = "Unnecessary stations" +expected = 0 + +[[asserts]] +arguments = [10, 9, [1]] +comment = "Refuel very early to make the long end jump" +expected = 1 + +[[asserts]] +arguments = [10, 9, [9]] +comment = "Refuel very late after long initial jump" +expected = 1 + +[[asserts]] +arguments = [100, 1, [1, 2, 3]] +comment = "Impossible with very small capacity" +expected = -1 + +[[asserts]] +arguments = [10, 3, [3, 6, 9]] +comment = "Exact bounds every step" +expected = 3 + +[[asserts]] +arguments = [10, 3, [1, 4, 7]] +comment = "Exact bounds with offset" +expected = 3 + +[[asserts]] +arguments = [10, 4, [2, 4, 6, 8]] +comment = "Capacity allows skipping alternating stations" +expected = 2 \ No newline at end of file diff --git a/tasks/medium/math/lucky_base.toml b/tasks/medium/math/lucky_base.toml new file mode 100644 index 0000000..7aceeda --- /dev/null +++ b/tasks/medium/math/lucky_base.toml @@ -0,0 +1,220 @@ +level = "medium" +name = "lucky_base" +tags = ["math", "number_theory", "brute_force"] +time_to_solve_sec = 400 + +description_en = """ +Schoolboy Vasya likes numbers that end with his lucky digit `k`. Every time he sees a natural number `n`, he tries to find a base `d` ($d > 2$) such that the representation of `n` in base `d` ends with the maximum possible number of digits `k`. + +Write a function that, given `n` and `k`, finds such `d`. +- A valid base must be strictly greater than $2$ and strictly greater than $k$ (since $k$ is a digit in base $d$). +- If there are multiple bases providing the same maximum number of trailing `k`s, return the smallest one. +- If no base can produce even a single `k` at the end, return the smallest valid base evaluated (which is $\\max(3, k + 1)$). +""" + +description_ru = """ +Школьнику Васе нравятся числа, которые заканчиваются счастливыми для него цифрами `k`. Поэтому каждый раз, когда он видит какое-нибудь натуральное число `n`, он сразу пытается подобрать такое основание системы счисления `d` ($d > 2$), чтобы число `n` в этой системе заканчивалось как можно большим количеством цифр `k`. + +Напишите функцию, которая по заданным `n` и `k` найдет такое `d`. +- Допустимое основание должно быть строго больше $2$ и строго больше $k$ (так как $k$ — это цифра в системе с основанием $d$). +- Если таких оснований несколько, верните наименьшее из них. +- Если ни одно основание не дает ни одной цифры `k` на конце, верните наименьшее проверяемое основание (то есть $\\max(3, k + 1)$). +""" + +limits = """ +- $1 \\leq n \\leq 10^4$ +- $0 \\leq k \\leq 10^4$ +""" + +solution = """ +def solution(n: int, k: int) -> int: + best_d, max_len = max(3, k + 1), -1 + for d in range(max(3, k + 1), n + 2): + t, c = n, 0 + while t > 0 and t % d == k: + c += 1 + t //= d + if c > max_len: + max_len, best_d = c, d + return best_d +""" + +examples = """ +solution(4, 2) == 3 +solution(10, 0) == 5 +solution(21, 1) == 4 +solution(20, 2) == 9 +""" + +[[input_signature]] +argument_name = "n" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "k" +[input_signature.type] +name = "integer" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [21, 1] +comment = "Normal case with base 4 giving three 1s" +expected = 4 + +[[asserts]] +arguments = [10, 0] +comment = "Ends in 0" +expected = 5 + +[[asserts]] +arguments = [4, 2] +comment = "No valid base, returns min allowed" +expected = 3 + +[[asserts]] +arguments = [16, 0] +comment = "Power of 2" +expected = 4 + +[[asserts]] +arguments = [100, 4] +comment = "Two 4s in base 6" +expected = 6 + +[[asserts]] +arguments = [1000, 5] +comment = "Large base for one 5" +expected = 199 + +[[asserts]] +arguments = [20, 2] +comment = "Two 2s in base 9" +expected = 9 + +[[asserts]] +arguments = [12, 0] +comment = "One 0 in multiple bases, picks smallest" +expected = 3 + +[[asserts]] +arguments = [7, 1] +comment = "Two 1s in base 6" +expected = 6 + +[[asserts]] +arguments = [2000, 0] +comment = "Three zeros in base 5" +expected = 5 + +[[asserts]] +arguments = [27, 0] +comment = "Three zeros in base 3" +expected = 3 + +[[asserts]] +arguments = [81, 0] +comment = "Four zeros in base 3" +expected = 3 + +[[asserts]] +arguments = [25, 0] +comment = "Two zeros in base 5" +expected = 5 + +[[asserts]] +arguments = [10000, 0] +comment = "Four zeros in base 5" +expected = 5 + +[[asserts]] +arguments = [10000, 9] +comment = "Large base prime factorization" +expected = 97 + +[[asserts]] +arguments = [1, 1] +comment = "n equals k" +expected = 3 + +[[asserts]] +arguments = [1, 0] +comment = "n less than base logic" +expected = 3 + +[[asserts]] +arguments = [8, 2] +comment = "Two 2s in base 3" +expected = 3 + +[[asserts]] +arguments = [15, 3] +comment = "Two 3s in base 4" +expected = 4 + +[[asserts]] +arguments = [31, 3] +comment = "Two 3s in base 4 as well" +expected = 4 + +[[asserts]] +arguments = [120, 0] +comment = "One 0, picks smallest base" +expected = 3 + +[[asserts]] +arguments = [24, 0] +comment = "One 0, picks smallest base" +expected = 3 + +[[asserts]] +arguments = [36, 0] +comment = "Two zeros in base 3 and 6, picks 3" +expected = 3 + +[[asserts]] +arguments = [48, 0] +comment = "Two zeros in base 4" +expected = 4 + +[[asserts]] +arguments = [111, 1] +comment = "Three 1s in base 10" +expected = 10 + +[[asserts]] +arguments = [1000, 0] +comment = "Three zeros in base 5 (beats base 10)" +expected = 5 + +[[asserts]] +arguments = [255, 3] +comment = "Four 3s in base 4" +expected = 4 + +[[asserts]] +arguments = [15, 1] +comment = "One 1 in base 7" +expected = 7 + +[[asserts]] +arguments = [3, 2] +comment = "No valid base, n > k and no match" +expected = 3 + +[[asserts]] +arguments = [6, 5] +comment = "No valid base, returns minimum possible base 6" +expected = 6 + +[[asserts]] +arguments = [80, 8] +comment = "Two 8s in base 9" +expected = 9 + +[[asserts]] +arguments = [1000, 1] +comment = "One 1 in base 3" +expected = 3 \ No newline at end of file diff --git a/tasks/medium/math/minimal_time_partition.toml b/tasks/medium/math/minimal_time_partition.toml new file mode 100644 index 0000000..420f2e8 --- /dev/null +++ b/tasks/medium/math/minimal_time_partition.toml @@ -0,0 +1,186 @@ +level = "medium" +name = "minimal_time_partition" +tags = ["math", "algorithms", "optimization"] +time_to_solve_sec = 450 + +description_en = """ +On a distant planet, a day lasts exactly $n$ seconds. + +Represent the number $n$ as a product of three natural numbers $a, b, c$ ($a \cdot b \cdot c = n$) such that the difference between the maximum and minimum of these three numbers is **minimal**. + +Return the three numbers as a list sorted in ascending order. +""" + +description_ru = """ +На некоторой планете сутки длятся ровно $n$ секунд. + +Представьте число $n$ в виде произведения трёх натуральных чисел $a, b, c$ ($a \cdot b \cdot c = n$) так, чтобы разность между максимальным и минимальным из этих чисел была **минимальной**. + +Верните эти три числа в виде списка, отсортированного по возрастанию. +""" + +limits = """ +- $1 \leq n \leq 10^9$ +""" + +solution = """ +def solution(n: int) -> list: + res, min_diff = [], n + for a in range(1, int(n**(1/3)) + 2): + if n % a == 0: + k = n // a + for b in range(int(k**0.5), a - 1, -1): + if k % b == 0: + c = k // b + if c - a < min_diff: + min_diff, res = c - a, [a, b, c] + break + return sorted(res) +""" + +examples = """ +solution(1) == [1, 1, 1] +solution(24) == [2, 3, 4] +solution(60) == [3, 4, 5] +solution(1000) == [10, 10, 10] +""" + +[[input_signature]] +argument_name = "n" +[input_signature.type] +name = "integer" + +[output_signature.type] +name = "array" +[output_signature.type.nested] +name = "integer" + +[[asserts]] +arguments = [1] +comment = "Smallest possible input" +expected = [1, 1, 1] + +[[asserts]] +arguments = [2] +comment = "Small prime" +expected = [1, 1, 2] + +[[asserts]] +arguments = [3] +comment = "Small prime" +expected = [1, 1, 3] + +[[asserts]] +arguments = [4] +comment = "Perfect square" +expected = [1, 2, 2] + +[[asserts]] +arguments = [6] +comment = "Small composite" +expected = [1, 2, 3] + +[[asserts]] +arguments = [8] +comment = "Perfect cube" +expected = [2, 2, 2] + +[[asserts]] +arguments = [12] +comment = "Multiple factors" +expected = [2, 2, 3] + +[[asserts]] +arguments = [24] +comment = "Standard Earth hour/day logic" +expected = [2, 3, 4] + +[[asserts]] +arguments = [27] +comment = "Odd perfect cube" +expected = [3, 3, 3] + +[[asserts]] +arguments = [30] +comment = "Product of three primes" +expected = [2, 3, 5] + +[[asserts]] +arguments = [48] +comment = "Minimal difference search" +expected = [3, 4, 4] + +[[asserts]] +arguments = [60] +comment = "Standard Earth minute/hour logic" +expected = [3, 4, 5] + +[[asserts]] +arguments = [64] +comment = "Power of 2" +expected = [4, 4, 4] + +[[asserts]] +arguments = [72] +comment = "Highly composite" +expected = [3, 4, 6] + +[[asserts]] +arguments = [100] +comment = "Perfect square 10x10" +expected = [4, 5, 5] + +[[asserts]] +arguments = [120] +comment = "Composite near cube root" +expected = [4, 5, 6] + +[[asserts]] +arguments = [125] +comment = "Perfect cube of 5" +expected = [5, 5, 5] + +[[asserts]] +arguments = [216] +comment = "Perfect cube of 6" +expected = [6, 6, 6] + +[[asserts]] +arguments = [999] +comment = "Large composite" +expected = [3, 9, 37] + +[[asserts]] +arguments = [1000] +comment = "Large perfect cube" +expected = [10, 10, 10] + +[[asserts]] +arguments = [1001] +comment = "Product of 7, 11, 13" +expected = [7, 11, 13] + +[[asserts]] +arguments = [3600] +comment = "Seconds in an hour" +expected = [15, 15, 16] + +[[asserts]] +arguments = [86400] +comment = "Seconds in a standard day" +expected = [40, 45, 48] + +[[asserts]] +arguments = [999999937] +comment = "Large prime number" +expected = [1, 1, 999999937] + +[[asserts]] +arguments = [1000000] +comment = "One million" +expected = [100, 100, 100] + +[[asserts]] +arguments = [1000000000] +comment = "Maximum input - one billion" +expected = [1000, 1000, 1000] \ No newline at end of file diff --git a/tasks/medium/math/modulo_inverse.toml b/tasks/medium/math/modulo_inverse.toml new file mode 100644 index 0000000..468ce6d --- /dev/null +++ b/tasks/medium/math/modulo_inverse.toml @@ -0,0 +1,238 @@ +level = "medium" +name = "modular_inverse" +tags = ["math", "number_theory", "modular_arithmetic"] +time_to_solve_sec = 450 + +description_en = """ +Given an integer $a$ and a prime number $m$, find the modular multiplicative inverse of $a$ modulo $m$. + +The modular inverse of $a$ modulo $m$ is an integer $x$ such that $(a \\times x) \\pmod m = 1$. + +If the inverse does not exist (for example, if $a$ is a multiple of $m$), return $-1$. +""" + +description_ru = """ +Даны целое число $a$ и простое число $m$. Найдите модульное мультипликативное обратное для $a$ по модулю $m$. + +Модульное обратное для $a$ по модулю $m$ — это такое целое число $x$, что $(a \\times x) \\pmod m = 1$. + +Если обратного не существует (например, если $a$ кратно $m$), верните $-1$. +""" + +limits = """ +- $-10^9 \\leq a \\leq 10^9$ +- $2 \\leq m \\leq 10^9+7$ +- $m$ is always a prime number +""" + +solution = """ +def solution(a: int, m: int) -> int: + a = a % m + if a == 0: + return -1 + return pow(a, m - 2, m) +""" + +examples = """ +solution(0, 5) == -1 +solution(3, 11) == 4 +solution(10, 17) == 12 +""" + +[[input_signature]] +argument_name = "a" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "m" +[input_signature.type] +name = "integer" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [3, 11] +comment = "Simple prime modulo" +expected = 4 + +[[asserts]] +arguments = [10, 17] +comment = "Another prime modulo" +expected = 12 + +[[asserts]] +arguments = [2, 5] +comment = "Smallest odd prime" +expected = 3 + +[[asserts]] +arguments = [0, 7] +comment = "Zero input, no inverse" +expected = -1 + +[[asserts]] +arguments = [7, 7] +comment = "Multiple of modulo, no inverse" +expected = -1 + +[[asserts]] +arguments = [-3, 11] +comment = "Negative input" +expected = 7 + +[[asserts]] +arguments = [1, 13] +comment = "One modulo any prime is 1" +expected = 1 + +[[asserts]] +arguments = [-1, 13] +comment = "Minus one modulo prime" +expected = 12 + +[[asserts]] +arguments = [100, 3] +comment = "Large number small prime" +expected = 1 + +[[asserts]] +arguments = [2, 3] +comment = "Self-inverse modulo 3" +expected = 2 + +[[asserts]] +arguments = [3, 5] +comment = "Prime modulo 5" +expected = 2 + +[[asserts]] +arguments = [4, 5] +comment = "Modulo 5 minus one" +expected = 4 + +[[asserts]] +arguments = [5, 7] +comment = "Prime modulo 7" +expected = 3 + +[[asserts]] +arguments = [6, 7] +comment = "Self inverse modulo 7" +expected = 6 + +[[asserts]] +arguments = [2, 7] +comment = "Small number modulo 7" +expected = 4 + +[[asserts]] +arguments = [4, 7] +comment = "Symmetric case modulo 7" +expected = 2 + +[[asserts]] +arguments = [2, 11] +comment = "Modulo 11" +expected = 6 + +[[asserts]] +arguments = [5, 11] +comment = "Middle number modulo 11" +expected = 9 + +[[asserts]] +arguments = [8, 11] +comment = "Larger number modulo 11" +expected = 7 + +[[asserts]] +arguments = [9, 11] +comment = "Modulo 11 symmetric" +expected = 5 + +[[asserts]] +arguments = [14, 11] +comment = "Greater than modulo" +expected = 4 + +[[asserts]] +arguments = [-2, 11] +comment = "Negative input modulo 11" +expected = 5 + +[[asserts]] +arguments = [-4, 5] +comment = "Negative equivalent to 1" +expected = 1 + +[[asserts]] +arguments = [-5, 5] +comment = "Negative multiple of modulo" +expected = -1 + +[[asserts]] +arguments = [1, 2] +comment = "Smallest prime" +expected = 1 + +[[asserts]] +arguments = [2, 2] +comment = "Even number modulo 2" +expected = -1 + +[[asserts]] +arguments = [-1, 2] +comment = "Negative odd number modulo 2" +expected = 1 + +[[asserts]] +arguments = [15, 17] +comment = "Modulo 17" +expected = 8 + +[[asserts]] +arguments = [9, 19] +comment = "Modulo 19" +expected = 17 + +[[asserts]] +arguments = [-20, 19] +comment = "Negative exceeding modulo" +expected = 18 + +[[asserts]] +arguments = [2, 1000000007] +comment = "Large prime modulo, simple number" +expected = 500000004 + +[[asserts]] +arguments = [1000000006, 1000000007] +comment = "Large prime modulo, minus one equivalent" +expected = 1000000006 + +[[asserts]] +arguments = [1000000007, 1000000007] +comment = "Exact large prime multiple" +expected = -1 + +[[asserts]] +arguments = [-1000000000, 1000000007] +comment = "Large negative input near modulo" +expected = 142857144 + +[[asserts]] +arguments = [-2, 1000000007] +comment = "Negative small number with large prime" +expected = 500000003 + +[[asserts]] +arguments = [2, 998244353] +comment = "Alternative famous large prime" +expected = 499122177 + +[[asserts]] +arguments = [3, 998244353] +comment = "Alternative large prime inverse of 3" +expected = 332748118 \ No newline at end of file diff --git a/tasks/medium/math/prime_factorization.toml b/tasks/medium/math/prime_factorization.toml new file mode 100644 index 0000000..01e80c0 --- /dev/null +++ b/tasks/medium/math/prime_factorization.toml @@ -0,0 +1,199 @@ +level = "medium" +name = "prime_factorization" +tags = ["math", "algorithms"] +time_to_solve_sec = 400 + +description_en = """ +Given an integer $n$, decompose it into prime factors and return the result as a string. + +The prime factors must be ordered in ascending order. Represent the decomposition in the format `"p1^k1*p2^k2*..."`. If a prime factor has a power of $1$, omit the exponent. +""" + +description_ru = """ +Дано целое число $n$. Разложите его на простые множители и верните результат в виде строки. + +Простые множители должны быть расположены в порядке возрастания. Представьте разложение в формате `"p1^k1*p2^k2*..."`. Если степень множителя равна $1$, опустите показатель степени. +""" + +limits = """ +- $2 \leq n \leq 10^9$ +""" + +solution = """ +def solution(n: int) -> str: + res, d = [], 2 + while d * d <= n: + c = 0 + while n % d == 0: + c, n = c + 1, n // d + if c: + res.append(f"{d}^{c}" if c > 1 else str(d)) + d += 1 + if n > 1: + res.append(str(n)) + return "*".join(res) +""" + +examples = """ +solution(2) == "2" +solution(12) == "2^2*3" +solution(1008) == "2^4*3^2*7" +""" + +[[input_signature]] +argument_name = "n" +[input_signature.type] +name = "integer" + +[output_signature.type] +name = "string" + +[[asserts]] +arguments = [2] +comment = "Smallest prime" +expected = "2" + +[[asserts]] +arguments = [3] +comment = "Small prime" +expected = "3" + +[[asserts]] +arguments = [4] +comment = "Smallest composite" +expected = "2^2" + +[[asserts]] +arguments = [12] +comment = "Mixed small factors" +expected = "2^2*3" + +[[asserts]] +arguments = [13] +comment = "Prime number" +expected = "13" + +[[asserts]] +arguments = [25] +comment = "Square of prime" +expected = "5^2" + +[[asserts]] +arguments = [27] +comment = "Cube of prime" +expected = "3^3" + +[[asserts]] +arguments = [30] +comment = "Product of distinct small primes" +expected = "2*3*5" + +[[asserts]] +arguments = [97] +comment = "Prime near 100" +expected = "97" + +[[asserts]] +arguments = [100] +comment = "Powers of 2 and 5" +expected = "2^2*5^2" + +[[asserts]] +arguments = [121] +comment = "Square of 11" +expected = "11^2" + +[[asserts]] +arguments = [144] +comment = "Square of 12" +expected = "2^4*3^2" + +[[asserts]] +arguments = [210] +comment = "Product of first four primes" +expected = "2*3*5*7" + +[[asserts]] +arguments = [360] +comment = "Multiple factors" +expected = "2^3*3^2*5" + +[[asserts]] +arguments = [1008] +comment = "From description" +expected = "2^4*3^2*7" + +[[asserts]] +arguments = [1024] +comment = "Power of 2" +expected = "2^10" + +[[asserts]] +arguments = [86400] +comment = "Seconds in a day" +expected = "2^7*3^3*5^2" + +[[asserts]] +arguments = [123456] +comment = "Contains larger prime factor" +expected = "2^6*3*643" + +[[asserts]] +arguments = [131072] +comment = "Power of 2" +expected = "2^17" + +[[asserts]] +arguments = [65537] +comment = "Fermat prime" +expected = "65537" + +[[asserts]] +arguments = [510510] +comment = "Product of first 7 primes" +expected = "2*3*5*7*11*13*17" + +[[asserts]] +arguments = [1000003] +comment = "Prime just over a million" +expected = "1000003" + +[[asserts]] +arguments = [1048575] +comment = "Composite near power of 2" +expected = "3*5^2*11*31*41" + +[[asserts]] +arguments = [1048576] +comment = "2^20" +expected = "2^20" + +[[asserts]] +arguments = [1999966] +comment = "2 times large prime" +expected = "2*999983" + +[[asserts]] +arguments = [9699690] +comment = "Product of first 8 primes" +expected = "2*3*5*7*11*13*17*19" + +[[asserts]] +arguments = [223092870] +comment = "Product of first 9 primes" +expected = "2*3*5*7*11*13*17*19*23" + +[[asserts]] +arguments = [536870912] +comment = "Large power of 2" +expected = "2^29" + +[[asserts]] +arguments = [999983] +comment = "Large prime" +expected = "999983" + +[[asserts]] +arguments = [1000000000] +comment = "Max limit boundary" +expected = "2^9*5^9" \ No newline at end of file diff --git a/tasks/medium/math/twin_prime_count.toml b/tasks/medium/math/twin_prime_count.toml new file mode 100644 index 0000000..a95817f --- /dev/null +++ b/tasks/medium/math/twin_prime_count.toml @@ -0,0 +1,203 @@ +level = "medium" +name = "twin_prime_count" +tags = ["math", "algorithms"] +time_to_solve_sec = 400 + +description_en = """ +A prime number $p$ is considered to have a "pair" if there exists another prime number $x$ such that $|p - x| = 2$. + +Given a segment $[a, b]$, find the total number of prime numbers within this segment that have a pair. + +Note that the pair $x$ does not necessarily have to belong to the segment $[a, b]$. +""" + +description_ru = """ +Назовём парой простого числа $p$ такое простое число $x$, что $|p - x| = 2$. + +На отрезке $[a, b]$ найдите количество простых чисел, имеющих пару. + +Обратите внимание, что парное число $x$ не обязательно должно принадлежать отрезку $[a, b]$. +""" + +limits = """ +- $0 \\leq a \\leq b \\leq 10^5$ +""" + +solution = """ +def solution(a: int, b: int) -> int: + def is_prime(n: int) -> bool: + if n < 2: return False + for i in range(2, int(n**0.5) + 1): + if n % i == 0: return False + return True + return sum(1 for p in range(a, b + 1) if is_prime(p) and (is_prime(p - 2) or is_prime(p + 2))) +""" + +examples = """ +solution(3, 3) == 1 +solution(1, 5) == 2 +solution(10, 20) == 4 +""" + +[[input_signature]] +argument_name = "a" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "b" +[input_signature.type] +name = "integer" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [1, 5] +comment = "Small interval with pairs" +expected = 2 + +[[asserts]] +arguments = [10, 20] +comment = "Interval with multiple twin primes" +expected = 4 + +[[asserts]] +arguments = [3, 3] +comment = "Single prime with a pair" +expected = 1 + +[[asserts]] +arguments = [1, 10] +comment = "First ten numbers" +expected = 3 + +[[asserts]] +arguments = [20, 30] +comment = "Interval with one paired prime" +expected = 1 + +[[asserts]] +arguments = [30, 40] +comment = "Interval with one paired prime" +expected = 1 + +[[asserts]] +arguments = [40, 50] +comment = "Interval with two paired primes" +expected = 2 + +[[asserts]] +arguments = [50, 60] +comment = "Interval with one paired prime" +expected = 1 + +[[asserts]] +arguments = [60, 70] +comment = "Interval with one paired prime" +expected = 1 + +[[asserts]] +arguments = [70, 80] +comment = "Interval with two paired primes" +expected = 2 + +[[asserts]] +arguments = [80, 90] +comment = "Interval with no paired primes" +expected = 0 + +[[asserts]] +arguments = [90, 100] +comment = "Interval with no paired primes" +expected = 0 + +[[asserts]] +arguments = [1, 100] +comment = "Large interval up to 100" +expected = 15 + +[[asserts]] +arguments = [2, 2] +comment = "Single prime without a pair" +expected = 0 + +[[asserts]] +arguments = [5, 5] +comment = "Single prime with pairs on both sides" +expected = 1 + +[[asserts]] +arguments = [7, 7] +comment = "Single prime with one pair" +expected = 1 + +[[asserts]] +arguments = [8, 8] +comment = "Single non-prime" +expected = 0 + +[[asserts]] +arguments = [13, 13] +comment = "Single prime with a pair" +expected = 1 + +[[asserts]] +arguments = [14, 16] +comment = "Interval without primes" +expected = 0 + +[[asserts]] +arguments = [100, 110] +comment = "Interval over 100 with multiple pairs" +expected = 4 + +[[asserts]] +arguments = [110, 120] +comment = "Prime in interval without a pair" +expected = 0 + +[[asserts]] +arguments = [227, 229] +comment = "Exact interval matching twin primes" +expected = 2 + +[[asserts]] +arguments = [200, 220] +comment = "Prime in interval without a pair" +expected = 0 + +[[asserts]] +arguments = [1, 2] +comment = "Interval with prime 2 only" +expected = 0 + +[[asserts]] +arguments = [140, 150] +comment = "Prime with a pair outside the right boundary" +expected = 1 + +[[asserts]] +arguments = [150, 160] +comment = "Prime with a pair outside the left boundary" +expected = 1 + +[[asserts]] +arguments = [149, 151] +comment = "Exact bounds matching twin primes" +expected = 2 + +[[asserts]] +arguments = [137, 139] +comment = "Exact bounds matching twin primes" +expected = 2 + +[[asserts]] +arguments = [1, 20] +comment = "First twenty numbers" +expected = 7 + +[[asserts]] +arguments = [0, 1] +comment = "Zeros and ones" +expected = 0 \ No newline at end of file diff --git a/tasks/medium/regex/alien_signal_compression.toml b/tasks/medium/regex/alien_signal_compression.toml new file mode 100644 index 0000000..3179423 --- /dev/null +++ b/tasks/medium/regex/alien_signal_compression.toml @@ -0,0 +1,204 @@ +level = "medium" +name = "alien_signal_compression" +tags = ["strings", "regex"] +time_to_solve_sec = 400 + +description_en = """ +You intercept an alien transmission and need to compress it to save storage space. + +The transmission is a string containing words (only English letters), numbers (valid 32-bit integers without leading zeros), spaces, tabs, and newlines. Compress the message using the following three steps: + +1. Replace all newlines (`\n`) with semicolons (`;`), then remove all spaces and tabs. +2. Reduce every word (a contiguous sequence of letters) to just its first letter, preserving the original case. +3. Compress numbers ending in consecutive zeros using standard scientific notation (e.g., `1750000` becomes `175e4`). Only do this if the resulting string is **strictly shorter** than the original number. + +Return the fully compressed transmission. +""" + +description_ru = """ +Вы перехватили инопланетную передачу, и ее необходимо сжать для экономии места. + +Передача представляет собой строку, содержащую слова (только английские буквы), числа (корректные 32-битные целые числа без ведущих нулей), пробелы, табуляции и символы перевода строки. Сожмите сообщение, выполнив следующие три шага: + +1. Замените все переводы строк (`\n`) на точки с запятой (`;`), затем удалите все пробелы и табуляции. +2. Сократите каждое слово (непрерывную последовательность букв) до первой буквы, сохранив её регистр. +3. Сожмите числа, оканчивающиеся на идущие подряд нули, используя стандартную нотацию (например, `1750000` становится `175e4`). Делайте это **только если** полученная строка строго короче исходного числа. + +Верните полностью сжатую передачу. +""" + +limits = """ +- $1 \leq \text{len}(\text{text}) \leq 10^4$ +- $\text{text}$ contains only English letters, digits, spaces, tabs, and newline characters. +- All numbers are valid 32-bit integers without leading zeros (except for $0$ itself). +""" + +solution = """ +import re + +def solution(text: str) -> str: + text = re.sub(r'[a-zA-Z]+', lambda m: m.group()[0], text) + + def comp_num(m): + v = m.group() + s = v.rstrip('0') + return min(v, f"{s}e{len(v)-len(s)}" if s else v, key=len) + + text = re.sub(r'\\d+', comp_num, text) + return text.replace(' ', '').replace('\\t', '').replace('\\n', ';') +""" + +examples = """ +solution("Alpha 1000") == "A1e3" +solution("Hello\\nWorld") == "H;W" +solution("100 1000") == "1001e3" +solution("A 0 B 0") == "A0B0" +""" + +[[input_signature]] +argument_name = "text" +[input_signature.type] +name = "string" + +[output_signature.type] +name = "string" + +[[asserts]] +arguments = ["Alpha 1000"] +comment = "Compress number and word" +expected = "A1e3" + +[[asserts]] +arguments = ["Hello\nWorld"] +comment = "Newline to semicolon" +expected = "H;W" + +[[asserts]] +arguments = ["100 1000"] +comment = "Strictly shorter requirement for numbers" +expected = "1001e3" + +[[asserts]] +arguments = ["A 0 B 0"] +comment = "Zero handling" +expected = "A0B0" + +[[asserts]] +arguments = ["Space Tabs\t\t\tHere"] +comment = "Multiple whitespace removal" +expected = "STH" + +[[asserts]] +arguments = ["Number 5000000 is Big"] +comment = "Large number compression" +expected = "N5e6iB" + +[[asserts]] +arguments = ["Very\nLong\nTransmission\n1000000000"] +comment = "Multiple newlines and large number" +expected = "V;L;T;1e9" + +[[asserts]] +arguments = ["NoZerosHere 12345"] +comment = "Number without zeros" +expected = "NH12345" + +[[asserts]] +arguments = ["ZerosAtStart 1002000"] +comment = "Zeros inside and at end" +expected = "ZAS1002e3" + +[[asserts]] +arguments = ["Mix 100 and 1000"] +comment = "Mix of compressible and uncompressible numbers" +expected = "M100a1e3" + +[[asserts]] +arguments = [" \t\n "] +comment = "Only whitespace" +expected = ";" + +[[asserts]] +arguments = ["ABC DEF GHI"] +comment = "All caps words" +expected = "ADG" + +[[asserts]] +arguments = ["a1b2c3d4"] +comment = "Alternating words and numbers without spaces" +expected = "a1b2c3d4" + +[[asserts]] +arguments = ["1200 34000 560000"] +comment = "Multiple compressible and uncompressible numbers" +expected = "120034e356e4" + +[[asserts]] +arguments = ["End of transmission 0"] +comment = "Words with zero" +expected = "Eot0" + +[[asserts]] +arguments = ["A B C\n1 2 3\nD E F\n4000 50000"] +comment = "Complex mixed string" +expected = "ABC;123;DEF;4e35e4" + +[[asserts]] +arguments = ["Trailing zeros in word 1000"] +comment = "Sentence with compressible number" +expected = "Tziw1e3" + +[[asserts]] +arguments = ["One 1 Two 20 Three 300 Four 4000"] +comment = "Scaling zeros" +expected = "O1T20T300F4e3" + +[[asserts]] +arguments = ["X Y Z 1000000000 2000000000"] +comment = "Maximum 32-bit limits" +expected = "XYZ1e92e9" + +[[asserts]] +arguments = ["lower CASE upper CASE"] +comment = "Mixed casing preservation" +expected = "lCuC" + +[[asserts]] +arguments = ["Multi\nLine\n\n\nTest"] +comment = "Consecutive newlines" +expected = "M;L;;;T" + +[[asserts]] +arguments = ["1"] +comment = "Single digit" +expected = "1" + +[[asserts]] +arguments = ["Z"] +comment = "Single letter" +expected = "Z" + +[[asserts]] +arguments = ["10"] +comment = "Ten is not strictly shorter as 1e1" +expected = "10" + +[[asserts]] +arguments = ["200"] +comment = "Two hundred is not strictly shorter as 2e2" +expected = "200" + +[[asserts]] +arguments = ["50000000 000"] +comment = "Space separated zeros" +expected = "5e7000" + +[[asserts]] +arguments = ["a\n\n\nb\t\t\tc 10000"] +comment = "Dense separators" +expected = "a;;;bc1e4" + +[[asserts]] +arguments = ["word1000word"] +comment = "Number sandwiched between words" +expected = "w1e3w" \ No newline at end of file diff --git a/tasks/medium/regex/censor_emails.toml b/tasks/medium/regex/censor_emails.toml new file mode 100644 index 0000000..46fd812 --- /dev/null +++ b/tasks/medium/regex/censor_emails.toml @@ -0,0 +1,196 @@ +level = "medium" +name = "censor_emails" +tags = ["strings", "formatting"] +time_to_solve_sec = 400 + +description_en = """ +Given a string `text` containing words separated by single spaces. Some of these words are email addresses. + +In this task, an email address is defined as any word that contains exactly one `@` symbol and has at least one character before the `@`. + +Your task is to censor these email addresses by keeping the first character of the local part (the part before `@`), replacing the rest of the local part with exactly three asterisks `***`, and keeping the `@` and the domain part intact. + +Return the censored text. +""" + +description_ru = """ +Дана строка `text`, содержащая слова, разделенные одиночными пробелами. Некоторые из этих слов являются email-адресами. + +В этой задаче email-адрес определяется как любое слово, содержащее ровно один символ `@` и имеющее хотя бы один символ перед `@`. + +Ваша задача — зацензурить эти email-адреса: оставьте первый символ локальной части (до `@`), замените остальную локальную часть ровно на три звездочки `***`, а символ `@` и доменную часть оставьте без изменений. + +Верните зацензуренный текст. +""" + +limits = """ +- $0 \\leq \\text{len}(\\text{text}) \\leq 10^4$ +""" + +solution = """ +def solution(text: str) -> str: + if not text: + return "" + res = [] + for word in text.split(" "): + if word.count("@") == 1 and word.index("@") > 0: + u, d = word.split("@") + word = f"{u[0]}***@{d}" + res.append(word) + return " ".join(res) +""" + +examples = """ +solution("") == "" +solution("a@b.com") == "a***@b.com" +solution("Contact a@a.com") == "Contact a***@a.com" +solution("Hello john@example.com") == "Hello j***@example.com" +""" + +[[input_signature]] +argument_name = "text" +[input_signature.type] +name = "string" + +[output_signature.type] +name = "string" + +[[asserts]] +arguments = ["john@example.com"] +comment = "Single valid email" +expected = "j***@example.com" + +[[asserts]] +arguments = ["My email is john@example.com today"] +comment = "Email in sentence" +expected = "My email is j***@example.com today" + +[[asserts]] +arguments = ["Hello world"] +comment = "No emails" +expected = "Hello world" + +[[asserts]] +arguments = ["Contact a@a.com or b@b.com"] +comment = "Multiple emails" +expected = "Contact a***@a.com or b***@b.com" + +[[asserts]] +arguments = [""] +comment = "Empty string" +expected = "" + +[[asserts]] +arguments = ["q@q.com"] +comment = "Single char username" +expected = "q***@q.com" + +[[asserts]] +arguments = ["a@@b.com"] +comment = "Multiple @, not an email" +expected = "a@@b.com" + +[[asserts]] +arguments = ["@twitter"] +comment = "Starts with @, not an email" +expected = "@twitter" + +[[asserts]] +arguments = ["@"] +comment = "Just @" +expected = "@" + +[[asserts]] +arguments = ["admin@mail.ru is my email"] +comment = "Email at start" +expected = "a***@mail.ru is my email" + +[[asserts]] +arguments = ["Send to support@github.com"] +comment = "Email at end" +expected = "Send to s***@github.com" + +[[asserts]] +arguments = ["Email: john@mail.com."] +comment = "Email with punctuation attached" +expected = "Email: j***@mail.com." + +[[asserts]] +arguments = ["john.doe@example.com"] +comment = "Dots in username" +expected = "j***@example.com" + +[[asserts]] +arguments = ["a@b.com c@d.com"] +comment = "Consecutive emails" +expected = "a***@b.com c***@d.com" + +[[asserts]] +arguments = ["abc@superlongdomain.org"] +comment = "Long domain" +expected = "a***@superlongdomain.org" + +[[asserts]] +arguments = ["ADMIN@SYS.COM"] +comment = "All caps" +expected = "A***@SYS.COM" + +[[asserts]] +arguments = ["user123@123.com"] +comment = "Numbers in email" +expected = "u***@123.com" + +[[asserts]] +arguments = ["hello"] +comment = "Single word no email" +expected = "hello" + +[[asserts]] +arguments = ["a@b.com and @handle or a@@b.com and valid@email.com"] +comment = "Mixed valid and invalid" +expected = "a***@b.com and @handle or a@@b.com and v***@email.com" + +[[asserts]] +arguments = ["supercalifragilisticexpialidocious@mail.com"] +comment = "Very long username" +expected = "s***@mail.com" + +[[asserts]] +arguments = ["user@a.b.c.d.com"] +comment = "Multiple dots in domain" +expected = "u***@a.b.c.d.com" + +[[asserts]] +arguments = ["admin@"] +comment = "Missing domain" +expected = "a***@" + +[[asserts]] +arguments = ["1admin@sys.net"] +comment = "Username starts with number" +expected = "1***@sys.net" + +[[asserts]] +arguments = ["_admin@sys.net"] +comment = "Username starts with underscore" +expected = "_***@sys.net" + +[[asserts]] +arguments = ["ab@c.com"] +comment = "Username length 2" +expected = "a***@c.com" + +[[asserts]] +arguments = ["This is text without any emails at all"] +comment = "Long text without emails" +expected = "This is text without any emails at all" + +[[asserts]] +arguments = ["Multiple formats user@domain.com admin@corp.net test@test.org"] +comment = "Many emails" +expected = "Multiple formats u***@domain.com a***@corp.net t***@test.org" + +[[asserts]] +arguments = ["Nospaceshere:email@domain.com"] +comment = "Punctuation before" +expected = "N***@domain.com" \ No newline at end of file diff --git a/tasks/medium/regex/remove_comments.toml b/tasks/medium/regex/remove_comments.toml new file mode 100644 index 0000000..28aedcd --- /dev/null +++ b/tasks/medium/regex/remove_comments.toml @@ -0,0 +1,176 @@ +level = "medium" +name = "remove_comments" +tags = ["strings", "regex", "parsing"] +time_to_solve_sec = 400 + +description_en = """ +Given a string `code`, remove all single-line comments starting with `//`. + +A comment starts with `//` and continues until the end of the line (the `\\n` character). However, if `//` is located inside a string literal (enclosed in double `"` or single `'` quotes), it should **not** be removed. + +Assume that quotes are always properly closed and there are no escaped quotes (like `\\"`) inside the strings. Return the modified code. +""" + +description_ru = """ +Дана строка `code`. Удалите из нее все однострочные комментарии, начинающиеся с `//`. + +Комментарий начинается с `//` и продолжается до конца строки (символа переноса строки `\\n`). Однако, если `//` находится внутри строкового литерала (заключенного в двойные `"` или одинарные `'` кавычки), он **не** должен удаляться. + +Гарантируется, что кавычки всегда закрыты и внутри строк нет экранированных кавычек (например, `\\"`). Верните измененный код. +""" + +limits = """ +- $0 \\leq \\text{len}(\\text{code}) \\leq 10^4$ +- The string only contains valid ASCII characters. +""" + +solution = """ +import re + +def solution(code: str) -> str: + return re.sub(r'(".*?"|\\'.*?\\')|//.*', lambda m: m.group(1) or "", code) +""" + +examples = """ +solution("//") == "" +solution("a = 1 // c") == "a = 1 " +solution("s = '//' // no") == "s = '//' " +""" + +[[input_signature]] +argument_name = "code" +[input_signature.type] +name = "string" + +[output_signature.type] +name = "string" + +[[asserts]] +arguments = [""] +comment = "Empty string" +expected = "" + +[[asserts]] +arguments = ["//"] +comment = "Only comment" +expected = "" + +[[asserts]] +arguments = ["a = 1;"] +comment = "No comment" +expected = "a = 1;" + +[[asserts]] +arguments = ["a = 1; // variable"] +comment = "Simple comment" +expected = "a = 1; " + +[[asserts]] +arguments = ["\"//\""] +comment = "Comment inside double quotes" +expected = "\"//\"" + +[[asserts]] +arguments = ["'//'"] +comment = "Comment inside single quotes" +expected = "'//'" + +[[asserts]] +arguments = ["a = \"//\"; // comment"] +comment = "String and comment" +expected = "a = \"//\"; " + +[[asserts]] +arguments = ["a = '//'; // comment"] +comment = "Single quoted string and comment" +expected = "a = '//'; " + +[[asserts]] +arguments = ["a = 1\n// b\nc = 2"] +comment = "Newline and whole line comment" +expected = "a = 1\n\nc = 2" + +[[asserts]] +arguments = ["//1\n//2\n//3"] +comment = "Multiple comment lines" +expected = "\n\n" + +[[asserts]] +arguments = ["a // 1\nb // 2"] +comment = "Code and comments on multiple lines" +expected = "a \nb " + +[[asserts]] +arguments = ["///"] +comment = "Three slashes" +expected = "" + +[[asserts]] +arguments = ["////"] +comment = "Four slashes" +expected = "" + +[[asserts]] +arguments = ["/"] +comment = "Single slash" +expected = "/" + +[[asserts]] +arguments = ["a / b"] +comment = "Division operator" +expected = "a / b" + +[[asserts]] +arguments = ["a // b // c"] +comment = "Comment character inside comment" +expected = "a " + +[[asserts]] +arguments = ["\"//\" // \"//\""] +comment = "Quotes inside comment" +expected = "\"//\" " + +[[asserts]] +arguments = ["'\"//\"' // comment"] +comment = "Nested quotes 1" +expected = "'\"//\"' " + +[[asserts]] +arguments = ["\"'//'\" // comment"] +comment = "Nested quotes 2" +expected = "\"'//'\" " + +[[asserts]] +arguments = ["print(\"hello // world\"); // print"] +comment = "Real life print statement" +expected = "print(\"hello // world\"); " + +[[asserts]] +arguments = ["// a\n b // c\n d"] +comment = "Staggered code and comments" +expected = "\n b \n d" + +[[asserts]] +arguments = ["return \"//\";\n// end"] +comment = "Return statement and comment" +expected = "return \"//\";\n" + +[[asserts]] +arguments = ["string s = \"//\";"] +comment = "Just string definition" +expected = "string s = \"//\";" + +[[asserts]] +arguments = ["char c = '/'; // slash"] +comment = "Char literal and comment" +expected = "char c = '/'; " + +[[asserts]] +arguments = [" // "] +comment = "Comment with leading space" +expected = " " + +[[asserts]] +arguments = [" //"] +comment = "Comment with multiple leading spaces" +expected = " " \ No newline at end of file