Skip to content

How to Find Consecutive Odd Integer Pairs Below a Limit with a Sum Threshold in Python

Learn efficient Python methods to find all pairs of consecutive odd numbers under a given limit a where their sum exceeds threshold b, with optimized loops, edge case handling, and performance comparisons.

Finding pairs of consecutive odd positive integers that satisfy boundary and sum constraints is a practical exercise in number theory and algorithmic thinking. Given two positive integers - an upper limit a and a sum threshold b - the task is to find every pair of consecutive odd numbers where both values are smaller than a and their combined sum is greater than b.

In this guide, you'll learn clear, efficient approaches to solve this problem in Python with proper explanations, edge case handling, and best practices.

Understanding the Problem

Consecutive odd numbers are odd integers that differ by exactly 2: (1, 3), (3, 5), (11, 13), etc.

Given positive integers a and b, find all pairs (x, x + 2) satisfying:

  • Both x and x + 2 are odd positive integers
  • Both x and x + 2 are strictly less than a
  • x + (x + 2) > b (the pair's sum exceeds b)

Worked example with a = 60, b = 100:

Pair Both < 60? Sum Sum > 100? Valid?
(47, 49) ✅ 96 ❌ ❌
(49, 51) ✅ 100 ❌ ❌
(51, 53) ✅ 104 ✅ ✅
(53, 55) ✅ 108 ✅ ✅
(55, 57) ✅ 112 ✅ ✅
(57, 59) ✅ 116 ✅ ✅
(59, 61) ❌ - - ❌

Using an Optimized Loop with a Calculated Starting Point

The most efficient approach skips numbers that can never form valid pairs. Since the sum of (x, x + 2) equals 2x + 2, the condition 2x + 2 > b means x > (b - 2) / 2. We derive the starting point directly:

def find_consecutive_odd_pairs(a, b):
    """Find consecutive odd integer pairs < a with sum > b."""
    if a <= 0 or b <= 0:
        return []

    min_x = max(1, (b - 2) // 2 + 1)
    if min_x % 2 == 0:
        min_x += 1  # Ensure starting on an odd number

    pairs = []
    for x in range(min_x, a, 2):
        if x + 2 < a and x + (x + 2) > b:
            pairs.append((x, x + 2))

    return pairs


a, b = 60, 100
result = find_consecutive_odd_pairs(a, b)

if result:
    print("Pairs of consecutive odd numbers:")
    for x, y in result:
        print(f"  ({x}, {y}) → sum = {x + y}")
else:
    print("None")

Output:

Pairs of consecutive odd numbers:
  (51, 53) → sum = 104
  (53, 55) → sum = 108
  (55, 57) → sum = 112
  (57, 59) → sum = 116

How it works:

  1. The minimum starting point is derived from b, skipping all numbers guaranteed to produce sums ≤ b.
  2. range(min_x, a, 2) steps by 2, visiting only odd numbers.
  3. x + 2 < a ensures both numbers stay strictly below the limit.
  4. x + (x + 2) > b filters by the sum threshold.

Using List Comprehension

List comprehension provides a clean, Pythonic single-expression solution:

def find_consecutive_odd_pairs(a, b):
    """Find consecutive odd pairs < a with sum > b."""
    return [
        (x, x + 2)
        for x in range(1, a, 2)
        if x + 2 < a and 2 * x + 2 > b
    ]


a, b = 60, 100
result = find_consecutive_odd_pairs(a, b)

if result:
    print("Pairs of consecutive odd numbers:")
    for x, y in result:
        print(f"{x} , {y}")
else:
    print("None")

Output:

Pairs of consecutive odd numbers:
51 , 53
53 , 55
55 , 57
57 , 59

Handling the Edge Case: No Valid Pairs

When b is too large relative to a, no pair can satisfy both constraints:

def find_consecutive_odd_pairs(a, b):
    """Find consecutive odd pairs < a with sum > b."""
    return [
        (x, x + 2)
        for x in range(1, a, 2)
        if x + 2 < a and 2 * x + 2 > b
    ]

a, b = 20, 200
result = find_consecutive_odd_pairs(a, b)

if result:
    for x, y in result:
        print(f"{x} , {y}")
else:
    print("None")

Output:

None

The largest possible pair under 20 is (17, 19) with sum 36, far below 200.

Common Mistake: Iterating Over All Integers Instead of Odd Numbers

A frequent error is looping through every integer and checking for oddness inside the loop, which wastes half the iterations.

Inefficient approach

a, b = 60, 100
pairs = []

for x in range(1, a):         # Checks EVERY integer
    if x % 2 != 0:            # Filters for odd (wasteful)
        if x + 2 < a and x + (x + 2) > b:
            pairs.append((x, x + 2))

print(pairs)

This iterates through 59 numbers, checking the oddness condition 59 times.

Efficient approach: step by 2

a, b = 60, 100
pairs = []

for x in range(1, a, 2):      # Only visits odd numbers
    if x + 2 < a and x + (x + 2) > b:
        pairs.append((x, x + 2))

print(pairs)
[(51, 53), (53, 55), (55, 57), (57, 59)]

This iterates through only 30 numbers with no wasted checks. Using range(start, stop, 2) with an odd starting value guarantees every visited number is odd.

Common Mistake: Confusing < with <= for the Boundary

The problem states both numbers must be smaller than a. Using <= instead of < can include invalid pairs.

Wrong: includes a itself

a = 60

for x in range(1, a, 2):
    if x + 2 <= a:  # Wrong: should be strictly less than
        pass

With a = 59 (odd), this would allow the pair (57, 59) where 59 is not smaller than 59.

Correct: strict less-than

a = 60

for x in range(1, a, 2):
    if x + 2 < a:  # Correct: both values strictly less than a
        pass

Using a Generator for Memory Efficiency

For very large values of a, a generator avoids building the entire list in memory:

def consecutive_odd_pairs_gen(a, b):
    """Yield consecutive odd pairs < a with sum > b."""
    min_x = max(1, (b - 2) // 2 + 1)
    if min_x % 2 == 0:
        min_x += 1

    for x in range(min_x, a, 2):
        if x + 2 < a and 2 * x + 2 > b:
            yield (x, x + 2)


a, b = 1_000_000, 999_000
count = sum(1 for _ in consecutive_odd_pairs_gen(a, b))
print(f"Found {count} valid pairs.")

Output:

Found 250249 valid pairs.

Adding Input Validation

Robust code should validate inputs before processing:

def find_consecutive_odd_pairs(a, b):
    """Find consecutive odd pairs < a with sum > b.

    Args:
        a: Upper limit (positive integer).
        b: Sum threshold (positive integer).

    Returns:
        List of tuples of valid consecutive odd pairs.

    Raises:
        TypeError: If inputs are not integers.
        ValueError: If inputs are not positive.
    """
    if not isinstance(a, int) or not isinstance(b, int):
        raise TypeError("Both a and b must be integers.")
    if a <= 0 or b <= 0:
        raise ValueError("Both a and b must be positive integers.")

    return [
        (x, x + 2)
        for x in range(1, a, 2)
        if x + 2 < a and 2 * x + 2 > b
    ]


print(find_consecutive_odd_pairs(60, 100))

try:
    find_consecutive_odd_pairs(-5, 100)
except ValueError as e:
    print(f"Error: {e}")

Output:

[(51, 53), (53, 55), (55, 57), (57, 59)]
Error: Both a and b must be positive integers.

Quick Comparison of Approaches

Approach Efficiency Memory Best For
Optimized loop (smart start) ⭐⭐⭐ Best O(k) General use (recommended)
List comprehension ⭐⭐ Good O(k) Clean, concise code
Generator ⭐⭐⭐ Best O(1) Very large ranges

k = number of valid pairs found.

Conclusion

Finding consecutive odd pairs under a limit with a sum threshold is straightforward in Python when you apply the right techniques:

  • Use range() with step 2 starting from an odd number to iterate over only odd integers, avoiding wasted iterations on even numbers.
  • Calculate the minimum starting point mathematically from b to skip numbers that can't produce valid sums.
  • Use strict < comparisons for "smaller than" constraints to avoid off-by-one errors.
  • Prefer generators for very large ranges where memory is a concern.
  • Validate inputs to handle edge cases like negative numbers or non-integer types.

The time complexity is O(a) for the basic approach or O(a - b/2) with the optimized starting point, and space complexity is O(1) when using a generator.

Navigation