Ios 在Swift中有效地在阵列上生成连续且相同的编号

Ios 在Swift中有效地在阵列上生成连续且相同的编号,ios,arrays,swift,algorithm,multidimensional-array,Ios,Arrays,Swift,Algorithm,Multidimensional Array,我在应用程序中有一个例子,它创建了一个数字pin模式,该模式不应该有一个连续的数字和相同的所有数字 被拒绝的引脚图案示例如下: 123456, 234567, 345678, 654321, 765432, 876543, 000000和其他类似的PIN模式 var rejectedPinList: [[Int]] = [[Int]]() var consecutiveNumber = [0,1,2,3,4,5,6,7,8,9,0] func incrementNumber(currentIn

我在应用程序中有一个例子,它创建了一个数字pin模式,该模式不应该有一个连续的数字和相同的所有数字

被拒绝的引脚图案示例如下:

123456, 234567, 345678, 654321, 765432, 876543, 000000和其他类似的PIN模式

var rejectedPinList: [[Int]] = [[Int]]()
var consecutiveNumber = [0,1,2,3,4,5,6,7,8,9,0]

func incrementNumber(currentIndex: Int) -> [Int] {
    var rejectedPinPattern: [Int] = [Int]()
    for currentIndex in stride(from: currentIndex, to: currentIndex+6, by: 1){
        rejectedPinPattern.append(consecutiveNumber[currentIndex])
    }
    return rejectedPinPattern
}

func decrementNumber(currentIndex: Int) -> [Int] {
    var rejectedPinPattern: [Int] = [Int]()
    for currentIndex in stride(from: currentIndex, to: currentIndex-6, by: -1){
        rejectedPinPattern.append(consecutiveNumber[currentIndex])
    }
    return rejectedPinPattern
}

func constantNumber(currentIndex: Int) -> [Int] {
    var rejectedPinPattern: [Int] = [Int]()
    for _ in currentIndex...currentIndex+6  {
        rejectedPinPattern.append(consecutiveNumber[currentIndex])
    }
    return rejectedPinPattern
}


for number in consecutiveNumber {
    rejectedPinList.append(constantNumber(currentIndex: number))
    if number < 5 {
        rejectedPinList.append(incrementNumber(currentIndex: number))
    } else if number > 5 {
        rejectedPinList.append(decrementNumber(currentIndex: number))
    } else {
        rejectedPinList.append(incrementNumber(currentIndex: number))
        rejectedPinList.append(decrementNumber(currentIndex: number))
    }
}

func inputPin(pin: [Int]) {
    if rejectedPinList.contains(pin) {
        print("Pin Rejected!")
    } else {
    }
}
inputPin(pin: [8,7,6,5,4,3]) // Should be Rejected!

我要寻找的是,在生成连续且相同的数字时,比我上面所做的算法代码更有效。因为在我看来,我编写的代码太长,效率不高,可能是浪费。谢谢大家!

我想这应该是你想要的。它检查是否有任何连续数字的绝对差值不是1。如果是这样,则在检查重复数字之前,PIN可能有效

要检查重复的数字,请将这些数字添加到NSCountedSet。如果任何数字的计数与位数相同,则PIN无效

func validatePIN(_ candidate: [Int]) -> Bool {
    
    guard !candidate.isEmpty else {
        return false
    }
    
    let digitSet = NSCountedSet()
    
    var possiblyValid = false
    var lastSign: Int?
    
    for i in 0..<candidate.count {
        digitSet.add(candidate[i])
        if i > 0 && !possiblyValid {
            let difference = candidate[i]-candidate[i-1]
            let thisSign = difference.signum()
            if abs(difference) != 1 {
                possiblyValid = true
            } else if let sign = lastSign, sign != thisSign {
                possiblyValid = true
            }
            lastSign = thisSign
        }
    }
    
    for digit in digitSet {
        if digitSet.count(for: digit) == candidate.count {
            return false
        }
    }
    
    return possiblyValid
}

print(validatePIN([]))
print(validatePIN([8,7,6,5,3,3]))
print(validatePIN([8,7,6,5,4,3]))
print(validatePIN([2,2,2,2,2,2]))
print(validatePIN([1,2,3,4,3,2]))
给出:

假的

真的

假的

假的

真的


您还可以在guard语句中添加一个最小长度测试

我认为这应该满足您的要求。它检查是否有任何连续数字的绝对差值不是1。如果是这样,则在检查重复数字之前,PIN可能有效

要检查重复的数字,请将这些数字添加到NSCountedSet。如果任何数字的计数与位数相同,则PIN无效

func validatePIN(_ candidate: [Int]) -> Bool {
    
    guard !candidate.isEmpty else {
        return false
    }
    
    let digitSet = NSCountedSet()
    
    var possiblyValid = false
    var lastSign: Int?
    
    for i in 0..<candidate.count {
        digitSet.add(candidate[i])
        if i > 0 && !possiblyValid {
            let difference = candidate[i]-candidate[i-1]
            let thisSign = difference.signum()
            if abs(difference) != 1 {
                possiblyValid = true
            } else if let sign = lastSign, sign != thisSign {
                possiblyValid = true
            }
            lastSign = thisSign
        }
    }
    
    for digit in digitSet {
        if digitSet.count(for: digit) == candidate.count {
            return false
        }
    }
    
    return possiblyValid
}

print(validatePIN([]))
print(validatePIN([8,7,6,5,3,3]))
print(validatePIN([8,7,6,5,4,3]))
print(validatePIN([2,2,2,2,2,2]))
print(validatePIN([1,2,3,4,3,2]))
给出:

假的

真的

假的

假的

真的


您还可以在guard语句中添加最小长度测试,因为问题是为了提高效率,下面的方法在开始循环数组之前执行一些初始检查,以最小化总迭代次数/时间

func validatePin(_ pin: [Int], minLength: Int = 2 ) -> Bool {
   guard pin.count >= max(minLength, 2)  else {return false}

   guard Set(pin).count != 1 else {return false}  //all the same

   guard abs(pin.first! - pin.last!) == pin.count - 1 else {return true} //can't be a sequence

   let delta = pin.first! < pin.last! ? -1 : 1
   for index in (0...pin.count - 2) {
      if pin[index] - pin[index + 1] != delta {return true}  //items not sequential
   }
   return false  //items are sequential
}

由于问题是为了提高效率,下面的方法在开始在阵列中循环之前执行一些初始检查,以最小化总迭代次数/时间

func validatePin(_ pin: [Int], minLength: Int = 2 ) -> Bool {
   guard pin.count >= max(minLength, 2)  else {return false}

   guard Set(pin).count != 1 else {return false}  //all the same

   guard abs(pin.first! - pin.last!) == pin.count - 1 else {return true} //can't be a sequence

   let delta = pin.first! < pin.last! ? -1 : 1
   for index in (0...pin.count - 2) {
      if pin[index] - pin[index + 1] != delta {return true}  //items not sequential
   }
   return false  //items are sequential
}

您可以通过计算相邻数字的所有差异集来验证给定管脚,而不是预先计算所有无效管脚的列表。如果集仅由-1、0或+1组成,则pin无效:


您可以通过计算相邻数字的所有差异集来验证给定管脚,而不是预先计算所有无效管脚的列表。如果集仅由-1、0或+1组成,则pin无效:


谢谢大家帮助我。我还即兴创作了我的算法。这是我的密码:

func validatePIN(_ pin: [Int]) -> Bool {
    if (pin.isEmpty == true) ||
        (pin[0] < 5 && pin == Array(pin[0]...pin[0]+5)) ||
        (pin[0] > 5 && pin == Array(stride(from: pin[0], through: pin[0]-5, by: -1)) ||
        (pin.allSatisfy({ $0 == pin[0] }))) { return false }; return true
}

谢谢大家帮助我。我还即兴创作了我的算法。这是我的密码:

func validatePIN(_ pin: [Int]) -> Bool {
    if (pin.isEmpty == true) ||
        (pin[0] < 5 && pin == Array(pin[0]...pin[0]+5)) ||
        (pin[0] > 5 && pin == Array(stride(from: pin[0], through: pin[0]-5, by: -1)) ||
        (pin.allSatisfy({ $0 == pin[0] }))) { return false }; return true
}


为什么不使用随机数Int.randomin:0..是否允许使用任何连续数字或根本不使用?例如,561924有效吗?是否允许任何重复的数字?例如,419314有效吗?我想检查给定的pin是否增加/减少/相同字符比事先创建所有“阻止”pin的列表更容易。您好@Afsaredrisy,我只是更改了变量的名称以避免误解。您可以再次检查。Hi@Paulw11,561924有效,419314也有效。为什么不使用随机数Int.randomin:0..是否允许使用任何连续数字或根本不使用?例如,561924有效吗?是否允许任何重复的数字?例如,419314有效吗?我想检查给定的pin是否增加/减少/相同字符比事先创建所有“阻止”pin的列表更容易。您好@Afsaredrisy,我只是更改了变量的名称以避免误解。您可以再次检查。Hi@paulw11561924有效,419314也有效。请注意,这将拒绝[1,2,3,4,3,2]。抓到了。修复了该问题。请注意,这将拒绝[1,2,3,4,3,2]。捕获效果很好。修正了这个问题。注意这将拒绝[1,2,4,6,3,1]。您只检查第一个和最后一个数字是否相等,而不是所有数字是否相等。此外,pin码[2,5,5,5,1]的代码也会崩溃。您可能希望将插脚[0]<5替换为插脚[0]<5]。最后一次检查可以简化为插脚。AllConfect{$0==pin[0]}太棒了!谢谢。请注意,这将拒绝[1,2,4,6,3,1]。您只检查第一个和最后一个数字是否相等,而不是所有数字是否相等。此外,pin码[2,5,5,5,1]的代码也会崩溃。您可能希望将插脚[0]<5替换为插脚[0]<5]。最后一次检查可以简化为插脚。AllConfect{$0==pin[0]}太棒了!非常感谢。