Single-line function in Swift - ios

Can someone explain me how to write this function, which should return the factorial of x.
The way I tried to do it gives me an error.
This line is inside a dictionary and refers to Operation.UnaryOperation that is (Double) -> Double
I tried to write the function I need extensively, It should look like this:
private func factorial(n: Double) -> Double {
if (n<=1) {
return 1
}
return n * factorial(n-1)
}
Now I need to convert it to a single-line function, how do I do it? would it look something like this?, why am I getting an error?
"x!" : Operation.UnaryOperation({if ($0<=1) {return 1} else {return $0 * factorial($0-1)}}),

Just embed the named function in the closure - like this
enum Operation {
case UnaryOperation( (Double) -> Double)
case BinaryOperation( (Double, Double) -> Double)
}
let dictionary: [String: Operation] = [
"+" : Operation.BinaryOperation({ return $0 + $1 }),
"!" : Operation.UnaryOperation({
arg: Double in
func factorial(x: Double) -> Double {
if x <= 1 {
return 1
} else {
return x * factorial(x - 1)
}
}
return factorial(arg)
})
]

let x = Operation.UnaryOperation(factorial{if ($0<=1) {return 1} else {return $0 * factorial($0-1)}})

func factorial(_ x: UInt) -> UInt {
return x == 0 ? 1 : x * factorial(x - 1)
}
// Example:
print(factorial(6))
// 720

Related

Jaro Winkler distance in Objective-C or Swift

I need to do fuzzy comparison of a large number of strings and am looking at Jaro-Winkler which respects differences in the order of letters. Is anyone aware of a way to do this in Objective-C or Swift either using Jaro-Winkler or some method native to IOS?
Thanks for any recommendations or suggestions.
I took an inspiration in Apache Commons and rewritten it to Swift:
extension String {
static func jaroWinglerDistance(_ first: String, _ second: String) -> Double {
let longer = Array(first.count > second.count ? first : second)
let shorter = Array(first.count > second.count ? second : first)
let (numMatches, numTranspositions) = jaroWinklerData(longer: longer, shorter: shorter)
if numMatches == 0 {
return 0
}
let defaultScalingFactor = 0.1;
let percentageRoundValue = 100.0;
let jaro = [
numMatches / Double(first.count),
numMatches / Double(second.count),
(numMatches - numTranspositions) / numMatches
].reduce(0, +) / 3
let jaroWinkler: Double
if jaro < 0.7 {
jaroWinkler = jaro
} else {
let commonPrefixLength = Double(commonPrefix(first, second).count)
jaroWinkler = jaro + Swift.min(defaultScalingFactor, 1 / Double(longer.count)) * commonPrefixLength * (1 - jaro)
}
return round(jaroWinkler * percentageRoundValue) / percentageRoundValue
}
private static func commonPrefix(_ first: String, _ second: String) -> String{
return String(
zip(first, second)
.prefix { $0.0 == $0.1 }
.map { $0.0 }
)
}
private static func jaroWinklerData(
longer: Array<Character>,
shorter: Array<Character>
) -> (numMatches: Double, numTranspositions: Double) {
let window = Swift.max(longer.count / 2 - 1, 0)
var shorterMatchedChars: [Character] = []
var longerMatches = Array<Bool>(repeating: false, count: longer.count)
for (offset, shorterChar) in shorter.enumerated() {
let windowRange = Swift.max(offset - window, 0) ..< Swift.min(offset + window + 1, longer.count)
if let matchOffset = windowRange.first(where: { !longerMatches[$0] && shorterChar == longer[$0] }) {
shorterMatchedChars.append(shorterChar)
longerMatches[matchOffset] = true
}
}
let longerMatchedChars = longerMatches
.enumerated()
.filter { $0.element }
.map { longer[$0.offset] }
let numTranspositions: Int = zip(shorterMatchedChars, longerMatchedChars)
.lazy
.filter { $0.0 != $0.1 }
.count / 2
return (
numMatches: Double(shorterMatchedChars.count),
numTranspositions: Double(numTranspositions)
)
}
}
Tested by the examples found in the original code:
print(String.jaroWinglerDistance("", ""))
print(String.jaroWinglerDistance("", "a"))
print(String.jaroWinglerDistance("aaapppp", ""))
print(String.jaroWinglerDistance("frog", "fog"))
print(String.jaroWinglerDistance("fly", "ant"))
print(String.jaroWinglerDistance("elephant", "hippo"))
print(String.jaroWinglerDistance("hippo", "elephant"))
print(String.jaroWinglerDistance("hippo", "zzzzzzzz"))
print(String.jaroWinglerDistance("hello", "hallo"))
print(String.jaroWinglerDistance("ABC Corporation", "ABC Corp"))
print(String.jaroWinglerDistance("D N H Enterprises Inc", "D & H Enterprises, Inc."))
print(String.jaroWinglerDistance("My Gym Children's Fitness Center", "My Gym. Childrens Fitness"))
print(String.jaroWinglerDistance("PENNSYLVANIA", "PENNCISYLVNIA"))
I have also found another implementation of String similarity functions in github.

Xcode "Cannot convert return expression of type 'String' to return type 'Float'"

I am trying to create a BMI calculator that takes the user's height and weight as inputs then calculates their BMI; from there, it uses a series of if-else statements to return a message to the user that states if they are healthy/over/underweight. I have no problem getting the program to return the calculated BMI value; but when I incorporate the if-else statement, I get the "Cannot convert return expression of type 'String' to return type 'Float'" error.
Here's my code (I've only done one if-else statement so far):
import UIKit
func bodyMassIndex (userHeight : Float, userWeight : Float) -> String {
let userHeightSquared = (userHeight*userHeight)
let userWeight = userWeight
let userBMI = (userWeight/userHeightSquared)
return userBMI
if userBMI > 25 {
return "Overweight"
}
}
print(bodyMassIndex (userHeight : 1.82, userWeight: 90.7))
Your logic looks a little confused here:
return userBMI
if userBMI > 25 {
return "Overweight"
}
What is your function supposed to do? Return a BMI number, or a descriptive String? (It's trying to do both, and the compiler isn't happy)
If I were a user, I'd want to see both the number and a statement about what it means - so you'd need two functions:
func bodyMassIndex (userHeight : Float, userWeight : Float) -> String {
let userHeightSquared = (userHeight*userHeight)
let userWeight = userWeight
let userBMI = (userWeight/userHeightSquared)
return userBMI
}
func bodyMassDiagnosis (bodyMassIndex : Float) {
if userBMI > 25 {
return "Overweight"
}
return "You're doing fine"
}
And then:
let bodyMassIndex = bodyMassIndex(height, weight)
let diagnosis = bodyMassDiagnosis(bodyMassIndex)
self.indexLabel.text = "BMI \(bodyMassIndex)"
self.diagnosisLabel.text = diagnosis
You just have to wrap the Float value of userBMI into a String.
func bodyMassIndex (userHeight : Float, userWeight : Float) -> String {
let userHeightSquared = (userHeight*userHeight)
let userWeight = userWeight
let userBMI = (userWeight/userHeightSquared)
return String(userBMI)
if userBMI > 25 {
return "Overweight"
}
}

How to make a "for" loop on the condition of a number interval Xcode Swift2

Hey I'm trying to figure out how to tally up soccer goals on the condition that the goal was scored in under 45 minutes, but the func has some slight errors with swift 2. Any help? Thanks!
Code:
var barcelonavsRealMadrid1goals : [String : Int] = ["barcelonaGoal1":21,"RealMadridGoal2":23,"barcelonaGoal3":24,"RealMadridGoal4":27]
func Run() {
var goalCount=0
for (goal,numbers) in barcelonavsRealMadrid1goals{
for(var number in numbers) {
if(number < 45)
goalCount++
}
}
You have an extra for..in loop in there that's not needed:
for(var number in numbers) {
It also has an extraneous ( and ) around it
for var number in numbers {
Here is a working version of your code:
var barcelonavsRealMadrid1goals = ["barcelonaGoal1":21,"RealMadridGoal2":23,"barcelonaGoal3":24,"RealMadridGoal4":27]
func run() -> Int { // functions should start with lower case
var goalCount=0
for (_,numbers) in barcelonavsRealMadrid1goals where numbers < 45 {
goalCount++
}
return goalCount
}
let goalCount = run()
And the functional way would be something like:
let goalCount = goals.reduce(0) {
if $0.1.1 < 45 {
return $0.0 + 1
}
return $0.0
}
With explanation:
var goals = [
"barcelonaGoal1" :21,
"RealMadridGoal2":23,
"barcelonaGoal3" :24,
"RealMadridGoal4":27,
"RealMadridGoal5":45]
// For our use reduce takes an initial value of Int
// and a combine function of type
// (Int, (String, Int)) -> Int
//
// Reduce will call the closure once with
// each value in the map and the previous return value
let goalCount = goals.reduce(0, combine: {
(initial:Int, current:(key:String, value:Int)) -> Int in
var currentCount = initial
// print to show input and output of closure
print( "parameters:(\(initial), (\"\(current.key)\", \(current.value)))", terminator:", ")
defer {
print("return:\(currentCount)")
}
// end printing
if current.value < 45 {
++currentCount // add 1 to the running total
return currentCount
}
return currentCount
})
// console output:
// parameters:(0, ("barcelonaGoal1", 21)), return:1
// parameters:(1, ("RealMadridGoal4", 27)), return:2
// parameters:(2, ("RealMadridGoal5", 45)), return:2
// parameters:(2, ("RealMadridGoal2", 23)), return:3
// parameters:(3, ("barcelonaGoal3", 24)), return:4
For solving of you're problem try to use functional programing that is introduced in swift :
var barcelonavsRealMadrid1goals : [String : Int] = ["barcelonaGoal1":95,"RealMadridGoal2":23,"barcelonaGoal3":24,"RealMadridGoal4":27]
var filtered = barcelonavsRealMadrid1goals.filter { (team:String, minute:Int) -> Bool in
var state = false
if (minute > 45)
{
return true
}
return state
}
let totalCount = filtered.count
Try this method.
func Run() {
var goalCount=0
for (_, score) in barcelonavsRealMadrid1goals {
if(score < 45) {
goalCount++
}
}
print(goalCount)
}

Override typecasting with custom operators

Let say I have something like this:
var x: Int = 6
var y: Float = 11.5
so, the result has to be written like this
var result = Float(x) * y
or
var result = x * Int(y)
This makes sense, right ? However, I think that a little clumsy, so I'm trying to make some custom operators for this:
infix operator *~ { associativity left precedence 150 } //floating
func *~ (lhs: Float, rhs: Int) -> Float {
return lhs * Float(rhs)
}
func *~ (lhs: Int, rhs: Float) -> Float {
return rhs * Float(lhs)
}
infix operator *| { associativity left precedence 150 } //Integer
func *| (lhs: Float, rhs: Int) -> Int {
return Int(lhs) * rhs
}
func *| (lhs: Int, rhs: Float) -> Int {
return Int(rhs) * lhs
}
It works but there are too many of them, so I'm trying to make a generic version for these functions. My attempt so far:
func *~ <T: FloatingPointType, V:IntegerType>(lhs: T, rhs: V) -> T {
return lhs * T(rhs)
// error:
// Could not find an overload for 'init' that accepts the supplied arguments
}
Can somebody help please ? Thank you.
protocol Fraction {
init(_ value: Double)
var asDouble: Double { get }
}
extension Int : Fraction { var asDouble : Double { return Double(self) } }
extension Double : Fraction { var asDouble : Double { return self } }
extension Float : Fraction { var asDouble : Double { return Double(self) } }
extension CGFloat : Fraction { var asDouble : Double { return Double(self) } }
infix operator ** { associativity left precedence 170 }
func **(lhs:Int, rhs:Int) -> Int {
return lhs * rhs
}
func **<T:Fraction, U:Fraction>(lhs:T, rhs:U) -> Double {
return lhs.asDouble * rhs.asDouble
}
2 ** 2 // 4
2 ** 2.2 // 4.4
2.5 ** 2 // 5.0
2.2 ** 2.2 // 4.84
What you are doing is more than counter productive.
What you are calling clumsy is preventing one of the biggest sources of errors. So you want to invest lots of time and work to undo this, and make your source code unreadable in the process.
Anybody ever getting hold of your source code will first spend hours undoing your work and turning everything into normal Swift code.

Array of Arithmetic Operators in Swift

Is it possible to have an array of arithmetic operators in Swift? Something like:
var operatorArray = ['+', '-', '*', '/'] // or =[+, -, *, /] ?
I just want to randomly generate numbers and then randomly pick an arithmetic operator from the array above and perform the equation. For example,
var firstNum = Int(arc4random_uniform(120))
var secondNum = Int(arc4random_uniform(120))
var equation = firstNum + operatorArray[Int(arc4random_uniform(3))] + secondNum //
Will the above 'equation' work?
Thank you.
It will - but you need to use the operators a little differently.
Single operator:
// declare a variable that holds a function
let op: (Int,Int)->Int = (+)
// run the function on two arguments
op(10,10)
And with an array, you could use map to apply each one:
// operatorArray is an array of functions that take two ints and return an int
let operatorArray: [(Int,Int)->Int] = [(+), (-), (*), (/)]
// apply each operator to two numbers
let result = map(operatorArray) { op in op(10,10) }
// result is [20, 0, 100, 1]
You can use NSExpression class for doing the same.
var operatorArray = ["+", "-", "*", "/"]
var firstNum = Int(arc4random_uniform(120))
var secondNum = Int(arc4random_uniform(120))
var equation = "\(firstNum) \(operatorArray[Int(arc4random_uniform(3))]) \(secondNum)"
var exp = NSExpression(format: equation, argumentArray: [])
println(exp.expressionValueWithObject(nil, context: nil))
This is an old fashion Object Oriented approach.
protocol Operation {
func calculate(op1:Int, op2:Int) -> Int
}
class Addition : Operation {
func calculate(op1: Int, op2: Int) -> Int {
return op1 + op2
}
}
class Subtraction : Operation {
func calculate(op1: Int, op2: Int) -> Int {
return op1 - op2
}
}
class Multiplication : Operation {
func calculate(op1: Int, op2: Int) -> Int {
return op1 * op2
}
}
class Division : Operation {
func calculate(op1: Int, op2: Int) -> Int {
return op1 / op2
}
}
var operatorArray : [Operation] = [Addition(), Subtraction(), Multiplication(), Division()]
var firstNum = Int(arc4random_uniform(120))
var secondNum = Int(arc4random_uniform(120))
var equation = operatorArray[Int(arc4random_uniform(3))].calculate(firstNum, op2: secondNum)

Resources