I don't think this can be written using for anymore, but you can use while
loop to get the job done:
var nSize = merkleTree.count
while nSize > 1 {
// loop body
nSize = (nSize + 1) / 2
}
I would expect stride
not to work in this case, because as your error states, you cannot use nSize
as the stride
parameter - nSize
is iterating variable that gets declared based on the range, so you need the range to exist. At least that's my interpretation of the error (I know that theoretically you can generate range based on the previously generated item, but obviously stride
does not work that way).
I believe you can find a way to generate a proper array of values using reduce
(because I was able to, see below, maybe you can make it simpler), or by implementing your own stride
that would accept a closure instead of a step (which would allow you to compute next item based on previous one), but both approaches are more complicated and obscure than using the simple while loop, so I personally prefer the while
loop.
My not so nice reduce implementation (in result it uses an array and not a range, since by looking at NSRange
I don't think you can create a range that does not step by 1):
let merkleTree = [1,2,3,4,5,6,7,8,9]
let numberOfDivisions = Int(log2(Double(merkleTree.count))) + 1
let startValue = merkleTree.count
let nSizes = (0..<numberOfDivisions).reduce([startValue]) { (result, next) -> [Int] in
var newResult = result
newResult.append((result.last! + 1) / 2)
return newResult
}
print(nSizes)
// and now you can for-in it:
for nSize in nSizes {
// ...
}