Error Handling in a Recursive Swift Function [duplicate] - ios

I am making fuction that calculate factorial in swift. like this
func factorial(factorialNumber: UInt64) -> UInt64 {
if factorialNumber == 0 {
return 1
} else {
return factorialNumber * factorial(factorialNumber - 1)
}
}
let x = factorial(20)
this fuction can calculate untill 20.
I think factorial(21) value bigger than UINT64_MAX.
then How to calculate the 21! (21 factorial) in swift?

func factorial(_ n: Int) -> Double {
return (1...n).map(Double.init).reduce(1.0, *)
}
(1...n): We create an array of all the numbers that are involved in the operation (i.e: [1, 2, 3, ...]).
map(Double.init): We change from Int to Double because we can represent bigger numbers with Doubles than with Ints (https://en.wikipedia.org/wiki/Double-precision_floating-point_format). So, we now have the array of all the numbers that are involved in the operation as Doubles (i.e: [1.0, 2.0, 3.0, ...]).
reduce(1.0, *): We start multiplying 1.0 with the first element in the array (1.0*1.0 = 1.0), then the result of that with the next one (1.0*2.0 = 2.0), then the result of that with the next one (2.0*3.0 = 6.0), and so on.
Step 2 is to avoid the overflow issue.
Step 3 is to save us from explicitly defining a variable for keeping track of the partial results.

Unsigned 64 bit integer has a maximum value of 18,446,744,073,709,551,615. While 21! = 51,090,942,171,709,440,000. For this kind of case, you need a Big Integer type. I found a question about Big Integer in Swift. There's a library for Big Integer in that link.
BigInteger equivalent in Swift?

Did you think about using a double perhaps? Or NSDecimalNumber?
Also calling the same function recursively is really bad performance wise.
How about using a loop:
let value = number.intValue - 1
var product = NSDecimalNumber(value: number.intValue)
for i in (1...value).reversed() {
product = product.multiplying(by: NSDecimalNumber(value: i))
}

Here's a function that accepts any type that conforms to the Numeric protocol, which are all builtin number types.
func factorial<N: Numeric>(_ x: N) -> N {
x == 0 ? 1 : x * factorial(x - 1)
}

First we need to declare temp variable of type double so it can hold size of number.
Then we create a function that takes a parameter of type double.
Then we check, if the number equal 0 we can return or do nothing. We have an if condition so we can break the recursion of the function. Finally we return temp, which holds the factorial of given number.
var temp:Double = 1.0
func factorial(x:Double) -> Double{
if(x==0){
//do nothing
}else{
factorial(x: x-1)
temp *= x
}
return temp
}
factorial(x: 21.0)

I make function calculate factorial like this:
func factorialNumber( namber : Int ) -> Int {
var x = 1
for i in 1...namber {
x *= i
}
return x
}
print ( factorialNumber (namber : 5 ))

If you are willing to give up precision you can use a Double to roughly calculate factorials up to 170:
func factorial(_ n: Int) -> Double {
if n == 0 {
return 1
}
var a: Double = 1
for i in 1...n {
a *= Double(i)
}
return a
}
If not, use a big integer library.

func factoruial(_ num:Int) -> Int{
if num == 0 || num == 1{
return 1
}else{
return(num*factoruial(num - 1))
}
}

Using recursion to solve this problem:
func factorial(_ n: UInt) -> UInt {
return n < 2 ? 1 : n*factorial(n - 1)
}

func factorial(a: Int) -> Int {
return a == 1 ? a : a * factorial(a: a - 1)
}
print(factorial(a : 5))
print(factorial(a: 9))

Related

Getting "Argument passed to call that takes no arguments" when trying to use arc4random [duplicate]

I need to generate a random number.
It appears the arc4random function no longer exists as well as the arc4random_uniform function.
The options I have are arc4random_stir(), arc4random_buf(UnsafeMutablePointer<Void>, Int), and arc4random_addrandom(UnsafeMutablePointer<UInt8>, Int32).
I can't find any docs on the functions and no comments in the header files give hints.
let randomIntFrom0To10 = Int.random(in: 1..<10)
let randomFloat = Float.random(in: 0..<1)
// if you want to get a random element in an array
let greetings = ["hey", "hi", "hello", "hola"]
greetings.randomElement()
You could try as well:
let diceRoll = Int(arc4random_uniform(UInt32(6)))
I had to add "UInt32" to make it work.
Just call this function and provide minimum and maximum range of number and you will get a random number.
eg.like randomNumber(MIN: 0, MAX: 10) and You will get number between 0 to 9.
func randomNumber(MIN: Int, MAX: Int)-> Int{
return Int(arc4random_uniform(UInt32(MAX-MIN)) + UInt32(MIN));
}
Note:- You will always get output an Integer number.
After some investigation I wrote this:
import Foundation
struct Math {
private static var seeded = false
static func randomFractional() -> CGFloat {
if !Math.seeded {
let time = Int(NSDate().timeIntervalSinceReferenceDate)
srand48(time)
Math.seeded = true
}
return CGFloat(drand48())
}
}
Now you can just do Math.randomFraction() to get random numbers [0..1[ without having to remember seeding first. Hope this helps someone :o)
Update with swift 4.2 :
let randomInt = Int.random(in: 1..<5)
let randomFloat = Float.random(in: 1..<10)
let randomDouble = Double.random(in: 1...100)
let randomCGFloat = CGFloat.random(in: 1...1000)
Another option is to use the xorshift128plus algorithm:
func xorshift128plus(seed0 : UInt64, _ seed1 : UInt64) -> () -> UInt64 {
var state0 : UInt64 = seed0
var state1 : UInt64 = seed1
if state0 == 0 && state1 == 0 {
state0 = 1 // both state variables cannot be 0
}
func rand() -> UInt64 {
var s1 : UInt64 = state0
let s0 : UInt64 = state1
state0 = s0
s1 ^= s1 << 23
s1 ^= s1 >> 17
s1 ^= s0
s1 ^= s0 >> 26
state1 = s1
return UInt64.addWithOverflow(state0, state1).0
}
return rand
}
This algorithm has a period of 2^128 - 1 and passes all the tests of the BigCrush test suite. Note that while this is a high-quality pseudo-random number generator with a long period, it is not a cryptographically secure random number generator.
You could seed it from the current time or any other random source of entropy. For example, if you had a function called urand64() that read a UInt64 from /dev/urandom, you could use it like this:
let rand = xorshift128plus(urand64(), urand64())
for _ in 1...10 {
print(rand())
}
let MAX : UInt32 = 9
let MIN : UInt32 = 1
func randomNumber()
{
var random_number = Int(arc4random_uniform(MAX) + MIN)
print ("random = ", random_number);
}
In Swift 3 :
It will generate random number between 0 to limit
let limit : UInt32 = 6
print("Random Number : \(arc4random_uniform(limit))")
My implementation as an Int extension. Will generate random numbers in range from..<to
public extension Int {
static func random(from: Int, to: Int) -> Int {
guard to > from else {
assertionFailure("Can not generate negative random numbers")
return 0
}
return Int(arc4random_uniform(UInt32(to - from)) + UInt32(from))
}
}
This is how I get a random number between 2 int's!
func randomNumber(MIN: Int, MAX: Int)-> Int{
var list : [Int] = []
for i in MIN...MAX {
list.append(i)
}
return list[Int(arc4random_uniform(UInt32(list.count)))]
}
usage:
print("My Random Number is: \(randomNumber(MIN:-10,MAX:10))")
Another option is to use GKMersenneTwisterRandomSource from GameKit. The docs say:
A deterministic pseudo-random source that generates random numbers
based on a mersenne twister algorithm. This is a deterministic random
source suitable for creating reliable gameplay mechanics. It is
slightly slower than an Arc4 source, but more random, in that it has a
longer period until repeating sequences. While deterministic, this is
not a cryptographic random source. It is however suitable for
obfuscation of gameplay data.
import GameKit
let minValue = 0
let maxValue = 100
var randomDistribution: GKRandomDistribution?
let randomSource = GKMersenneTwisterRandomSource()
randomDistribution = GKRandomDistribution(randomSource: randomSource, lowestValue: minValue, highestValue: maxValue)
let number = randomDistribution?.nextInt() ?? 0
print(number)
Example taken from Apple's sample code: https://github.com/carekit-apple/CareKit/blob/master/CareKitPrototypingTool/OCKPrototyper/CareKitPatient/RandomNumberGeneratorHelper.swift
I'm late to the party 🤩🎉
Using a function that allows you to change the size of the array and the range selection on the fly is the most versatile method. You can also use map so it's very concise. I use it in all of my performance testing/bench marking.
elements is the number of items in the array
only including numbers from 0...max
func randArr(_ elements: Int, _ max: Int) -> [Int] {
return (0..<elements).map{ _ in Int.random(in: 0...max) }
}
Code Sense / Placeholders look like this.
randArr(elements: Int, max: Int)
10 elements in my array ranging from 0 to 1000.
randArr(10, 1000) // [554, 8, 54, 87, 10, 33, 349, 888, 2, 77]
you can use this in specific rate:
let die = [1, 2, 3, 4, 5, 6]
let firstRoll = die[Int(arc4random_uniform(UInt32(die.count)))]
let secondRoll = die[Int(arc4random_uniform(UInt32(die.count)))]
Lets Code with Swift for the random number or random string :)
let quotes: NSArray = ["R", "A", "N", "D", "O", "M"]
let randomNumber = arc4random_uniform(UInt32(quotes.count))
let quoteString = quotes[Int(randomNumber)]
print(quoteString)
it will give you output randomly.
Don't forget that some numbers will repeat! so you need to do something like....
my totalQuestions was 47.
func getRandomNumbers(totalQuestions:Int) -> NSMutableArray
{
var arrayOfRandomQuestions: [Int] = []
print("arraySizeRequired = 40")
print("totalQuestions = \(totalQuestions)")
//This will output a 40 random numbers between 0 and totalQuestions (47)
while arrayOfRandomQuestions.count < 40
{
let limit: UInt32 = UInt32(totalQuestions)
let theRandomNumber = (Int(arc4random_uniform(limit)))
if arrayOfRandomQuestions.contains(theRandomNumber)
{
print("ping")
}
else
{
//item not found
arrayOfRandomQuestions.append(theRandomNumber)
}
}
print("Random Number set = \(arrayOfRandomQuestions)")
print("arrayOutputCount = \(arrayOfRandomQuestions.count)")
return arrayOfRandomQuestions as! NSMutableArray
}
look, i had the same problem but i insert
the function as a global variable
as
var RNumber = Int(arc4random_uniform(9)+1)
func GetCase(){
your code
}
obviously this is not efficent, so then i just copy and paste the code into the function so it could be reusable, then xcode suggest me to set the var as constant so my code were
func GetCase() {
let RNumber = Int(arc4random_uniform(9)+1)
if categoria == 1 {
}
}
well thats a part of my code so xcode tell me something of inmutable and initialization but, it build the app anyway and that advice simply dissapear
hope it helps

Swift3 Random Extension Method

I was using this extension method to generate a random number:
func Rand(_ range: Range<UInt32>) -> Int {
return Int(range.lowerBound + arc4random_uniform(range.upperBound - range.lowerBound + 1))
}
I liked it b/c it was no nonsense, you just called it like this:
let test = Rand(1...5) //generates a random number between 1 and 5
I honestly don't know why things need to be so complicated in Swift but I digress..
So i'm receiving an error now in Swift3
No '...' candidates produce the expected contextual result type 'Range<UInt32>'
Would anyone know what this means or how I could get my awesome Rand function working again? I guess x...y no longer creates Ranges or x..y must be explicitly defined as UInt32? Any advice for me to make things a tad easier?
Thanks so much, appreciate your time!
In Swift 3 there are four Range structures:
"x" ..< "y" ⇒ Range<T>
"x" ... "y" ⇒ ClosedRange<T>
1 ..< 5 ⇒ CountableRange<T>
1 ... 5 ⇒ CountableClosedRange<T>
(The operators ..< and ... are overloaded so that if the elements are stridable (random-access iterators e.g. numbers and pointers), a Countable Range will be returned. But these operators can still return plain Ranges to satisfy the type checker.)
Since Range and ClosedRange are different structures, you cannot implicitly convert a them with each other, and thus the error.
If you want Rand to accept a ClosedRange as well as Range, you must overload it:
// accepts Rand(0 ..< 5)
func Rand(_ range: Range<UInt32>) -> Int {
return Int(range.lowerBound + arc4random_uniform(range.upperBound - range.lowerBound))
}
// accepts Rand(1 ... 5)
func Rand(_ range: ClosedRange<UInt32>) -> Int {
return Int(range.lowerBound + arc4random_uniform(range.upperBound + 1 - range.lowerBound))
}
A nice solution is presented in Generic Range Algorithms
(based on How to be DRY on ranges and closed ranges? in the swift-users mailing list).
It uses the fact that both CountableRange and CountableClosedRange
are collections, and in fact a RandomAccessCollection.
So you can define a single (generic) function which accepts both open and closed
integer ranges:
func rand<C: RandomAccessCollection>(_ coll: C) -> C.Iterator.Element {
precondition(coll.count > 0, "Cannot select random element from empty collection")
let offset = arc4random_uniform(numericCast(coll.count))
let idx = coll.index(coll.startIndex, offsetBy: numericCast(offset))
return coll[idx]
}
rand(1...5) // random number between 1 and 5
rand(2..<10) // random number between 2 and 9
but also:
rand(["a", "b", "c", "d"]) // random element from the array
Alternatively as a protocol extension method:
extension RandomAccessCollection {
func rand() -> Iterator.Element {
precondition(count > 0, "Cannot select random element from empty collection")
let offset = arc4random_uniform(numericCast(count))
let idx = index(startIndex, offsetBy: numericCast(offset))
return self[idx]
}
}
(1...5).rand()
(2..<10).rand()
["a", "b", "c", "d"].rand()
You could rewrite Rand() to use Int if that is your primary use case:
func Rand(_ range: Range<Int>) -> Int {
let distance = UInt32(range.upperBound - range.lowerBound)
return range.lowerBound + Int(arc4random_uniform(distance + 1))
}
Or as kennytm points out, use Rand(1..<6)

Replacement for C-style loop in Swift 2.2

Swift 2.2 deprecated the C-style loop. However in some cases, the new range operator just doesn't work the same.
for var i = 0; i < -1; ++i { ... }
and
for i in 0..<-1 { ... }
The later one will fail at run-time. I can wrap the loop with an if, but it's a bit cluttered. Sometimes this kind of loop is useful.
Any thoughts?
Use cases
You need to enumerate all elements of an array, except the last one.
You need to enumerate all whole integer numbers in a decimal range, but the range can be like [0.5, 0.9] and so there's no integers (after some maths), which results in an empty loop.
Although it's not as "pretty", you can use stride:
for var i in 0.stride(to: -1, by: -1) {
print(i)
}
Mimicking the "C-style loop"
Not entirely pretty, but you can wrap the range:s upper bound with a max(0, ..) to ascertain it never takes negative values.
let foo : [Int] = []
for i in 0..<max(0,foo.count-1) {
print(i)
}
I'd prefer, however, the from.stride(to:by) solution (that has already been mentioned in the other answers, see e.g. Michael:s answer).
I think it's valuable to explicitly point out, however, that from.stride(to:by) neatly returns an empty StrideTo (or, if converted to an array: an empty array) if attempting to stride to a number that is less than from but by a positive stride. E.g., striding from 0 to -42 by 1 will not attempt to stride all the way through "∞ -> -∞ -> -42" (i.e., an error case), but simply returns an empty StrideTo (as it should):
Array(0.stride(to: -42, by: 1)) // []
// -> equivalent to your C loop:
for i in 0.stride(to: foo.count-1, by: 1) {
print(i)
}
Use case 1: enumerate all but the last element of an array
For this specific use case, a simple solution is using dropLast() (as described by Sulthan in the comments to your question) followed by forEach.
let foo = Array(1...5)
foo.dropLast().forEach { print($0) } // 1 2 3 4
Or, if you need more control over what to drop out, apply a filter to your array
let foo = Array(1...5)
foo.filter { $0 < foo.count }.forEach { print($0) } // 1 2 3 4
Use case 2: enumerate all integers in a decimal range, allowing this enumeration to be empty
For your decimal/double closed interval example ([0.6, 0.9]; an interval rather than a range in the context of Swift syntax), you can convert the closed interval to an integer range (using ceil function) and apply a forEach over the latter
let foo : (ClosedInterval<Double>) -> () = {
(Int(ceil($0.start))..<Int(ceil($0.end)))
.forEach { print($0) }
}
foo(0.5...1.9) // 1
foo(0.5...0.9) // nothing
Or, if you specifically want to enumerate the (possible) integers contained in this interval; use as en extension fit to your purpose:
protocol MyDoubleBounds {
func ceilToInt() -> Int
}
extension Double: MyDoubleBounds {
func ceilToInt() -> Int {
return Int(ceil(self)) // no integer bounds check in this simple example
}
}
extension ClosedInterval where Bound: MyDoubleBounds {
func enumerateIntegers() -> EnumerateSequence<(Range<Int>)> {
return (self.start.ceilToInt()
..< self.end.ceilToInt())
.enumerate()
}
}
Example usage:
for (i, intVal) in (1.3...3.2).enumerateIntegers() {
print(i, intVal)
} /* 0 2
1 3 */
for (i, intVal) in (0.6...0.9).enumerateIntegers() {
print(i, intVal)
} /* nothing */
For reference:
In swift 3.0 stride is now defined globally which makes for loop look more natural:
for i in stride(from: 10, to: 0, by: -1){
print(i)
} /* 10 9 8 7 6 5 4 3 2 1 */
For Swift 3 and need to change the "index"
for var index in stride(from: 0, to: 10, by: 1){}

Swift error, cannot convert type Int to int 16

This function compares the number with the sum of the cubes of the components of this number. For example abc=a^3 + b^3 + c^3. There is an error converting, please help.
func triKuba ( i:Int16, k:Int16, var array:[Int16]=[] ) ->Int16{
for var i=100;i<1000; i++ {
array.append(Int16(i))
if array[i] == pow(array[i]/10) + pow(array[i]/100) + pow(array[i]%10) {
return array[i]
} else {
return 0
}
}
}
triKuba(0, k: 0)
next error in line around method pow 'Cannot invoke pow with argument list of type Int16' if I understood correctly, method pow is a^3
I strongly suspect this is what you are looking for:
func arithmeticRoot3(var value: Int) -> Int {
var result = 0
while value > 0 {
let digit = value % 10
result += digit * digit * digit
value /= 10
}
return result
}
func triKuba() -> [Int] {
return (100...999).filter() {
$0 == arithmeticRoot3($0)
}
}
print(triKuba()) // [153, 370, 371, 407]
Rather than just solving your issue, I'm going to explain what the problem is, and why it throws an error. With this information you should be able to fix the issue (and similar ones in the future!).
In Swift, you can't always do things like multiply an Int with a Float, or return an Int16 from a Double type return function. To you, it might be obvious that 'casting' the variable to the intended type would be fine - but the compiler doesn't know that.
If you're sure it will be safe, you can 'cast' variables to the required type:
Int(int16Variable) // int16Variable has been casted to an 'Int'.
The method you posted had several syntax issues. I fixed them. Working method below:
func triKuba ( i:Int16, k:Int16, var array:[Int16]=[] ) ->Int16{
for var i=100;i<1000; i++ {
array.append(Int16(i))
if Double(array[i]) == pow(Double(array[i])/10, 3.0) + pow(Double(array[i]/100), 3.0) + pow(Double(array[i]%10), 3.0) {
return array[i]
} else {
return 0
}
}
}
Error you were getting was about missing cast from Int to Int16(i)
in your for loop you are declaring a new i variable which is implied to be of type Int as opposed to Int16. (Due to shadowing this is the variable being used in your function body, the parameter i you pass in is never being used.
I would advise either changing the type for your function parameters to be of type Int like so:
func triKuba (var i: Int, var k: Int, var array: [Int]=[] ) -> Int {
or cast your Int16 variables to Ints like so:
array.append(Int16(i))

How do I return functions with inout parameters and a return type of Void in Swift?

I have attempted to run this code in an Xcode 6.0 playground and in an iOS project through the viewController viewDidLoad function, and in both settings the program crashes the compiler. I have read about people having similar issues when returning inout functions when the program is run through a playground, however the issue was resolved when they ran their program through a project. Is something incorrect with my code, and if so what is wrong, or am I running the code incorrectly in the playground or project?
// testingPlayground
// July 18, 2015
func chooseFunction(isYNegative lessThanZero: Bool) -> (inout Int) -> Void {
func increaseY(inout #yValue: Int){ // Increases yValue
yValue += 1
}
func decreaseY(inout #yValue: Int){ // Decreases yValue
yValue -= 1
}
return lessThanZero ? increaseY : decreaseY // Returns either the increase or decrease yValue function
}
var yValue = -1
var changeYFunction = chooseFunction(isYNegative: yValue < 0)
while yValue != 0 {
changeYFunction(&yValue) // Increments/Decrements yValue
}
The code works fine for me after removing the # from both of the #yValue: Int parameters inside chooseFunction (having the # would imply that an argument name must be given, which you don't do).
Alternatively, you need to specify the parameter name in the return type of chooseFunction and use it when you call the returned function, i.e.:
func chooseFunction(isYNegative lessThanZero: Bool) -> ((inout yValue: Int) -> Void) {
And:
changeYFunction(yValue: &yValue)
In other words, the problem is that you are not consistent with whether or not the returned functions require a name for the argument or not.
edit: As yet another alternative, you could consider refactoring the whole thing, e.g., use the shorthand for curried functions:
func stepper(increase increase: Bool)(inout _ y: Int) {
increase ? ++y : --y
}
var y = -5
let step = stepper(increase: y < 0)
while y != 0 {
step(&y)
}
In fact, even the following works, although the hairy syntax required makes me wary:
func stepper(increase increase: Bool)(inout _ y: Int)() {
increase ? ++y : --y
}
var y = -5
let stepY = stepper(increase: y < 0)(&y)
while y != 0 {
stepY()
}

Resources