cs193p – Assignment #1 Task #3

cs193p-assignment-1-task-3

Add some more operations buttons to your calculator such that it has at least a dozen operations total (it can have even more if you like). You can choose whatever operations appeal to you. The buttons must arrange themselves nicely in portrait and landscape modes on all iPhone 6’s and 7’s.

Start adding the new operations to the brain model:

    private let operations: Dictionary<String,Operation> = [
        ...        
        "x²" : Operation.unaryOperation({ pow($0, 2) }),
        "x³" : Operation.unaryOperation({ pow($0, 3) }),
        "x⁻¹" : Operation.unaryOperation({ 1 / $0 }),
        "sin" : Operation.unaryOperation(sin),
        "tan" : Operation.unaryOperation(tan),
        "sinh" : Operation.unaryOperation(sinh),
        "cosh" : Operation.unaryOperation(cosh),
        "tanh" : Operation.unaryOperation(tanh),
        "ln" : Operation.unaryOperation(log),
        "log" : Operation.unaryOperation(log10),
        "eˣ" : Operation.unaryOperation(exp),
        "10ˣ" : Operation.unaryOperation({ pow(10, $0) }),
        "x!" : Operation.unaryOperation(factorial),
        "xʸ" : Operation.binaryOperation(pow),
        ]

Most of them are straight forward, only the factorial is not available as native function. The following implementation works really only for integer values, for non-integers you might want to implement a solution using gamma functions:

func factorial(_ op1: Double) -> Double {
    if (op1 <= 1.0) {
        return 1.0
    }
    return op1 * factorial(op1 - 1.0)
}

Adjusting different layouts for portrait and landscape using “installed” in story board for different size classes, would be nice … but still does not work for stacks. Just add the buttons:
cs193p-assignment-1-task-3-storyboard

And tag the buttons you want to show only in landscape mode with “1”, the ones you want to show only in portrait mode with “2” and leave the other ones untagged (with “0”).

A helper function hides and shoes them in the different modes, iterating recursively over the available views:

    private func adjustButtonLayout(for view: UIView, isPortrait: Bool) {
        for subview in view.subviews {
            if subview.tag == 1 {
                subview.isHidden = isPortrait
            } else if subview.tag == 2 {
                subview.isHidden = !isPortrait
            }
            if let stack = subview as? UIStackView {
                adjustButtonLayout(for: stack, isPortrait: isPortrait);
            }
        }
    }

The helper function needs to be called twice – at the beginning, and when the dimensions change:

    override func viewDidLoad() {
        super.viewDidLoad()
        adjustButtonLayout(for: view, isPortrait: traitCollection.horizontalSizeClass == .compact && traitCollection.verticalSizeClass == .regular)
    }
    
    override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) {
        super.willTransition(to: newCollection, with: coordinator)
        adjustButtonLayout(for: view, isPortrait: newCollection.horizontalSizeClass == .compact && newCollection.verticalSizeClass == .regular)
    }

The complete code for the assignment #1 task #3 is available on GitHub.

FacebooktwitterredditpinterestlinkedintumblrmailFacebooktwitterredditpinterestlinkedintumblrmail

Leave a Reply

Your email address will not be published.