Build a MinMaxScaler class that normalizes numeric data using fit, transform, and fit_transform.
Create a class `MinMaxScaler` that normalizes numeric data to a given range [feature_range_min, feature_range_max] (default 0 and 1). The scaler must support the following methods:
- `__init__(self, feature_range=(0, 1))`: Initializes the scaler with a tuple `(min, max)` specifying the desired output range. Defaults to `(0, 1)`. Assume `feature_range[0] < feature_range[1]`.
- `fit(self, data)`: Accepts a list of numbers (1D) or a list of lists (2D, each inner list is a row of features). For 1D data, computes and stores the minimum and maximum of the data. For 2D data, computes the min and max for each column (feature). Returns `self`.
- `transform(self, data)`: Scales the given data using the stored min and max values. Returns scaled data in the same shape as the input. The scaling formula for a value `x` is:
`x_scaled = (x - min) / (max - min) * (range_max - range_min) + range_min`
If `max == min` (all values identical for a feature or 1D), the scaled value should be `range_min` (e.g., 0.0 for default).
- `fit_transform(self, data)`: Calls `fit(data)` then `transform(data)` and returns the result.
Additionally, you must implement a module-level function `MinMaxScaler_fit_transform(data, feature_range=(0, 1))` that creates a `MinMaxScaler` with the given feature_range, calls `fit_transform` on the data, and returns the result. This function is what the tests will call.
**Assumptions:**
- Input data is numeric (ints or floats).
- 1D data is a list of numbers; 2D data is a list of lists where each inner list has the same length.
- Data is non-empty and has at least 1 element.
- All 2D rows have the same length.
- The `feature_range` tuple is always valid (min < max).
The methods should not modify the input data. Return new lists (or lists of lists) as appropriate.
Constraints
Data length is between 1 and 10^4. Number of features (columns in 2D) is between 1 and 100. Values are within ±10^9. Time complexity O(n) per invocation.
Example
>>> MinMaxScaler_fit_transform([1, 2, 3])
[0.0, 0.5, 1.0]
>>> MinMaxScaler_fit_transform([4, 6, 8], (0, 2))
[0.0, 1.0, 2.0]
>>> MinMaxScaler_fit_transform([[1, 10], [2, 20], [3, 30]])
[[0.0, 0.0], [0.5, 0.5], [1.0, 1.0]]
>>> MinMaxScaler_fit_transform([5, 5, 5])
[0.0, 0.0, 0.0]
8 points
~12 min