Implement a Flexible createCounter Function
Modern user interfaces frequently require managing simple numerical states, like quantities in a shopping cart, progress indicators, or interactive scores. A dedicated createCounter function (analogous to a React hook) abstracts away the complexity of managing these count values, providing a clean API for common operations.
Problem Description
Your task is to implement a createCounter function that manages a single numeric counter. This function should initialize the counter and provide methods to manipulate its value, respecting optional bounds.
The createCounter function should accept an optional initialValue and an optional options object.
The options object can contain:
min: The minimum allowed value for the counter.max: The maximum allowed value for the counter.
The createCounter function should return an object with the following properties:
currentValue: The current numerical value of the counter.increment(step = 1): A function that increasescurrentValuebystep. Ifmaxis defined,currentValueshould not exceed it.decrement(step = 1): A function that decreasescurrentValuebystep. Ifminis defined,currentValueshould not go below it.reset(): A function that setscurrentValueback to itsinitialValue. IfinitialValuewas not provided, it resets to0.
Key Requirements:
- Initialization: If no
initialValueis provided, the counter should start at0. - Default Step: If no
stepis provided toincrementordecrement, it should default to1. - Bounds Enforcement:
- When incrementing, the counter must not exceed the
maxvalue if specified. - When decrementing, the counter must not go below the
minvalue if specified.
- When incrementing, the counter must not exceed the
- Reset Behavior: The
resetfunction must restore the counter to its initial configured state (theinitialValuepassed duringcreateCounterinvocation, or0if none was passed). - Edge Cases:
- If
minis greater thanmaxin theoptions, treatminas0andmaxasInfinityfor practical clamping purposes. - Operations should not throw errors due to reaching bounds; they should simply clamp the value at the respective
minormax.
- If
Examples
Example 1: Basic Counter
// Initialize a basic counter
counter1 = createCounter()
// Access initial value
print(counter1.currentValue) // Output: 0
// Increment by default step (1)
counter1.increment()
print(counter1.currentValue) // Output: 1
// Decrement by default step (1)
counter1.decrement()
print(counter1.currentValue) // Output: 0
// Reset
counter1.reset()
print(counter1.currentValue) // Output: 0
Explanation: The counter starts at 0, increments to 1, decrements back to 0, and resets to 0.
Example 2: Counter with Initial Value and Custom Steps
// Initialize counter starting at 10
counter2 = createCounter(10)
// Access initial value
print(counter2.currentValue) // Output: 10
// Increment by 5
counter2.increment(5)
print(counter2.currentValue) // Output: 15
// Decrement by 3
counter2.decrement(3)
print(counter2.currentValue) // Output: 12
// Reset
counter2.reset()
print(counter2.currentValue) // Output: 10
Explanation: The counter starts at 10, increments by 5 to 15, decrements by 3 to 12, and resets to 10.
Example 3: Counter with Bounds and Reset
// Initialize counter with value 5, min 0, max 10
counter3 = createCounter(5, { min: 0, max: 10 })
// Access initial value
print(counter3.currentValue) // Output: 5
// Attempt to increment past max
counter3.increment(7) // 5 + 7 = 12, but max is 10. Clamps at 10.
print(counter3.currentValue) // Output: 10
// Attempt to decrement past min
counter3.decrement(15) // 10 - 15 = -5, but min is 0. Clamps at 0.
print(counter3.currentValue) // Output: 0
// Increment by a valid step within bounds
counter3.increment(3)
print(counter3.currentValue) // Output: 3
// Reset
counter3.reset()
print(counter3.currentValue) // Output: 5
Explanation: The counter starts at 5, respects the max bound of 10 when incrementing, respects the min bound of 0 when decrementing, and resets to its initial value of 5.
Constraints
initialValue,step,min,maxwill be integers.stepwill be a positive integer (greater than 0).minandmaxare optional; if provided, they will be integers.- The
createCounterfunction and its returned methods should operate in O(1) time complexity. - The implementation should not rely on external UI framework-specific state management libraries for its core logic (e.g., React's
useState). It should be a self-contained state management implementation.
Notes
Think about how you would encapsulate state within the createCounter function. In many languages, this might involve closures or class-like structures to maintain currentValue and initialValue across calls to the returned methods. The problem focuses on the logic of state management and operations, not UI rendering. Remember to consistently apply the min and max bounds after every operation (increment, decrement).