2726. Calculator with Method Chaining


Problem Description

The problem requires designing a Calculator class that supports basic mathematical operations like addition, subtraction, multiplication, division, and exponentiation. The class is not only asked to perform these operations but to do so in a way that allows for method chaining, which means calling multiple methods in a single statement. When an instance of the Calculator class is created, it receives an initial number that is used as its starting result. The following methods need to be implemented:

  • add(value) - Adds a number to the current result and returns the Calculator instance for chaining.
  • subtract(value) - Subtracts a number from the current result and returns the Calculator instance for chaining.
  • multiply(value) - Multiplies the current result by a number and returns the Calculator instance for chaining.
  • divide(value) - Divides the current result by a number and returns the Calculator instance for chaining, with an error for division by zero.
  • power(value) - Raises the current result to the power of a number and returns the Calculator instance for chaining.
  • getResult() - Returns the current result.

The problem also specifies that results within a tolerance of 10^-5 are considered correct, indicating that some degree of imprecision from floating-point arithmetic is acceptable.

Intuition

To solve this problem, the main idea is to structure the Calculator class with a private property to hold the current result. Each mathematical operation will be a method that performs the appropriate calculation on this result and then returns the Calculator object to allow method chaining.

The intuition behind each method is straightforward:

  • add(): Update result by adding the provided value.
  • subtract(): Update result by subtracting the provided value.
  • multiply(): Update result by multiplying it by the provided value.
  • divide(): Check for division by zero, throw an error if it occurs, otherwise update result by dividing it by the provided value.
  • power(): Update result by raising it to the power of the provided value using the exponentiation operator.
  • getResult(): Simply return the current result.

Overall, the principle is to encapsulate the state of the calculator in each instance and use method chaining to make the calculator more expressive and convenient to use.

Not Sure What to Study? Take the 2-min Quiz to Find Your Missing Piece:

Problem: Given a list of tasks and a list of requirements, compute a sequence of tasks that can be performed, such that we complete every task once while satisfying all the requirements.

Which of the following method should we use to solve this problem?

Solution Approach

The implementation of the Calculator class is quite straightforward. The class uses an instance variable x to store the current result. Each method performs a simple arithmetic operation and returns the instance (this) for method chaining. Here's the breakdown of the solution:

  • Constructor: The constructor initializes the Calculator with a starting value. This value is stored in the private variable x.

    1constructor(value: number) {
    2    this.x = value;
    3}
  • Addition: The add method takes a value and adds it to the x. The method then returns the Calculator instance for further chaining.

    1add(value: number): Calculator {
    2    this.x += value;
    3    return this;
    4}
  • Subtraction: The subtract function is similar to add, but it subtracts the given value from x.

    1subtract(value: number): Calculator {
    2    this.x -= value;
    3    return this;
    4}
  • Multiplication: The multiply method multiplies x by the specified value.

    1multiply(value: number): Calculator {
    2    this.x *= value;
    3    return this;
    4}
  • Division: In the divide method, the class first checks if the value is zero, and if so, throws an exception since division by zero is undefined. Otherwise, it divides x by the value.

    1divide(value: number): Calculator {
    2    if (value === 0) {
    3        throw new Error('Division by zero is not allowed');
    4    }
    5    this.x /= value;
    6    return this;
    7}
  • Exponentiation: The power method raises x to the power of the value provided.

    1power(value: number): Calculator {
    2    this.x **= value;
    3    return this;
    4}
  • Get Result: Finally, the getResult method simply returns the variable x.

    1getResult(): number {
    2    return this.x;
    3}

No complex algorithms or data structures are needed; the solution relies on the basic arithmetic operators provided by TypeScript/javascript. The design pattern used is method chaining, which is commonly used to create more readable and expressive code. This pattern is also known as the fluent interface pattern. The class methods perform their operation and then return the object itself, which allows these method calls to be connected in a single chain.

Discover Your Strengths and Weaknesses: Take Our 2-Minute Quiz to Tailor Your Study Plan:

What are the most two important steps in writing a depth first search function? (Select 2)

Example Walkthrough

Let's create an example to illustrate how to use the Calculator class and demonstrate the solution approach mentioned above.

Suppose we want to perform a sequence of operations starting with the number 10. We would like to add 5, subtract 2, multiply by 3, divide by 4, and then raise to the power of 2. We aim to achieve this using method chaining provided by our Calculator class.

First, we create a new instance of the Calculator class and initialize it with the number 10.

1let calc = new Calculator(10);

Now we can start chaining our operations. The first operation is to add 5 to our initial number, which we achieve by calling the add method.

1calc.add(5); // Starting with 10, we now have 15

Next, we chain the subtract method to subtract 2 from our current result.

1calc.subtract(2); // From 15, subtracting 2 gives us 13

We continue with the multiply method to multiply our result by 3.

1calc.multiply(3); // Multiplying 13 by 3 gets us 39

The sequence then calls for division by 4, which we apply using the divide method.

1calc.divide(4); // Dividing 39 by 4 gives us 9.75

Finally, we chain the power method to raise our result to the power of 2.

1calc.power(2); // 9.75 raised to the power of 2 is approximately 95.0625

After performing all the chained operations, we use the getResult method to obtain and print out the final result.

1let result = calc.getResult(); // Retrieves the final result, which is approximately 95.0625
2console.log(result); // This will output 95.0625

Putting all the chained operations together, we can express the entire sequence in one line of code as follows:

1let finalResult = new Calculator(10).add(5).subtract(2).multiply(3).divide(4).power(2).getResult();
2console.log(finalResult); // Outputs the same result: 95.0625

The example above demonstrates how constructor initialization, method chaining, and straightforward arithmetic operations are implemented and used in the Calculator class. Each method modifies the internal state of the Calculator object and returns the object itself, making the sequence of operations concise and readable. This implementation leverages the principle of fluent interfaces for an expressive code style.

Solution Implementation

1# Define a variable for storing current value of calculations
2current_value = 0
3
4def initialize_calculator(value):
5    """
6    Initializes the calculator with a specific value.
7
8    :param value: The initial value to set the calculator to.
9    """
10    global current_value
11    current_value = value
12
13def add(value):
14    """
15    Adds a given value to the current value.
16
17    :param value: The value to be added.
18    """
19    global current_value
20    current_value += value
21
22def subtract(value):
23    """
24    Subtracts a given value from the current value.
25
26    :param value: The value to be subtracted.
27    """
28    global current_value
29    current_value -= value
30
31def multiply(value):
32    """
33    Multiplies the current value by a given value.
34
35    :param value: The value to multiply by.
36    """
37    global current_value
38    current_value *= value
39
40def divide(value):
41    """
42    Divides the current value by a given value.
43    Throws an error if division by zero is attempted.
44
45    :param value: The value to divide by.
46    """
47    global current_value
48    if value == 0:
49        raise ValueError('Division by zero is not allowed')
50    current_value /= value
51
52def power(value):
53    """
54    Raises the current value to the power of a given value.
55
56    :param value: The exponent to raise the current value to.
57    """
58    global current_value
59    current_value **= value
60
61def get_result():
62    """
63    Retrieves the current result of the calculator's operations.
64
65    :return: The current value.
66    """
67    return current_value
68
69# Example usage:
70initialize_calculator(10) # Set the current value to 10
71add(5)                    # Add 5 to the current value
72subtract(3)               # Subtract 3 from the current value
73multiply(2)               # Multiply the current value by 2
74divide(4)                 # Divide the current value by 4
75power(2)                  # Raise the current value to the power of 2
76print(get_result())       # Output the current result
77
1public class Calculator {
2
3    // Variable for storing current value of calculations
4    private double currentValue;
5
6    /**
7     * Initializes the calculator with a specific value.
8     *
9     * @param value The initial value to set the calculator to.
10     */
11    public void initializeCalculator(double value) {
12        this.currentValue = value;
13    }
14
15    /**
16     * Adds a given value to the current value.
17     *
18     * @param value The value to be added.
19     */
20    public void add(double value) {
21        this.currentValue += value;
22    }
23
24    /**
25     * Subtracts a given value from the current value.
26     *
27     * @param value The value to be subtracted.
28     */
29    public void subtract(double value) {
30        this.currentValue -= value;
31    }
32
33    /**
34     * Multiplies the current value by a given value.
35     *
36     * @param value The value to multiply by.
37     */
38    public void multiply(double value) {
39        this.currentValue *= value;
40    }
41
42    /**
43     * Divides the current value by a given value.
44     * Throws an IllegalArgumentException if division by zero is attempted.
45     *
46     * @param value The value to divide by.
47     */
48    public void divide(double value) {
49        if (value == 0) {
50            throw new IllegalArgumentException("Division by zero is not allowed");
51        }
52        this.currentValue /= value;
53    }
54
55    /**
56     * Raises the current value to the power of a given value.
57     *
58     * @param value The exponent to raise the current value to.
59     */
60    public void power(double value) {
61        this.currentValue = Math.pow(this.currentValue, value);
62    }
63
64    /**
65     * Retrieves the current result of the calculator's operations.
66     *
67     * @return The current value.
68     */
69    public double getResult() {
70        return this.currentValue;
71    }
72
73    // Example usage
74    public static void main(String[] args) {
75        Calculator calc = new Calculator(); // Create a new Calculator instance.
76      
77        calc.initializeCalculator(10); // Set the current value to 10.
78        calc.add(5);                   // Add 5 to the current value.
79        calc.subtract(3);              // Subtract 3 from the current value.
80        calc.multiply(2);              // Multiply the current value by 2.
81        calc.divide(4);                // Divide the current value by 4.
82        calc.power(2);                 // Raise the current value to the power of 2.
83      
84        System.out.println(calc.getResult()); // Outputs the current result.
85    }
86}
87
1#include <iostream>
2#include <stdexcept>
3
4// Declare a variable for storing the current value of calculations.
5double currentValue = 0;
6
7/**
8 * Initializes the calculator with a specific value.
9 * @param value The initial value to set the calculator to.
10 */
11void initializeCalculator(double value) {
12    currentValue = value;
13}
14
15/**
16 * Adds a given value to the current value.
17 * @param value The value to be added.
18 */
19void add(double value) {
20    currentValue += value;
21}
22
23/**
24 * Subtracts a given value from the current value.
25 * @param value The value to be subtracted.
26 */
27void subtract(double value) {
28    currentValue -= value;
29}
30
31/**
32 * Multiplies the current value by a given value.
33 * @param value The value to multiply by.
34 */
35void multiply(double value) {
36    currentValue *= value;
37}
38
39/**
40 * Divides the current value by a given value.
41 * Throws an error if division by zero is attempted.
42 * @param value The value to divide by.
43 */
44void divide(double value) {
45    if (value == 0) {
46        throw std::invalid_argument("Division by zero is not allowed.");
47    }
48    currentValue /= value;
49}
50
51/**
52 * Raises the current value to the power of a given value.
53 * @param value The exponent to raise the current value to.
54 */
55void power(double value) {
56    currentValue = std::pow(currentValue, value);
57}
58
59/**
60 * Retrieves the current result of the calculator's operations.
61 * @return The current value.
62 */
63double getResult() {
64    return currentValue;
65}
66
67// Function to demonstrate example usage of the calculator functions.
68void exampleUsage() {
69    initializeCalculator(10); // Set the current value to 10.
70    add(5);                   // Add 5 to the current value.
71    subtract(3);              // Subtract 3 from the current value.
72    multiply(2);              // Multiply the current value by 2.
73    divide(4);                // Divide the current value by 4.
74    power(2);                 // Raises the current value to the power of 2.
75    std::cout << getResult(); // Outputs the current result.
76}
77
78int main() {
79    // Call the example usage function to demonstrate the calculator's functionality.
80    exampleUsage();
81    return 0;
82}
83
1// Define a variable for storing current value of calculations
2let currentValue: number = 0;
3
4/**
5 * Initializes the calculator with a specific value.
6 * @param {number} value - The initial value to set the calculator to.
7 */
8function initializeCalculator(value: number): void {
9    currentValue = value;
10}
11
12/**
13 * Adds a given value to the current value.
14 * @param {number} value - The value to be added.
15 * @returns The calculator object for method chaining.
16 */
17function add(value: number): void {
18    currentValue += value;
19}
20
21/**
22 * Subtracts a given value from the current value.
23 * @param {number} value - The value to be subtracted.
24 * @returns The calculator object for method chaining.
25 */
26function subtract(value: number): void {
27    currentValue -= value;
28}
29
30/**
31 * Multiplies the current value by a given value.
32 * @param {number} value - The value to multiply by.
33 * @returns The calculator object for method chaining.
34 */
35function multiply(value: number): void {
36    currentValue *= value;
37}
38
39/**
40 * Divides the current value by a given value.
41 * Throws an error if division by zero is attempted.
42 * @param {number} value - The value to divide by.
43 * @returns The calculator object for method chaining.
44 */
45function divide(value: number): void {
46    if (value === 0) {
47        throw new Error('Division by zero is not allowed');
48    }
49    currentValue /= value;
50}
51
52/**
53 * Raises the current value to the power of a given value.
54 * @param {number} value - The exponent to raise the current value to.
55 * @returns The calculator object for method chaining.
56 */
57function power(value: number): void {
58    currentValue **= value;
59}
60
61/**
62 * Retrieves the current result of the calculator's operations.
63 * @returns The current value.
64 */
65function getResult(): number {
66    return currentValue;
67}
68
69// Example usage:
70initializeCalculator(10); // Set the current value to 10.
71add(5);                   // Add 5 to the current value.
72subtract(3);              // Subtract 3 from the current value.
73multiply(2);              // Multiply the current value by 2.
74divide(4);                // Divide the current value by 4.
75power(2);                 // Raises the current value to the power of 2.
76console.log(getResult()); // Outputs the current result.
77
Not Sure What to Study? Take the 2-min Quiz:

What is the worst case running time for finding an element in a binary tree (not necessarily binary search tree) of size n?

Time and Space Complexity

The time complexity of the Calculator class methods is O(1) for the add, subtract, multiply, divide, and power methods, because each of these operations consists of a single arithmetic operation that is independent of the size of the input.

The space complexity of the Calculator class is also O(1) as it only stores a single number regardless of the operations performed.

Fast Track Your Learning with Our Quick Skills Quiz:

What is the space complexity of the following code?

1int sum(int n) {
2  if (n <= 0) {
3    return 0;
4  }
5  return n + sum(n - 1);
6}

Recommended Readings


Got a question? Ask the Teaching Assistant anything you don't understand.

Still not clear? Ask in the Forum,  Discord or Submit the part you don't understand to our editors.


TA 👨‍🏫