5

How to count maximum consecutive positive numbers using closures?

var numbers = [1,3,4,-1,-2,5,2,-2,-3,-4,5]
//in this case it should be 3

print(numbers.reduce(0, { $1 > 0 ? $0 + 1 : $0 } ))//this counts total positive numbers
Anton
  • 339
  • 5
  • 15
  • we look for the number in numbers: 1,3,4 - all positive, we count them - its 3. then 2 negative numbers, 2 positive, 3 negative and 1 positive. So, maximum consecutive positive numbers - 3. – Anton Nov 06 '17 at 12:53

5 Answers5

9

Update: Simpler solution: Split the array into slices of positive elements, and determine the maximal slice length:

let  numbers = [1,3,4,-1,-2,5,2,-2,-3,-4,5]
let maxConsecutive = numbers.split(whereSeparator: { $0 <= 0 }).map { $0.count }.max()!
print(maxConsecutive) // 3

Old answer:) Using the ideas from Swift running sum:

let  numbers = [1,3,4,-1,-2,5,2,-2,-3,-4,5]

let maxConsecutive = numbers.map({
    () -> (Int) -> Int in var c = 0; return { c = $0 > 0 ? c + 1 : 0; return c }
}()).max()!

Here map() maps each array element to the count of consecutive positive numbers up to the elements position, in this case

[1, 2, 3, 0, 0, 1, 2, 0, 0, 0, 1]

The transformation is created as an "immediately evaluated closure" to capture a variable c which holds the current number of consecutive positive numbers. The transformation increments or resets c, and returns the updated value.

If the array is possibly large then change it to

let maxConsecutive = numbers.lazy.map( ... ).max()!

so that the maximum run length is determined without creating an intermediate array.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Thanks, that's exactly what I want - simple and short solution! How can I find average consecutive positive number? With map we get [1, 2, 3, 0, 0, 1, 2, 0, 0, 0, 1], now what to use, filter and reduce? The result should be [3,2,1], then sum 6 divide by count 3 = 2 – Anton Nov 06 '17 at 17:25
  • @Anton: Inspired by your new question, I have updated this answer with a much simpler solution. – Martin R Nov 07 '17 at 15:11
2
var currentResult = 0
var maxResult = 0
for i in numbers {
    currentResult = i > 0 ? currentResult + 1 : 0
    if maxResult < currentResult {
       maxResult = currentResult
    }
}
print(maxResult)

Solution without closures

Utemissov
  • 106
  • 4
2
var numbers = [1, 3, 4, -1, -2, 5, 2, -2, -3, -4, 5]

let result = numbers.reduce((current: 0, max: 0)) { result, number in
    var value = result

    if number > 0 {
        value.current += 1
        value.max = max(value.current, value.max)
    } else {
        value.current = 0
    }

    return value
}



result.max
Arsen
  • 10,815
  • 2
  • 34
  • 46
1

Generating subsequences:

let numbers = [1,3,4,-1,-2,5,2,-2,-3,-4,5]
let subsequences: [[Int]] = numbers.reduce(into: []) { (result, number) in
    guard
        var currentSequence = result.last,
        let lastNumber = currentSequence.last
    else {
        result = [[number]]
        return
    }

    if number == lastNumber + 1 {
        currentSequence.append(number)
        result.removeLast()
        result.append(currentSequence)
    } else {
        result.append([number])
    }
}
let longest = subsequences.max { $0.count < $1.count }
print(subsequences)
print("Longest subsequence: \(longest)")
print("Longest length: \(longest?.count)")
Sulthan
  • 128,090
  • 22
  • 218
  • 270
0

Detect Three consecutive number in an array

var  data = [1,2,5,4,56,6,7,9,6,5,4,5,1,2,5,4,56,6,7,9,8,1,1,2,5,4,56,6,7,9,8,1,1,2,5,4,56,6,7,9,8,1,1,2,5,4,56,6,7,9,8,1,1,2,5,4,56,6,7,9,8,11,2,5,4,56,6,7,9,8,1,2,3]

for i in 0...data.count{
    if i+2 < data.count{
        if Int(data[i] + data[i+2]) / 2 == data[i+1] && Int(data[i] + data[i+2]) % data[i+1] == 0 && data[i+1] != 1 && data[i] < data[i+1]{
            print(data[i] ,data[i+1], data[i+2])
        }
    }
}
Syscall
  • 19,327
  • 10
  • 37
  • 52