From 4a31cfe3121c1437f669b13050a79987ed8bcc7b Mon Sep 17 00:00:00 2001 From: Vitaly Kozlov Date: Sat, 16 May 2026 01:41:14 +0300 Subject: [PATCH 1/3] Add new tasks --- .../arrays/largest_perimeter_triangle.toml | 186 +++++++ tasks/easy/arrays/max_stock_profit.toml | 197 ++++++++ tasks/easy/arrays/maximum_altitude.toml | 183 +++++++ tasks/easy/arrays/permutation_period.toml | 185 +++++++ tasks/easy/arrays/summary_ranges.toml | 195 +++++++ tasks/easy/arrays/toeplitz_matrix.toml | 199 ++++++++ tasks/easy/arrays/town_judge.toml | 215 ++++++++ .../easy/hash_maps/peak_performance_sum.toml | 184 +++++++ tasks/easy/math/custom_fibonacci.toml | 198 ++++++++ tasks/easy/math/expanded_notation_array.toml | 175 +++++++ .../math/primes_with_prime_digit_sum.toml | 178 +++++++ tasks/easy/math/self_dividing_numbers.toml | 182 +++++++ tasks/easy/strings/center_strings.toml | 205 ++++++++ tasks/easy/strings/digit_snake_formatter.toml | 207 ++++++++ .../strings/longest_balanced_substring.toml | 198 ++++++++ tasks/easy/strings/longest_common_prefix.toml | 186 +++++++ .../strings/string_blocks_transposition.toml | 204 ++++++++ tasks/medium/algo/insert_interval.toml | 236 +++++++++ tasks/medium/dp/turtle_max_path_sum.toml | 179 +++++++ tasks/medium/games/game_of_life_step.toml | 210 ++++++++ tasks/medium/games/valid_sudoku.toml | 477 ++++++++++++++++++ tasks/medium/graphs/flood_fill.toml | 226 +++++++++ .../graphs/topological_sort_possible.toml | 206 ++++++++ .../greedy/minimum_bracket_reversals.toml | 216 ++++++++ 24 files changed, 5027 insertions(+) create mode 100644 tasks/easy/arrays/largest_perimeter_triangle.toml create mode 100644 tasks/easy/arrays/max_stock_profit.toml create mode 100644 tasks/easy/arrays/maximum_altitude.toml create mode 100644 tasks/easy/arrays/permutation_period.toml create mode 100644 tasks/easy/arrays/summary_ranges.toml create mode 100644 tasks/easy/arrays/toeplitz_matrix.toml create mode 100644 tasks/easy/arrays/town_judge.toml create mode 100644 tasks/easy/hash_maps/peak_performance_sum.toml create mode 100644 tasks/easy/math/custom_fibonacci.toml create mode 100644 tasks/easy/math/expanded_notation_array.toml create mode 100644 tasks/easy/math/primes_with_prime_digit_sum.toml create mode 100644 tasks/easy/math/self_dividing_numbers.toml create mode 100644 tasks/easy/strings/center_strings.toml create mode 100644 tasks/easy/strings/digit_snake_formatter.toml create mode 100644 tasks/easy/strings/longest_balanced_substring.toml create mode 100644 tasks/easy/strings/longest_common_prefix.toml create mode 100644 tasks/easy/strings/string_blocks_transposition.toml create mode 100644 tasks/medium/algo/insert_interval.toml create mode 100644 tasks/medium/dp/turtle_max_path_sum.toml create mode 100644 tasks/medium/games/game_of_life_step.toml create mode 100644 tasks/medium/games/valid_sudoku.toml create mode 100644 tasks/medium/graphs/flood_fill.toml create mode 100644 tasks/medium/graphs/topological_sort_possible.toml create mode 100644 tasks/medium/greedy/minimum_bracket_reversals.toml diff --git a/tasks/easy/arrays/largest_perimeter_triangle.toml b/tasks/easy/arrays/largest_perimeter_triangle.toml new file mode 100644 index 0000000..75be510 --- /dev/null +++ b/tasks/easy/arrays/largest_perimeter_triangle.toml @@ -0,0 +1,186 @@ +level = "easy" +name = "largest_perimeter_triangle" +tags = ["arrays", "math", "geometry", "sorting"] +time_to_solve_sec = 200 + +description_en = """ +Given an integer array `nums` representing the lengths of line segments, return the largest perimeter of a triangle with a non-zero area, formed from three of these lengths. + +If it is impossible to form any triangle, return `0`. + +A triangle can be formed by three segments of lengths $a$, $b$, and $c$ if and only if the sum of the lengths of any two segments is strictly greater than the length of the third segment (i.e., $a + b > c$). +""" + +description_ru = """ +Дан массив целых чисел `nums`, представляющий длины отрезков. Верните наибольший периметр треугольника с ненулевой площадью, который можно составить из трех таких отрезков. + +Если составить треугольник невозможно, верните `0`. + +Треугольник можно составить из трех отрезков с длинами $a$, $b$ и $c$, если и только если сумма длин любых двух отрезков строго больше длины третьего отрезка (то есть $a + b > c$). +""" + +limits = """ +- $3 \\leq \\text{len}(nums) \\leq 10^4$ +- $1 \\leq nums[i] \\leq 10^6$ +""" + +solution = """ +def solution(nums: list) -> int: + nums.sort(reverse=True) + for i in range(len(nums) - 2): + if nums[i] < nums[i+1] + nums[i+2]: + return nums[i] + nums[i+1] + nums[i+2] + return 0 +""" + +examples = """ +solution([1, 2, 1]) == 0 +solution([2, 1, 2]) == 5 +solution([3, 6, 2, 3]) == 8 +solution([3, 2, 3, 4]) == 10 +""" + +[[input_signature]] +argument_name = "nums" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "integer" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [[2, 1, 2]] +comment = "Simple valid triangle" +expected = 5 + +[[asserts]] +arguments = [[1, 2, 1]] +comment = "Degenerate triangle (impossible)" +expected = 0 + +[[asserts]] +arguments = [[3, 2, 3, 4]] +comment = "Multiple elements, forms 3, 3, 4" +expected = 10 + +[[asserts]] +arguments = [[3, 6, 2, 3]] +comment = "Elements form 3, 3, 2" +expected = 8 + +[[asserts]] +arguments = [[3, 4, 5]] +comment = "Exact 3 elements, right triangle" +expected = 12 + +[[asserts]] +arguments = [[1, 1, 1]] +comment = "Equilateral triangle" +expected = 3 + +[[asserts]] +arguments = [[2, 2, 2, 2]] +comment = "Four equal elements" +expected = 6 + +[[asserts]] +arguments = [[10, 9, 8, 2, 1]] +comment = "Descending sequence" +expected = 27 + +[[asserts]] +arguments = [[100, 1, 1, 1]] +comment = "One huge element, rest forms small triangle" +expected = 3 + +[[asserts]] +arguments = [[10, 5, 4, 3]] +comment = "Largest element skipped" +expected = 12 + +[[asserts]] +arguments = [[1, 2, 3, 4, 5, 6]] +comment = "Consecutive numbers" +expected = 15 + +[[asserts]] +arguments = [[1, 1, 2, 3, 5, 8, 13]] +comment = "Fibonacci sequence (no triangle possible)" +expected = 0 + +[[asserts]] +arguments = [[1, 1, 2, 3, 5, 8, 13, 20]] +comment = "Slightly modified Fibonacci (valid)" +expected = 41 + +[[asserts]] +arguments = [[5, 5, 10, 10, 20]] +comment = "Repeated elements, skips 20" +expected = 25 + +[[asserts]] +arguments = [[7, 8, 9, 100, 101, 102]] +comment = "Two distinct groups, largest group works" +expected = 303 + +[[asserts]] +arguments = [[10, 10, 10, 100, 100, 100]] +comment = "Two distinct groups of equal elements" +expected = 300 + +[[asserts]] +arguments = [[10, 10, 100, 100]] +comment = "Isosceles triangle from large elements" +expected = 210 + +[[asserts]] +arguments = [[1, 2, 1, 10]] +comment = "Impossible even with more elements" +expected = 0 + +[[asserts]] +arguments = [[9, 8, 7, 6, 5]] +comment = "Descending sequence starting at 9" +expected = 24 + +[[asserts]] +arguments = [[1000, 1000, 1000]] +comment = "Large values" +expected = 3000 + +[[asserts]] +arguments = [[5, 12, 13]] +comment = "Pythagorean triple" +expected = 30 + +[[asserts]] +arguments = [[3, 4, 5, 6, 8, 10]] +comment = "Multiple triples" +expected = 24 + +[[asserts]] +arguments = [[2, 3, 4, 5, 10]] +comment = "Largest element cannot be used" +expected = 12 + +[[asserts]] +arguments = [[1, 1, 1, 1000]] +comment = "One huge outlier" +expected = 3 + +[[asserts]] +arguments = [[100, 10, 10, 10]] +comment = "One huge, three identical smaller" +expected = 30 + +[[asserts]] +arguments = [[2, 2, 3]] +comment = "Valid isosceles" +expected = 7 + +[[asserts]] +arguments = [[1, 10, 100, 1000, 10000]] +comment = "Powers of 10 (no triangle possible)" +expected = 0 \ No newline at end of file diff --git a/tasks/easy/arrays/max_stock_profit.toml b/tasks/easy/arrays/max_stock_profit.toml new file mode 100644 index 0000000..df69af7 --- /dev/null +++ b/tasks/easy/arrays/max_stock_profit.toml @@ -0,0 +1,197 @@ +level = "easy" +name = "max_stock_profit" +tags = ["arrays", "greedy", "math"] +time_to_solve_sec = 250 + +description_en = """ +Given an array `prices` where `prices[i]` is the price of a given stock on the $i$-th day. + +You want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock. + +Return the maximum profit you can achieve from this transaction. If you cannot achieve any profit, return `0`. +""" + +description_ru = """ +Дан массив `prices`, где `prices[i]` — это цена акции в $i$-й день. + +Вы хотите максимизировать свою прибыль, выбрав один день для покупки одной акции и другой день в будущем для ее продажи. + +Верните максимальную прибыль, которую вы можете получить от этой сделки. Если получить прибыль невозможно, верните `0`. +""" + +limits = """ +- $1 \\leq \\text{len}(\\text{prices}) \\leq 10^5$ +- $0 \\leq \\text{prices}[i] \\leq 10^4$ +""" + +solution = """ +def solution(prices: list) -> int: + max_p, min_p = 0, float('inf') + for price in prices: + min_p = min(min_p, price) + max_p = max(max_p, price - min_p) + return max_p +""" + +examples = """ +solution([1]) == 0 +solution([1, 2]) == 1 +solution([2, 1]) == 0 +solution([7, 6, 4, 3, 1]) == 0 +solution([7, 1, 5, 3, 6, 4]) == 5 +""" + +[[input_signature]] +argument_name = "prices" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "integer" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [[7, 1, 5, 3, 6, 4]] +comment = "Buy on day 2, sell on day 5" +expected = 5 + +[[asserts]] +arguments = [[7, 6, 4, 3, 1]] +comment = "Decreasing prices, no profit possible" +expected = 0 + +[[asserts]] +arguments = [[1, 2]] +comment = "Two days, profit possible" +expected = 1 + +[[asserts]] +arguments = [[2, 1]] +comment = "Two days, decreasing prices" +expected = 0 + +[[asserts]] +arguments = [[1]] +comment = "Single day, no transaction possible" +expected = 0 + +[[asserts]] +arguments = [[1, 1, 1, 1]] +comment = "Constant prices" +expected = 0 + +[[asserts]] +arguments = [[2, 4, 1]] +comment = "Max price before min price" +expected = 2 + +[[asserts]] +arguments = [[3, 2, 6, 5, 0, 3]] +comment = "Multiple peaks and valleys" +expected = 4 + +[[asserts]] +arguments = [[1, 2, 3, 4, 5]] +comment = "Increasing prices" +expected = 4 + +[[asserts]] +arguments = [[5, 4, 3, 2, 1]] +comment = "Strictly decreasing prices" +expected = 0 + +[[asserts]] +arguments = [[1, 5, 1, 5, 1, 5]] +comment = "Alternating low and high" +expected = 4 + +[[asserts]] +arguments = [[10000, 0]] +comment = "Max possible value then 0" +expected = 0 + +[[asserts]] +arguments = [[0, 10000]] +comment = "0 then max possible value" +expected = 10000 + +[[asserts]] +arguments = [[3, 3, 5, 0, 0, 3, 1, 4]] +comment = "Mixed elements with zeroes" +expected = 4 + +[[asserts]] +arguments = [[7, 2, 5, 1, 6, 4]] +comment = "Best buy is later in the array" +expected = 5 + +[[asserts]] +arguments = [[8, 9, 2, 5, 4, 7, 1]] +comment = "Highest peak at start, best profit in middle" +expected = 5 + +[[asserts]] +arguments = [[5, 1, 5, 1, 5]] +comment = "Repeating pattern" +expected = 4 + +[[asserts]] +arguments = [[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]] +comment = "Long increasing sequence" +expected = 90 + +[[asserts]] +arguments = [[100, 90, 80, 70, 60, 50, 40, 30, 20, 10]] +comment = "Long decreasing sequence" +expected = 0 + +[[asserts]] +arguments = [[1, 2, 10, 1, 20]] +comment = "Two distinct upward trends" +expected = 19 + +[[asserts]] +arguments = [[20, 1, 10, 2, 11]] +comment = "Buy at absolute min, sell at local max" +expected = 10 + +[[asserts]] +arguments = [[10, 8, 7, 5, 2]] +comment = "No profit, all decreasing" +expected = 0 + +[[asserts]] +arguments = [[2, 2, 2, 2, 3]] +comment = "Flat then small increase" +expected = 1 + +[[asserts]] +arguments = [[3, 2, 1, 4, 5, 6]] +comment = "Drop to min, then steady increase" +expected = 5 + +[[asserts]] +arguments = [[1, 100]] +comment = "Simple max gain" +expected = 99 + +[[asserts]] +arguments = [[5, 8, 2, 10]] +comment = "Two possible buy days" +expected = 8 + +[[asserts]] +arguments = [[10, 2, 8, 1, 7]] +comment = "Profit 6 on both valid transactions, best is 6" +expected = 6 + +[[asserts]] +arguments = [[1, 2, 4, 2, 5, 7, 2, 4, 9, 0, 8]] +comment = "Complex long array" +expected = 8 + +[[asserts]] +arguments = [[0, 0, 0, 0]] +comment = "All zeroes" +expected = 0 \ No newline at end of file diff --git a/tasks/easy/arrays/maximum_altitude.toml b/tasks/easy/arrays/maximum_altitude.toml new file mode 100644 index 0000000..752a7a4 --- /dev/null +++ b/tasks/easy/arrays/maximum_altitude.toml @@ -0,0 +1,183 @@ +level = "easy" +name = "maximum_altitude" +tags = ["arrays", "math"] +time_to_solve_sec = 200 + +description_en = """ +A cyclist starts their journey at an altitude of $0$. You are given an integer array `gain` of length $n$, where `gain[i]` represents the net altitude gain between point $i$ and point $i + 1$. + +Return the highest altitude the cyclist reaches during their journey. +""" + +description_ru = """ +Велосипедист начинает свой путь на высоте $0$. Вам дан целочисленный массив `gain` длины $n$, где `gain[i]` — это изменение высоты между точкой $i$ и точкой $i + 1$. + +Верните максимальную высоту, которой достигнет велосипедист за время пути. +""" + +limits = """ +- $1 \\leq \text{len}(\text{gain}) \\leq 100$ +- $-100 \\leq \text{gain}[i] \\leq 100$ +""" + +solution = """ +def solution(gain: list) -> int: + curr = max_alt = 0 + for g in gain: + curr += g + max_alt = max(max_alt, curr) + return max_alt +""" + +examples = """ +solution([0]) == 0 +solution([1]) == 1 +solution([-4, -3, -2, -1, 4, 3, 2]) == 0 +solution([-5, 1, 5, 0, -7]) == 1 +solution([10, -5, 10, -5]) == 15 +""" + +[[input_signature]] +argument_name = "gain" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "integer" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [[-5, 1, 5, 0, -7]] +comment = "Max altitude reached in the middle" +expected = 1 + +[[asserts]] +arguments = [[-4, -3, -2, -1, 4, 3, 2]] +comment = "Never goes above starting altitude" +expected = 0 + +[[asserts]] +arguments = [[10, -5, 10, -5]] +comment = "Fluctuating altitude" +expected = 15 + +[[asserts]] +arguments = [[1]] +comment = "Single positive element" +expected = 1 + +[[asserts]] +arguments = [[-1]] +comment = "Single negative element" +expected = 0 + +[[asserts]] +arguments = [[0]] +comment = "Single zero element" +expected = 0 + +[[asserts]] +arguments = [[0, 0, 0]] +comment = "All zeros" +expected = 0 + +[[asserts]] +arguments = [[5, 5, 5]] +comment = "Constantly ascending" +expected = 15 + +[[asserts]] +arguments = [[-5, -5, -5]] +comment = "Constantly descending" +expected = 0 + +[[asserts]] +arguments = [[100, 100, -200, 50]] +comment = "Large peak then drop" +expected = 200 + +[[asserts]] +arguments = [[-100, 50, 60, -20]] +comment = "Large drop then peak" +expected = 10 + +[[asserts]] +arguments = [[10, 20, 30, 40, 50]] +comment = "Monotonically increasing" +expected = 150 + +[[asserts]] +arguments = [[-10, -20, -30, -40, -50]] +comment = "Monotonically decreasing" +expected = 0 + +[[asserts]] +arguments = [[50, -50, 50, -50]] +comment = "Oscillating starting positive" +expected = 50 + +[[asserts]] +arguments = [[-50, 50, -50, 50]] +comment = "Oscillating starting negative" +expected = 0 + +[[asserts]] +arguments = [[1, -1, 1, -1, 1, -1]] +comment = "Small oscillations starting positive" +expected = 1 + +[[asserts]] +arguments = [[-1, 1, -1, 1, -1, 1]] +comment = "Small oscillations starting negative" +expected = 0 + +[[asserts]] +arguments = [[100]] +comment = "Max possible single value" +expected = 100 + +[[asserts]] +arguments = [[-100]] +comment = "Min possible single value" +expected = 0 + +[[asserts]] +arguments = [[0, 1, -1, 0, 2, -2]] +comment = "Mixed with zeros" +expected = 2 + +[[asserts]] +arguments = [[5, 4, 3, 2, 1]] +comment = "Decreasing positive steps" +expected = 15 + +[[asserts]] +arguments = [[-5, 4, 3, 2, 1]] +comment = "Starts with dip, then recovers" +expected = 5 + +[[asserts]] +arguments = [[-10, 2, 3, 4, 5]] +comment = "Starts with big dip, recovers over time" +expected = 4 + +[[asserts]] +arguments = [[2, 3, -10, 4, 5]] +comment = "Dip in the middle" +expected = 5 + +[[asserts]] +arguments = [[10, -20, 30, -40, 50]] +comment = "Increasing oscillation amplitudes" +expected = 30 + +[[asserts]] +arguments = [[1, 2, 3, 4, 5, -15, 20]] +comment = "Drops completely then rises again" +expected = 20 + +[[asserts]] +arguments = [[50, 50, -100, 1, 2]] +comment = "Peak at the start, drop, small rise" +expected = 100 \ No newline at end of file diff --git a/tasks/easy/arrays/permutation_period.toml b/tasks/easy/arrays/permutation_period.toml new file mode 100644 index 0000000..ce6a314 --- /dev/null +++ b/tasks/easy/arrays/permutation_period.toml @@ -0,0 +1,185 @@ +level = "easy" +name = "permutation_period" +tags = ["arrays", "math", "simulation"] +time_to_solve_sec = 250 + +description_en = """ +You are given an array `p` of length $n$ containing integers from $0$ to $n - 1$. + +Imagine we have an initial array $\\text{arr} = [0, 1, 2, \\dots, n - 1]$. +In one step, we permute the elements of $\\text{arr}$ such that the new array is $\\text{new\\_arr}$, where $\\text{new\\_arr}[i] = \\text{arr}[p[i]]$. + +Return the minimum number of steps required to return $\\text{arr}$ to its initial state $[0, 1, 2, \\dots, n - 1]$. +If it is impossible to ever return to the initial state, return $-1$. +""" + +description_ru = """ +Вам дан массив `p` длины $n$, содержащий целые числа от $0$ до $n - 1$. + +Представьте, что у нас есть исходный массив $\\text{arr} = [0, 1, 2, \\dots, n - 1]$. +За один шаг мы переставляем элементы $\\text{arr}$ так, что получается новый массив $\\text{new\\_arr}$, где $\\text{new\\_arr}[i] = \\text{arr}[p[i]]$. + +Верните минимальное количество шагов, за которое массив $\\text{arr}$ вернется в свое исходное состояние $[0, 1, 2, \\dots, n - 1]$. +Если вернуться в исходное состояние невозможно, верните $-1$. +""" + +limits = """ +- $1 \\leq \\text{len}(p) \\leq 30$ +- $0 \\leq p[i] < \\text{len}(p)$ +""" + +solution = """ +def solution(p: list[int]) -> int: + if len(set(p)) != len(p): return -1 + curr, target, steps = list(p), list(range(len(p))), 1 + while curr != target: curr, steps = [curr[i] for i in p], steps + 1 + return steps +""" + +examples = """ +solution([0]) == 1 +solution([1, 0]) == 2 +solution([1, 2, 0]) == 3 +solution([0, 1, 1]) == -1 +solution([1, 2, 0, 4, 3]) == 6 +""" + +[[input_signature]] +argument_name = "p" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "integer" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [[0]] +comment = "Length 1, identical" +expected = 1 + +[[asserts]] +arguments = [[1, 0]] +comment = "Length 2, swap" +expected = 2 + +[[asserts]] +arguments = [[0, 1]] +comment = "Length 2, identical" +expected = 1 + +[[asserts]] +arguments = [[1, 2, 0]] +comment = "Cycle of 3" +expected = 3 + +[[asserts]] +arguments = [[0, 1, 2]] +comment = "Length 3, identical" +expected = 1 + +[[asserts]] +arguments = [[1, 0, 2]] +comment = "Cycle of 2 and 1" +expected = 2 + +[[asserts]] +arguments = [[1, 2, 3, 0]] +comment = "Cycle of 4" +expected = 4 + +[[asserts]] +arguments = [[1, 0, 3, 2]] +comment = "Two cycles of 2" +expected = 2 + +[[asserts]] +arguments = [[1, 2, 0, 4, 3]] +comment = "Cycles of 3 and 2 (LCM = 6)" +expected = 6 + +[[asserts]] +arguments = [[1, 2, 3, 4, 0]] +comment = "Cycle of 5" +expected = 5 + +[[asserts]] +arguments = [[0, 0, 0]] +comment = "Invalid permutation" +expected = -1 + +[[asserts]] +arguments = [[1, 1]] +comment = "Invalid permutation" +expected = -1 + +[[asserts]] +arguments = [[2, 0, 1, 4, 3, 5]] +comment = "Cycles of 3, 2, 1" +expected = 6 + +[[asserts]] +arguments = [[1, 2, 3, 0, 5, 6, 4]] +comment = "Cycles of 4 and 3 (LCM = 12)" +expected = 12 + +[[asserts]] +arguments = [[1, 2, 3, 4, 0, 6, 7, 8, 5]] +comment = "Cycles of 5 and 4 (LCM = 20)" +expected = 20 + +[[asserts]] +arguments = [[1, 2, 3, 4, 5, 0, 7, 8, 9, 6]] +comment = "Cycles of 6 and 4 (LCM = 12)" +expected = 12 + +[[asserts]] +arguments = [[1, 2, 3, 4, 5, 6, 0, 8, 9, 7]] +comment = "Cycles of 7 and 3 (LCM = 21)" +expected = 21 + +[[asserts]] +arguments = [[1, 2, 3, 4, 5, 6, 7, 0, 9, 8]] +comment = "Cycles of 8 and 2" +expected = 8 + +[[asserts]] +arguments = [[1, 2, 3, 4, 5, 6, 7, 8, 0, 9]] +comment = "Cycles of 9 and 1" +expected = 9 + +[[asserts]] +arguments = [[1, 2, 0, 4, 5, 6, 7, 3, 9, 10, 11, 12, 13, 8, 15, 14]] +comment = "Cycles of 3, 5, 6, 2 (LCM = 30)" +expected = 30 + +[[asserts]] +arguments = [[1, 2, 3, 4, 0, 6, 7, 8, 9, 10, 11, 5, 13, 14, 12]] +comment = "Cycles of 5, 7, 3 (LCM = 105)" +expected = 105 + +[[asserts]] +arguments = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 8]] +comment = "Not a permutation" +expected = -1 + +[[asserts]] +arguments = [[1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0]] +comment = "Not a permutation with 0 duplicates" +expected = -1 + +[[asserts]] +arguments = [[2, 2, 2, 2, 2]] +comment = "All same elements" +expected = -1 + +[[asserts]] +arguments = [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 15]] +comment = "Two cycles of 15" +expected = 15 + +[[asserts]] +arguments = [[1, 0, 3, 4, 2, 6, 7, 8, 5, 10, 11, 12, 13, 9]] +comment = "Cycles of 2, 3, 4, 5 (LCM = 60)" +expected = 60 \ No newline at end of file diff --git a/tasks/easy/arrays/summary_ranges.toml b/tasks/easy/arrays/summary_ranges.toml new file mode 100644 index 0000000..1e9cc36 --- /dev/null +++ b/tasks/easy/arrays/summary_ranges.toml @@ -0,0 +1,195 @@ +level = "easy" +name = "summary_ranges" +tags = ["arrays", "strings"] +time_to_solve_sec = 300 + +description_en = """ +You are given a sorted array of unique integers `nums`. + +Return the smallest sorted list of ranges that cover all the numbers in the array exactly. That is, each element of `nums` is covered by exactly one of the ranges, and there is no integer `x` such that `x` is in one of the ranges but not in `nums`. + +Each range `[a, b]` in the list should be formatted as: +- `"a->b"` if $a \\neq b$ +- `"a"` if $a = b$ +""" + +description_ru = """ +Вам дан отсортированный массив уникальных целых чисел `nums`. + +Верните минимальный отсортированный список диапазонов, которые в точности покрывают все числа в массиве. Это означает, что каждый элемент `nums` покрыт ровно одним диапазоном, и не существует такого целого числа `x`, которое находится в одном из диапазонов, но отсутствует в `nums`. + +Каждый диапазон `[a, b]` в списке должен быть отформатирован как: +- `"a->b"`, если $a \\neq b$ +- `"a"`, если $a = b$ +""" + +limits = """ +- $0 \\leq \\text{len}(nums) \\leq 10^4$ +- $-10^9 \\leq nums[i] \\leq 10^9$ +- $nums$ is strictly increasing +""" + +solution = """ +def solution(nums: list[int]) -> list[str]: + res = [] + for n in nums: + if res and res[-1][1] == n - 1: + res[-1][1] = n + else: + res.append([n, n]) + return [f"{s}->{e}" if s != e else str(s) for s, e in res] +""" + +examples = """ +solution([]) == [] +solution([-1]) == ["-1"] +solution([0, 1, 2, 4, 5, 7]) == ["0->2", "4->5", "7"] +solution([0, 2, 3, 4, 6, 8, 9]) == ["0", "2->4", "6", "8->9"] +""" + +[[input_signature]] +argument_name = "nums" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "integer" + +[output_signature.type] +name = "array" +[output_signature.type.nested] +name = "string" + +[[asserts]] +arguments = [[]] +comment = "Empty array" +expected = [] + +[[asserts]] +arguments = [[0]] +comment = "Single element zero" +expected = ["0"] + +[[asserts]] +arguments = [[-1]] +comment = "Single negative element" +expected = ["-1"] + +[[asserts]] +arguments = [[1, 2]] +comment = "Single pair" +expected = ["1->2"] + +[[asserts]] +arguments = [[1, 3]] +comment = "Two disconnected elements" +expected = ["1", "3"] + +[[asserts]] +arguments = [[0, 1, 2, 4, 5, 7]] +comment = "Mix of intervals and single elements" +expected = ["0->2", "4->5", "7"] + +[[asserts]] +arguments = [[0, 2, 3, 4, 6, 8, 9]] +comment = "Another mix from examples" +expected = ["0", "2->4", "6", "8->9"] + +[[asserts]] +arguments = [[1, 2, 3, 4, 5]] +comment = "One single interval" +expected = ["1->5"] + +[[asserts]] +arguments = [[2, 4, 6, 8]] +comment = "All isolated elements" +expected = ["2", "4", "6", "8"] + +[[asserts]] +arguments = [[-5, -4, -3, -1, 0, 1]] +comment = "Negative to positive transition" +expected = ["-5->-3", "-1->1"] + +[[asserts]] +arguments = [[-2, -1, 1, 2]] +comment = "Symmetric around zero" +expected = ["-2->-1", "1->2"] + +[[asserts]] +arguments = [[10, 11, 12, 13, 14, 15]] +comment = "Larger strictly consecutive range" +expected = ["10->15"] + +[[asserts]] +arguments = [[-10, -9, -8, 0, 1, 2, 8, 9, 10]] +comment = "Multiple separate continuous intervals" +expected = ["-10->-8", "0->2", "8->10"] + +[[asserts]] +arguments = [[-1000000000, 1000000000]] +comment = "Extreme values without overflow issues" +expected = ["-1000000000", "1000000000"] + +[[asserts]] +arguments = [[100, 101, 102, 103, 105, 106, 107]] +comment = "Two large consecutive ranges" +expected = ["100->103", "105->107"] + +[[asserts]] +arguments = [[1, 2, 3, 5, 6, 7, 9, 10, 11]] +comment = "Triplets" +expected = ["1->3", "5->7", "9->11"] + +[[asserts]] +arguments = [[-50, -49, -48]] +comment = "Negative sequence" +expected = ["-50->-48"] + +[[asserts]] +arguments = [[0, 1]] +comment = "Smallest consecutive positive" +expected = ["0->1"] + +[[asserts]] +arguments = [[-1, 0]] +comment = "Zero included" +expected = ["-1->0"] + +[[asserts]] +arguments = [[-3, -2, -1]] +comment = "Small negative sequence" +expected = ["-3->-1"] + +[[asserts]] +arguments = [[10, 20, 30, 40]] +comment = "Tens apart" +expected = ["10", "20", "30", "40"] + +[[asserts]] +arguments = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]] +comment = "Long zero to nine sequence" +expected = ["0->9"] + +[[asserts]] +arguments = [[-100, -99, -98, -96, -95, -94]] +comment = "Two negative chunks" +expected = ["-100->-98", "-96->-94"] + +[[asserts]] +arguments = [[7, 8, 9, 10, 12, 13]] +comment = "Two differently sized chunks" +expected = ["7->10", "12->13"] + +[[asserts]] +arguments = [[4, 6, 8, 10, 12]] +comment = "Even numbers" +expected = ["4", "6", "8", "10", "12"] + +[[asserts]] +arguments = [[1, 3, 5, 7, 9]] +comment = "Odd numbers" +expected = ["1", "3", "5", "7", "9"] + +[[asserts]] +arguments = [[-10, -5, 0, 5, 10]] +comment = "Step of 5" +expected = ["-10", "-5", "0", "5", "10"] \ No newline at end of file diff --git a/tasks/easy/arrays/toeplitz_matrix.toml b/tasks/easy/arrays/toeplitz_matrix.toml new file mode 100644 index 0000000..7f51e6a --- /dev/null +++ b/tasks/easy/arrays/toeplitz_matrix.toml @@ -0,0 +1,199 @@ +level = "easy" +name = "toeplitz_matrix" +tags = ["arrays", "matrices"] +time_to_solve_sec = 200 + +description_en = """ +Given an $m \\times n$ `matrix`, return `True` if the matrix is Toeplitz. Otherwise, return `False`. + +A matrix is **Toeplitz** if every diagonal from top-left to bottom-right has the same elements. +""" + +description_ru = """ +Дана матрица `matrix` размером $m \\times n$. Верните `True`, если матрица является Тёплицевой. В противном случае верните `False`. + +Матрица называется **Тёплицевой**, если каждая диагональ от верхнего левого угла до нижнего правого состоит из одинаковых элементов. +""" + +limits = """ +- $1 \\leq m, n \\leq 20$ +- $0 \\leq \\text{matrix}[i][j] \\leq 100$ +""" + +solution = """ +def solution(matrix: list[list[int]]) -> bool: + for i in range(1, len(matrix)): + for j in range(1, len(matrix[0])): + if matrix[i][j] != matrix[i-1][j-1]: + return False + return True +""" + +examples = """ +solution([[1]]) == True +solution([[1, 2], [3, 1]]) == True +solution([[1, 2], [2, 2]]) == False +solution([[1, 2, 3], [4, 1, 2], [5, 4, 1]]) == True +""" + +[[input_signature]] +argument_name = "matrix" +[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]]] +comment = "1x1 matrix is always Toeplitz" +expected = true + +[[asserts]] +arguments = [[[1, 2, 3, 4]]] +comment = "1xN matrix is always Toeplitz" +expected = true + +[[asserts]] +arguments = [[[1], [2], [3], [4]]] +comment = "Mx1 matrix is always Toeplitz" +expected = true + +[[asserts]] +arguments = [[[1, 2], [3, 1]]] +comment = "2x2 Toeplitz matrix" +expected = true + +[[asserts]] +arguments = [[[1, 2], [2, 2]]] +comment = "2x2 non-Toeplitz matrix" +expected = false + +[[asserts]] +arguments = [[[1, 2, 3, 4], [5, 1, 2, 3], [9, 5, 1, 2]]] +comment = "3x4 Toeplitz matrix" +expected = true + +[[asserts]] +arguments = [[[1, 2, 3, 4], [5, 1, 9, 3], [9, 5, 1, 2]]] +comment = "3x4 non-Toeplitz matrix with one incorrect element" +expected = false + +[[asserts]] +arguments = [[[1, 2], [1, 2]]] +comment = "Columns are identical, but diagonals are not" +expected = false + +[[asserts]] +arguments = [[[0, 0], [0, 0]]] +comment = "Matrix with all zeros" +expected = true + +[[asserts]] +arguments = [[[1, 2, 3], [4, 5, 6], [7, 8, 9]]] +comment = "Sequential matrix is not Toeplitz" +expected = false + +[[asserts]] +arguments = [[[3, 3, 3], [3, 3, 3], [3, 3, 3]]] +comment = "Matrix with all identical elements" +expected = true + +[[asserts]] +arguments = [[[1, 2, 3], [2, 1, 2], [3, 2, 1]]] +comment = "Symmetric Toeplitz matrix" +expected = true + +[[asserts]] +arguments = [[[1, 2, 3], [2, 1, 4], [3, 2, 1]]] +comment = "Almost symmetric but non-Toeplitz" +expected = false + +[[asserts]] +arguments = [[[9, 8, 7, 6], [5, 9, 8, 7], [4, 5, 9, 8], [3, 4, 5, 9]]] +comment = "4x4 Toeplitz matrix" +expected = true + +[[asserts]] +arguments = [[[9, 8, 7, 6], [5, 9, 8, 7], [4, 5, 9, 8], [3, 4, 5, 1]]] +comment = "4x4 non-Toeplitz matrix, last element wrong" +expected = false + +[[asserts]] +arguments = [[[1, 2, 3, 4, 5], [6, 1, 2, 3, 4], [7, 6, 1, 2, 3]]] +comment = "3x5 Toeplitz matrix" +expected = true + +[[asserts]] +arguments = [[[1, 2, 3, 4, 5], [6, 1, 2, 3, 4], [7, 6, 1, 2, 9]]] +comment = "3x5 non-Toeplitz matrix" +expected = false + +[[asserts]] +arguments = [[[1, 1], [2, 1], [3, 2], [4, 3]]] +comment = "4x2 Toeplitz matrix" +expected = true + +[[asserts]] +arguments = [[[1, 1], [2, 1], [3, 2], [4, 4]]] +comment = "4x2 non-Toeplitz matrix" +expected = false + +[[asserts]] +arguments = [[[5, 4, 3], [6, 5, 4], [7, 6, 5], [8, 7, 6]]] +comment = "4x3 Toeplitz matrix" +expected = true + +[[asserts]] +arguments = [[[5, 4, 3], [6, 5, 4], [7, 6, 5], [8, 7, 5]]] +comment = "4x3 non-Toeplitz matrix" +expected = false + +[[asserts]] +arguments = [[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]] +comment = "Identity matrix is Toeplitz" +expected = true + +[[asserts]] +arguments = [[[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 0]]] +comment = "Slightly modified identity matrix" +expected = false + +[[asserts]] +arguments = [[[8, 8, 8, 8], [8, 8, 8, 8], [8, 8, 8, 8], [8, 8, 8, 8]]] +comment = "4x4 matrix of 8s" +expected = true + +[[asserts]] +arguments = [[[1, 2], [3, 1], [4, 3], [5, 4], [6, 5]]] +comment = "5x2 Toeplitz matrix" +expected = true + +[[asserts]] +arguments = [[[1, 2, 3, 4, 5, 6]]] +comment = "1x6 matrix" +expected = true + +[[asserts]] +arguments = [[[1, 2], [2, 1], [1, 2]]] +comment = "Alternating elements form a valid Toeplitz pattern" +expected = true + +[[asserts]] +arguments = [[[1, 1, 1, 1], [2, 2, 2, 2]]] +comment = "Rows are internally identical but diagonals are not" +expected = false + +[[asserts]] +arguments = [[[1, 1, 1, 1], [2, 1, 1, 1]]] +comment = "Shifted identical rows form a Toeplitz matrix" +expected = true + +[[asserts]] +arguments = [[[3, 4, 5, 6], [2, 3, 4, 5], [1, 2, 3, 4]]] +comment = "Another valid 3x4 Toeplitz matrix" +expected = true \ No newline at end of file diff --git a/tasks/easy/arrays/town_judge.toml b/tasks/easy/arrays/town_judge.toml new file mode 100644 index 0000000..5cc930b --- /dev/null +++ b/tasks/easy/arrays/town_judge.toml @@ -0,0 +1,215 @@ +level = "easy" +name = "town_judge" +tags = ["arrays", "graphs"] +time_to_solve_sec = 250 + +description_en = """ +In a town, there are $n$ people labeled from $1$ to $n$. There is a rumor that one of these people is secretly the town judge. + +The town judge satisfies two properties: +1. The town judge trusts nobody. +2. Everybody (except for the town judge) trusts the town judge. + +You are given an array `trust` where `trust[i] = [a, b]` representing that the person labeled `a` trusts the person labeled `b`. + +Return the label of the town judge if they exist and can be identified, or return `-1` otherwise. +""" + +description_ru = """ +В городе живут $n$ людей, пронумерованных от $1$ до $n$. Ходят слухи, что один из них — городской судья. + +Судья должен соответствовать двум условиям: +1. Судья никому не доверяет. +2. Все остальные жители города (кроме самого судьи) доверяют судье. + +Вам дан массив пар `trust`, где `trust[i] = [a, b]` означает, что человек `a` доверяет человеку `b`. + +Верните номер городского судьи, если он существует, иначе верните `-1`. +""" + +limits = """ +- $1 \\leq n \\leq 1000$ +- $0 \\leq \\text{len}(\\text{trust}) \\leq 10^4$ +- $\\text{trust}[i][0] \\neq \\text{trust}[i][1]$ +""" + +solution = """ +def solution(n: int, trust: list) -> int: + d = [0] * (n + 1) + for a, b in trust: + d[a] -= 1 + d[b] += 1 + for i in range(1, n + 1): + if d[i] == n - 1: + return i + return -1 +""" + +examples = """ +solution(2, [[1, 2]]) == 2 +solution(3, [[1, 3], [2, 3]]) == 3 +solution(3, [[1, 3], [2, 3], [3, 1]]) == -1 +solution(3, [[1, 2], [2, 3]]) == -1 +""" + +[[input_signature]] +argument_name = "n" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "trust" +[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 = [2, [[1, 2]]] +comment = "Simple case: 1 trusts 2" +expected = 2 + +[[asserts]] +arguments = [3, [[1, 3], [2, 3]]] +comment = "Everyone trusts 3" +expected = 3 + +[[asserts]] +arguments = [3, [[1, 3], [2, 3], [3, 1]]] +comment = "Judge trusts someone (invalid)" +expected = -1 + +[[asserts]] +arguments = [3, [[1, 2], [2, 3]]] +comment = "No one is trusted by everyone else" +expected = -1 + +[[asserts]] +arguments = [4, [[1, 3], [1, 4], [2, 3], [2, 4], [4, 3]]] +comment = "3 is trusted by 1, 2, 4 and trusts no one" +expected = 3 + +[[asserts]] +arguments = [1, []] +comment = "Single person is the judge by default" +expected = 1 + +[[asserts]] +arguments = [2, []] +comment = "Two people, no trust" +expected = -1 + +[[asserts]] +arguments = [4, [[1, 2], [1, 3], [2, 1], [2, 3], [4, 1], [4, 2], [4, 3]]] +comment = "3 is trusted by everyone" +expected = 3 + +[[asserts]] +arguments = [4, [[1, 4], [2, 4], [3, 4], [4, 1]]] +comment = "Judge trusts someone" +expected = -1 + +[[asserts]] +arguments = [3, [[1, 2], [2, 1]]] +comment = "Cyclic trust with no clear judge" +expected = -1 + +[[asserts]] +arguments = [2, [[2, 1]]] +comment = "2 trusts 1" +expected = 1 + +[[asserts]] +arguments = [5, [[1, 5], [2, 5], [3, 5], [4, 5]]] +comment = "Everyone trusts 5" +expected = 5 + +[[asserts]] +arguments = [5, [[1, 5], [2, 5], [3, 5], [4, 5], [5, 4]]] +comment = "5 trusts 4, cannot be judge" +expected = -1 + +[[asserts]] +arguments = [3, [[1, 3], [1, 2], [2, 3]]] +comment = "3 is the judge" +expected = 3 + +[[asserts]] +arguments = [4, [[1, 2], [2, 3], [3, 4]]] +comment = "No one trusted by all" +expected = -1 + +[[asserts]] +arguments = [5, [[1, 2], [2, 3], [3, 4], [4, 5], [5, 1]]] +comment = "Trust cycle" +expected = -1 + +[[asserts]] +arguments = [6, [[1, 6], [2, 6], [3, 6], [4, 6], [5, 6]]] +comment = "6 is judge" +expected = 6 + +[[asserts]] +arguments = [6, [[1, 6], [2, 6], [3, 6], [4, 6], [5, 6], [1, 2]]] +comment = "Extra trust between non-judges" +expected = 6 + +[[asserts]] +arguments = [3, [[1, 2], [2, 3], [3, 2]]] +comment = "2 is trusted by 1 and 3, but 2 trusts 3" +expected = -1 + +[[asserts]] +arguments = [4, [[1, 4], [2, 4], [3, 4], [1, 2], [2, 1]]] +comment = "Complex non-judge trust" +expected = 4 + +[[asserts]] +arguments = [2, [[1, 2], [2, 1]]] +comment = "Mutual trust" +expected = -1 + +[[asserts]] +arguments = [5, [[1, 3], [2, 3], [4, 3], [5, 3], [1, 2], [2, 4]]] +comment = "3 is judge, others have complex relations" +expected = 3 + +[[asserts]] +arguments = [10, [[1, 10], [2, 10], [3, 10], [4, 10], [5, 10], [6, 10], [7, 10], [8, 10], [9, 10]]] +comment = "Large group judge" +expected = 10 + +[[asserts]] +arguments = [4, [[1, 4], [2, 4]]] +comment = "Not everyone trusts 4" +expected = -1 + +[[asserts]] +arguments = [3, [[1, 2], [1, 3]]] +comment = "No one trusted by 2 people" +expected = -1 + +[[asserts]] +arguments = [5, [[1, 2], [1, 3], [1, 4], [1, 5], [2, 3], [2, 4], [2, 5], [3, 4], [3, 5], [4, 5]]] +comment = "5 is the judge" +expected = 5 + +[[asserts]] +arguments = [3, [[1, 3], [2, 3], [2, 1]]] +comment = "3 is the judge" +expected = 3 + +[[asserts]] +arguments = [4, [[2, 1], [3, 1], [4, 1]]] +comment = "1 is judge, others trust 1" +expected = 1 + +[[asserts]] +arguments = [3, [[1, 3], [2, 3], [1, 2]]] +comment = "1 trusts 2 and 3, 2 trusts 3" +expected = 3 \ No newline at end of file diff --git a/tasks/easy/hash_maps/peak_performance_sum.toml b/tasks/easy/hash_maps/peak_performance_sum.toml new file mode 100644 index 0000000..39fde24 --- /dev/null +++ b/tasks/easy/hash_maps/peak_performance_sum.toml @@ -0,0 +1,184 @@ +level = "easy" +name = "peak_performance_sum" +tags = ["hashmaps", "arrays"] +time_to_solve_sec = 250 + +description_en = """ +You are given two arrays of the same length: `teams` and `scores`. +For each index $i$, `teams[i]` is the name of a team, and `scores[i]` is the score they achieved in a specific match. + +A team can participate in multiple matches. Find the **highest** score achieved by each unique team across all their matches, and return the sum of these highest scores. + +If the input arrays are empty, return $0$. +""" + +description_ru = """ +Вам даны два массива одинаковой длины: `teams` и `scores`. +Для каждого индекса $i$, `teams[i]` — это название команды, а `scores[i]` — количество баллов, которые она получила в конкретном матче. + +Команда может участвовать в нескольких матчах. Найдите **наивысший** балл, полученный каждой уникальной командой за все её матчи, и верните сумму этих наивысших баллов. + +Если входные массивы пусты, верните $0$. +""" + +limits = """ +- $0 \\leq \\text{len}(\\text{teams}) = \\text{len}(\\text{scores}) \\leq 10^4$ +- $-10^4 \\leq \\text{scores}[i] \\leq 10^4$ +""" + +solution = """ +def solution(teams: list, scores: list) -> int: + best = {} + for t, s in zip(teams, scores): + best[t] = max(best.get(t, s), s) + return sum(best.values()) +""" + +examples = """ +solution([], []) == 0 +solution(["A", "A"], [-10, -5]) == -5 +solution(["A", "B"], [10, 20]) == 30 +solution(["A", "B", "A"], [10, 20, 30]) == 50 +""" + +[[input_signature]] +argument_name = "teams" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "string" + +[[input_signature]] +argument_name = "scores" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "integer" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [[], []] +comment = "Empty arrays" +expected = 0 + +[[asserts]] +arguments = [["A"], [10]] +comment = "Single team, single score" +expected = 10 + +[[asserts]] +arguments = [["A", "A"], [10, 20]] +comment = "Single team, multiple increasing scores" +expected = 20 + +[[asserts]] +arguments = [["A", "A"], [20, 10]] +comment = "Single team, multiple decreasing scores" +expected = 20 + +[[asserts]] +arguments = [["A", "A"], [-10, -5]] +comment = "Single team, negative increasing scores" +expected = -5 + +[[asserts]] +arguments = [["A", "A"], [-5, -10]] +comment = "Single team, negative decreasing scores" +expected = -5 + +[[asserts]] +arguments = [["A", "B"], [10, 20]] +comment = "Two distinct teams" +expected = 30 + +[[asserts]] +arguments = [["A", "B", "A"], [10, 20, 30]] +comment = "Two teams, one improves" +expected = 50 + +[[asserts]] +arguments = [["A", "B", "A", "B"], [5, 5, 5, 5]] +comment = "Multiple teams with identical scores" +expected = 10 + +[[asserts]] +arguments = [["Red", "Blue", "Green"], [-10, -20, -30]] +comment = "Distinct teams with negative scores" +expected = -60 + +[[asserts]] +arguments = [["T1", "T2", "T1", "T2"], [100, -100, -50, 50]] +comment = "Mix of negative and positive improvements" +expected = 150 + +[[asserts]] +arguments = [["X"], [0]] +comment = "Single zero score" +expected = 0 + +[[asserts]] +arguments = [["X", "X", "X"], [0, 0, 0]] +comment = "Multiple zero scores for one team" +expected = 0 + +[[asserts]] +arguments = [["TeamA", "TeamB", "TeamC", "TeamA"], [15, 25, 35, 10]] +comment = "Later score is lower" +expected = 75 + +[[asserts]] +arguments = [["Alpha", "Beta", "Alpha", "Beta", "Gamma"], [1, 2, 3, 4, 5]] +comment = "Various teams interleaving" +expected = 12 + +[[asserts]] +arguments = [["Z", "Y", "X", "W"], [10, 10, 10, 10]] +comment = "All distinct teams, same score" +expected = 40 + +[[asserts]] +arguments = [["T1", "T1", "T1", "T1", "T1"], [-1, -2, -3, -4, -5]] +comment = "Strictly decreasing negative sequence" +expected = -1 + +[[asserts]] +arguments = [["T1", "T1", "T1", "T1", "T1"], [-5, -4, -3, -2, -1]] +comment = "Strictly increasing negative sequence" +expected = -1 + +[[asserts]] +arguments = [["One"], [9999]] +comment = "Large single value" +expected = 9999 + +[[asserts]] +arguments = [["A", "B", "C", "D", "E"], [1, -1, 2, -2, 3]] +comment = "Alternating positive and negative base line" +expected = 3 + +[[asserts]] +arguments = [["Cats", "Dogs", "Cats", "Dogs"], [13, 14, 13, 15]] +comment = "Minor score adjustments" +expected = 28 + +[[asserts]] +arguments = [["A", "a"], [10, 20]] +comment = "Case sensitivity test" +expected = 30 + +[[asserts]] +arguments = [["Team1", "Team2", "Team3", "Team1"], [-1000, 500, 0, -500]] +comment = "Deep negative improvement" +expected = 0 + +[[asserts]] +arguments = [["Same", "Same", "Different"], [50, 50, 100]] +comment = "Duplicate scores on same team" +expected = 150 + +[[asserts]] +arguments = [["A", "B", "C", "A", "B", "C"], [1, 2, 3, 4, 5, 6]] +comment = "Double pass of the same teams" +expected = 15 \ No newline at end of file diff --git a/tasks/easy/math/custom_fibonacci.toml b/tasks/easy/math/custom_fibonacci.toml new file mode 100644 index 0000000..1279dc7 --- /dev/null +++ b/tasks/easy/math/custom_fibonacci.toml @@ -0,0 +1,198 @@ +level = "easy" +name = "custom_fibonacci" +tags = ["math", "algorithms"] +time_to_solve_sec = 200 + +description_en = """ +Given three integers `f0`, `f1`, and `n`. + +Consider a sequence where the first two elements are `f0` and `f1`, and every subsequent element is the sum of the two preceding elements. + +Return `True` if `n` belongs to this sequence, and `False` otherwise. +""" + +description_ru = """ +Даны три целых числа `f0`, `f1` и `n`. + +Рассмотрим последовательность, первые два элемента которой равны `f0` и `f1`, а каждый последующий элемент равен сумме двух предыдущих. + +Верните `True`, если `n` принадлежит этой последовательности, и `False` в противном случае. +""" + +limits = """ +- $0 \\leq f_0, f_1 \\leq 1000$ +- $0 \\leq n \\leq 10^9$ +""" + +solution = """ +def solution(f0: int, f1: int, n: int) -> bool: + if n in (f0, f1): return True + if f0 == 0 and f1 == 0: return False + while f1 < n: + f0, f1 = f1, f0 + f1 + return f1 == n +""" + +examples = """ +solution(0, 1, 5) == True +solution(2, 1, 4) == True +solution(10, 20, 100) == False +""" + +[[input_signature]] +argument_name = "f0" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "f1" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "n" +[input_signature.type] +name = "integer" + +[output_signature.type] +name = "boolean" + +[[asserts]] +arguments = [0, 1, 5] +comment = "Classic Fibonacci, n = 5 is in the sequence" +expected = true + +[[asserts]] +arguments = [0, 1, 8] +comment = "Classic Fibonacci, n = 8 is in the sequence" +expected = true + +[[asserts]] +arguments = [0, 1, 4] +comment = "Classic Fibonacci, n = 4 is NOT in the sequence" +expected = false + +[[asserts]] +arguments = [2, 1, 3] +comment = "Lucas numbers, 3 is in (2, 1, 3)" +expected = true + +[[asserts]] +arguments = [2, 1, 4] +comment = "Lucas numbers, 4 is in (2, 1, 3, 4)" +expected = true + +[[asserts]] +arguments = [2, 1, 7] +comment = "Lucas numbers, 7 is in (2, 1, 3, 4, 7)" +expected = true + +[[asserts]] +arguments = [2, 1, 10] +comment = "Lucas numbers, 10 is NOT in sequence" +expected = false + +[[asserts]] +arguments = [0, 0, 0] +comment = "Zero sequence, n = 0" +expected = true + +[[asserts]] +arguments = [0, 0, 5] +comment = "Zero sequence, n = 5 is NOT in sequence" +expected = false + +[[asserts]] +arguments = [5, 5, 10] +comment = "Equal starting numbers, 10 is in sequence" +expected = true + +[[asserts]] +arguments = [5, 5, 15] +comment = "Equal starting numbers, 15 is in sequence" +expected = true + +[[asserts]] +arguments = [5, 5, 20] +comment = "Equal starting numbers, 20 is NOT in sequence" +expected = false + +[[asserts]] +arguments = [10, 20, 30] +comment = "Multiples of 10, 30 is in sequence" +expected = true + +[[asserts]] +arguments = [10, 20, 50] +comment = "Multiples of 10, 50 is in sequence" +expected = true + +[[asserts]] +arguments = [10, 20, 80] +comment = "Multiples of 10, 80 is in sequence" +expected = true + +[[asserts]] +arguments = [10, 20, 130] +comment = "Multiples of 10, 130 is in sequence" +expected = true + +[[asserts]] +arguments = [10, 20, 100] +comment = "Multiples of 10, 100 is NOT in sequence" +expected = false + +[[asserts]] +arguments = [100, 1, 101] +comment = "Decreasing start, 101 is in sequence" +expected = true + +[[asserts]] +arguments = [100, 1, 102] +comment = "Decreasing start, 102 is in sequence" +expected = true + +[[asserts]] +arguments = [100, 1, 203] +comment = "Decreasing start, 203 is in sequence" +expected = true + +[[asserts]] +arguments = [100, 1, 200] +comment = "Decreasing start, 200 is NOT in sequence" +expected = false + +[[asserts]] +arguments = [5, 10, 5] +comment = "n is equal to f0" +expected = true + +[[asserts]] +arguments = [5, 10, 10] +comment = "n is equal to f1" +expected = true + +[[asserts]] +arguments = [50, 60, 10] +comment = "n is smaller than both f0 and f1" +expected = false + +[[asserts]] +arguments = [0, 1, 102334155] +comment = "Large Fibonacci number" +expected = true + +[[asserts]] +arguments = [0, 1, 102334156] +comment = "Large number NOT in Fibonacci sequence" +expected = false + +[[asserts]] +arguments = [0, 1, 701408733] +comment = "Another large Fibonacci number" +expected = true + +[[asserts]] +arguments = [13, 21, 5] +comment = "n is smaller than f0, f1 with Fibonacci sequence" +expected = false \ No newline at end of file diff --git a/tasks/easy/math/expanded_notation_array.toml b/tasks/easy/math/expanded_notation_array.toml new file mode 100644 index 0000000..961bb2d --- /dev/null +++ b/tasks/easy/math/expanded_notation_array.toml @@ -0,0 +1,175 @@ +level = "easy" +name = "expanded_notation_array" +tags = ["math", "strings", "parsing", "arrays"] +time_to_solve_sec = 250 + +description_en = """ +Expanded Notation means an integer is written as the sum of its digits multiplied with its place value (in strictly descending powers of $10$). + +For example, $85063 = 8 \\times 10000 + 5 \\times 1000 + 6 \\times 10 + 3$. + +You are given an array of strings `arr`, where each string represents a natural number in expanded notation. The strings use `"x"` for multiplication and `"+"` for addition, with no spaces. Your task is to compute the sum for each string and return an array of these numbers in their normal integer form. +""" + +description_ru = """ +Развернутая запись означает, что целое число записано в виде суммы его цифр, умноженных на их разрядное значение (в строго убывающих степенях $10$). + +Например, $85063 = 8 \\times 10000 + 5 \\times 1000 + 6 \\times 10 + 3$. + +Вам дан массив строк `arr`, где каждая строка представляет натуральное число в развернутой записи. В строках используется `"x"` для умножения и `"+"` для сложения, без пробелов. Ваша задача — вычислить сумму для каждой строки и вернуть массив этих чисел в обычном целом виде. +""" + +limits = """ +- $1 \\leq \\text{len}(arr) \\leq 100$ +- $3 \\leq \\text{len}(arr[i]) \\leq 100$ +- $arr[i]$ contains only digits, `"x"`, and `"+"` +- Place values are powers of $10$ +""" + +solution = """ +def solution(arr: list) -> list: + return [sum(int(part.split('x')[0]) * int(part.split('x')[1]) for part in s.split('+')) for s in arr] +""" + +examples = """ +solution(["1x1"]) == [1] +solution(["9x10", "1x1"]) == [90, 1] +solution(["7x100+2x1", "8x10000+5x1000+6x10+3"]) == [702, 85063] +""" + +[[input_signature]] +argument_name = "arr" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "string" + +[output_signature.type] +name = "array" +[output_signature.type.nested] +name = "integer" + +[[asserts]] +arguments = [["8x10000+5x1000+6x10+3x1"]] +comment = "Complex example from description" +expected = [85063] + +[[asserts]] +arguments = [["7x100+2x1", "1x1"]] +comment = "Multiple elements" +expected = [702, 1] + +[[asserts]] +arguments = [["1x1"]] +comment = "Single digit" +expected = [1] + +[[asserts]] +arguments = [["9x10", "4x100000+2x100"]] +comment = "Varying lengths" +expected = [90, 400200] + +[[asserts]] +arguments = [["1x1000+1x1"]] +comment = "One thousand and one" +expected = [1001] + +[[asserts]] +arguments = [["1x10", "1x100", "1x1000"]] +comment = "Increasing powers of ten" +expected = [10, 100, 1000] + +[[asserts]] +arguments = [["5x1000+5x10", "6x10000+6x100+6x1", "7x1000000"]] +comment = "Array with three different complexities" +expected = [5050, 60606, 7000000] + +[[asserts]] +arguments = [["9x1000+9x100+9x10+9x1"]] +comment = "All nines" +expected = [9999] + +[[asserts]] +arguments = [["1x100000000+2x10000000+3x1000000+4x100000+5x10000+6x1000+7x100+8x10+9x1"]] +comment = "Consecutive digits" +expected = [123456789] + +[[asserts]] +arguments = [["2x1000000+1x1", "3x10"]] +comment = "Millions and tens" +expected = [2000001, 30] + +[[asserts]] +arguments = [["4x100+4x1", "5x100+5x10"]] +comment = "Hundreds" +expected = [404, 550] + +[[asserts]] +arguments = [["5x10000+5x1000"]] +comment = "Fifty five thousand" +expected = [55000] + +[[asserts]] +arguments = [["8x100000000", "9x100000000+9x1000000+9x10000+9x100+9x1"]] +comment = "Alternating nines and zeros" +expected = [800000000, 909090909] + +[[asserts]] +arguments = [["1x10000+1x1000+1x100+1x10+1x1", "2x100+2x10+2x1"]] +comment = "All ones and all twos" +expected = [11111, 222] + +[[asserts]] +arguments = [["3x10+3x1", "4x1"]] +comment = "All threes and fours" +expected = [33, 4] + +[[asserts]] +arguments = [["1x1000000000"]] +comment = "One billion" +expected = [1000000000] + +[[asserts]] +arguments = [["1x1000000000+1x10000000+1x100000+1x1000+1x10"]] +comment = "Alternating ones and zeros" +expected = [1010101010] + +[[asserts]] +arguments = [["5x10000+4x1000+3x100+2x10+1x1", "1x1"]] +comment = "Descending digits" +expected = [54321, 1] + +[[asserts]] +arguments = [["9x100000000+8x10000000+7x1000000+6x100000+5x10000+4x1000+3x100+2x10+1x1"]] +comment = "Long descending digits" +expected = [987654321] + +[[asserts]] +arguments = [["9x100+9x10+9x1", "8x100+8x10+8x1"]] +comment = "Nines and eights" +expected = [999, 888] + +[[asserts]] +arguments = [["7x1000+2x1", "6x1000+3x10", "5x1000+4x100"]] +comment = "Zeros in different positions" +expected = [7002, 6030, 5400] + +[[asserts]] +arguments = [["1x10000", "2x10000", "3x10000"]] +comment = "Same order of magnitude" +expected = [10000, 20000, 30000] + +[[asserts]] +arguments = [["1x100000", "2x1000000"]] +comment = "Powers of ten variations" +expected = [100000, 2000000] + +[[asserts]] +arguments = [["1x1000000+2x100000+3x10000", "4x1000+5x100+6x10+7x1"]] +comment = "Split full number across array elements" +expected = [1230000, 4567] + +[[asserts]] +arguments = [["8x100000+5x100+3x1", "2x10000+4x100+1x1"]] +comment = "Various missing place values" +expected = [800503, 20401] \ No newline at end of file diff --git a/tasks/easy/math/primes_with_prime_digit_sum.toml b/tasks/easy/math/primes_with_prime_digit_sum.toml new file mode 100644 index 0000000..0595507 --- /dev/null +++ b/tasks/easy/math/primes_with_prime_digit_sum.toml @@ -0,0 +1,178 @@ +level = "easy" +name = "primes_with_prime_digit_sum" +tags = ["math", "numbers"] +time_to_solve_sec = 250 + +description_en = """ +Find all prime numbers in the inclusive range $[a, b]$ such that the sum of their digits is also a prime number. Return the result as an array. +""" + +description_ru = """ +Найдите все простые числа на отрезке $[a, b]$ (включительно), сумма цифр которых также является простым числом. Верните результат в виде массива. +""" + +limits = """ +- $1 \\leq a \\leq b \\leq 10^4$ +""" + +solution = """ +def solution(a: int, b: int) -> list: + P = lambda n: n > 1 and all(n % i for i in range(2, int(n**0.5) + 1)) + return [x for x in range(a, b + 1) if P(x) and P(sum(map(int, str(x))))] +""" + +examples = """ +solution(30, 40) == [] +solution(10, 20) == [11] +solution(1, 10) == [2, 3, 5, 7] +""" + +[[input_signature]] +argument_name = "a" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "b" +[input_signature.type] +name = "integer" + +[output_signature.type] +name = "array" +[output_signature.type.nested] +name = "integer" + +[[asserts]] +arguments = [1, 10] +comment = "Single digit primes" +expected = [2, 3, 5, 7] + +[[asserts]] +arguments = [10, 20] +comment = "First two-digit numbers" +expected = [11] + +[[asserts]] +arguments = [20, 30] +comment = "Twenties" +expected = [23, 29] + +[[asserts]] +arguments = [30, 40] +comment = "No matching primes in this range" +expected = [] + +[[asserts]] +arguments = [40, 50] +comment = "Forties" +expected = [41, 43, 47] + +[[asserts]] +arguments = [50, 60] +comment = "Fifties without matches" +expected = [] + +[[asserts]] +arguments = [60, 70] +comment = "Sixties" +expected = [61, 67] + +[[asserts]] +arguments = [70, 80] +comment = "Seventies without matches" +expected = [] + +[[asserts]] +arguments = [80, 90] +comment = "Eighties" +expected = [83, 89] + +[[asserts]] +arguments = [90, 100] +comment = "Nineties without matches" +expected = [] + +[[asserts]] +arguments = [100, 120] +comment = "Early hundreds" +expected = [101, 113] + +[[asserts]] +arguments = [130, 140] +comment = "Range with consecutive valid primes" +expected = [131, 137, 139] + +[[asserts]] +arguments = [190, 200] +comment = "Late hundreds" +expected = [191, 193, 197, 199] + +[[asserts]] +arguments = [200, 210] +comment = "Early two-hundreds with no valid primes" +expected = [] + +[[asserts]] +arguments = [200, 250] +comment = "Larger slice in two-hundreds" +expected = [223, 227, 229, 241] + +[[asserts]] +arguments = [300, 320] +comment = "Early three-hundreds" +expected = [311, 313, 317] + +[[asserts]] +arguments = [400, 420] +comment = "Early four-hundreds" +expected = [401, 409] + +[[asserts]] +arguments = [500, 520] +comment = "Early five-hundreds without matches" +expected = [] + +[[asserts]] +arguments = [600, 620] +comment = "Early six-hundreds" +expected = [601, 607] + +[[asserts]] +arguments = [700, 720] +comment = "Early seven-hundreds" +expected = [719] + +[[asserts]] +arguments = [800, 820] +comment = "Early eight-hundreds" +expected = [809] + +[[asserts]] +arguments = [900, 920] +comment = "Early nine-hundreds" +expected = [911, 919] + +[[asserts]] +arguments = [990, 1000] +comment = "Approaching one thousand" +expected = [991] + +[[asserts]] +arguments = [1, 1] +comment = "Single value 1 (not prime)" +expected = [] + +[[asserts]] +arguments = [2, 2] +comment = "Single value 2 (prime)" +expected = [2] + +[[asserts]] +arguments = [11, 11] +comment = "Single value boundary check" +expected = [11] + +[[asserts]] +arguments = [1000, 1010] +comment = "Past one thousand without matches" +expected = [] \ No newline at end of file diff --git a/tasks/easy/math/self_dividing_numbers.toml b/tasks/easy/math/self_dividing_numbers.toml new file mode 100644 index 0000000..e3f913a --- /dev/null +++ b/tasks/easy/math/self_dividing_numbers.toml @@ -0,0 +1,182 @@ +level = "easy" +name = "self_dividing_numbers" +tags = ["math", "loops"] +time_to_solve_sec = 240 + +description_en = """ +A self-dividing number is a number that is divisible by every digit it contains. +For example, `128` is a self-dividing number because $128 \\pmod 1 = 0$, $128 \\pmod 2 = 0$, and $128 \\pmod 8 = 0$. + +A self-dividing number is not allowed to contain the digit `0`. + +Given two integers `left` and `right`, return an array of all the self-dividing numbers in the range `[left, right]` (inclusive). +""" + +description_ru = """ +Самоделящееся число — это число, которое без остатка делится на каждую из своих цифр. +Например, `128` является самоделящимся числом, так как $128 \\pmod 1 = 0$, $128 \\pmod 2 = 0$ и $128 \\pmod 8 = 0$. + +Самоделящееся число не должно содержать цифру `0`. + +Даны два целых числа `left` и `right`. Верните массив всех самоделящихся чисел в диапазоне `[left, right]` (включительно). +""" + +limits = """ +- $1 \\leq \\text{left} \\leq \\text{right} \\leq 10^4$ +""" + +solution = """ +def solution(left: int, right: int) -> list[int]: + return [n for n in range(left, right + 1) if all(int(d) != 0 and n % int(d) == 0 for d in str(n))] +""" + +examples = """ +solution(47, 49) == [48] +solution(10, 15) == [11, 12, 15] +solution(1, 10) == [1, 2, 3, 4, 5, 6, 7, 8, 9] +""" + +[[input_signature]] +argument_name = "left" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "right" +[input_signature.type] +name = "integer" + +[output_signature.type] +name = "array" +[output_signature.type.nested] +name = "integer" + +[[asserts]] +arguments = [1, 10] +comment = "Single digits" +expected = [1, 2, 3, 4, 5, 6, 7, 8, 9] + +[[asserts]] +arguments = [10, 15] +comment = "Small range with zero" +expected = [11, 12, 15] + +[[asserts]] +arguments = [47, 49] +comment = "Short range with one match" +expected = [48] + +[[asserts]] +arguments = [1, 22] +comment = "Range across two tens" +expected = [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 15, 22] + +[[asserts]] +arguments = [13, 14] +comment = "Range with no self-dividing numbers" +expected = [] + +[[asserts]] +arguments = [47, 85] +comment = "Mid-size range" +expected = [48, 55, 66, 77] + +[[asserts]] +arguments = [128, 128] +comment = "Three-digit match" +expected = [128] + +[[asserts]] +arguments = [100, 110] +comment = "Range full of zeros" +expected = [] + +[[asserts]] +arguments = [111, 115] +comment = "Range with small identical digits" +expected = [111, 112, 115] + +[[asserts]] +arguments = [15, 21] +comment = "Cross-tens range with one match" +expected = [15] + +[[asserts]] +arguments = [33, 33] +comment = "Identical digits self-dividing" +expected = [33] + +[[asserts]] +arguments = [23, 23] +comment = "Single number, non self-dividing" +expected = [] + +[[asserts]] +arguments = [312, 312] +comment = "Three-digit match check" +expected = [312] + +[[asserts]] +arguments = [41, 45] +comment = "Check divisibility logic" +expected = [44] + +[[asserts]] +arguments = [80, 90] +comment = "High two-digits range" +expected = [88] + +[[asserts]] +arguments = [300, 311] +comment = "Zeros and non-dividing" +expected = [] + +[[asserts]] +arguments = [200, 212] +comment = "Zeros jumping to valid" +expected = [212] + +[[asserts]] +arguments = [72, 73] +comment = "Exact bounds" +expected = [] + +[[asserts]] +arguments = [1000, 1010] +comment = "Thousands with zeros" +expected = [] + +[[asserts]] +arguments = [120, 130] +comment = "Hundreds range" +expected = [122, 124, 126, 128] + +[[asserts]] +arguments = [999, 999] +comment = "Maximum triple digits" +expected = [999] + +[[asserts]] +arguments = [24, 25] +comment = "Adjacent values" +expected = [24] + +[[asserts]] +arguments = [104, 104] +comment = "Contains zero, despite other checks" +expected = [] + +[[asserts]] +arguments = [61, 65] +comment = "Range with no matches" +expected = [] + +[[asserts]] +arguments = [25, 30] +comment = "Range leading to zero" +expected = [] + +[[asserts]] +arguments = [300, 315] +comment = "Wider range in hundreds" +expected = [312, 315] \ No newline at end of file diff --git a/tasks/easy/strings/center_strings.toml b/tasks/easy/strings/center_strings.toml new file mode 100644 index 0000000..7ec3828 --- /dev/null +++ b/tasks/easy/strings/center_strings.toml @@ -0,0 +1,205 @@ +level = "easy" +name = "center_strings" +tags = ["strings", "formatting"] +time_to_solve_sec = 200 + +description_en = """ +Given an array of strings, return a new array where each string is centered to the length of the longest string in the original array, padded with spaces (`" "`). + +If the padding is uneven (i.e., the difference between the maximum length and the current string's length is odd), apply the standard Python `str.center()` behavior: +- If the target width is odd and the margin is odd, the extra space goes to the **left**. +- Otherwise, the extra space goes to the **right**. + +If the input array is empty, return an empty array. +""" + +description_ru = """ +Дан массив строк. Верните новый массив, в котором каждая строка отцентрирована по длине самой длинной строки в исходном массиве и дополнена пробелами (`" "`). + +Если количество добавляемых пробелов нечетное, используйте стандартное поведение метода `str.center()` в Python: +- Если целевая ширина нечетная и общая разница нечетная, дополнительный пробел добавляется **слева**. +- Во всех остальных случаях дополнительный пробел добавляется **справа**. + +Если исходный массив пуст, верните пустой массив. +""" + +limits = """ +- $0 \\leq \\text{len}(strings) \\leq 100$ +- $0 \\leq \\text{len}(strings[i]) \\leq 100$ +""" + +solution = """ +def solution(strings: list[str]) -> list[str]: + if not strings: + return [] + max_len = max(len(s) for s in strings) + return [s.center(max_len) for s in strings] +""" + +examples = """ +solution([]) == [] +solution(["hi", "hello"]) == [" hi ", "hello"] +solution(["a", "abc", "a"]) == [" a ", "abc", " a "] +""" + +[[input_signature]] +argument_name = "strings" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "string" + +[output_signature.type] +name = "array" +[output_signature.type.nested] +name = "string" + +[[asserts]] +arguments = [[]] +comment = "Empty array" +expected = [] + +[[asserts]] +arguments = [["hello"]] +comment = "Single string" +expected = ["hello"] + +[[asserts]] +arguments = [["a", "abc"]] +comment = "Odd max len, odd string, even margin -> equal padding" +expected = [" a ", "abc"] + +[[asserts]] +arguments = [["ab", "abcd"]] +comment = "Even max len, even string, even margin -> equal padding" +expected = [" ab ", "abcd"] + +[[asserts]] +arguments = [["a", "abcd"]] +comment = "Even max len, odd string, odd margin -> extra space right" +expected = [" a ", "abcd"] + +[[asserts]] +arguments = [["abc", "a"]] +comment = "Max string first" +expected = ["abc", " a "] + +[[asserts]] +arguments = [["hi", "hello"]] +comment = "Odd max len, even string, odd margin -> extra space left" +expected = [" hi ", "hello"] + +[[asserts]] +arguments = [["", "a"]] +comment = "Odd max len, empty string, odd margin" +expected = [" ", "a"] + +[[asserts]] +arguments = [["", "ab"]] +comment = "Even max len, empty string, even margin" +expected = [" ", "ab"] + +[[asserts]] +arguments = [["A", "BB", "CCC", "DDDD"]] +comment = "Multiple lengths with max 4" +expected = [" A ", " BB ", "CCC ", "DDDD"] + +[[asserts]] +arguments = [["*", "***", "*****"]] +comment = "Stars with max 5" +expected = [" * ", " *** ", "*****"] + +[[asserts]] +arguments = [["python", "is", "fun"]] +comment = "Words with max 6" +expected = ["python", " is ", " fun "] + +[[asserts]] +arguments = [["short", "loooong"]] +comment = "Words with max 7" +expected = [" short ", "loooong"] + +[[asserts]] +arguments = [["1", "123456789"]] +comment = "1 char to 9 chars" +expected = [" 1 ", "123456789"] + +[[asserts]] +arguments = [["12", "123456789"]] +comment = "2 chars to 9 chars (extra space left)" +expected = [" 12 ", "123456789"] + +[[asserts]] +arguments = [["123", "123456789"]] +comment = "3 chars to 9 chars" +expected = [" 123 ", "123456789"] + +[[asserts]] +arguments = [["1234", "123456789"]] +comment = "4 chars to 9 chars (extra space left)" +expected = [" 1234 ", "123456789"] + +[[asserts]] +arguments = [["12345", "123456789"]] +comment = "5 chars to 9 chars" +expected = [" 12345 ", "123456789"] + +[[asserts]] +arguments = [["123456", "123456789"]] +comment = "6 chars to 9 chars (extra space left)" +expected = [" 123456 ", "123456789"] + +[[asserts]] +arguments = [["1234567", "123456789"]] +comment = "7 chars to 9 chars" +expected = [" 1234567 ", "123456789"] + +[[asserts]] +arguments = [["12345678", "123456789"]] +comment = "8 chars to 9 chars (extra space left)" +expected = [" 12345678", "123456789"] + +[[asserts]] +arguments = [["word", ""]] +comment = "Empty string padded to even length" +expected = ["word", " "] + +[[asserts]] +arguments = [["even", "odd lengths"]] +comment = "4 chars to 11 chars (extra space left)" +expected = [" even ", "odd lengths"] + +[[asserts]] +arguments = [["same", "size"]] +comment = "Already same size" +expected = ["same", "size"] + +[[asserts]] +arguments = [["a", "a", "a"]] +comment = "All identical" +expected = ["a", "a", "a"] + +[[asserts]] +arguments = [[" ", " "]] +comment = "Spaces only" +expected = [" ", " "] + +[[asserts]] +arguments = [["x", "y", "longword"]] +comment = "Single chars to even max length" +expected = [" x ", " y ", "longword"] + +[[asserts]] +arguments = [["", "", ""]] +comment = "All empty strings" +expected = ["", "", ""] + +[[asserts]] +arguments = [["align", "me", "please", "to", "center"]] +comment = "Multiple mixed strings, max 6" +expected = ["align ", " me ", "please", " to ", "center"] + +[[asserts]] +arguments = [["12345", "1234", "123", "12", "1", ""]] +comment = "Decreasing lengths, max 5" +expected = ["12345", " 1234", " 123 ", " 12 ", " 1 ", " "] \ No newline at end of file diff --git a/tasks/easy/strings/digit_snake_formatter.toml b/tasks/easy/strings/digit_snake_formatter.toml new file mode 100644 index 0000000..613a116 --- /dev/null +++ b/tasks/easy/strings/digit_snake_formatter.toml @@ -0,0 +1,207 @@ +level = "easy" +name = "digit_snake_formatter" +tags = ["strings", "formatting"] +time_to_solve_sec = 250 + +description_en = """ +Transform a digit string `n` into a "snake" format based on an integer `c`: + +1. Extract the first `c` digits from string `n`. If `c` exceeds the length of `n`, use all available digits. +2. Split the resulting substring into chunks of $8$ characters. +3. Pad the final chunk with the character `X` on the right until it reaches a length of $8$. +4. Reverse chunks located at odd indices ($1, 3, 5, \\dots$). Keep chunks at even indices ($0, 2, 4, \\dots$) as they are. +5. Return the chunks joined by newline characters (`\\n`). +""" + +description_ru = """ +Преобразуйте строку цифр `n` в формат «змейки» на основе целого числа `c`: + +1. Возьмите первые `c` цифр из строки `n`. Если `c` больше длины `n`, используйте все имеющиеся цифры. +2. Разделите полученную подстроку на блоки по $8$ символов. +3. Дополните последний блок символом `X` справа, пока его длина не станет равной $8$. +4. Разверните блоки, находящиеся на нечетных индексах ($1, 3, 5, \\dots$). Блоки на четных индексах ($0, 2, 4, \\dots$) оставьте без изменений. +5. Верните блоки, объединенные символом переноса строки (`\\n`). +""" + +limits = """ +- $0 \\leq \\text{len}(n) \\leq 1000$ +- $0 \\leq c \\leq 1000$ +- $n$ contains only digits $0-9$ +""" + +solution = """ +def solution(n: str, c: int) -> str: + s = n[:c] + chunks = [s[i:i+8].ljust(8, 'X') for i in range(0, len(s), 8)] + return "\\n".join(x[::-1] if i % 2 else x for i, x in enumerate(chunks)) +""" + +examples = """ +solution("", 5) == "" +solution("123", 0) == "" +solution("123", 2) == "12XXXXXX" +solution("1234567890", 10) == "12345678\\nXXXXXX09" +""" + +[[input_signature]] +argument_name = "n" +[input_signature.type] +name = "string" + +[[input_signature]] +argument_name = "c" +[input_signature.type] +name = "integer" + +[output_signature.type] +name = "string" + +[[asserts]] +arguments = ["", 10] +comment = "Empty string input" +expected = "" + +[[asserts]] +arguments = ["12345", 0] +comment = "Zero characters requested" +expected = "" + +[[asserts]] +arguments = ["1", 1] +comment = "Single character padding" +expected = "1XXXXXXX" + +[[asserts]] +arguments = ["12345678", 8] +comment = "Exactly one full chunk" +expected = "12345678" + +[[asserts]] +arguments = ["123456789", 9] +comment = "Two chunks, second needs padding and reversal" +expected = "12345678\nXXXXXXX9" + +[[asserts]] +arguments = ["1234567890123456", 16] +comment = "Two full chunks, second reversed" +expected = "12345678\n65432109" + +[[asserts]] +arguments = ["111111112222222233333333", 24] +comment = "Three full chunks" +expected = "11111111\n22222222\n33333333" + +[[asserts]] +arguments = ["123", 5] +comment = "c is greater than string length" +expected = "123XXXXX" + +[[asserts]] +arguments = ["0000000000000000", 16] +comment = "Identical digits" +expected = "00000000\n00000000" + +[[asserts]] +arguments = ["12345678123456781234567812345678", 32] +comment = "Four full chunks" +expected = "12345678\n87654321\n12345678\n87654321" + +[[asserts]] +arguments = ["987654321", 5] +comment = "c is smaller than first chunk size" +expected = "98765XXX" + +[[asserts]] +arguments = ["1234567890", 11] +comment = "c is larger than length, but logic handles it" +expected = "12345678\nXXXXXX09" + +[[asserts]] +arguments = ["123456781", 9] +comment = "Last chunk is single digit" +expected = "12345678\nXXXXXXX1" + +[[asserts]] +arguments = ["123456781234567", 15] +comment = "Last chunk is almost full" +expected = "12345678\nX7654321" + +[[asserts]] +arguments = ["1234567887654321", 16] +comment = "Reversing a reversed sequence" +expected = "12345678\n12345678" + +[[asserts]] +arguments = ["01234567890123456789", 20] +comment = "Three chunks, middle one full reversed" +expected = "01234567\n54321098\n6789XXXX" + +[[asserts]] +arguments = ["12121212", 8] +comment = "Repeating pattern" +expected = "12121212" + +[[asserts]] +arguments = ["1234123412341234", 16] +comment = "Repeating chunks" +expected = "12341234\n43214321" + +[[asserts]] +arguments = ["1111111100000000", 16] +comment = "Switching values between chunks" +expected = "11111111\n00000000" + +[[asserts]] +arguments = ["5555", 2] +comment = "c limits string to less than original" +expected = "55XXXXXX" + +[[asserts]] +arguments = ["123456789012345678901234567890", 25] +comment = "Multiple chunks with padding at the very end" +expected = "12345678\n65432109\n78901234\nXXXXXXX5" + +[[asserts]] +arguments = ["888888887777777766666666", 20] +comment = "Non-full third chunk" +expected = "88888888\n77777777\n6666XXXX" + +[[asserts]] +arguments = ["0000000100000002", 16] +comment = "Check specific digit placement" +expected = "00000001\n20000000" + +[[asserts]] +arguments = ["123456789999999912345678", 24] +comment = "Middle chunk all 9s" +expected = "12345678\n99999999\n12345678" + +[[asserts]] +arguments = ["1000000020000000", 16] +comment = "Zeros and specific digits" +expected = "10000000\n00000002" + +[[asserts]] +arguments = ["1234567812345678123456781234567812345678", 40] +comment = "Five chunks check" +expected = "12345678\n87654321\n12345678\n87654321\n12345678" + +[[asserts]] +arguments = ["111122223333444455556666", 24] +comment = "Alternating even/odd reversal" +expected = "11112222\n44443333\n55556666" + +[[asserts]] +arguments = ["12345678", 9] +comment = "c slightly larger than len(n)" +expected = "12345678" + +[[asserts]] +arguments = ["9", 1] +comment = "Min non-zero case" +expected = "9XXXXXXX" + +[[asserts]] +arguments = ["12345678901234567890", 17] +comment = "Last chunk is single char, index 2 (even)" +expected = "12345678\n65432109\n7XXXXXXX" \ No newline at end of file diff --git a/tasks/easy/strings/longest_balanced_substring.toml b/tasks/easy/strings/longest_balanced_substring.toml new file mode 100644 index 0000000..3da20f0 --- /dev/null +++ b/tasks/easy/strings/longest_balanced_substring.toml @@ -0,0 +1,198 @@ +level = "easy" +name = "longest_balanced_segment" +tags = ["strings", "hash-map", "algorithms"] +time_to_solve_sec = 250 + +description_en = """ +A binary segment is called balanced if it contains the same number of `$0$`s and `$1$`s. + +Given a binary string `$s$`, determine the length of the longest balanced contiguous segment. If no such segment exists, return `$0$`. +""" + +description_ru = """ +Бинарный сегмент называется сбалансированным, если он содержит одинаковое количество `$0$` и `$1$`. + +Дана бинарная строка `$s$`. Определите длину самого длинного сбалансированного непрерывного сегмента. Если такого сегмента не существует, верните `$0$`. +""" + +limits = """ +- $0 \\leq \\text{len}(s) \\leq 10^5$ +- $s[i] \\in \\{0, 1\\}$ +""" + +solution = """ +def solution(s: str) -> int: + d, c, r = {0: -1}, 0, 0 + for i, v in enumerate(s): + c += 1 if v == '1' else -1 + if c in d: r = max(r, i - d[c]) + else: d[c] = i + return r +""" + +examples = """ +solution("0") == 0 +solution("01") == 2 +solution("111") == 0 +solution("1100") == 4 +solution("11010") == 4 +solution("101010") == 6 +""" + +[[input_signature]] +argument_name = "s" +[input_signature.type] +name = "string" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [""] +comment = "Empty string case" +expected = 0 + +[[asserts]] +arguments = ["0"] +comment = "Single character zero" +expected = 0 + +[[asserts]] +arguments = ["1"] +comment = "Single character one" +expected = 0 + +[[asserts]] +arguments = ["01"] +comment = "Smallest balanced segment" +expected = 2 + +[[asserts]] +arguments = ["10"] +comment = "Smallest balanced reversed" +expected = 2 + +[[asserts]] +arguments = ["000"] +comment = "Multiple zeros, no balance" +expected = 0 + +[[asserts]] +arguments = ["111"] +comment = "Multiple ones, no balance" +expected = 0 + +[[asserts]] +arguments = ["001"] +comment = "Balanced part at the end" +expected = 2 + +[[asserts]] +arguments = ["110"] +comment = "Balanced part at the end with one" +expected = 2 + +[[asserts]] +arguments = ["100"] +comment = "Balanced part at the start" +expected = 2 + +[[asserts]] +arguments = ["011"] +comment = "Balanced part at the start with zero" +expected = 2 + +[[asserts]] +arguments = ["0011"] +comment = "Fully balanced symmetric" +expected = 4 + +[[asserts]] +arguments = ["1100"] +comment = "Fully balanced symmetric reversed" +expected = 4 + +[[asserts]] +arguments = ["0101"] +comment = "Alternating fully balanced" +expected = 4 + +[[asserts]] +arguments = ["1010"] +comment = "Alternating fully balanced starting with one" +expected = 4 + +[[asserts]] +arguments = ["000111"] +comment = "Longer fully balanced symmetric" +expected = 6 + +[[asserts]] +arguments = ["111000"] +comment = "Longer fully balanced symmetric reversed" +expected = 6 + +[[asserts]] +arguments = ["11010"] +comment = "Balanced segment within unbalanced string" +expected = 4 + +[[asserts]] +arguments = ["10101"] +comment = "Alternating with trailing extra char" +expected = 4 + +[[asserts]] +arguments = ["001100"] +comment = "Balanced segment embedded in zeros" +expected = 4 + +[[asserts]] +arguments = ["01110"] +comment = "Short balanced segments at edges" +expected = 2 + +[[asserts]] +arguments = ["00001"] +comment = "Large imbalance, small result" +expected = 2 + +[[asserts]] +arguments = ["11110"] +comment = "Large imbalance with ones" +expected = 2 + +[[asserts]] +arguments = ["00011"] +comment = "Imbalanced prefix" +expected = 4 + +[[asserts]] +arguments = ["11100"] +comment = "Imbalanced prefix with ones" +expected = 4 + +[[asserts]] +arguments = ["010101"] +comment = "Long alternating balanced" +expected = 6 + +[[asserts]] +arguments = ["101010"] +comment = "Long alternating balanced starting with one" +expected = 6 + +[[asserts]] +arguments = ["0000111"] +comment = "Large imbalance at start" +expected = 6 + +[[asserts]] +arguments = ["1111000"] +comment = "Large imbalance at start with ones" +expected = 6 + +[[asserts]] +arguments = ["01101100"] +comment = "Full string is balanced with internal patterns" +expected = 8 \ No newline at end of file diff --git a/tasks/easy/strings/longest_common_prefix.toml b/tasks/easy/strings/longest_common_prefix.toml new file mode 100644 index 0000000..3072986 --- /dev/null +++ b/tasks/easy/strings/longest_common_prefix.toml @@ -0,0 +1,186 @@ +level = "easy" +name = "longest_common_prefix" +tags = ["strings", "arrays"] +time_to_solve_sec = 250 + +description_en = """ +Write a function to find the longest common prefix string amongst an array of strings. + +If there is no common prefix, return an empty string `""`. +""" + +description_ru = """ +Напишите функцию для поиска самого длинного общего префикса среди массива строк. + +Если общего префикса нет, верните пустую строку `""`. +""" + +limits = """ +- $1 \\leq \\text{len}(\\text{strs}) \\leq 200$ +- $0 \\leq \\text{len}(\\text{strs}[i]) \\leq 200$ +""" + +solution = """ +def solution(strs: list[str]) -> str: + res = "" + for chars in zip(*strs): + if len(set(chars)) != 1: break + res += chars[0] + return res +""" + +examples = """ +solution(["a"]) == "a" +solution(["dog", "racecar", "car"]) == "" +solution(["flower", "flow", "flight"]) == "fl" +""" + +[[input_signature]] +argument_name = "strs" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "string" + +[output_signature.type] +name = "string" + +[[asserts]] +arguments = [["flower", "flow", "flight"]] +comment = "Standard case with a common prefix" +expected = "fl" + +[[asserts]] +arguments = [["dog", "racecar", "car"]] +comment = "No common prefix" +expected = "" + +[[asserts]] +arguments = [["a"]] +comment = "Single string" +expected = "a" + +[[asserts]] +arguments = [[""]] +comment = "Single empty string" +expected = "" + +[[asserts]] +arguments = [["", "b"]] +comment = "First string is empty" +expected = "" + +[[asserts]] +arguments = [["a", ""]] +comment = "Last string is empty" +expected = "" + +[[asserts]] +arguments = [["ab", "a"]] +comment = "Longest prefix is the entire second string" +expected = "a" + +[[asserts]] +arguments = [["a", "ab"]] +comment = "Longest prefix is the entire first string" +expected = "a" + +[[asserts]] +arguments = [["abc", "abc", "abc"]] +comment = "All strings are identical" +expected = "abc" + +[[asserts]] +arguments = [["abc", "abcd", "abcde"]] +comment = "Strings in increasing length" +expected = "abc" + +[[asserts]] +arguments = [["abcde", "abcd", "abc"]] +comment = "Strings in decreasing length" +expected = "abc" + +[[asserts]] +arguments = [["ab", "a", "abc"]] +comment = "Shortest string is in the middle" +expected = "a" + +[[asserts]] +arguments = [["inters", "interstellar", "internet", "internal"]] +comment = "Long prefix" +expected = "inter" + +[[asserts]] +arguments = [["throne", "throne"]] +comment = "Two identical strings" +expected = "throne" + +[[asserts]] +arguments = [["throne", "dungeon"]] +comment = "Two completely different strings" +expected = "" + +[[asserts]] +arguments = [["prefix", "prefixes", "preform"]] +comment = "Prefix variation" +expected = "pref" + +[[asserts]] +arguments = [["apple", "ape", "april"]] +comment = "Common starting letters" +expected = "ap" + +[[asserts]] +arguments = [["car", "cir"]] +comment = "Single common character" +expected = "c" + +[[asserts]] +arguments = [["c", "c"]] +comment = "Identical single characters" +expected = "c" + +[[asserts]] +arguments = [["c", "d"]] +comment = "Different single characters" +expected = "" + +[[asserts]] +arguments = [["alone", "aloof", "albatross"]] +comment = "Common start" +expected = "al" + +[[asserts]] +arguments = [["zebra", "z", "zephyr"]] +comment = "Single character bounds the prefix" +expected = "z" + +[[asserts]] +arguments = [["same", "same", "same", "same", "same"]] +comment = "Many identical strings" +expected = "same" + +[[asserts]] +arguments = [["a", "a", "b"]] +comment = "One string breaks the prefix at the end" +expected = "" + +[[asserts]] +arguments = [["abcdefgh", "abcdefghij", "abcdefghijk", "abcdefghijkl"]] +comment = "Increasing length with long common prefix" +expected = "abcdefgh" + +[[asserts]] +arguments = [["x", "x", "x", "y"]] +comment = "Break at last string single character" +expected = "" + +[[asserts]] +arguments = [["hello", "helloworld", "hell"]] +comment = "Substring in middle" +expected = "hell" + +[[asserts]] +arguments = [["python", "pyramid", "pyrite", "pyre"]] +comment = "Another normal case" +expected = "py" \ No newline at end of file diff --git a/tasks/easy/strings/string_blocks_transposition.toml b/tasks/easy/strings/string_blocks_transposition.toml new file mode 100644 index 0000000..14c1782 --- /dev/null +++ b/tasks/easy/strings/string_blocks_transposition.toml @@ -0,0 +1,204 @@ +level = "easy" +name = "string_blocks_transposition" +tags = ["strings", "formatting"] +time_to_solve_sec = 200 + +description_en = """ +You are given a string `s` and an integer `k`. + +If the length of the string `s` is not divisible by `k`, return an empty string `""`. +Otherwise, split the string into blocks of length `k`. Construct and return a new string by taking the first character from each block, then the second character from each block, and so on, up to the `k`-th character. +""" + +description_ru = """ +Дана строка `s` и целое число `k`. + +Если длина строки `s` не делится на `k`, верните пустую строку `""`. +В противном случае разбейте строку на блоки длины `k`. Сформируйте и верните новую строку, беря сначала первый символ из каждого блока, затем второй символ из каждого блока, и так далее, вплоть до `k`-го символа. +""" + +limits = """ +- $0 \\leq \\text{len}(s) \\leq 100$ +- $1 \\leq k \\leq 100$ +""" + +solution = """ +def solution(s: str, k: int) -> str: + if len(s) % k != 0: + return "" + return "".join(s[i::k] for i in range(k)) +""" + +examples = """ +solution("abcdef", 2) == "acebdf" +solution("abcdef", 3) == "adbecf" +solution("abc", 2) == "" +""" + +[[input_signature]] +argument_name = "s" +[input_signature.type] +name = "string" + +[[input_signature]] +argument_name = "k" +[input_signature.type] +name = "integer" + +[output_signature.type] +name = "string" + +[[asserts]] +arguments = ["abcdef", 2] +comment = "Even length, divided into blocks of 2" +expected = "acebdf" + +[[asserts]] +arguments = ["abcdef", 3] +comment = "Length 6, divided into blocks of 3" +expected = "adbecf" + +[[asserts]] +arguments = ["abc", 2] +comment = "Length not divisible by k" +expected = "" + +[[asserts]] +arguments = ["abcdef", 1] +comment = "k equals 1" +expected = "abcdef" + +[[asserts]] +arguments = ["abcdef", 6] +comment = "k equals string length" +expected = "abcdef" + +[[asserts]] +arguments = ["abcdef", 4] +comment = "Length not divisible by 4" +expected = "" + +[[asserts]] +arguments = ["", 1] +comment = "Empty string" +expected = "" + +[[asserts]] +arguments = ["", 5] +comment = "Empty string with larger k" +expected = "" + +[[asserts]] +arguments = ["a", 1] +comment = "Single character string" +expected = "a" + +[[asserts]] +arguments = ["ab", 1] +comment = "Length 2, k=1" +expected = "ab" + +[[asserts]] +arguments = ["ab", 2] +comment = "Length 2, k=2" +expected = "ab" + +[[asserts]] +arguments = ["hello", 5] +comment = "String length equals k" +expected = "hello" + +[[asserts]] +arguments = ["hello", 2] +comment = "Length 5, k=2 (not divisible)" +expected = "" + +[[asserts]] +arguments = ["helloworld", 2] +comment = "Longer string, k=2" +expected = "hloolelwrd" + +[[asserts]] +arguments = ["123456789", 3] +comment = "Numeric string, blocks of 3" +expected = "147258369" + +[[asserts]] +arguments = ["1234567890", 5] +comment = "Numeric string, blocks of 5" +expected = "1627384950" + +[[asserts]] +arguments = ["aabbcc", 2] +comment = "Pairs of characters, k=2" +expected = "abcabc" + +[[asserts]] +arguments = ["ababab", 2] +comment = "Repeating pattern, k=2" +expected = "aaabbb" + +[[asserts]] +arguments = ["abcdefgh", 4] +comment = "Length 8, blocks of 4" +expected = "aebfcgdh" + +[[asserts]] +arguments = ["abcdefgh", 8] +comment = "Length 8, k=8" +expected = "abcdefgh" + +[[asserts]] +arguments = ["x", 5] +comment = "Length 1, k=5 (not divisible)" +expected = "" + +[[asserts]] +arguments = ["xxxxxxxx", 2] +comment = "Homogeneous string" +expected = "xxxxxxxx" + +[[asserts]] +arguments = ["python", 2] +comment = "Length 6, k=2" +expected = "ptoyhn" + +[[asserts]] +arguments = ["python", 3] +comment = "Length 6, k=3" +expected = "phyotn" + +[[asserts]] +arguments = ["programming", 1] +comment = "Length 11, k=1" +expected = "programming" + +[[asserts]] +arguments = ["programming", 2] +comment = "Length 11, k=2 (not divisible)" +expected = "" + +[[asserts]] +arguments = ["coder", 5] +comment = "Length 5, k=5" +expected = "coder" + +[[asserts]] +arguments = ["xyzxyzxyz", 3] +comment = "Repeating pattern, k=3" +expected = "xxxyyyzzz" + +[[asserts]] +arguments = ["ABCDEFGHIJKLMNOPQRST", 4] +comment = "Length 20, k=4" +expected = "AEIMQBFJNRCGKOSDHLPT" + +[[asserts]] +arguments = ["abcabcabc", 3] +comment = "Repeating triplets, k=3" +expected = "aaabbbccc" + +[[asserts]] +arguments = ["12345678", 2] +comment = "Sequence of 8 numbers, k=2" +expected = "13572468" \ No newline at end of file diff --git a/tasks/medium/algo/insert_interval.toml b/tasks/medium/algo/insert_interval.toml new file mode 100644 index 0000000..4d6605b --- /dev/null +++ b/tasks/medium/algo/insert_interval.toml @@ -0,0 +1,236 @@ +level = "medium" +name = "insert_interval" +tags = ["algo", "intervals", "sorting"] +time_to_solve_sec = 400 + +description_en = """ +You are given an array of non-overlapping `intervals` where $\\text{intervals}[i] = [start_i, end_i]$ represent the start and the end of the $i$-th interval. The array `intervals` is sorted in ascending order by $start_i$. + +You are also given an array $\\text{new\\_interval} = [start, end]$ that represents the start and end of another interval. + +Insert $\\text{new\\_interval}$ into `intervals` such that `intervals` is still sorted in ascending order by $start_i$ and `intervals` still does not have any overlapping intervals (merge overlapping intervals if necessary). + +Return `intervals` after the insertion. +""" + +description_ru = """ +Вам дан массив непересекающихся интервалов `intervals`, где $\\text{intervals}[i] = [start_i, end_i]$ представляют начало и конец $i$-го интервала. Массив `intervals` отсортирован по возрастанию $start_i$. + +Вам также дан массив $\\text{new\\_interval} = [start, end]$, который представляет собой начало и конец другого интервала. + +Вставьте $\\text{new\\_interval}$ в `intervals` так, чтобы `intervals` оставался отсортированным по возрастанию $start_i$ и не содержал пересекающихся интервалов (при необходимости объедините пересекающиеся интервалы). + +Верните `intervals` после вставки. +""" + +limits = """ +- $0 \\leq \\text{len}(\\text{intervals}) \\leq 10^4$ +- $\\text{len}(\\text{intervals}[i]) == 2$ +- $\\text{len}(\\text{new\\_interval}) == 2$ +- $0 \\leq \\text{start}_i \\leq \\text{end}_i \\leq 10^5$ +- $0 \\leq \\text{new\\_interval}[0] \\leq \\text{new\\_interval}[1] \\leq 10^5$ +""" + +solution = """ +def solution(intervals: list[list[int]], new_interval: list[int]) -> list[list[int]]: + res = [] + i = 0 + n = len(intervals) + + while i < n and intervals[i][1] < new_interval[0]: + res.append(intervals[i]) + i += 1 + + start, end = new_interval[0], new_interval[1] + while i < n and intervals[i][0] <= end: + start = min(start, intervals[i][0]) + end = max(end, intervals[i][1]) + i += 1 + res.append([start, end]) + + while i < n: + res.append(intervals[i]) + i += 1 + + return res +""" + +examples = """ +solution([], [5, 7]) == [[5, 7]] +solution([[1, 5]], [2, 3]) == [[1, 5]] +solution([[1, 3], [6, 9]], [2, 5]) == [[1, 5], [6, 9]] +solution([[1, 2], [3, 5], [6, 7], [8, 10], [12, 16]], [4, 8]) == [[1, 2], [3, 10], [12, 16]] +""" + +[[input_signature]] +argument_name = "intervals" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "array" +[input_signature.type.nested.nested] +name = "integer" + +[[input_signature]] +argument_name = "new_interval" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "integer" + +[output_signature.type] +name = "array" +[output_signature.type.nested] +name = "array" +[output_signature.type.nested.nested] +name = "integer" + +[[asserts]] +arguments = [[], [5, 7]] +comment = "Empty intervals" +expected = [[5, 7]] + +[[asserts]] +arguments = [[[1, 3], [6, 9]], [2, 5]] +comment = "Merge with first interval" +expected = [[1, 5], [6, 9]] + +[[asserts]] +arguments = [[[1, 2], [3, 5], [6, 7], [8, 10], [12, 16]], [4, 8]] +comment = "Merge multiple intervals" +expected = [[1, 2], [3, 10], [12, 16]] + +[[asserts]] +arguments = [[[1, 5]], [2, 3]] +comment = "New interval completely inside" +expected = [[1, 5]] + +[[asserts]] +arguments = [[[1, 5]], [0, 6]] +comment = "New interval covers all" +expected = [[0, 6]] + +[[asserts]] +arguments = [[[1, 5]], [6, 8]] +comment = "Insert at the end without merge" +expected = [[1, 5], [6, 8]] + +[[asserts]] +arguments = [[[3, 5]], [1, 2]] +comment = "Insert at the beginning without merge" +expected = [[1, 2], [3, 5]] + +[[asserts]] +arguments = [[[1, 2], [5, 6]], [3, 4]] +comment = "Insert in the middle without merge" +expected = [[1, 2], [3, 4], [5, 6]] + +[[asserts]] +arguments = [[[1, 2], [5, 6]], [2, 5]] +comment = "Merge exactly touching boundaries" +expected = [[1, 6]] + +[[asserts]] +arguments = [[[1, 2], [3, 4], [5, 6]], [2, 5]] +comment = "Merge touching multiple boundaries" +expected = [[1, 6]] + +[[asserts]] +arguments = [[[1, 5], [6, 9]], [1, 5]] +comment = "Exact duplicate interval" +expected = [[1, 5], [6, 9]] + +[[asserts]] +arguments = [[[1, 5]], [1, 5]] +comment = "Duplicate single interval" +expected = [[1, 5]] + +[[asserts]] +arguments = [[[1, 5], [8, 9]], [5, 8]] +comment = "Bridge two intervals" +expected = [[1, 9]] + +[[asserts]] +arguments = [[[1, 2], [4, 5], [7, 8]], [2, 7]] +comment = "Bridge three intervals exactly" +expected = [[1, 8]] + +[[asserts]] +arguments = [[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]], [1, 10]] +comment = "Swallow many small intervals" +expected = [[1, 10]] + +[[asserts]] +arguments = [[[2, 3], [5, 6], [8, 9]], [0, 1]] +comment = "Insert completely before all" +expected = [[0, 1], [2, 3], [5, 6], [8, 9]] + +[[asserts]] +arguments = [[[2, 3], [5, 6], [8, 9]], [10, 11]] +comment = "Insert completely after all" +expected = [[2, 3], [5, 6], [8, 9], [10, 11]] + +[[asserts]] +arguments = [[[2, 4], [7, 9]], [4, 7]] +comment = "Exact fill the gap" +expected = [[2, 9]] + +[[asserts]] +arguments = [[[1, 1]], [1, 2]] +comment = "Point interval merged" +expected = [[1, 2]] + +[[asserts]] +arguments = [[[1, 3], [6, 9]], [3, 6]] +comment = "Connect two intervals perfectly" +expected = [[1, 9]] + +[[asserts]] +arguments = [[[0, 0], [2, 2], [4, 4]], [0, 4]] +comment = "Merge multiple points" +expected = [[0, 4]] + +[[asserts]] +arguments = [[[0, 2], [4, 6], [8, 10]], [3, 7]] +comment = "Merge with partial overlaps" +expected = [[0, 2], [3, 7], [8, 10]] + +[[asserts]] +arguments = [[[1, 3], [5, 7], [9, 11]], [4, 8]] +comment = "Merge middle elements" +expected = [[1, 3], [4, 8], [9, 11]] + +[[asserts]] +arguments = [[[1, 100]], [50, 60]] +comment = "New interval is a subsegment" +expected = [[1, 100]] + +[[asserts]] +arguments = [[[10, 20], [30, 40], [50, 60]], [15, 55]] +comment = "Merge all with offsets" +expected = [[10, 60]] + +[[asserts]] +arguments = [[[1, 2], [3, 4], [5, 6]], [3, 3]] +comment = "New interval is a point inside existing" +expected = [[1, 2], [3, 4], [5, 6]] + +[[asserts]] +arguments = [[[1, 2], [4, 5]], [3, 3]] +comment = "New interval is an isolated point" +expected = [[1, 2], [3, 3], [4, 5]] + +[[asserts]] +arguments = [[[1, 5], [10, 15], [20, 25]], [6, 9]] +comment = "Insert large gap without merge" +expected = [[1, 5], [6, 9], [10, 15], [20, 25]] + +[[asserts]] +arguments = [[[1, 5], [10, 15], [20, 25]], [12, 22]] +comment = "Merge last two partially" +expected = [[1, 5], [10, 25]] + +[[asserts]] +arguments = [[[0, 1000]], [0, 1000]] +comment = "Same exact large bounds" +expected = [[0, 1000]] \ No newline at end of file diff --git a/tasks/medium/dp/turtle_max_path_sum.toml b/tasks/medium/dp/turtle_max_path_sum.toml new file mode 100644 index 0000000..7c178d0 --- /dev/null +++ b/tasks/medium/dp/turtle_max_path_sum.toml @@ -0,0 +1,179 @@ +level = "medium" +name = "turtle_max_path_sum" +tags = ["dp", "matrix", "arrays"] +time_to_solve_sec = 400 + +description_en = """ +You are given an $m \\times n$ matrix of integers. A turtle starts its journey in the top-left corner $(0, 0)$ and wants to reach the bottom-right corner $(m-1, n-1)$. + +The turtle can only move **right** or **down**. + +Return the maximum sum of the elements along its path. +""" + +description_ru = """ +Дана матрица целых чисел размером $m \\times n$. Черепашка начинает свой путь в левом верхнем углу $(0, 0)$ и хочет добраться до правого нижнего угла $(m-1, n-1)$. + +Черепашка может двигаться только **вправо** или **вниз**. + +Верните максимальную сумму элементов на ее пути. +""" + +limits = """ +- $1 \\leq m, n \\leq 100$ +- $-1000 \\leq \\text{matrix}[i][j] \\leq 1000$ +""" + +solution = """ +def solution(matrix: list[list[int]]) -> int: + for i in range(len(matrix)): + for j in range(len(matrix[0])): + if i > 0 and j > 0: matrix[i][j] += max(matrix[i-1][j], matrix[i][j-1]) + elif i > 0: matrix[i][j] += matrix[i-1][j] + elif j > 0: matrix[i][j] += matrix[i][j-1] + return matrix[-1][-1] +""" + +examples = """ +solution([[0]]) == 0 +solution([[1, 2], [3, 4]]) == 8 +solution([[-1, -2], [-3, -4]]) == -7 +solution([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) == 29 +""" + +[[input_signature]] +argument_name = "matrix" +[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 element matrix" +expected = 1 + +[[asserts]] +arguments = [[[0]]] +comment = "Single zero" +expected = 0 + +[[asserts]] +arguments = [[[-5]]] +comment = "Single negative element" +expected = -5 + +[[asserts]] +arguments = [[[1, 2, 3]]] +comment = "Single row" +expected = 6 + +[[asserts]] +arguments = [[[1], [2], [3]]] +comment = "Single column" +expected = 6 + +[[asserts]] +arguments = [[[1, 2], [3, 4]]] +comment = "2x2 positive matrix" +expected = 8 + +[[asserts]] +arguments = [[[-1, -2], [-3, -4]]] +comment = "2x2 negative matrix" +expected = -7 + +[[asserts]] +arguments = [[[0, 0], [0, 0]]] +comment = "2x2 zero matrix" +expected = 0 + +[[asserts]] +arguments = [[[1, 2, 3], [4, 5, 6], [7, 8, 9]]] +comment = "3x3 sequential numbers" +expected = 29 + +[[asserts]] +arguments = [[[-1, -2, -3], [-4, -5, -6], [-7, -8, -9]]] +comment = "3x3 sequential negative numbers" +expected = -21 + +[[asserts]] +arguments = [[[5, 5, 5], [1, 1, 5], [1, 1, 5]]] +comment = "Path along the right edge is optimal" +expected = 25 + +[[asserts]] +arguments = [[[1, 5, 1], [1, 5, 1], [1, 5, 1]]] +comment = "Path down the middle" +expected = 17 + +[[asserts]] +arguments = [[[9, 9, 9], [1, 1, 9], [1, 1, 9]]] +comment = "Path making an L-shape" +expected = 45 + +[[asserts]] +arguments = [[[1, 1, 1], [9, 9, 1], [1, 9, 9]]] +comment = "Optimal path zigzags" +expected = 37 + +[[asserts]] +arguments = [[[100, -100, -100], [-100, 100, -100], [-100, -100, 100]]] +comment = "Diagonal positive numbers surrounded by negative" +expected = 100 + +[[asserts]] +arguments = [[[1, -1, 1], [-1, 1, -1], [1, -1, 1]]] +comment = "Alternating 1s and -1s" +expected = 1 + +[[asserts]] +arguments = [[[0, 10, 0], [0, 10, 0], [0, 10, 0]]] +comment = "Straight vertical high values" +expected = 30 + +[[asserts]] +arguments = [[[10, 0, 0], [0, 10, 0], [0, 0, 10]]] +comment = "Diagonal values" +expected = 30 + +[[asserts]] +arguments = [[[1, 1, 1, 1], [1, 1, 1, 1]]] +comment = "Uniform 2x4 matrix" +expected = 5 + +[[asserts]] +arguments = [[[2, 2, 2, 2], [2, 2, 2, 2], [2, 2, 2, 2]]] +comment = "Uniform 3x4 matrix" +expected = 12 + +[[asserts]] +arguments = [[[1, 2], [3, 4], [5, 6], [7, 8]]] +comment = "Narrow 4x2 matrix" +expected = 24 + +[[asserts]] +arguments = [[[1, 3, 5, 7], [2, 4, 6, 8]]] +comment = "Wide 2x4 matrix" +expected = 24 + +[[asserts]] +arguments = [[[1, 2, 3, 4, 5]]] +comment = "1x5 matrix" +expected = 15 + +[[asserts]] +arguments = [[[5], [4], [3], [2], [1]]] +comment = "5x1 matrix" +expected = 15 + +[[asserts]] +arguments = [[[0, -1, -2], [-3, -4, -5], [-6, -7, -8]]] +comment = "Negative sequence starting with zero" +expected = -16 \ No newline at end of file diff --git a/tasks/medium/games/game_of_life_step.toml b/tasks/medium/games/game_of_life_step.toml new file mode 100644 index 0000000..deba89b --- /dev/null +++ b/tasks/medium/games/game_of_life_step.toml @@ -0,0 +1,210 @@ +level = "medium" +name = "game_of_life_step" +tags = ["games", "simulation", "algorithms"] +time_to_solve_sec = 600 + +description_en = """ +You are given a 2D integer array `grid` representing the current state of a grid in Conway's Game of Life. `1` represents a live cell and `0` represents a dead cell. + +Calculate and return the next state of the grid after exactly one step. + +The rules are: +1. A live cell with fewer than `2` live neighbors dies (underpopulation). +2. A live cell with `2` or `3` live neighbors lives on. +3. A live cell with more than `3` live neighbors dies (overpopulation). +4. A dead cell with exactly `3` live neighbors becomes a live cell (reproduction). + +Neighbors are the 8 cells horizontally, vertically, or diagonally adjacent. +""" + +description_ru = """ +Вам дан двумерный массив целых чисел `grid`, представляющий текущее состояние сетки в «Игре Жизнь» Конвея, где `1` представляет живую клетку, а `0` — мертвую. + +Рассчитайте и верните следующее состояние сетки ровно через один шаг. + +Правила: +1. Живая клетка, у которой меньше `2` живых соседей, умирает (от недонаселения). +2. Живая клетка с `2` или `3` живыми соседями продолжает жить. +3. Живая клетка, у которой больше `3` живых соседей, умирает (от перенаселения). +4. Мертвая клетка, у которой ровно `3` живых соседа, становится живой (размножение). + +Соседями считаются 8 клеток по горизонтали, вертикали и диагонали. +""" + +limits = """ +- $1 \\leq \\text{len}(grid) \\leq 50$ +- $1 \\leq \\text{len}(grid[0]) \\leq 50$ +- $grid[i][j] \\in \\{0, 1\\}$ +""" + +solution = """ +def solution(grid: list) -> list: + m, n = len(grid), len(grid[0]) + res = [[0] * n for _ in range(m)] + for i in range(m): + for j in range(n): + lives = sum(grid[r][c] for r in range(max(0, i-1), min(m, i+2)) + for c in range(max(0, j-1), min(n, j+2))) - grid[i][j] + if grid[i][j] == 1 and lives in (2, 3): + res[i][j] = 1 + if grid[i][j] == 0 and lives == 3: + res[i][j] = 1 + return res +""" + +examples = """ +solution([[1]]) == [[0]] +solution([[0, 1, 0], [0, 1, 0], [0, 1, 0]]) == [[0, 0, 0], [1, 1, 1], [0, 0, 0]] +solution([[1, 1], [1, 1]]) == [[1, 1], [1, 1]] +""" + +[[input_signature]] +argument_name = "grid" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "array" +[input_signature.type.nested.nested] +name = "integer" + +[output_signature.type] +name = "array" +[output_signature.type.nested] +name = "array" +[output_signature.type.nested.nested] +name = "integer" + +[[asserts]] +arguments = [[[0]]] +comment = "1x1 dead" +expected = [[0]] + +[[asserts]] +arguments = [[[1]]] +comment = "1x1 live" +expected = [[0]] + +[[asserts]] +arguments = [[[0, 0]]] +comment = "1x2 dead" +expected = [[0, 0]] + +[[asserts]] +arguments = [[[1, 1]]] +comment = "1x2 live" +expected = [[0, 0]] + +[[asserts]] +arguments = [[[1], [1]]] +comment = "2x1 live" +expected = [[0], [0]] + +[[asserts]] +arguments = [[[0, 0], [0, 0]]] +comment = "2x2 dead" +expected = [[0, 0], [0, 0]] + +[[asserts]] +arguments = [[[1, 1], [1, 1]]] +comment = "2x2 block (Still life)" +expected = [[1, 1], [1, 1]] + +[[asserts]] +arguments = [[[1, 0], [0, 0]]] +comment = "2x2 single live" +expected = [[0, 0], [0, 0]] + +[[asserts]] +arguments = [[[1, 1], [0, 0]]] +comment = "2x2 two live" +expected = [[0, 0], [0, 0]] + +[[asserts]] +arguments = [[[1, 1], [1, 0]]] +comment = "2x2 three live (creates block)" +expected = [[1, 1], [1, 1]] + +[[asserts]] +arguments = [[[0, 0, 0], [0, 0, 0], [0, 0, 0]]] +comment = "3x3 dead" +expected = [[0, 0, 0], [0, 0, 0], [0, 0, 0]] + +[[asserts]] +arguments = [[[0, 0, 0], [0, 1, 0], [0, 0, 0]]] +comment = "3x3 center live" +expected = [[0, 0, 0], [0, 0, 0], [0, 0, 0]] + +[[asserts]] +arguments = [[[0, 0, 0], [1, 1, 1], [0, 0, 0]]] +comment = "3x3 blinker horizontal (Oscillator)" +expected = [[0, 1, 0], [0, 1, 0], [0, 1, 0]] + +[[asserts]] +arguments = [[[0, 1, 0], [0, 1, 0], [0, 1, 0]]] +comment = "3x3 blinker vertical (Oscillator)" +expected = [[0, 0, 0], [1, 1, 1], [0, 0, 0]] + +[[asserts]] +arguments = [[[0, 1, 0], [1, 0, 1], [0, 1, 0]]] +comment = "3x3 tub (Still life)" +expected = [[0, 1, 0], [1, 0, 1], [0, 1, 0]] + +[[asserts]] +arguments = [[[1, 1, 1], [1, 1, 1], [1, 1, 1]]] +comment = "3x3 all live" +expected = [[1, 0, 1], [0, 0, 0], [1, 0, 1]] + +[[asserts]] +arguments = [[[0, 1, 0], [1, 1, 1], [0, 1, 0]]] +comment = "3x3 cross" +expected = [[1, 1, 1], [1, 0, 1], [1, 1, 1]] + +[[asserts]] +arguments = [[[1, 0, 0], [1, 1, 0], [0, 0, 0]]] +comment = "3x3 L-shape" +expected = [[1, 1, 0], [1, 1, 0], [0, 0, 0]] + +[[asserts]] +arguments = [[[0, 0, 0, 0], [0, 1, 1, 0], [0, 1, 1, 0], [0, 0, 0, 0]]] +comment = "4x4 block in center" +expected = [[0, 0, 0, 0], [0, 1, 1, 0], [0, 1, 1, 0], [0, 0, 0, 0]] + +[[asserts]] +arguments = [[[0, 0, 0, 0], [0, 1, 1, 1], [1, 1, 1, 0], [0, 0, 0, 0]]] +comment = "4x4 toad phase 1 (Oscillator)" +expected = [[0, 0, 1, 0], [1, 0, 0, 1], [1, 0, 0, 1], [0, 1, 0, 0]] + +[[asserts]] +arguments = [[[0, 0, 1, 0], [1, 0, 0, 1], [1, 0, 0, 1], [0, 1, 0, 0]]] +comment = "4x4 toad phase 2 (Oscillator)" +expected = [[0, 0, 0, 0], [0, 1, 1, 1], [1, 1, 1, 0], [0, 0, 0, 0]] + +[[asserts]] +arguments = [[[1, 1, 0, 0], [1, 1, 0, 0], [0, 0, 1, 1], [0, 0, 1, 1]]] +comment = "4x4 beacon (Oscillator)" +expected = [[1, 1, 0, 0], [1, 0, 0, 0], [0, 0, 0, 1], [0, 0, 1, 1]] + +[[asserts]] +arguments = [[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]] +comment = "4x4 all live" +expected = [[1, 0, 0, 1], [0, 0, 0, 0], [0, 0, 0, 0], [1, 0, 0, 1]] + +[[asserts]] +arguments = [[[0, 1, 0], [0, 0, 1], [1, 1, 1], [0, 0, 0]]] +comment = "4x3 glider step 1" +expected = [[0, 0, 0], [1, 0, 1], [0, 1, 1], [0, 1, 0]] + +[[asserts]] +arguments = [[[0, 0, 0, 0], [1, 1, 1, 1], [0, 0, 0, 0]]] +comment = "3x4 horizontal line" +expected = [[0, 1, 1, 0], [0, 1, 1, 0], [0, 1, 1, 0]] + +[[asserts]] +arguments = [[[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 1, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]]] +comment = "5x5 3x3 square in center" +expected = [[0, 0, 1, 0, 0], [0, 1, 0, 1, 0], [1, 0, 0, 0, 1], [0, 1, 0, 1, 0], [0, 0, 1, 0, 0]] + +[[asserts]] +arguments = [[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]] +comment = "5x5 completely empty" +expected = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]] \ No newline at end of file diff --git a/tasks/medium/games/valid_sudoku.toml b/tasks/medium/games/valid_sudoku.toml new file mode 100644 index 0000000..ff6dd66 --- /dev/null +++ b/tasks/medium/games/valid_sudoku.toml @@ -0,0 +1,477 @@ +level = "medium" +name = "valid_sudoku" +tags = ["arrays", "matrix", "hash"] +time_to_solve_sec = 600 + +description_en = """ +Determine if a $9 \\times 9$ Sudoku board is valid. Only the filled cells need to be validated according to the following rules: + +1. Each row must contain the digits `"1"`-`"9"` without repetition. +2. Each column must contain the digits `"1"`-`"9"` without repetition. +3. Each of the nine $3 \\times 3$ sub-boxes of the grid must contain the digits `"1"`-`"9"` without repetition. + +The Sudoku board could be partially filled, where empty cells are filled with the character `"."`. +""" + +description_ru = """ +Определите, является ли поле для судоку $9 \\times 9$ валидным. Только заполненные ячейки необходимо проверять в соответствии со следующими правилами: + +1. Каждая строка должна содержать цифры от `"1"` до `"9"` без повторений. +2. Каждый столбец должен содержать цифры от `"1"` до `"9"` без повторений. +3. Каждый из девяти подквадратов $3 \\times 3$ должен содержать цифры от `"1"` до `"9"` без повторений. + +Поле судоку может быть частично заполнено, пустые ячейки обозначаются символом `"."`. +""" + +limits = """ +- $\\text{len}(\\text{board}) = 9$ +- $\\text{len}(\\text{board}[i]) = 9$ +- $\\text{board}[i][j] \\in \\{"1", \\dots, "9", "."\\}$ +""" + +solution = """ +def solution(board: list) -> bool: + r = [set() for _ in range(9)] + c = [set() for _ in range(9)] + b = [set() for _ in range(9)] + + for i in range(9): + for j in range(9): + v = board[i][j] + if v != ".": + k = (i // 3) * 3 + j // 3 + if v in r[i] or v in c[j] or v in b[k]: + return False + r[i].add(v) + c[j].add(v) + b[k].add(v) + return True +""" + +examples = """ +solution([ + ["5","3",".",".","7",".",".",".","."], + ["6",".",".","1","9","5",".",".","."], + [".","9","8",".",".",".",".","6","."], + ["8",".",".",".","6",".",".",".","3"], + ["4",".",".","8",".","3",".",".","1"], + ["7",".",".",".","2",".",".",".","6"], + [".","6",".",".",".",".","2","8","."], + [".",".",".","4","1","9",".",".","5"], + [".",".",".",".","8",".",".","7","9"] +]) == True + +solution([ + ["8","3",".",".","7",".",".",".","."], + ["6",".",".","1","9","5",".",".","."], + [".","9","8",".",".",".",".","6","."], + ["8",".",".",".","6",".",".",".","3"], + ["4",".",".","8",".","3",".",".","1"], + ["7",".",".",".","2",".",".",".","6"], + [".","6",".",".",".",".","2","8","."], + [".",".",".","4","1","9",".",".","5"], + [".",".",".",".","8",".",".","7","9"] +]) == False +""" + +[[input_signature]] +argument_name = "board" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "array" +[input_signature.type.nested.nested] +name = "string" + +[output_signature.type] +name = "boolean" + +[[asserts]] +arguments = [[ + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."] +]] +comment = "Completely empty board" +expected = true + +[[asserts]] +arguments = [[ + ["5","3",".",".","7",".",".",".","."], + ["6",".",".","1","9","5",".",".","."], + [".","9","8",".",".",".",".","6","."], + ["8",".",".",".","6",".",".",".","3"], + ["4",".",".","8",".","3",".",".","1"], + ["7",".",".",".","2",".",".",".","6"], + [".","6",".",".",".",".","2","8","."], + [".",".",".","4","1","9",".",".","5"], + [".",".",".",".","8",".",".","7","9"] +]] +comment = "Valid partial board" +expected = true + +[[asserts]] +arguments = [[ + ["8","3",".",".","7",".",".",".","."], + ["6",".",".","1","9","5",".",".","."], + [".","9","8",".",".",".",".","6","."], + ["8",".",".",".","6",".",".",".","3"], + ["4",".",".","8",".","3",".",".","1"], + ["7",".",".",".","2",".",".",".","6"], + [".","6",".",".",".",".","2","8","."], + [".",".",".","4","1","9",".",".","5"], + [".",".",".",".","8",".",".","7","9"] +]] +comment = "Invalid partial board (two '8's in first column)" +expected = false + +[[asserts]] +arguments = [[ + ["1","2","3","4","5","6","7","8","9"], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."] +]] +comment = "Valid single row" +expected = true + +[[asserts]] +arguments = [[ + ["1","2","3","4","5","6","7","8","1"], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."] +]] +comment = "Invalid single row (duplicate '1')" +expected = false + +[[asserts]] +arguments = [[ + ["1",".",".",".",".",".",".",".","."], + ["2",".",".",".",".",".",".",".","."], + ["3",".",".",".",".",".",".",".","."], + ["4",".",".",".",".",".",".",".","."], + ["5",".",".",".",".",".",".",".","."], + ["6",".",".",".",".",".",".",".","."], + ["7",".",".",".",".",".",".",".","."], + ["8",".",".",".",".",".",".",".","."], + ["9",".",".",".",".",".",".",".","."] +]] +comment = "Valid single column" +expected = true + +[[asserts]] +arguments = [[ + ["1",".",".",".",".",".",".",".","."], + ["2",".",".",".",".",".",".",".","."], + ["3",".",".",".",".",".",".",".","."], + ["4",".",".",".",".",".",".",".","."], + ["5",".",".",".",".",".",".",".","."], + ["6",".",".",".",".",".",".",".","."], + ["7",".",".",".",".",".",".",".","."], + ["8",".",".",".",".",".",".",".","."], + ["1",".",".",".",".",".",".",".","."] +]] +comment = "Invalid single column (duplicate '1')" +expected = false + +[[asserts]] +arguments = [[ + ["1","2","3",".",".",".",".",".","."], + ["4","5","6",".",".",".",".",".","."], + ["7","8","9",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."] +]] +comment = "Valid single box" +expected = true + +[[asserts]] +arguments = [[ + ["1","2","3",".",".",".",".",".","."], + ["4","5","6",".",".",".",".",".","."], + ["7","8","1",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."] +]] +comment = "Invalid single box (duplicate '1')" +expected = false + +[[asserts]] +arguments = [[ + ["5","3","4","6","7","8","9","1","2"], + ["6","7","2","1","9","5","3","4","8"], + ["1","9","8","3","4","2","5","6","7"], + ["8","5","9","7","6","1","4","2","3"], + ["4","2","6","8","5","3","7","9","1"], + ["7","1","3","9","2","4","8","5","6"], + ["9","6","1","5","3","7","2","8","4"], + ["2","8","7","4","1","9","6","3","5"], + ["3","4","5","2","8","6","1","7","9"] +]] +comment = "Fully solved valid board" +expected = true + +[[asserts]] +arguments = [[ + ["5","3","4","6","7","8","9","1","2"], + ["6","7","2","1","9","5","3","4","8"], + ["1","9","8","3","4","2","5","6","7"], + ["8","5","9","7","6","1","4","2","3"], + ["4","2","6","8","5","3","7","9","1"], + ["7","1","3","9","2","4","8","5","6"], + ["9","6","1","5","3","7","2","8","4"], + ["2","8","7","4","1","9","6","3","5"], + ["3","4","5","2","8","6","1","7","3"] +]] +comment = "Invalid fully filled board (duplicate '3' in bottom right)" +expected = false + +[[asserts]] +arguments = [[ + [".",".",".",".",".",".",".",".","."], + [".","1",".",".",".",".",".","2","."], + [".",".",".",".","3",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".","4",".",".",".","5",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".","6",".",".",".","."], + [".","7",".",".",".",".",".","8","."], + [".",".",".",".",".",".",".",".","."] +]] +comment = "Valid sparse board" +expected = true + +[[asserts]] +arguments = [[ + [".",".",".",".",".",".",".",".","."], + [".","1",".",".",".",".",".","2","."], + [".",".",".",".","3",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".","4",".",".",".","5",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".","6",".",".",".","."], + [".","1",".",".",".",".",".","8","."], + [".",".",".",".",".",".",".",".","."] +]] +comment = "Invalid sparse board (duplicate '1' in column 1)" +expected = false + +[[asserts]] +arguments = [[ + ["9",".",".",".",".",".",".",".","9"], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + ["9",".",".",".",".",".",".",".","9"] +]] +comment = "9 in all corners (invalid due to row/col sharing)" +expected = false + +[[asserts]] +arguments = [[ + [".",".",".",".",".",".",".",".","9"], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + ["9",".",".",".",".",".",".",".","."] +]] +comment = "Two 9s in different corners (valid)" +expected = true + +[[asserts]] +arguments = [[ + ["1",".",".",".",".",".",".",".","."], + [".","2",".",".",".",".",".",".","."], + [".",".","3",".",".",".",".",".","."], + [".",".",".","4",".",".",".",".","."], + [".",".",".",".","5",".",".",".","."], + [".",".",".",".",".","6",".",".","."], + [".",".",".",".",".",".","7",".","."], + [".",".",".",".",".",".",".","8","."], + [".",".",".",".",".",".",".",".","9"] +]] +comment = "Valid main diagonal" +expected = true + +[[asserts]] +arguments = [[ + ["1",".",".",".",".",".",".",".","."], + [".","2",".",".",".",".",".",".","."], + [".",".","1",".",".",".",".",".","."], + [".",".",".","4",".",".",".",".","."], + [".",".",".",".","5",".",".",".","."], + [".",".",".",".",".","6",".",".","."], + [".",".",".",".",".",".","7",".","."], + [".",".",".",".",".",".",".","8","."], + [".",".",".",".",".",".",".",".","9"] +]] +comment = "Invalid diagonal (top-left box has duplicate '1')" +expected = false + +[[asserts]] +arguments = [[ + [".",".",".",".",".",".","1","2","3"], + [".",".",".",".",".",".","4","5","6"], + [".",".",".",".",".",".","7","8","9"], + ["1","2","3",".",".",".",".",".","."], + ["4","5","6",".",".",".",".",".","."], + ["7","8","9",".",".",".",".",".","."], + [".",".",".","1","2","3",".",".","."], + [".",".",".","4","5","6",".",".","."], + [".",".",".","7","8","9",".",".","."] +]] +comment = "Valid blocks staggered across grid" +expected = true + +[[asserts]] +arguments = [[ + [".",".",".",".",".",".","1","2","3"], + [".",".",".",".",".",".","4","5","6"], + [".",".",".",".",".",".","7","8","9"], + ["1","2","3",".",".",".",".",".","."], + ["4","5","6",".",".",".",".",".","."], + ["7","8","9",".",".",".",".",".","."], + [".",".",".","1","2","3",".",".","."], + [".",".",".","4","5","6",".",".","."], + [".",".",".","7","8","1",".",".","."] +]] +comment = "Invalid staggered blocks (duplicate '1' in bottom-middle box)" +expected = false + +[[asserts]] +arguments = [[ + [".",".","4",".",".",".","6","3","."], + [".",".",".",".",".",".",".",".","."], + ["5",".",".",".",".","9",".",".","."], + [".",".",".","5","6",".",".",".","."], + ["4",".","3",".",".",".",".",".","1"], + [".",".",".","7",".",".",".",".","."], + [".",".",".","5",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."] +]] +comment = "Invalid due to two 5s in the middle column (col 3)" +expected = false + +[[asserts]] +arguments = [[ + [".","1",".",".",".",".",".",".","."], + ["1",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."] +]] +comment = "Two identical numbers in the same box, but different row/col" +expected = false + +[[asserts]] +arguments = [[ + [".",".",".","1",".",".","1",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."] +]] +comment = "Two identical numbers in the same row, but different box/col" +expected = false + +[[asserts]] +arguments = [[ + [".",".",".","1",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".","1",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."] +]] +comment = "Two identical numbers in the same col, but different box/row" +expected = false + +[[asserts]] +arguments = [[ + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".","5",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."], + [".",".",".",".",".",".",".",".","."] +]] +comment = "Single element is always valid" +expected = true + +[[asserts]] +arguments = [[ + ["3",".","6","5",".","8","4",".","."], + ["5","2",".",".",".",".",".",".","."], + [".","8","7",".",".",".",".","3","1"], + [".",".","3",".","1",".",".","8","."], + ["9",".",".","8","6","3",".",".","5"], + [".","5",".",".","9",".","6",".","."], + ["1","3",".",".",".",".","2","5","."], + [".",".",".",".",".",".",".","7","4"], + [".",".","5","2",".","6","3",".","."] +]] +comment = "Complex real valid puzzle" +expected = true + +[[asserts]] +arguments = [[ + ["3",".","6","5",".","8","4",".","."], + ["5","2",".",".",".",".",".",".","."], + [".","8","7",".",".",".",".","3","1"], + [".",".","3",".","1",".",".","8","."], + ["9",".",".","8","6","3",".",".","5"], + [".","5",".",".","9",".","6",".","."], + ["1","3",".",".",".",".","2","5","."], + [".",".",".",".",".",".",".","7","4"], + [".",".","5","2",".","6","3",".","8"] +]] +comment = "Complex real valid puzzle" +expected = true \ No newline at end of file diff --git a/tasks/medium/graphs/flood_fill.toml b/tasks/medium/graphs/flood_fill.toml new file mode 100644 index 0000000..298c197 --- /dev/null +++ b/tasks/medium/graphs/flood_fill.toml @@ -0,0 +1,226 @@ +level = "medium" +name = "flood_fill" +tags = ["graphs"] +time_to_solve_sec = 400 + +description_en = """ +An image is represented by a 2D integer array `image`, where `image[i][j]` represents the pixel value of the image. + +You are also given three integers `sr`, `sc`, and `color`. You should perform a flood fill on the image starting from the pixel `image[sr][sc]`. + +To perform a flood fill, consider the starting pixel, plus any pixels connected 4-directionally to the starting pixel of the same color as the starting pixel, plus any pixels connected 4-directionally to those pixels (also with the same color), and so on. Replace the color of all of the aforementioned pixels with `color`. + +Return the modified image after performing the flood fill. +""" + +description_ru = """ +Изображение представлено в виде двумерного массива целых чисел `image`, где `image[i][j]` — это значение пикселя. + +Вам также даны три целых числа: `sr`, `sc` и `color`. Вы должны выполнить заливку (flood fill) изображения, начиная с пикселя `image[sr][sc]`. + +Для выполнения заливки возьмите начальный пиксель, а также все соседние по вертикали и горизонтали пиксели того же цвета, что и начальный. Затем возьмите соседние пиксели для добавленных пикселей (также того же цвета), и так далее. Замените цвет всех этих пикселей на новый `color`. + +Верните измененное изображение после выполнения заливки. +""" + +limits = """ +- $1 \\leq \\text{len}(\\text{image}) \\leq 50$ +- $1 \\leq \\text{len}(\\text{image}[0]) \\leq 50$ +- $0 \\leq \\text{image}[i][j], \\text{color} \\leq 100$ +- $0 \\leq \\text{sr} < \\text{len}(\\text{image})$ +- $0 \\leq \\text{sc} < \\text{len}(\\text{image}[0])$ +""" + +solution = """ +def solution(image: list[list[int]], sr: int, sc: int, color: int) -> list[list[int]]: + old = image[sr][sc] + if old == color: return image + def dfs(r, c): + if 0 <= r < len(image) and 0 <= c < len(image[0]) and image[r][c] == old: + image[r][c] = color + dfs(r + 1, c); dfs(r - 1, c); dfs(r, c + 1); dfs(r, c - 1) + dfs(sr, sc) + return image +""" + +examples = """ +solution([[1]], 0, 0, 2) == [[2]] +solution([[0, 0], [0, 0]], 0, 0, 2) == [[2, 2], [2, 2]] +solution([[1, 1, 1], [1, 1, 0], [1, 0, 1]], 1, 1, 2) == [[2, 2, 2], [2, 2, 0], [2, 0, 1]] +""" + +[[input_signature]] +argument_name = "image" +[input_signature.type] +name = "array" +[input_signature.type.nested] +name = "array" +[input_signature.type.nested.nested] +name = "integer" + +[[input_signature]] +argument_name = "sr" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "sc" +[input_signature.type] +name = "integer" + +[[input_signature]] +argument_name = "color" +[input_signature.type] +name = "integer" + +[output_signature.type] +name = "array" +[output_signature.type.nested] +name = "array" +[output_signature.type.nested.nested] +name = "integer" + +[[asserts]] +arguments = [[[1]], 0, 0, 2] +comment = "1x1 grid, standard fill" +expected = [[2]] + +[[asserts]] +arguments = [[[2]], 0, 0, 2] +comment = "1x1 grid, same color no change" +expected = [[2]] + +[[asserts]] +arguments = [[[1, 1], [1, 1]], 0, 0, 3] +comment = "2x2 grid, all same color" +expected = [[3, 3], [3, 3]] + +[[asserts]] +arguments = [[[1, 2], [3, 4]], 0, 0, 5] +comment = "2x2 grid, distinct colors, start top-left" +expected = [[5, 2], [3, 4]] + +[[asserts]] +arguments = [[[1, 2], [3, 4]], 1, 1, 5] +comment = "2x2 grid, distinct colors, start bottom-right" +expected = [[1, 2], [3, 5]] + +[[asserts]] +arguments = [[[1, 1, 1], [1, 1, 0], [1, 0, 1]], 1, 1, 2] +comment = "Classic connected component shape" +expected = [[2, 2, 2], [2, 2, 0], [2, 0, 1]] + +[[asserts]] +arguments = [[[0, 0, 0], [0, 0, 0]], 0, 0, 0] +comment = "Grid already the target color" +expected = [[0, 0, 0], [0, 0, 0]] + +[[asserts]] +arguments = [[[1, 2, 1], [2, 1, 2], [1, 2, 1]], 1, 1, 3] +comment = "Checkerboard, isolated center" +expected = [[1, 2, 1], [2, 3, 2], [1, 2, 1]] + +[[asserts]] +arguments = [[[1, 2, 1], [2, 1, 2], [1, 2, 1]], 0, 0, 3] +comment = "Checkerboard, isolated corner" +expected = [[3, 2, 1], [2, 1, 2], [1, 2, 1]] + +[[asserts]] +arguments = [[[1, 1, 1], [2, 2, 2], [1, 1, 1]], 1, 1, 3] +comment = "Horizontal stripe" +expected = [[1, 1, 1], [3, 3, 3], [1, 1, 1]] + +[[asserts]] +arguments = [[[1, 2, 1], [1, 2, 1], [1, 2, 1]], 1, 1, 3] +comment = "Vertical stripe" +expected = [[1, 3, 1], [1, 3, 1], [1, 3, 1]] + +[[asserts]] +arguments = [[[0, 0, 0], [0, 1, 0], [0, 0, 0]], 1, 1, 2] +comment = "Single central pixel different from background" +expected = [[0, 0, 0], [0, 2, 0], [0, 0, 0]] + +[[asserts]] +arguments = [[[0, 0, 0], [0, 1, 0], [0, 0, 0]], 0, 0, 2] +comment = "Surrounding background avoiding center" +expected = [[2, 2, 2], [2, 1, 2], [2, 2, 2]] + +[[asserts]] +arguments = [[[1, 0, 0], [0, 1, 0], [0, 0, 1]], 0, 0, 2] +comment = "Diagonal connection (does not spread)" +expected = [[2, 0, 0], [0, 1, 0], [0, 0, 1]] + +[[asserts]] +arguments = [[[1, 1, 1, 1]], 0, 2, 5] +comment = "1D horizontal row" +expected = [[5, 5, 5, 5]] + +[[asserts]] +arguments = [[[1], [1], [1], [1]], 2, 0, 5] +comment = "1D vertical column" +expected = [[5], [5], [5], [5]] + +[[asserts]] +arguments = [[[1, 1, 1], [1, 0, 1], [1, 1, 1]], 0, 0, 2] +comment = "Ring shape, fill outside" +expected = [[2, 2, 2], [2, 0, 2], [2, 2, 2]] + +[[asserts]] +arguments = [[[1, 1, 1], [1, 0, 1], [1, 1, 1]], 1, 1, 2] +comment = "Ring shape, fill inside" +expected = [[1, 1, 1], [1, 2, 1], [1, 1, 1]] + +[[asserts]] +arguments = [[[0, 1, 0], [1, 0, 1], [0, 1, 0]], 1, 1, 2] +comment = "Hollow cross, fill center" +expected = [[0, 1, 0], [1, 2, 1], [0, 1, 0]] + +[[asserts]] +arguments = [[[0, 1, 0], [1, 1, 1], [0, 1, 0]], 1, 1, 2] +comment = "Filled cross, fill cross" +expected = [[0, 2, 0], [2, 2, 2], [0, 2, 0]] + +[[asserts]] +arguments = [[[7, 7, 8], [7, 8, 8], [9, 9, 9]], 0, 0, 1] +comment = "Asymmetric blob shape" +expected = [[1, 1, 8], [1, 8, 8], [9, 9, 9]] + +[[asserts]] +arguments = [[[2, 2, 2, 2], [2, 3, 3, 2], [2, 3, 3, 2], [2, 2, 2, 2]], 1, 1, 4] +comment = "Square inside a square" +expected = [[2, 2, 2, 2], [2, 4, 4, 2], [2, 4, 4, 2], [2, 2, 2, 2]] + +[[asserts]] +arguments = [[[5, 5, 5], [5, 5, 5], [5, 5, 5]], 2, 2, 5] +comment = "3x3 all same, target color is same" +expected = [[5, 5, 5], [5, 5, 5], [5, 5, 5]] + +[[asserts]] +arguments = [[[1, 2, 3], [4, 5, 6], [7, 8, 9]], 2, 2, 0] +comment = "All distinct numbers" +expected = [[1, 2, 3], [4, 5, 6], [7, 8, 0]] + +[[asserts]] +arguments = [[[1, 1], [0, 1]], 1, 1, 3] +comment = "L-shape component" +expected = [[3, 3], [0, 3]] + +[[asserts]] +arguments = [[[0, 1], [1, 1]], 0, 1, 3] +comment = "Reverse L-shape component" +expected = [[0, 3], [3, 3]] + +[[asserts]] +arguments = [[[1, 1], [1, 1], [1, 1]], 0, 0, 2] +comment = "3x2 full block" +expected = [[2, 2], [2, 2], [2, 2]] + +[[asserts]] +arguments = [[[1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 0, 1, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1]], 2, 2, 2] +comment = "Nested rings, center isolated pixel" +expected = [[1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 0, 2, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1]] + +[[asserts]] +arguments = [[[1, 1, 1, 1, 1], [1, 0, 0, 0, 1], [1, 0, 1, 0, 1], [1, 0, 0, 0, 1], [1, 1, 1, 1, 1]], 0, 0, 2] +comment = "Nested rings, outer boundary" +expected = [[2, 2, 2, 2, 2], [2, 0, 0, 0, 2], [2, 0, 1, 0, 2], [2, 0, 0, 0, 2], [2, 2, 2, 2, 2]] \ No newline at end of file diff --git a/tasks/medium/graphs/topological_sort_possible.toml b/tasks/medium/graphs/topological_sort_possible.toml new file mode 100644 index 0000000..46bce1d --- /dev/null +++ b/tasks/medium/graphs/topological_sort_possible.toml @@ -0,0 +1,206 @@ +level = "medium" +name = "topological_sort_possible" +tags = ["graphs", "algorithms", "topological_sort"] +time_to_solve_sec = 400 + +description_en = """ +You are given `n` nodes labeled from $0$ to $n - 1$ and a list of directed `edges`. + +Each edge $[u, v]$ indicates that node $u$ must appear before node $v$ in a topological ordering. + +Return `True` if it is possible to topologically sort the graph (i.e., it contains no directed cycles), and `False` otherwise. +""" + +description_ru = """ +Вам дано `n` вершин, пронумерованных от $0$ до $n - 1$, и список ориентированных ребер `edges`. + +Каждое ребро $[u, v]$ означает, что вершина $u$ должна идти перед вершиной $v$ в топологической сортировке. + +Верните `True`, если граф можно отсортировать топологически (то есть в нем нет ориентированных циклов), и `False` в противном случае. +""" + +limits = """ +- $1 \\leq n \\leq 10^4$ +- $0 \\leq \\text{len}(\\text{edges}) \\leq 10^4$ +- $\\text{edges}[i] = [u, v]$ +- $0 \\leq u, v < n$ +""" + +solution = """ +def solution(n: int, edges: list) -> bool: + from graphlib import TopologicalSorter, CycleError + + graph = {i: set() for i in range(n)} + for u, v in edges: + graph[v].add(u) + + try: + TopologicalSorter(graph).prepare() + return True + except CycleError: + return False +""" + +examples = """ +solution(1, []) == True +solution(2, [[0, 1]]) == True +solution(2, [[0, 1], [1, 0]]) == False +solution(4, [[0, 1], [1, 2], [2, 3]]) == True +""" + +[[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 = "boolean" + +[[asserts]] +arguments = [1, []] +comment = "Single node without edges" +expected = true + +[[asserts]] +arguments = [2, [[0, 1]]] +comment = "Two nodes, simple directed edge" +expected = true + +[[asserts]] +arguments = [2, [[0, 1], [1, 0]]] +comment = "Two nodes, cycle" +expected = false + +[[asserts]] +arguments = [3, [[0, 1], [1, 2]]] +comment = "Three nodes, straight line" +expected = true + +[[asserts]] +arguments = [3, [[0, 1], [1, 2], [2, 0]]] +comment = "Three nodes, simple cycle" +expected = false + +[[asserts]] +arguments = [4, [[0, 1], [1, 2], [2, 3]]] +comment = "Four nodes, straight line" +expected = true + +[[asserts]] +arguments = [4, [[0, 1], [1, 2], [2, 3], [3, 0]]] +comment = "Four nodes, full cycle" +expected = false + +[[asserts]] +arguments = [4, [[0, 1], [2, 3]]] +comment = "Disconnected components, no cycles" +expected = true + +[[asserts]] +arguments = [5, [[0, 1], [1, 2], [3, 4], [4, 3]]] +comment = "Disconnected components, one has a cycle" +expected = false + +[[asserts]] +arguments = [3, [[0, 1], [0, 2]]] +comment = "Tree pointing outwards" +expected = true + +[[asserts]] +arguments = [3, [[1, 0], [2, 0]]] +comment = "Tree pointing inwards" +expected = true + +[[asserts]] +arguments = [4, [[0, 1], [0, 2], [1, 3], [2, 3]]] +comment = "Diamond shape, acyclic" +expected = true + +[[asserts]] +arguments = [4, [[0, 1], [1, 3], [3, 2], [2, 0]]] +comment = "Cycle of 4 nodes" +expected = false + +[[asserts]] +arguments = [1, [[0, 0]]] +comment = "Self-loop edge" +expected = false + +[[asserts]] +arguments = [5, [[0, 1], [1, 2], [2, 3], [3, 4], [1, 3]]] +comment = "DAG with a forward edge" +expected = true + +[[asserts]] +arguments = [5, [[0, 1], [1, 2], [2, 3], [3, 4], [3, 1]]] +comment = "Line with a back edge (cycle of 3)" +expected = false + +[[asserts]] +arguments = [6, [[0, 1], [1, 2], [3, 4], [4, 5]]] +comment = "Two separate paths" +expected = true + +[[asserts]] +arguments = [6, [[0, 1], [1, 2], [2, 0], [3, 4], [4, 5], [5, 3]]] +comment = "Two separate cyclic components" +expected = false + +[[asserts]] +arguments = [2, [[0, 1], [0, 1]]] +comment = "Duplicate edges, no cycles" +expected = true + +[[asserts]] +arguments = [3, [[0, 1], [1, 2], [2, 0], [0, 1]]] +comment = "Cycle with duplicate edges" +expected = false + +[[asserts]] +arguments = [5, []] +comment = "Multiple nodes with no edges" +expected = true + +[[asserts]] +arguments = [7, [[0, 1], [0, 2], [1, 3], [1, 4], [2, 5], [2, 6]]] +comment = "Binary tree structure" +expected = true + +[[asserts]] +arguments = [7, [[0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 6], [6, 0]]] +comment = "Large cycle of 7 nodes" +expected = false + +[[asserts]] +arguments = [4, [[0, 1], [0, 2], [0, 3], [1, 2], [1, 3], [2, 3]]] +comment = "Complete DAG" +expected = true + +[[asserts]] +arguments = [4, [[0, 1], [1, 2], [2, 3], [3, 1]]] +comment = "Lollipop graph (line going into a cycle)" +expected = false + +[[asserts]] +arguments = [5, [[0, 4], [1, 4], [2, 4], [3, 4]]] +comment = "Star graph directed to center" +expected = true + +[[asserts]] +arguments = [5, [[4, 0], [4, 1], [4, 2], [4, 3]]] +comment = "Star graph directed from center" +expected = true + +[[asserts]] +arguments = [8, [[0, 1], [1, 2], [3, 4], [4, 5], [6, 7], [7, 6]]] +comment = "Large forest with one cycle hidden" +expected = false \ No newline at end of file diff --git a/tasks/medium/greedy/minimum_bracket_reversals.toml b/tasks/medium/greedy/minimum_bracket_reversals.toml new file mode 100644 index 0000000..9ec881c --- /dev/null +++ b/tasks/medium/greedy/minimum_bracket_reversals.toml @@ -0,0 +1,216 @@ +level = "medium" +name = "minimum_bracket_reversals" +tags = ["greedy", "strings"] +time_to_solve_sec = 400 + +description_en = """ +Given a string `s` consisting only of curly brackets `{` and `}`, determine the minimum number of bracket reversals required to make the string balanced. + +A reversal changes `{` to `}` or `}` to `{`. +If it is impossible to balance the string, return `-1`. +""" + +description_ru = """ +Дана строка `s`, состоящая только из фигурных скобок `{` и `}`, определите минимальное количество переворотов скобок, необходимое для того, чтобы сделать строку сбалансированной. + +Переворот меняет `{` на `}` или `}` на `{`. +Если сбалансировать строку невозможно, верните `-1`. +""" + +limits = """ +- $0 \\leq \\text{len}(s) \\leq 10^5$ +""" + +solution = """ +def solution(s: str) -> int: + if len(s) % 2 != 0: + return -1 + + open_brackets = 0 + close_brackets = 0 + + for char in s: + if char == '{': + open_brackets += 1 + else: + if open_brackets > 0: + open_brackets -= 1 + else: + close_brackets += 1 + + return (open_brackets + 1) // 2 + (close_brackets + 1) // 2 +""" + +examples = """ +solution("}{") == 2 +solution("{{{") == -1 +solution("{{{}") == 1 +""" + +[[input_signature]] +argument_name = "s" +[input_signature.type] +name = "string" + +[output_signature.type] +name = "integer" + +[[asserts]] +arguments = [""] +comment = "Empty string" +expected = 0 + +[[asserts]] +arguments = ["{}"] +comment = "Already balanced" +expected = 0 + +[[asserts]] +arguments = ["}{"] +comment = "Two reversals needed" +expected = 2 + +[[asserts]] +arguments = ["{"] +comment = "Odd length string" +expected = -1 + +[[asserts]] +arguments = ["}"] +comment = "Odd length string" +expected = -1 + +[[asserts]] +arguments = ["{{{"] +comment = "Odd length string with all opens" +expected = -1 + +[[asserts]] +arguments = ["{{}}"] +comment = "Balanced nested brackets" +expected = 0 + +[[asserts]] +arguments = ["{}{}"] +comment = "Balanced consecutive brackets" +expected = 0 + +[[asserts]] +arguments = ["{{{{"] +comment = "All open brackets" +expected = 2 + +[[asserts]] +arguments = ["}}}}"] +comment = "All close brackets" +expected = 2 + +[[asserts]] +arguments = ["{{{{}}"] +comment = "More open than close" +expected = 1 + +[[asserts]] +arguments = ["}}}{{{"] +comment = "Fully inverted" +expected = 4 + +[[asserts]] +arguments = ["}}}{{"] +comment = "Odd length mixed" +expected = -1 + +[[asserts]] +arguments = ["}{{}}{{{"] +comment = "Complex mixed string" +expected = 3 + +[[asserts]] +arguments = ["{}{}{}{}{}{}{}{}{}{}{}{}"] +comment = "Long balanced string" +expected = 0 + +[[asserts]] +arguments = ["}}}}}}}}}}}}}}}}}}}}}}}}"] +comment = "Long all closing" +expected = 12 + +[[asserts]] +arguments = ["{{{{{{{{{{{{{{{{{{{{{{{{"] +comment = "Long all opening" +expected = 12 + +[[asserts]] +arguments = ["{}}}{{}}{{}}{{}}"] +comment = "Almost balanced" +expected = 1 + +[[asserts]] +arguments = ["}}{{}}{{}}{{}}{{"] +comment = "Repeated inverted pairs" +expected = 2 + +[[asserts]] +arguments = ["{{{{{{{{{{}}}}}}}}}}"] +comment = "Deep nesting" +expected = 0 + +[[asserts]] +arguments = ["}}}}{{{{"] +comment = "Symmetric inverted" +expected = 4 + +[[asserts]] +arguments = ["}{{}}}"] +comment = "Needs one open flip" +expected = 1 + +[[asserts]] +arguments = ["}}}}}}"] +comment = "Six closing" +expected = 3 + +[[asserts]] +arguments = ["{{"] +comment = "Two opening" +expected = 1 + +[[asserts]] +arguments = ["}}"] +comment = "Two closing" +expected = 1 + +[[asserts]] +arguments = ["}}}{"] +comment = "Three close one open" +expected = 3 + +[[asserts]] +arguments = ["}{{{"] +comment = "One close three open" +expected = 3 + +[[asserts]] +arguments = ["{}}}"] +comment = "One open three close" +expected = 1 + +[[asserts]] +arguments = ["{{}{"] +comment = "Three open one close" +expected = 1 + +[[asserts]] +arguments = ["}{}{"] +comment = "Alternating inverted" +expected = 2 + +[[asserts]] +arguments = ["{}{}{}{}{}{}{}{}{}{}{}{{"] +comment = "Balanced with two opens at end" +expected = 1 + +[[asserts]] +arguments = ["}}{}{}{}{}{}{}{}{}{}{}{}"] +comment = "Balanced with two closes at start" +expected = 1 \ No newline at end of file From 95b126466d593b9351fb23f3aacec3ec87b5a5ea Mon Sep 17 00:00:00 2001 From: Vitaly Kozlov Date: Sat, 16 May 2026 10:35:52 +0300 Subject: [PATCH 2/3] fix mismatched filename --- ...gest_balanced_substring.toml => longest_balanced_segment.toml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tasks/easy/strings/{longest_balanced_substring.toml => longest_balanced_segment.toml} (100%) diff --git a/tasks/easy/strings/longest_balanced_substring.toml b/tasks/easy/strings/longest_balanced_segment.toml similarity index 100% rename from tasks/easy/strings/longest_balanced_substring.toml rename to tasks/easy/strings/longest_balanced_segment.toml From b46427e87fc8688838041d4a28f6fe230b0c597e Mon Sep 17 00:00:00 2001 From: Vitaly Kozlov Date: Sat, 16 May 2026 10:45:21 +0300 Subject: [PATCH 3/3] update minimum_bracket_reversals --- .../greedy/minimum_bracket_reversals.toml | 111 ++++++++---------- 1 file changed, 51 insertions(+), 60 deletions(-) diff --git a/tasks/medium/greedy/minimum_bracket_reversals.toml b/tasks/medium/greedy/minimum_bracket_reversals.toml index 9ec881c..8839ce8 100644 --- a/tasks/medium/greedy/minimum_bracket_reversals.toml +++ b/tasks/medium/greedy/minimum_bracket_reversals.toml @@ -1,19 +1,19 @@ level = "medium" name = "minimum_bracket_reversals" -tags = ["greedy", "strings"] +tags = ["strings", "greedy", "stack"] time_to_solve_sec = 400 description_en = """ -Given a string `s` consisting only of curly brackets `{` and `}`, determine the minimum number of bracket reversals required to make the string balanced. +Given a string `s` consisting only of parentheses `(` and `)`, determine the minimum number of parentheses reversals required to make the string balanced. -A reversal changes `{` to `}` or `}` to `{`. +A reversal changes `(` to `)` or `)` to `(`. If it is impossible to balance the string, return `-1`. """ description_ru = """ -Дана строка `s`, состоящая только из фигурных скобок `{` и `}`, определите минимальное количество переворотов скобок, необходимое для того, чтобы сделать строку сбалансированной. +Дана строка `s`, состоящая только из круглых скобок `(` и `)`, определите минимальное количество переворотов скобок, необходимое для того, чтобы сделать строку сбалансированной. -Переворот меняет `{` на `}` или `}` на `{`. +Переворот меняет `(` на `)` или `)` на `(`. Если сбалансировать строку невозможно, верните `-1`. """ @@ -25,26 +25,22 @@ solution = """ def solution(s: str) -> int: if len(s) % 2 != 0: return -1 - - open_brackets = 0 - close_brackets = 0 - - for char in s: - if char == '{': - open_brackets += 1 + o = c = 0 + for x in s: + if x == '(': + o += 1 + elif o > 0: + o -= 1 else: - if open_brackets > 0: - open_brackets -= 1 - else: - close_brackets += 1 - - return (open_brackets + 1) // 2 + (close_brackets + 1) // 2 + c += 1 + return (o + 1) // 2 + (c + 1) // 2 """ examples = """ -solution("}{") == 2 -solution("{{{") == -1 -solution("{{{}") == 1 +solution("()") == 0 +solution(")(") == 2 +solution("(((") == -1 +solution(")))(((") == 4 """ [[input_signature]] @@ -61,156 +57,151 @@ comment = "Empty string" expected = 0 [[asserts]] -arguments = ["{}"] -comment = "Already balanced" -expected = 0 - -[[asserts]] -arguments = ["}{"] +arguments = [")("] comment = "Two reversals needed" expected = 2 [[asserts]] -arguments = ["{"] +arguments = ["("] comment = "Odd length string" expected = -1 [[asserts]] -arguments = ["}"] +arguments = [")"] comment = "Odd length string" expected = -1 [[asserts]] -arguments = ["{{{"] +arguments = ["((("] comment = "Odd length string with all opens" expected = -1 [[asserts]] -arguments = ["{{}}"] +arguments = ["(())"] comment = "Balanced nested brackets" expected = 0 [[asserts]] -arguments = ["{}{}"] +arguments = ["()()"] comment = "Balanced consecutive brackets" expected = 0 [[asserts]] -arguments = ["{{{{"] +arguments = ["(((("] comment = "All open brackets" expected = 2 [[asserts]] -arguments = ["}}}}"] +arguments = ["))))"] comment = "All close brackets" expected = 2 [[asserts]] -arguments = ["{{{{}}"] +arguments = ["(((())"] comment = "More open than close" expected = 1 [[asserts]] -arguments = ["}}}{{{"] +arguments = [")))((("] comment = "Fully inverted" expected = 4 [[asserts]] -arguments = ["}}}{{"] +arguments = [")))(("] comment = "Odd length mixed" expected = -1 [[asserts]] -arguments = ["}{{}}{{{"] +arguments = [")(())((("] comment = "Complex mixed string" expected = 3 [[asserts]] -arguments = ["{}{}{}{}{}{}{}{}{}{}{}{}"] +arguments = ["()()()()()()()()()()()()"] comment = "Long balanced string" expected = 0 [[asserts]] -arguments = ["}}}}}}}}}}}}}}}}}}}}}}}}"] +arguments = ["))))))))))))))))))))))))"] comment = "Long all closing" expected = 12 [[asserts]] -arguments = ["{{{{{{{{{{{{{{{{{{{{{{{{"] +arguments = ["(((((((((((((((((((((((("] comment = "Long all opening" expected = 12 [[asserts]] -arguments = ["{}}}{{}}{{}}{{}}"] +arguments = ["()))(())())(()"] comment = "Almost balanced" -expected = 1 +expected = 3 [[asserts]] -arguments = ["}}{{}}{{}}{{}}{{"] +arguments = ["))(())(())())(("] comment = "Repeated inverted pairs" -expected = 2 +expected = -1 [[asserts]] -arguments = ["{{{{{{{{{{}}}}}}}}}}"] +arguments = ["(((((((((())))))))))"] comment = "Deep nesting" expected = 0 [[asserts]] -arguments = ["}}}}{{{{"] +arguments = ["))))(((("] comment = "Symmetric inverted" expected = 4 [[asserts]] -arguments = ["}{{}}}"] +arguments = [")(()))"] comment = "Needs one open flip" expected = 1 [[asserts]] -arguments = ["}}}}}}"] +arguments = ["))))))"] comment = "Six closing" expected = 3 [[asserts]] -arguments = ["{{"] +arguments = ["(("] comment = "Two opening" expected = 1 [[asserts]] -arguments = ["}}"] +arguments = ["))"] comment = "Two closing" expected = 1 [[asserts]] -arguments = ["}}}{"] +arguments = [")))("] comment = "Three close one open" expected = 3 [[asserts]] -arguments = ["}{{{"] +arguments = [")((("] comment = "One close three open" expected = 3 [[asserts]] -arguments = ["{}}}"] -comment = "One open three close" -expected = 1 +arguments = ["())))"] +comment = "One open four close" +expected = -1 [[asserts]] -arguments = ["{{}{"] +arguments = ["(()("] comment = "Three open one close" expected = 1 [[asserts]] -arguments = ["}{}{"] +arguments = [")()("] comment = "Alternating inverted" expected = 2 [[asserts]] -arguments = ["{}{}{}{}{}{}{}{}{}{}{}{{"] +arguments = ["()()()()()()()()()()()()(("] comment = "Balanced with two opens at end" expected = 1 [[asserts]] -arguments = ["}}{}{}{}{}{}{}{}{}{}{}{}"] +arguments = ["))()()()()()()()()()()()()"] comment = "Balanced with two closes at start" expected = 1 \ No newline at end of file