Problem

Write a function, add_subtract, which alternately adds and subtracts curried arguments.

Examples

Example 1

1
2
3
Input: add_subtract(7)
Output: 7
Explanation: Single argument returns itself.

Example 2

1
2
3
Input: add_subtract(1)(2)(3)
Output: 0
Explanation: 1 + 2 - 3 = 0 (add first, then subtract)

Example 3

1
2
3
Input: add_subtract(-5)(10)(3)(9)
Output: 11
Explanation: -5 + 10 - 3 + 9 = 11 (alternating add/subtract starting with add)

Example 4

1
2
3
Input: add_subtract(10)(5)
Output: 15
Explanation: 10 + 5 = 15 (first addition)

Solution

Method 1 - Closure with State Tracking

Intuition

The key insight is to use closures to maintain state between function calls. We need to track the current result and whether the next operation should be addition or subtraction. Each function call returns a new function that captures the updated state, allowing for infinite chaining while alternating operations.

Approach

  1. Initialize state: Start with the first argument as the initial value and set the next operation to addition
  2. Create closure: Return a function that captures the current state (result and operation type)
  3. Alternate operations: On each subsequent call, apply the current operation and toggle to the next
  4. Chain functions: Each returned function maintains its own state for continued chaining
  5. Handle termination: The function should be callable as a value when chaining ends

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <functional>

class Solution {
public:
    class AddSubtract {
    private:
        int result;
        bool shouldAdd;
        
    public:
        AddSubtract(int val, bool add = true) : result(val), shouldAdd(add) {}
        
        AddSubtract operator()(int val) {
            if (shouldAdd) {
                return AddSubtract(result + val, false);
            } else {
                return AddSubtract(result - val, true);
            }
        }
        
        operator int() const {
            return result;
        }
        
        int getValue() const {
            return result;
        }
    };
    
    AddSubtract add_subtract(int val) {
        return AddSubtract(val);
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
type AddSubtract struct {
    result    int
    shouldAdd bool
}

func (as AddSubtract) Call(val int) AddSubtract {
    if as.shouldAdd {
        return AddSubtract{result: as.result + val, shouldAdd: false}
    } else {
        return AddSubtract{result: as.result - val, shouldAdd: true}
    }
}

func (as AddSubtract) Value() int {
    return as.result
}

func addSubtract(val int) AddSubtract {
    return AddSubtract{result: val, shouldAdd: true}
}

// Example usage:
// result := addSubtract(1).Call(2).Call(3).Value() // returns 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Solution {
    public static class AddSubtract {
        private int result;
        private boolean shouldAdd;
        
        public AddSubtract(int val) {
            this.result = val;
            this.shouldAdd = true;
        }
        
        private AddSubtract(int res, boolean add) {
            this.result = res;
            this.shouldAdd = add;
        }
        
        public AddSubtract apply(int val) {
            if (shouldAdd) {
                return new AddSubtract(result + val, false);
            } else {
                return new AddSubtract(result - val, true);
            }
        }
        
        public int getValue() {
            return result;
        }
        
        @Override
        public String toString() {
            return String.valueOf(result);
        }
    }
    
    public AddSubtract add_subtract(int val) {
        return new AddSubtract(val);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution:
    class AddSubtract:
        def __init__(self, result: int, should_add: bool = True):
            self.result = result
            self.should_add = should_add
        
        def __call__(self, val: int) -> 'AddSubtract':
            if self.should_add:
                return AddSubtract(self.result + val, False)
            else:
                return AddSubtract(self.result - val, True)
        
        def __int__(self) -> int:
            return self.result
        
        def __str__(self) -> str:
            return str(self.result)
        
        def __repr__(self) -> str:
            return str(self.result)
    
    def add_subtract(self, val: int) -> AddSubtract:
        return self.AddSubtract(val)

Complexity

  • ⏰ Time complexity: O(n), where n is the number of function calls. Each call performs constant time operations.
  • 🧺 Space complexity: O(n) for storing the chain of function closures, where each closure maintains its state.

Method 2 - Functional Approach with Lambda

Intuition

Instead of using classes, we can implement this using pure functions and lambda expressions. Each function call returns a new lambda that captures the current state. This approach is more functional in style and demonstrates closure behavior more explicitly.

Approach

  1. Create initial function: Return a lambda that captures the starting value
  2. Chain operations: Each lambda returns another lambda with updated state
  3. Embed state: Use closure variables to track result and operation type
  4. Handle evaluation: Provide a way to extract the final result
  5. Maintain immutability: Each step creates a new function rather than modifying state

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <functional>

class Solution {
public:
    std::function<std::function<int()>(int)> add_subtract(int initial) {
        return [initial](int next) -> std::function<int()> {
            return createChain(initial, next, false); // false means next operation is subtract
        };
    }
    
private:
    std::function<std::function<int()>(int)> createChain(int current, int next, bool shouldAdd) {
        int newResult = shouldAdd ? current + next : current + next;
        
        return [newResult, shouldAdd](int val) -> std::function<int()> {
            if (shouldAdd) {
                return createChainStep(newResult - val, true);
            } else {
                return createChainStep(newResult - val, true);
            }
        };
    }
    
    std::function<int()> createChainStep(int result, bool nextAdd) {
        return [result, nextAdd, this]() -> int {
            return result;
        };
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func addSubtractFunc(initial int) func(int) func() int {
    return func(next int) func() int {
        result := initial + next
        return createChain(result, false) // false means next should subtract
    }
}

func createChain(current int, shouldAdd bool) func(int) func() int {
    return func(val int) func() int {
        var newResult int
        if shouldAdd {
            newResult = current + val
        } else {
            newResult = current - val
        }
        
        return createChain(newResult, !shouldAdd)
    }
}

// Helper to get final value
func getValue(f func() int) int {
    return f()
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import java.util.function.Function;
import java.util.function.Supplier;

class Solution {
    public Function<Integer, Supplier<Integer>> add_subtract(int initial) {
        return next -> () -> createChain(initial + next, false).apply(0).get();
    }
    
    private Function<Integer, Supplier<Integer>> createChain(int current, boolean shouldAdd) {
        return val -> {
            int newResult = shouldAdd ? current + val : current - val;
            return () -> newResult;
        };
    }
    
    // Alternative implementation with better chaining
    public static class FunctionalAddSubtract {
        private final int value;
        private final boolean shouldAdd;
        
        public FunctionalAddSubtract(int val) {
            this.value = val;
            this.shouldAdd = true;
        }
        
        private FunctionalAddSubtract(int val, boolean add) {
            this.value = val;
            this.shouldAdd = add;
        }
        
        public Function<Integer, FunctionalAddSubtract> chain() {
            return val -> {
                if (shouldAdd) {
                    return new FunctionalAddSubtract(value + val, false);
                } else {
                    return new FunctionalAddSubtract(value - val, true);
                }
            };
        }
        
        public int getValue() {
            return value;
        }
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Solution:
    def add_subtract(self, initial: int):
        def chain(current: int, should_add: bool = True):
            def inner(val: int):
                if should_add:
                    new_result = current + val
                else:
                    new_result = current - val
                
                # Return a function that can continue the chain
                next_chain = chain(new_result, not should_add)
                next_chain.value = new_result
                return next_chain
            
            inner.value = current
            return inner
        
        return chain(initial)

# Alternative functional approach using closures
def add_subtract_functional(initial: int):
    def create_chain(current: int, should_add: bool):
        def apply_next(val: int):
            if should_add:
                new_result = current + val
            else:
                new_result = current - val
            
            result_func = create_chain(new_result, not should_add)
            result_func.value = new_result
            return result_func
        
        apply_next.value = current
        return apply_next
    
    return create_chain(initial, True)

Complexity

  • ⏰ Time complexity: O(n), where n is the number of chained function calls. Each function creation and call is constant time.
  • 🧺 Space complexity: O(n) for the chain of lambda functions, each capturing the state in its closure.

Method 3 - Iterator Pattern with State Machine

Intuition

We can model this as a state machine where each state represents the current result and the next operation to perform. This approach uses the iterator pattern to make the function calls feel more natural while maintaining clear state transitions.

Approach

  1. Define states: Create states for “add next” and “subtract next”
  2. Implement transitions: Each function call transitions to the next state
  3. Maintain result: Keep running total as operations are applied
  4. Provide interface: Make the object callable while maintaining state
  5. Handle edge cases: Ensure proper behavior for single arguments and empty chains

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Solution {
public:
    class StateMachine {
    private:
        int current;
        enum State { ADD_NEXT, SUBTRACT_NEXT };
        State state;
        
    public:
        StateMachine(int initial) : current(initial), state(ADD_NEXT) {}
        
        StateMachine operator()(int val) {
            StateMachine next(0);
            if (state == ADD_NEXT) {
                next.current = current + val;
                next.state = SUBTRACT_NEXT;
            } else {
                next.current = current - val;
                next.state = ADD_NEXT;
            }
            return next;
        }
        
        operator int() const { return current; }
        int getValue() const { return current; }
    };
    
    StateMachine add_subtract(int val) {
        return StateMachine(val);
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
type State int

const (
    AddNext State = iota
    SubtractNext
)

type StateMachine struct {
    current int
    state   State
}

func newStateMachine(initial int) StateMachine {
    return StateMachine{current: initial, state: AddNext}
}

func (sm StateMachine) Apply(val int) StateMachine {
    switch sm.state {
    case AddNext:
        return StateMachine{
            current: sm.current + val,
            state:   SubtractNext,
        }
    case SubtractNext:
        return StateMachine{
            current: sm.current - val,
            state:   AddNext,
        }
    }
    return sm
}

func (sm StateMachine) Value() int {
    return sm.current
}

func addSubtractState(val int) StateMachine {
    return newStateMachine(val)
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Solution {
    public enum Operation { ADD_NEXT, SUBTRACT_NEXT }
    
    public static class StateMachine {
        private final int current;
        private final Operation nextOp;
        
        public StateMachine(int val) {
            this.current = val;
            this.nextOp = Operation.ADD_NEXT;
        }
        
        private StateMachine(int curr, Operation op) {
            this.current = curr;
            this.nextOp = op;
        }
        
        public StateMachine apply(int val) {
            switch (nextOp) {
                case ADD_NEXT:
                    return new StateMachine(current + val, Operation.SUBTRACT_NEXT);
                case SUBTRACT_NEXT:
                    return new StateMachine(current - val, Operation.ADD_NEXT);
                default:
                    throw new IllegalStateException("Invalid operation");
            }
        }
        
        public int getValue() {
            return current;
        }
        
        @Override
        public String toString() {
            return String.valueOf(current);
        }
    }
    
    public StateMachine add_subtract(int val) {
        return new StateMachine(val);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from enum import Enum

class Solution:
    class Operation(Enum):
        ADD_NEXT = "add"
        SUBTRACT_NEXT = "subtract"
    
    class StateMachine:
        def __init__(self, current: int, next_op: 'Solution.Operation' = None):
            self.current = current
            self.next_op = next_op or Solution.Operation.ADD_NEXT
        
        def __call__(self, val: int) -> 'Solution.StateMachine':
            if self.next_op == Solution.Operation.ADD_NEXT:
                return Solution.StateMachine(
                    self.current + val, 
                    Solution.Operation.SUBTRACT_NEXT
                )
            else:
                return Solution.StateMachine(
                    self.current - val, 
                    Solution.Operation.ADD_NEXT
                )
        
        def __int__(self) -> int:
            return self.current
        
        def __str__(self) -> str:
            return str(self.current)
        
        def getValue(self) -> int:
            return self.current
    
    def add_subtract(self, val: int) -> StateMachine:
        return self.StateMachine(val)

Complexity

  • ⏰ Time complexity: O(n), where n is the number of operations. Each state transition takes constant time.
  • 🧺 Space complexity: O(1) per state machine instance, as each only stores current value and next operation. Total space is O(n) for n chained calls.