2726. Calculator with Method Chaining
Problem Description
This problem asks you to implement a Calculator class that supports basic mathematical operations and method chaining.
The Calculator class should:
- 
Initialize with a starting value: The constructor takes a number that becomes the initial
resultvalue. - 
Support five mathematical operations, each returning the
Calculatorinstance for chaining:add(value): Addsvalueto the current resultsubtract(value): Subtractsvaluefrom the current resultmultiply(value): Multiplies the current result byvaluedivide(value): Divides the current result byvalue(must throw error "Division by zero is not allowed" ifvalueis 0)power(value): Raises the current result to the power ofvalue
 - 
Provide a way to retrieve the result: The
getResult()method returns the current calculated value. - 
Enable method chaining: All operation methods return
this(the Calculator instance), allowing consecutive operations like:calculator.add(5).multiply(2).subtract(3).getResult() 
The solution uses a private property x to store the current result. Each operation method modifies x and returns this to enable chaining. The divide method includes validation to prevent division by zero. The getResult method simply returns the current value of x.
Results within 10^-5 of the actual answer are considered correct, accounting for floating-point precision issues.
Intuition
The key insight for this problem is recognizing that method chaining requires each method to return the object itself. When we call calculator.add(5).multiply(2), the add(5) method must return the calculator object so that we can immediately call multiply(2) on it.
To achieve this pattern, we need:
- 
State preservation: A single variable to hold the running result throughout all operations. This is why we use a private property
xto maintain the current value across method calls. - 
Return
thispattern: Each operation method performs its calculation on the stored value and then returnsthis(the current instance). This is the fundamental pattern that enables method chaining - by returning the object itself, we allow the next method to be called on the same object. - 
Mutating operations: Instead of creating new Calculator instances, we modify the existing instance's state. This makes sense because we want a continuous calculation flow where each operation builds upon the previous result.
 
The design follows the Fluent Interface pattern, commonly used in builder patterns and query builders. The idea is to make the code read more naturally, almost like a sentence: "take this number, add 5, multiply by 2, subtract 3, and give me the result."
For the division by zero check, we handle this explicitly before performing the division since JavaScript would return Infinity for division by zero, which isn't the desired behavior. By throwing an error with the exact message required, we prevent invalid mathematical operations while maintaining the chainable interface (the error stops the chain execution).
The getResult() method breaks the chain by returning a number instead of the Calculator instance, which makes logical sense as it's the terminating operation to retrieve our final answer.
Solution Approach
The implementation uses a class-based approach with a single private property to maintain state and instance methods that return this for chaining.
Core Structure:
- 
Private property
x: Stores the current calculation result. Using a private property ensures encapsulation and prevents external modification. - 
Constructor: Initializes the
xproperty with the provided starting value:constructor(value: number) { this.x = value; } 
Implementation of Each Operation:
Each arithmetic method follows the same pattern:
- Perform the operation on 
this.x - Return 
thisto enable chaining 
- 
Addition:
this.x += valueadds the value to the current result - 
Subtraction:
this.x -= valuesubtracts the value from the current result - 
Multiplication:
this.x *= valuemultiplies the current result by the value - 
Division:
divide(value: number): Calculator { if (value === 0) { throw new Error('Division by zero is not allowed'); } this.x /= value; return this; }First checks for zero to prevent invalid operations, then performs
this.x /= value - 
Power:
this.x **= valueraises the current result to the given power using the exponentiation operator 
Result Retrieval:
The getResult() method simply returns the current value of x without modifying it:
getResult(): number {
    return this.x;
}
Method Chaining Mechanism:
By returning this from each operation method, we enable consecutive method calls:
new Calculator(10) .add(5) // x becomes 15, returns this .multiply(2) // x becomes 30, returns this .divide(3) // x becomes 10, returns this .getResult() // returns 10
The solution is straightforward and efficient with O(1) time complexity for each operation and O(1) space complexity for the entire calculator instance.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a calculation step-by-step: new Calculator(2).add(5).multiply(3).subtract(4).divide(2).getResult()
Step 1: Initialize
new Calculator(2)
- Creates a new Calculator instance
 - Sets internal property 
x = 2 - Current state: 
x = 2 
Step 2: Add 5
.add(5)
- Executes: 
this.x = this.x + 5 = 2 + 5 = 7 - Returns 
this(the Calculator instance) - Current state: 
x = 7 
Step 3: Multiply by 3
.multiply(3)
- Executes: 
this.x = this.x * 3 = 7 * 3 = 21 - Returns 
this(the Calculator instance) - Current state: 
x = 21 
Step 4: Subtract 4
.subtract(4)
- Executes: 
this.x = this.x - 4 = 21 - 4 = 17 - Returns 
this(the Calculator instance) - Current state: 
x = 17 
Step 5: Divide by 2
.divide(2)
- First checks: Is 
value === 0? No, proceed - Executes: 
this.x = this.x / 2 = 17 / 2 = 8.5 - Returns 
this(the Calculator instance) - Current state: 
x = 8.5 
Step 6: Get Result
.getResult()
- Returns the current value of 
x - Final answer: 
8.5 
Key Points:
- Each operation method modifies the same internal variable 
x - Each operation returns 
this, allowing the next method to be called immediately - The chain continues until 
getResult()is called, which returns a number instead of the Calculator instance - If we tried 
.divide(0)at any point, it would throw an error and stop execution 
Solution Implementation
1# Global variable to store the current calculator value
2calculator_value = 0
3
4def initialize_calculator(value):
5    """
6    Initializes the calculator with a starting value
7  
8    Args:
9        value: The initial value for the calculator
10    """
11    global calculator_value
12    calculator_value = value
13
14def add(value):
15    """
16    Adds a value to the current calculator value
17  
18    Args:
19        value: The value to add
20  
21    Returns:
22        The updated calculator value
23    """
24    global calculator_value
25    calculator_value += value
26    return calculator_value
27
28def subtract(value):
29    """
30    Subtracts a value from the current calculator value
31  
32    Args:
33        value: The value to subtract
34  
35    Returns:
36        The updated calculator value
37    """
38    global calculator_value
39    calculator_value -= value
40    return calculator_value
41
42def multiply(value):
43    """
44    Multiplies the current calculator value by a given value
45  
46    Args:
47        value: The value to multiply by
48  
49    Returns:
50        The updated calculator value
51    """
52    global calculator_value
53    calculator_value *= value
54    return calculator_value
55
56def divide(value):
57    """
58    Divides the current calculator value by a given value
59  
60    Args:
61        value: The value to divide by
62  
63    Returns:
64        The updated calculator value
65  
66    Raises:
67        ValueError: If attempting to divide by zero
68    """
69    global calculator_value
70    if value == 0:
71        raise ValueError('Division by zero is not allowed')
72    calculator_value /= value
73    return calculator_value
74
75def power(value):
76    """
77    Raises the current calculator value to a given power
78  
79    Args:
80        value: The exponent value
81  
82    Returns:
83        The updated calculator value
84    """
85    global calculator_value
86    calculator_value **= value
87    return calculator_value
88
89def get_result():
90    """
91    Gets the current result of the calculator
92  
93    Returns:
94        The current calculator value
95    """
96    return calculator_value
971/**
2 * Calculator class that maintains a global state for calculator operations
3 */
4public class Calculator {
5  
6    // Global variable to store the current calculator value
7    private static double calculatorValue = 0;
8  
9    /**
10     * Initializes the calculator with a starting value
11     * @param value The initial value for the calculator
12     */
13    public static void initializeCalculator(double value) {
14        calculatorValue = value;
15    }
16  
17    /**
18     * Adds a value to the current calculator value
19     * @param value The value to add
20     * @return The updated calculator value
21     */
22    public static double add(double value) {
23        calculatorValue += value;
24        return calculatorValue;
25    }
26  
27    /**
28     * Subtracts a value from the current calculator value
29     * @param value The value to subtract
30     * @return The updated calculator value
31     */
32    public static double subtract(double value) {
33        calculatorValue -= value;
34        return calculatorValue;
35    }
36  
37    /**
38     * Multiplies the current calculator value by a given value
39     * @param value The value to multiply by
40     * @return The updated calculator value
41     */
42    public static double multiply(double value) {
43        calculatorValue *= value;
44        return calculatorValue;
45    }
46  
47    /**
48     * Divides the current calculator value by a given value
49     * @param value The value to divide by
50     * @return The updated calculator value
51     * @throws IllegalArgumentException if attempting to divide by zero
52     */
53    public static double divide(double value) {
54        if (value == 0) {
55            throw new IllegalArgumentException("Division by zero is not allowed");
56        }
57        calculatorValue /= value;
58        return calculatorValue;
59    }
60  
61    /**
62     * Raises the current calculator value to a given power
63     * @param value The exponent value
64     * @return The updated calculator value
65     */
66    public static double power(double value) {
67        calculatorValue = Math.pow(calculatorValue, value);
68        return calculatorValue;
69    }
70  
71    /**
72     * Gets the current result of the calculator
73     * @return The current calculator value
74     */
75    public static double getResult() {
76        return calculatorValue;
77    }
78}
791#include <stdexcept>
2#include <cmath>
3
4// Global variable to store the current calculator value
5double calculatorValue = 0.0;
6
7/**
8 * Initializes the calculator with a starting value
9 * @param value - The initial value for the calculator
10 */
11void initializeCalculator(double value) {
12    calculatorValue = value;
13}
14
15/**
16 * Adds a value to the current calculator value
17 * @param value - The value to add
18 * @return The updated calculator value
19 */
20double add(double value) {
21    calculatorValue += value;
22    return calculatorValue;
23}
24
25/**
26 * Subtracts a value from the current calculator value
27 * @param value - The value to subtract
28 * @return The updated calculator value
29 */
30double subtract(double value) {
31    calculatorValue -= value;
32    return calculatorValue;
33}
34
35/**
36 * Multiplies the current calculator value by a given value
37 * @param value - The value to multiply by
38 * @return The updated calculator value
39 */
40double multiply(double value) {
41    calculatorValue *= value;
42    return calculatorValue;
43}
44
45/**
46 * Divides the current calculator value by a given value
47 * @param value - The value to divide by
48 * @return The updated calculator value
49 * @throws std::invalid_argument if attempting to divide by zero
50 */
51double divide(double value) {
52    if (value == 0.0) {
53        throw std::invalid_argument("Division by zero is not allowed");
54    }
55    calculatorValue /= value;
56    return calculatorValue;
57}
58
59/**
60 * Raises the current calculator value to a given power
61 * @param value - The exponent value
62 * @return The updated calculator value
63 */
64double power(double value) {
65    calculatorValue = std::pow(calculatorValue, value);
66    return calculatorValue;
67}
68
69/**
70 * Gets the current result of the calculator
71 * @return The current calculator value
72 */
73double getResult() {
74    return calculatorValue;
75}
761// Global variable to store the current calculator value
2let calculatorValue: number = 0;
3
4/**
5 * Initializes the calculator with a starting value
6 * @param value - The initial value for the calculator
7 */
8function initializeCalculator(value: number): void {
9    calculatorValue = value;
10}
11
12/**
13 * Adds a value to the current calculator value
14 * @param value - The value to add
15 * @returns The updated calculator value
16 */
17function add(value: number): number {
18    calculatorValue += value;
19    return calculatorValue;
20}
21
22/**
23 * Subtracts a value from the current calculator value
24 * @param value - The value to subtract
25 * @returns The updated calculator value
26 */
27function subtract(value: number): number {
28    calculatorValue -= value;
29    return calculatorValue;
30}
31
32/**
33 * Multiplies the current calculator value by a given value
34 * @param value - The value to multiply by
35 * @returns The updated calculator value
36 */
37function multiply(value: number): number {
38    calculatorValue *= value;
39    return calculatorValue;
40}
41
42/**
43 * Divides the current calculator value by a given value
44 * @param value - The value to divide by
45 * @returns The updated calculator value
46 * @throws Error if attempting to divide by zero
47 */
48function divide(value: number): number {
49    if (value === 0) {
50        throw new Error('Division by zero is not allowed');
51    }
52    calculatorValue /= value;
53    return calculatorValue;
54}
55
56/**
57 * Raises the current calculator value to a given power
58 * @param value - The exponent value
59 * @returns The updated calculator value
60 */
61function power(value: number): number {
62    calculatorValue **= value;
63    return calculatorValue;
64}
65
66/**
67 * Gets the current result of the calculator
68 * @returns The current calculator value
69 */
70function getResult(): number {
71    return calculatorValue;
72}
73Time and Space Complexity
Time Complexity: Each method (add, subtract, multiply, divide, power, getResult) performs a constant-time operation. The arithmetic operations and the assignment take O(1) time. The constructor also runs in O(1) time as it only initializes a single variable. Therefore, each individual method call has a time complexity of O(1).
For a chain of n method calls (e.g., calculator.add(5).multiply(2).subtract(3)...), the total time complexity would be O(n), where n is the number of operations performed.
Space Complexity: The Calculator class stores only a single number x as its state, regardless of how many operations are performed. The space used remains constant throughout the lifetime of the object. Each method returns this (a reference to the same object), so no additional Calculator objects are created during method chaining. Therefore, the space complexity is O(1).
The method chaining pattern (fluent interface) doesn't create new objects but modifies and returns the same instance, maintaining constant space usage.
Common Pitfalls
1. Global State Management Issues
The Python implementation uses a global variable calculator_value, which creates several problems:
- No support for multiple calculator instances: You can't have two calculators running independently
 - State persistence between tests: The global value persists across different test cases, leading to incorrect results
 - Thread safety concerns: Global state is not thread-safe for concurrent operations
 
Example of the problem:
initialize_calculator(10) add(5) # calculator_value = 15 # Start a "new" calculator initialize_calculator(20) # But if someone forgets to initialize, they get the old value!
2. Loss of Method Chaining
The provided Python solution doesn't support method chaining as required by the problem. You can't write:
# This won't work with the global function approach result = Calculator(10).add(5).multiply(2).getResult()
3. Floating-Point Precision Issues
When performing division and power operations, floating-point arithmetic can introduce precision errors that might exceed the 10^-5 tolerance:
# Example: 0.1 + 0.2 != 0.3 in floating-point calculator_value = 0.1 add(0.2) # Might not exactly equal 0.3
Solution
Here's a proper class-based implementation that addresses these pitfalls:
class Calculator:
    def __init__(self, value: float):
        """Initialize calculator with a starting value"""
        self._result = float(value)  # Ensure float for consistency
  
    def add(self, value: float):
        """Add value to current result"""
        self._result += value
        return self  # Enable chaining
  
    def subtract(self, value: float):
        """Subtract value from current result"""
        self._result -= value
        return self
  
    def multiply(self, value: float):
        """Multiply current result by value"""
        self._result *= value
        return self
  
    def divide(self, value: float):
        """Divide current result by value"""
        if value == 0:
            raise ValueError('Division by zero is not allowed')
        self._result /= value
        return self
  
    def power(self, value: float):
        """Raise current result to the power of value"""
        self._result **= value
        return self
  
    def getResult(self) -> float:
        """Get the current result"""
        # Round to handle floating-point precision within 10^-5
        return round(self._result, 10)
# Usage example with proper chaining:
calc = Calculator(10)
result = calc.add(5).multiply(2).divide(3).getResult()
print(result)  # Output: 10.0
# Multiple independent instances work correctly:
calc1 = Calculator(10)
calc2 = Calculator(20)
calc1.add(5)
calc2.subtract(5)
print(calc1.getResult())  # 15.0
print(calc2.getResult())  # 15.0
Key improvements:
- Instance-based state: Each Calculator object has its own 
_resultproperty - Method chaining support: All operation methods return 
self - Proper encapsulation: Using 
_resultas a private property - Floating-point handling: Converting input to float and rounding output for precision
 - Multiple instances: Can create and use multiple calculators independently
 
Which of the following problems can be solved with backtracking (select multiple)
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion If you prefer videos here's a video that explains recursion in a fun and easy way Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask him
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!