Skip to content

S1Q3 · Repeat Second Half of a Tuple

⚡ Quick Reference

Function: repeat_second_half(t: tuple) -> tuple

Core idea: the second half starts at index n // 2. Return the original tuple concatenated with that slice.

def repeat_second_half(t: tuple) -> tuple:
    return t + t[len(t) // 2:]

Key rules: - Second half starts at n // 2 (integer division) - Odd length: middle element is in the first half → n//2 rounds down correctly - Returns a new tuple -tuple concatenation never mutates the original


Problem Statement

Problem

Write a function repeat_second_half(t) that returns a new tuple equal to t followed by the second half of t. For odd-length tuples, the middle element belongs to the first half.

Examples:

Input
(1, 2, 3, 4, 5)
Output
(1, 2, 3, 4, 5, 4, 5)
Input
(10, 20, 30, 40)
Output
(10, 20, 30, 40, 30, 40)
Input
('a', 'b', 'c', 'd', 'e', 'f')
Output
('a', 'b', 'c', 'd', 'e', 'f', 'd', 'e', 'f')
Input
(1, 2, 3)
Output
(1, 2, 3, 3)

Understanding the problem

The "second half" starts at index n // 2:

n n // 2 First half indices Second half indices
4 (even) 2 0, 1 2, 3
5 (odd) 2 0, 1, 2 3, 4
6 (even) 3 0, 1, 2 3, 4, 5
3 (odd) 1 0, 1 2

For odd n, n // 2 rounds down -the middle element (index n//2) ends up in the first half slice t[:n//2+1], while t[n//2:] includes it and beyond...

Wait -let me re-examine with (1, 2, 3, 4, 5) (n=5):

  • n // 2 = 2
  • t[2:] = (3, 4, 5) -but expected repeat is (4, 5) not (3, 4, 5)

So the split point must be math.ceil(n/2): - n=5: ceil(5/2) = 3t[3:] = (4, 5) - n=4: ceil(4/2) = 2t[2:] = (3, 4)
- n=6: ceil(6/2) = 3t[3:] = ('d','e','f') - n=3: ceil(3/2) = 2t[2:] = (3,)

The correct formula is t[ceil(n/2):] = t[(n+1)//2:].

ceil division without import

math.ceil(n/2) = (n + 1) // 2 using integer arithmetic. For n=5: (5+1)//2 = 3. For n=4: (4+1)//2 = 2. This avoids importing math.


Tracing all examples

Tuple n (n+1)//2 Second half t[(n+1)//2:] Result
(1,2,3,4,5) 5 3 (4,5) (1,2,3,4,5,4,5)
(10,20,30,40) 4 2 (30,40) (10,20,30,40,30,40)
('a','b','c','d','e','f') 6 3 ('d','e','f') ('a','b','c','d','e','f','d','e','f')
(1,2,3) 3 2 (3,) (1,2,3,3)

Solution approaches

def repeat_second_half(t: tuple) -> tuple:
    return t + t[(len(t) + 1) // 2:]

(len(t) + 1) // 2 is the ceiling of len(t) / 2 without importing math. Slice from that index, concatenate.

def repeat_second_half(t: tuple) -> tuple:
    n = len(t)
    split = (n + 1) // 2       # ceiling division -start of second half
    second_half = t[split:]    # elements from split to end
    return t + second_half

Each step named -split point, second half, final result.

import math

def repeat_second_half(t: tuple) -> tuple:
    split = math.ceil(len(t) / 2)
    return t + t[split:]

math.ceil(n / 2) is explicit and readable. Equivalent to (n+1)//2 but requires an import.

repeat_second_half = lambda t: t + t[(len(t) + 1) // 2:]

Entire function as a lambda. Useful when passing as an argument.


Key takeaways

01

Ceiling division: (n+1)//2

(n+1)//2 computes ceil(n/2) without importing math. For even n it equals n//2; for odd n it gives one more -placing the middle element in the first half.

02

Tuple + tuple = new tuple

Like list concatenation, tuple + creates a brand new tuple. It never modifies either operand -immutability is automatic.

03

Verify odd/even cases separately

When the split index depends on parity, always trace one even-length and one odd-length example. The formula (n+1)//2 works for both -confirming this with the trace saves debugging time.