Hone logo
Hone
Problems

Type-Level Radix Sort for Fixed-Size Integers

This challenge requires you to implement Radix Sort at the TypeScript type level. Your goal is to create a type that can sort an array of fixed-size integers, represented as literal types, without relying on runtime execution of sorting algorithms. This problem explores the boundaries of TypeScript's type system and its ability to perform complex computations.

Problem Description

You need to create a TypeScript type, let's call it TypeLevelRadixSort<T extends ReadonlyArray<number>>, that takes a tuple of literal numbers (T) as input and returns a new tuple where the numbers are sorted in ascending order. The sorting should be achieved purely through type-level manipulation, leveraging TypeScript's conditional types, inference, and recursive capabilities.

Key Requirements:

  1. Type-Level Computation: The sorting must happen entirely at compile time. No runtime functions should be used to perform the sorting logic.
  2. Input: The input T will be a ReadonlyArray of literal numbers (e.g., [3, 1, 4, 1, 5, 9]).
  3. Output: The output should be a new tuple representing the sorted version of the input tuple.
  4. Radix Sort Logic: You should aim to implement the core logic of Radix Sort, which typically involves iterating through digits (or bits) and using a stable sorting mechanism (like bucket sort or counting sort) at each digit position. For this type-level challenge, you'll need to abstract this process.
  5. Fixed-Size Integers: Assume the input numbers are non-negative integers within a reasonable, fixed range (e.g., 0-255, or 0-999, which implies a fixed number of digits/passes). The exact range can be specified in the constraints.

Expected Behavior:

Given an input tuple of numbers, the TypeLevelRadixSort type should resolve to a tuple containing the same numbers, but sorted in ascending order.

Edge Cases:

  • Empty input tuple: Should result in an empty tuple.
  • Tuple with duplicate numbers: Duplicates should be preserved in the sorted output.
  • Tuple with a single element: Should return the tuple unchanged.

Examples

Example 1:

type Input1 = [3, 1, 4, 1, 5, 9, 2, 6];
type Sorted1 = TypeLevelRadixSort<Input1>;
// Expected: [1, 1, 2, 3, 4, 5, 6, 9]

Explanation: The input array contains eight numbers, and the TypeLevelRadixSort should rearrange them into ascending order.

Example 2:

type Input2 = [99, 0, 15, 8, 42];
type Sorted2 = TypeLevelRadixSort<Input2>;
// Expected: [0, 8, 15, 42, 99]

Explanation: Another example demonstrating the sorting of a different set of numbers.

Example 3: Edge Case - Empty Input

type Input3 = [];
type Sorted3 = TypeLevelRadixSort<Input3>;
// Expected: []

Explanation: An empty input tuple should yield an empty sorted tuple.

Constraints

  • The input numbers will be non-negative integers between 0 and 255 (inclusive). This implies a maximum of 3 digits in base-10 (or 8 bits in base-2).
  • The input tuple length will not exceed 50 elements.
  • The performance of the type-level computation should be reasonably fast. Extremely deep recursion or overly complex conditional types that lead to excessive compilation times will be penalized.
  • The solution must not use any runtime code that would execute during the program's runtime. All logic must be contained within TypeScript's type definitions.

Notes

  • Radix Sort works by sorting numbers digit by digit, starting from the least significant digit (LSD) or most significant digit (MSD). For type-level sorting, implementing a stable sort at each "digit" pass is crucial.
  • Consider how you will represent and manipulate "digits" or positional values within the type system. You might need helper types to extract digits based on a given radix (e.g., base-10).
  • Think recursively. You'll likely need a mechanism to iterate through the "digits" or passes of the radix sort.
  • A stable sorting algorithm is essential for Radix Sort. This means that if two elements have the same key (digit value at the current pass), their relative order should be preserved from the previous pass. Implementing a type-level stable sort will be a significant part of this challenge.
  • You may need to define auxiliary types to help manage the state of the sorting process across different "passes" or digit extractions.
  • The constraint on numbers (0-255) suggests that you could potentially implement this using a base-10 approach (3 passes) or a base-2 (bit-wise) approach (8 passes). Choose an approach that you can manage effectively within the type system.
Loading editor...
typescript