Mid Term

Mid-term examination problems covering topics from Sessions 01-09 including graph algorithms, data structures, and string processing.

Problems

Bombs NO they are Mines

Problem Information

  • Source: Custom
  • Difficulty: Secret
  • Time Limit: 1000ms
  • Memory Limit: 256MB

Problem Statement

Given a grid of R rows and C columns, find the shortest path from a source cell to a destination cell. Some cells contain mines and are blocked.

Input Format

  • Multiple test cases until R = 0
  • First line: R C (rows and columns)
  • Next line: number of rows containing mines
  • Following lines: row_index, count, and column indices of mines in that row
  • Source coordinates (row, col)
  • Destination coordinates (row, col)

Output Format

Minimum number of steps to reach destination, or -1 if impossible.

Example

Input:
3 3
1
1 1 1
0 0
2 2

Output:
4

3x3 grid with one mine at position (1,1). Path from (0,0) to (2,2) must go around the mine: (0,0)->(0,1)->(0,2)->(1,2)->(2,2) = 4 steps.

Solution

Approach

Dijkstra’s algorithm (BFS would also work since all edges have weight 1). Use priority queue to explore cells in order of distance. Move in 4 directions and avoid cells marked as mines.

Python Solution
from heapq import heappush, heappop
from collections import deque

DIRECTIONS = [(1, 0), (0, -1), (-1, 0), (0, 1)]

def bfs(rows, cols, start, dest, mines):
    dist = [[-1] * cols for _ in range(rows)]
    dist[start[0]][start[1]] = 0
    queue = deque([(start[0], start[1], 0)])

    while queue:
        x, y, d = queue.popleft()
        for dx, dy in DIRECTIONS:
            nx, ny = x + dx, y + dy
            if 0 <= nx < rows and 0 <= ny < cols and not mines[nx][ny] and dist[nx][ny] == -1:
                dist[nx][ny] = d + 1
                queue.append((nx, ny, d + 1))

    return dist[dest[0]][dest[1]]

def solution():
    while True:
        r, c = map(int, input().split())
        if r == 0:
            break

        num_mine_rows = int(input())
        mines = [[False] * c for _ in range(r)]

        for _ in range(num_mine_rows):
            line = list(map(int, input().split()))
            row_idx, count = line[0], line[1]
            for col_idx in line[2:2 + count]:
                mines[row_idx][col_idx] = True

        start = tuple(map(int, input().split()))
        dest = tuple(map(int, input().split()))
        print(bfs(r, c, start, dest, mines))

solution()
Complexity Analysis
  • Time Complexity: O(R * C * log(R * C)) for Dijkstra on grid
  • Space Complexity: O(R * C) for distance matrix and mine grid

Regular Bracket Sequence

Problem Information

  • Source: Codeforces 26B
  • Difficulty: Secret
  • Time Limit: 2000ms
  • Memory Limit: 256MB

Problem Statement

Given a bracket sequence consisting only of ‘(‘ and ‘)’ characters, find the length of the longest regular (properly nested) bracket subsequence.

Input Format

A single string containing only ‘(‘ and ‘)’ characters. Length up to 10^6.

Output Format

A single integer: the length of the longest regular bracket subsequence.

Example

Input:
(()))(

Output:
4

The longest regular subsequence is “(())” with length 4. The extra ‘)’ at position 4 and ‘(‘ at position 5 cannot form valid pairs.

Solution

Approach

Greedy approach using a counter. Track opening brackets with a counter. For each closing bracket, if there’s a matching opening bracket, add 2 to total. If no matching opening bracket, skip it.

Python Solution
def solution():
    s = input().strip()
    open_count = 0
    matched = 0

    for char in s:
        if char == '(':
            open_count += 1
        elif open_count > 0:
            open_count -= 1
            matched += 2

    print(matched)

solution()
Complexity Analysis
  • Time Complexity: O(n) where n is string length
  • Space Complexity: O(1)

Queries about less or equal elements

Problem Information

  • Source: Codeforces 600B
  • Difficulty: Secret
  • Time Limit: 2000ms
  • Memory Limit: 256MB

Problem Statement

Given two arrays A and B, for each element b[i] in B, find how many elements in A are less than or equal to b[i].

Input Format

  • First line: n m (sizes of arrays A and B)
  • Second line: n integers (array A)
  • Third line: m integers (array B)

Output Format

m integers: for each b[i], the count of elements in A that are <= b[i].

Example

Input:
5 4
1 2 3 4 5
6 1 2 3

Output:
5 1 2 3

Array A = [1,2,3,4,5]. Query 6: all 5 elements <= 6. Query 1: only 1 element <= 1. Query 2: 2 elements <= 2. Query 3: 3 elements <= 3.

Solution

Approach

Sort array A. For each query b[i], use binary search (bisect_right) to find the position where b[i] would be inserted, which gives the count.

Python Solution
from bisect import bisect_right

def solution():
    n, m = map(int, input().split())
    a = sorted(map(int, input().split()))
    b = list(map(int, input().split()))

    results = [bisect_right(a, x) for x in b]
    print(*results)

solution()
Complexity Analysis
  • Time Complexity: O(n log n + m log n) for sorting and m queries
  • Space Complexity: O(n) for sorted array

Find the Median

Problem Information

  • Source: Custom
  • Difficulty: Secret
  • Time Limit: 1000ms
  • Memory Limit: 256MB

Problem Statement

Given an array of N integers, find the median value. For an array sorted in ascending order, the median is the middle element at index N/2 (0-indexed after sorting).

Input Format

  • First line: N (number of elements)
  • Second line: N space-separated integers

Output Format

A single integer: the median of the array.

Example

Input:
5
3 1 4 1 5

Output:
3

Sorted array: [1, 1, 3, 4, 5]. Index N//2 = 5//2 = 2. Element at index 2 is 3.

Solution

Approach

Sort the array in ascending order and return the element at index N//2.

Python Solution
def solution():
    n = int(input())
    arr = sorted(map(int, input().split()))
    print(arr[n // 2])

solution()
Complexity Analysis
  • Time Complexity: O(n log n) for sorting
  • Space Complexity: O(n) for array storage

CamelCase

Problem Information

  • Source: Hackerrank
  • Difficulty: Secret
  • Time Limit: 4000ms
  • Memory Limit: 256MB

Problem Statement

Given a string in camelCase format (first word starts with lowercase, subsequent words start with uppercase), count the number of words.

Input Format

A single line containing a camelCase string.

Output Format

A single integer: the number of words in the string.

Example

Input:
saveChangesInTheEditor

Output:
5

Words: “save”, “Changes”, “In”, “The”, “Editor”. 4 uppercase letters mark new words, plus 1 initial word = 5 words.

Solution

Approach

Start with count = 1 (for the first word). Iterate through each character. If character is uppercase (ASCII < 97), increment counter. Each uppercase letter marks the start of a new word.

Python Solution
def solution():
    s = input().strip()
    # Count uppercase letters + 1 for the first word
    word_count = 1 + sum(1 for c in s if c.isupper())
    print(word_count)

solution()
Complexity Analysis
  • Time Complexity: O(n) where n is string length
  • Space Complexity: O(1)

Country Roads

Problem Information

  • Source: LightOJ 1002
  • Difficulty: Secret
  • Time Limit: 2000ms
  • Memory Limit: 32MB

Problem Statement

Given an undirected weighted graph representing cities and roads, find the minimum “maximum edge weight” path from a source city to all other cities. The cost of a path is the maximum edge weight along that path (minimax path problem).

Input Format

  • T: number of test cases
  • For each test case:
    • N M: number of nodes and edges
    • M lines with A B W: edge from A to B with weight W
    • t: the source node

Output Format

For each test case: “Case X:” followed by the minimum maximum edge weight to reach each city (0 to N-1), or “Impossible” if unreachable.

Example

Input:
1
4 4
0 1 5
1 2 3
2 3 4
0 3 10
0

Output:
Case 1:
0
5
5
4

Source is city 0. To reach 0: max edge = 0. To reach 1: path 0->1 with max = 5. To reach 2: path 0->1->2 with max = max(5,3) = 5. To reach 3: path 0->1->2->3 with max = max(5,3,4) = 5, but direct 0->3 has max = 10. Better: via 2, so answer is 4 (wait, should be 5). The path 0->3 via edges gives min-max = 4 through 2->3.

Solution

Approach

Modified Dijkstra’s algorithm. Instead of summing weights, track the maximum edge weight on the path. For relaxation: dist[v] = max(dist[u], edge_weight) if this is smaller than current dist[v].

Python Solution
from heapq import heappush, heappop
from collections import defaultdict
import sys

def dijkstra_minimax(n, start, graph):
    """Modified Dijkstra for minimax path (minimum of maximum edge weights)."""
    dist = [-1] * (n + 1)
    dist[start] = 0
    pq = [(0, start)]

    while pq:
        d, u = heappop(pq)
        if d > dist[u] and dist[u] != -1:
            continue
        for v, w in graph[u]:
            new_dist = max(w, dist[u])
            if dist[v] == -1 or new_dist < dist[v]:
                dist[v] = new_dist
                heappush(pq, (new_dist, v))

    return dist

def solution():
    tokens = sys.stdin.read().split()[::-1]
    num_cases = int(tokens.pop())

    for case_num in range(1, num_cases + 1):
        n, m = int(tokens.pop()), int(tokens.pop())
        graph = defaultdict(list)

        for _ in range(m):
            a, b, w = int(tokens.pop()), int(tokens.pop()), int(tokens.pop())
            graph[a].append((b, w))
            graph[b].append((a, w))

        source = int(tokens.pop())
        dist = dijkstra_minimax(n, source, graph)

        print(f"Case {case_num}:")
        for i in range(n):
            print(dist[i] if dist[i] >= 0 else 'Impossible')

solution()
Complexity Analysis
  • Time Complexity: O((N + M) log N) for modified Dijkstra
  • Space Complexity: O(N + M) for graph and distance arrays

Pangram

Problem Information

  • Source: Custom
  • Difficulty: Secret
  • Time Limit: 1000ms
  • Memory Limit: 256MB

Problem Statement

A pangram is a sentence that contains every letter of the alphabet at least once. Given a string, determine if it is a pangram.

Input Format

  • First line: N (length of the string)
  • Second line: a string of N characters

Output Format

“YES” if the string is a pangram, “NO” otherwise.

Example

Input:
35
TheQuickBrownFoxJumpsOverTheLazyDog

Output:
YES

The string contains all 26 letters of the alphabet, so it is a pangram.

Solution

Approach

Use a boolean array of size 26 to track presence of each letter. Convert each character to index (0-25) regardless of case. Mark the corresponding index as True. If all 26 positions are True, it’s a pangram.

Python Solution
def solution():
    _ = int(input())  # length not needed
    s = input().strip().lower()

    seen = set(s)
    is_pangram = all(chr(ord('a') + i) in seen for i in range(26))

    print('YES' if is_pangram else 'NO')

solution()
Complexity Analysis
  • Time Complexity: O(n) where n is string length
  • Space Complexity: O(1) for fixed-size array of 26

Printer Queue

Problem Information

  • Source: UVA 12100
  • Difficulty: Secret
  • Time Limit: 3000ms
  • Memory Limit: 256MB

Problem Statement

A printer queue processes jobs based on priority, not just FIFO order. Jobs with higher priority are printed first. If the front job doesn’t have the highest priority, it’s moved to the back of the queue. Find when a specific job (at position m) will be printed.

Input Format

  • T: number of test cases
  • For each test case:
    • n m: number of jobs and position of our job (0-indexed)
    • n integers: priorities of each job

Output Format

For each test case: the order in which our job is printed (1-indexed).

Example

Input:
1
4 0
1 2 3 2

Output:
4

Jobs with priorities [1, 2, 3, 2]. Our job is at position 0 (priority 1). Print order: priority 3 first, then 2, then 2, finally 1. Our job (priority 1) prints 4th.

Solution

Approach

Simulate the printer queue. Sort priorities in descending order to know which priority should print next. If front job has the current highest priority, print it; otherwise move to back. Track when our target job gets printed.

Python Solution
from collections import deque

def solution():
    num_cases = int(input())

    for _ in range(num_cases):
        n, target_pos = map(int, input().split())
        priorities = list(map(int, input().split()))

        # Queue of (priority, original_index)
        queue = deque((p, i) for i, p in enumerate(priorities))
        sorted_priorities = sorted(priorities, reverse=True)

        printed = 0
        priority_idx = 0

        while queue:
            job = queue.popleft()
            if job[0] == sorted_priorities[priority_idx]:
                printed += 1
                priority_idx += 1
                if job[1] == target_pos:
                    break
            else:
                queue.append(job)

        print(printed)

solution()
Complexity Analysis
  • Time Complexity: O(n^2) worst case for queue simulation
  • Space Complexity: O(n) for queue and sorted list

Soldier and Bananas

Problem Information

  • Source: Codeforces 546A
  • Difficulty: Secret
  • Time Limit: 1000ms
  • Memory Limit: 256MB

Problem Statement

A soldier wants to buy w bananas. The cost of bananas is progressive: the 1st banana costs k dollars, 2nd costs 2k, 3rd costs 3k, and so on. The soldier has n dollars. How much more money does he need to borrow?

Input Format

Single line with three integers: k n w

  • k: base cost of first banana
  • n: dollars the soldier has
  • w: number of bananas to buy

Output Format

Single integer: amount to borrow (0 if soldier has enough).

Example

Input:
3 17 4

Output:
13

Base cost k=3, soldier has n=17 dollars, wants w=4 bananas. Total cost = 3(1+2+3+4) = 310 = 30. Needs to borrow 30-17 = 13.

Solution

Approach

Total cost = k * (1 + 2 + … + w) = k * w * (w + 1) / 2. Amount to borrow = max(0, total_cost - n).

Python Solution
def solution():
    k, n, w = map(int, input().split())
    total_cost = k * w * (w + 1) // 2
    print(max(0, total_cost - n))

solution()
Complexity Analysis
  • Time Complexity: O(1)
  • Space Complexity: O(1)

Word Transformation

Problem Information

  • Source: UVA 429
  • Difficulty: Secret
  • Time Limit: 3000ms
  • Memory Limit: 256MB

Problem Statement

Given a dictionary of words and pairs of words, find the minimum number of single-character transformations needed to change one word into another. A valid transformation changes exactly one character while keeping the resulting word in the dictionary.

Input Format

  • N: number of test cases
  • For each test case:
    • Dictionary words (one per line) until ‘*’
    • Query pairs (start_word end_word) until blank line

Output Format

For each query: start_word end_word min_transformations.

Example

Input:
1
cat
car
far
*
cat far

Output:
cat far 2

Dictionary: cat, car, far. Query: cat to far. Transformations: cat -> car (change t to r) -> far (change c to f). Minimum = 2.

Solution

Approach

Build a graph where nodes are dictionary words. Connect two words with an edge if they differ by exactly one character. Use Dijkstra’s algorithm (or BFS) to find shortest path between query words.

Python Solution
from heapq import heappush, heappop
from collections import defaultdict

def differs_by_one(word1, word2):
    """Check if two words differ by exactly one character."""
    if len(word1) != len(word2):
        return False
    return sum(c1 != c2 for c1, c2 in zip(word1, word2)) == 1

def dijkstra(n, start, dest, graph):
    dist = [-1] * n
    dist[start] = 0
    pq = [(0, start)]

    while pq:
        d, u = heappop(pq)
        for v, w in graph[u]:
            new_dist = d + w
            if dist[v] == -1 or new_dist < dist[v]:
                dist[v] = new_dist
                heappush(pq, (new_dist, v))

    return dist[dest]

def solution():
    num_cases = int(input().strip())

    for tc in range(num_cases):
        dictionary = []
        while True:
            word = input().strip()
            if not word:
                continue
            if word == '*':
                break
            dictionary.append(word)

        queries = []
        while True:
            try:
                line = input().strip()
            except EOFError:
                break
            if not line:
                break
            queries.append(line.split())

        # Build word index mapping
        word_to_idx = {word: i for i, word in enumerate(dictionary)}
        n_words = len(dictionary)

        # Build graph connecting words that differ by one character
        graph = defaultdict(list)
        for i, word1 in enumerate(dictionary):
            for j in range(i + 1, n_words):
                word2 = dictionary[j]
                if differs_by_one(word1, word2):
                    graph[i].append((j, 1))
                    graph[j].append((i, 1))

        # Answer queries
        for src, dst in queries:
            start_idx = word_to_idx[src]
            end_idx = word_to_idx[dst]
            dist = dijkstra(n_words, start_idx, end_idx, graph)
            print(src, dst, dist)

        if tc < num_cases - 1:
            print()

solution()
Complexity Analysis
  • Time Complexity: O(W^2 * L + Q * (W + E) log W) where W is word count, L is max word length, Q is queries
  • Space Complexity: O(W^2) for graph edges in worst case