Hacker News new | ask | show | jobs
by xg15 762 days ago
I know this is exactly the opposite of the point OP wanted to make, but wouldn't this be the perfect use case for generators?

You could modify the quicksort in python like this:

  def quicksort_with_steps(arr: [Process]):
      # Standard Quicksort operations
      if len(arr) <= 1:
          yield arr
          return

      pivot = arr[len(arr) // 2]
      left = [process for process in arr if process.sort_key < pivot.sort_key]
      middle = [process for process in arr if process.sort_key == pivot.sort_key]
      right = [process for process in arr if process.sort_key > pivot.sort_key]

      # the magic happens here:
      # sort each half and pass through the intermediate results of the "sub-sorters" to our own caller, 
      # after modifying them so they contain the entire array again:

      # left half:
      left_final = None
      for left_intermediate in quicksort_with_steps(left):  # we're iterating over the "yield" calls here, not the sorted array.
          yield left_intermediate + middle + right  # pass on the intermediate result to our own caller. 
          left_final = left_intermediate  # the last iteration has the "final" result for the left side, so store it.
    
      assert left_final is not None  # the generator always yields at least one result, so this shouldn't happen.

      # right half: (shorter because we don't have to store anything)
      for right_intermediate in quicksort_with_steps(right):
          yield left_final + middle + right_intermediate

      # the last "yield" returns the fully sorted array.
Then if you call the function, it will return an iterator over all the steps of the algorithm. You could either put it in a for loop like in the recursive calls, or "manually" advance it one step using python's next() function, e.g. inside a frame callback.

I'm pretty sure, if you're insane enough, you could also whip up something using async/await where the algorithm literally "awaits" the end of the animation...