class Solver:
    def solve(self, start_number):
        recipient = 1
        remaining = start_number
        power = 1
        while remaining > 1:
            new_remaining = remaining // 2
            remaining_was_odd = remaining % 2
            power *= 2
            remaining = new_remaining
            if remaining_was_odd:
                recipient += power
        return recipient

    def solve_b(self, start_number):
        elves = list(range(1, start_number + 1))
        current_elf_index = 0
        while len(elves) > 1:
            jump_distance = len(elves) // 2
            target_elf = jump_distance + current_elf_index
            if target_elf >= len(elves):
                del elves[target_elf - len(elves)]
                current_elf_index -= 1
            else:
                del elves[target_elf]
            current_elf_index += 1
            current_elf_index %= len(elves)

        return elves[current_elf_index]

class Solver:
    def __init__(self):
        self.next_elves = {}

    def solve(self, start_number):
        recipient = 1
        remaining = start_number
        power = 1
        while remaining > 1:
            new_remaining = remaining // 2
            remaining_was_odd = remaining % 2
            power *= 2
            remaining = new_remaining
            if remaining_was_odd:
                recipient += power
        return recipient

    def solve_b(self, start_number):
        self.next_elves = {index: index + 1 for index in range(start_number)}
        self.next_elves[start_number - 1] = 0
        current_elf_index = 0
        elves_remaining = start_number
        while elves_remaining > 1:
            target_elf = current_elf_index
            jump_distance = elves_remaining // 2
            for i in range(jump_distance):
                previous_elf = target_elf
                target_elf = self.next_elves[target_elf]

            # remove target elf
            self.delete_target_elf(previous_elf, target_elf)

            current_elf_index = self.next_elves[current_elf_index]
            elves_remaining -= 1
        return current_elf_index + 1

    def delete_target_elf(self, previous_elf, target_elf):
        next_elf = self.next_elves[target_elf]
        self.next_elves[previous_elf] = next_elf
        target_elf %= len(self.next_elves)

Refactor to use linked list
Refactor to use linked list

  class Solver:
+     def __init__(self):
+         self.next_elves = {}
+ 
      def solve(self, start_number):
          recipient = 1
          remaining = start_number
          power = 1
          while remaining > 1:
              new_remaining = remaining // 2
              remaining_was_odd = remaining % 2
              power *= 2
              remaining = new_remaining
              if remaining_was_odd:
                  recipient += power
          return recipient
  
      def solve_b(self, start_number):
-         elves = list(range(1, start_number + 1))
+         self.next_elves = {index: index + 1 for index in range(start_number)}
+         self.next_elves[start_number - 1] = 0
          current_elf_index = 0
+         elves_remaining = start_number
-         while len(elves) > 1:
+         while elves_remaining > 1:
-             jump_distance = len(elves) // 2
-             target_elf = jump_distance + current_elf_index
+             target_elf = current_elf_index
+             jump_distance = elves_remaining // 2
+             for i in range(jump_distance):
+                 previous_elf = target_elf
-             if target_elf >= len(elves):
-                 del elves[target_elf - len(elves)]
-                 current_elf_index -= 1
-             else:
-                 del elves[target_elf]
+                 target_elf = self.next_elves[target_elf]
-             current_elf_index += 1
-             current_elf_index %= len(elves)
  
-         return elves[current_elf_index]
+             # remove target elf
+             self.delete_target_elf(previous_elf, target_elf)
  
+             current_elf_index = self.next_elves[current_elf_index]
+             elves_remaining -= 1
+         return current_elf_index + 1
+ 
+     def delete_target_elf(self, previous_elf, target_elf):
+         next_elf = self.next_elves[target_elf]
+         self.next_elves[previous_elf] = next_elf
+         target_elf %= len(self.next_elves)
+ 
Refactor to use linked list
## Code Before:
class Solver:
    def solve(self, start_number):
        recipient = 1
        remaining = start_number
        power = 1
        while remaining > 1:
            new_remaining = remaining // 2
            remaining_was_odd = remaining % 2
            power *= 2
            remaining = new_remaining
            if remaining_was_odd:
                recipient += power
        return recipient

    def solve_b(self, start_number):
        elves = list(range(1, start_number + 1))
        current_elf_index = 0
        while len(elves) > 1:
            jump_distance = len(elves) // 2
            target_elf = jump_distance + current_elf_index
            if target_elf >= len(elves):
                del elves[target_elf - len(elves)]
                current_elf_index -= 1
            else:
                del elves[target_elf]
            current_elf_index += 1
            current_elf_index %= len(elves)

        return elves[current_elf_index]

## Instruction:
Refactor to use linked list
## Code After:
class Solver:
    def __init__(self):
        self.next_elves = {}

    def solve(self, start_number):
        recipient = 1
        remaining = start_number
        power = 1
        while remaining > 1:
            new_remaining = remaining // 2
            remaining_was_odd = remaining % 2
            power *= 2
            remaining = new_remaining
            if remaining_was_odd:
                recipient += power
        return recipient

    def solve_b(self, start_number):
        self.next_elves = {index: index + 1 for index in range(start_number)}
        self.next_elves[start_number - 1] = 0
        current_elf_index = 0
        elves_remaining = start_number
        while elves_remaining > 1:
            target_elf = current_elf_index
            jump_distance = elves_remaining // 2
            for i in range(jump_distance):
                previous_elf = target_elf
                target_elf = self.next_elves[target_elf]

            # remove target elf
            self.delete_target_elf(previous_elf, target_elf)

            current_elf_index = self.next_elves[current_elf_index]
            elves_remaining -= 1
        return current_elf_index + 1

    def delete_target_elf(self, previous_elf, target_elf):
        next_elf = self.next_elves[target_elf]
        self.next_elves[previous_elf] = next_elf
        target_elf %= len(self.next_elves)
