ints listlinkedlistints ints true ints tuplerange5 tuplelinkedlistints ints true for i in range3 lenlinkedlistrangei i true true true lenlinkedlistabcdefgh 8 strlinkedlist strlinkedlistrange5 0 1 2 3 4 ll linkedlist1 2 tuplell 1 2 ll append3 tuplell 1 2 3 ll append4 tuplell 1 2 3 4 lenll 4 reverse nodes within groups of size k ll linkedlist1 2 3 4 5 ll reverseknodes2 tuplell 2 1 4 3 5 strll 2 1 4 3 5 ints list linkedlist ints ints true ints tuple range 5 tuple linkedlist ints ints true for i in range 3 len linkedlist range i i true true true len linkedlist abcdefgh 8 str linkedlist str linkedlist range 5 0 1 2 3 4 ll linkedlist 1 2 tuple ll 1 2 ll append 3 tuple ll 1 2 3 ll append 4 tuple ll 1 2 3 4 len ll 4 reverse nodes within groups of size k ll linkedlist 1 2 3 4 5 ll reverse_k_nodes 2 tuple ll 2 1 4 3 5 str ll 2 1 4 3 5
from __future__ import annotations

from collections.abc import Iterable, Iterator
from dataclasses import dataclass


@dataclass
class Node:
    data: int
    next_node: Node | None = None


class LinkedList:
    def __init__(self, ints: Iterable[int]) -> None:
        self.head: Node | None = None
        for i in ints:
            self.append(i)

    def __iter__(self) -> Iterator[int]:
        
        node = self.head
        while node:
            yield node.data
            node = node.next_node

    def __len__(self) -> int:
        
        return sum(1 for _ in self)

    def __str__(self) -> str:
        
        return " -> ".join([str(node) for node in self])

    def append(self, data: int) -> None:
        
        if not self.head:
            self.head = Node(data)
            return
        node = self.head
        while node.next_node:
            node = node.next_node
        node.next_node = Node(data)

    def reverse_k_nodes(self, group_size: int) -> None:
        
        if self.head is None or self.head.next_node is None:
            return

        length = len(self)
        dummy_head = Node(0)
        dummy_head.next_node = self.head
        previous_node = dummy_head

        while length >= group_size:
            current_node = previous_node.next_node
            assert current_node
            next_node = current_node.next_node
            for _ in range(1, group_size):
                assert next_node, current_node
                current_node.next_node = next_node.next_node
                assert previous_node
                next_node.next_node = previous_node.next_node
                previous_node.next_node = next_node
                next_node = current_node.next_node
            previous_node = current_node
            length -= group_size
        self.head = dummy_head.next_node


if __name__ == "__main__":
    import doctest

    doctest.testmod()
    ll = LinkedList([1, 2, 3, 4, 5])
    print(f"Original Linked List: {ll}")
    k = 2
    ll.reverse_k_nodes(k)
    print(f"After reversing groups of size {k}: {ll}")