How to find segments of close values in an array? - arrays

How to implement an algorithm that finds segments of continous close values in an array?
Let's say that we start with the following array:
array = [5, 6, 4, 0, 5, 10, 12, 10, 11, 4, 3, 2, 3, 2, 1, 3, 1, 0, 2]
Let's also assume that we will tolerate a "closeness" in each segment of maximum value of 3.
The segments produced would be something like the following:
seg[0] = [5, 6, 4]
seg[1] = [0]
seg[2] = [5]
seg[3] = [10, 12, 10, 11]
seg[4] = [4, 3, 2, 3, 2]
seg[5] = [1, 3, 1]
seg[6] = [0, 2]
Also, we could allow a "dropout" of, say, maximum one continous value that would fall out of the current segment but would be included if the following values fit in the segment. This would produce something like:
seg[0] = [5, 6, 4, 0, 5] //include 0 as a "dropout"
seg[1] = [10, 12, 10, 11]
seg[3] = [4, 3, 2, 3, 2, 1, 3] // include 1 as a "dropout"
seg[4] = [1, 3, 1, 0, 2] // include 0 as a "droput"
Ideas on how to implement such an algorithm?

Here's my own take on it. Written in Haxe (haxe.org).
The checkDropout() method checks for "dropouts" of n length, and "normalizes" them away to an average number of the current segment.
using Lambda;
class Example {
static function main() {
var a:Array<Float> = [5, 6, 4, 0, 5, 10, 12, 10, 11, 4, 3, 2, 3, 2, 1, 3, 1, 0, 2];
// Segment value tolerance of 2
// Dropout max length of 3
var segmentor = new Segmentor(2, 3);
// Callback for displaying result
segmentor.displayResult = (r, v) -> {
trace('-------------------------------------');
trace('value added: ' + v);
trace('result: ' + r);
}
// Feed the segmentor with the example values
a.map(i -> segmentor.addNumber(i));
// var result = [
// [5, 6, 4, 5, 5],
// [10, 12, 10, 11],
// [4, 3, 2, 3, 2],
// [1, 3, 1],
// [0, 2]
// ];
}
}
class Segmentor {
public function new(valueSpan:Int = 2, dropoutLength:Int = 1) {
this.valueSpan = valueSpan;
this.dropoutLength = dropoutLength;
this.result = [];
this.result.push([]);
}
var dropoutLength:Int = null;
var valueSpan:Int = null;
public var result(default, null):Array<Array<Float>>;
public function addNumber(v:Float) {
this.processNumber(v);
}
function processNumber(v:Float) {
var current = this.result[this.result.length - 1];
if (current.length == 0) {
current.push(v);
} else if (fitIn(current, v) || this.checkDropout(v)) {
var current2 = this.result[this.result.length - 1];
current2.push(v);
} else {
this.result.push([v]);
}
this.displayResult(this.result, v);
}
dynamic public function displayResult(result:Array<Array<Float>>, valueAdded:Float) {}
function checkDropout(v:Float):Bool {
if (this.result.length <= 1)
return false;
var last = this.result[this.result.length - 1];
if (last.length <= this.dropoutLength) {
var prev = this.result[this.result.length - 2];
if (fitIn(prev, v)) {
var mid = mid(prev);
var newLast = [for (i in 0...last.length) mid];
newLast.map(n -> prev.push(n));
this.result.pop();
return true;
}
}
return false;
}
function fitIn(a:Array<Float>, v:Float):Bool {
var max = a.fold((c, v) -> Math.max(v, c), a[0]);
var min = a.fold((c, v) -> Math.min(v, c), a[0]);
var fit = ((max - v <= this.valueSpan) && (v - min <= this.valueSpan));
return fit;
}
function mid(a:Array<Float>) {
var max = a.fold((c, v) -> Math.max(v, c), a[0]);
var min = a.fold((c, v) -> Math.min(v, c), a[0]);
return min + (max - min) / 2;
}
}

Related

how to multiply the array element in to the next element and output as an array in Swift

var numbers = [2, 4, 3, 7]
var computed = numbers
print(computed)
I want to multiply the first element to next, until the last will multiply to the first element
example:
2*4, 4*3, 3*7, 7*2
and the output will be [8, 12, 21, 14]
I don't know the Swift language but the algorithm is pretty simple and does not depend on any technology. Try with this one:
let numbers = [2, 4, 3, 7]
let indexAndNum = numbers.enumerated().map { (index, element) in
return element * numbers[(index + 1) % numbers.count]
}
print(indexAndNum)
Live demo here
var resultArray = [Int]()
for (index, number) in numbers.enumerated() {
if index < numbers.count - 1 {
resultArray.append(number * numbers[index + 1])
} else {
resultArray.append(number * numbers[0])
}
}
print(resultArray)
Succincter version of Sebastian Kaczmarek's answer:-
let numbers = [2, 4, 3, 7]
let computed = numbers.enumerated().map { $1 * numbers[($0 + 1) % numbers.count] }
print(computed)
Output:-
[8, 12, 21, 14]

Optimize Swift function to find a specific set of combinations of 3 digits within a larger integer array

I'm working on a function that will help me quickly find all the upper structure triads (3-note chord) that I can add to a 4-note 7th chord to create a larger compound chord, as well of the roots and names of each triad. The example I'm testing right now is a 13#11 chord, which has the following degrees in a 12-note octave (when the root is 0): [0, 2, 4, 6, 7, 9, 10]*
*side note: [0, 4, 6, 7, 9, 10] would also match as a 13#11.
The base 7th chord is a dominant 7th: [0, 4, 7, 9].I already know which triads complete the chord: a major triad on the 9th, [2, 6, 9], and a diminished triad on the #11, 0, 6, 9 (only the 6 (#11th) and 9 (13th) are actually necessary to build a 13#11 chord; the 2 (9th) is optional).
I actually already have a function that will give me these results, I'm just wondering if there's a faster/more efficient way to do it? It just feels a little bulky/clunky right now. Any help would be appreciated.
Thanks!
Jake
extension Int {
func degreeInOctave() -> Int {
switch self {
case 0...11:
return self
case 12...:
return self - 12
default:
return self + 12
}
}
}
var ust: [Int] = [0, 2, 4, 6, 7, 9, 10]
let maj = [0, 4, 7]
let min = [0, 3, 7]
let aug = [0, 4, 8]
let dim = [0, 3, 6]
let sus4 = [0, 5, 7]
let sus2 = [0, 2, 7]
let triadDegs = [maj, min, aug, dim, sus4, sus2]
var triadRoots: [Int] = []
var triadQualities: [String] = []
func findUpperStructureTriads(degs: [Int]) {
let degCount = degs.count
var firstIndex = 0
while firstIndex < (degCount - 2) {
var secondIndex = firstIndex + 1
while secondIndex < (degCount - 1) {
var thirdIndex = secondIndex + 1
while thirdIndex < (degCount) {
var threeNoteGroup = [degs[firstIndex], degs[secondIndex], degs[thirdIndex]]
func checkForTriad(triad: [Int]) -> Bool {
if triadDegs.contains(triad) {
switch triad {
case maj:
triadQualities.append("major")
case min:
triadQualities.append("minor")
case aug:
triadQualities.append("augmented")
case dim:
triadQualities.append("diminished")
case sus4:
triadQualities.append("sus4")
case sus2:
triadQualities.append("sus2")
default:
()
}
return true
} else {
return false
}
}
if threeNoteGroup.contains(6), threeNoteGroup.contains(9){
var inversionCount = 0
var newGroup = threeNoteGroup.map {$0 - threeNoteGroup[0]}
while inversionCount < 3 {
func invert() {
newGroup = newGroup.map {($0 - newGroup[1]).degreeInOctave()}
let newlast = newGroup.remove(at: 0)
newGroup.append(newlast)
}
if checkForTriad(triad: newGroup) {
print(threeNoteGroup, threeNoteGroup[inversionCount])
triadRoots.append(threeNoteGroup[inversionCount])
break
}
invert()
inversionCount += 1
}
}
thirdIndex += 1
}
secondIndex += 1
}
firstIndex += 1
}
for i in 0...(triadRoots.count - 1) {
print(triadRoots[i], triadQualities[i])
}
}
findUpperStructureTriads(degs: ust)
outputs:
[0, 6, 9] 6
[2, 6, 9] 2
6 diminished
2 major

How to find the lowest number in an array? [duplicate]

This question already has answers here:
Find min / max value in Swift Array
(16 answers)
Closed 1 year ago.
I am writing an algorithm to find the lowest number in an array however my print statement keeps saying that the lowest number is 0. I have the following:
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
func findMin(numbers: NSArray) {
var minValue = numbers[0]
var isSmallest: Bool
for i in 0...numbers.count {
isSmallest = true
for j in 0...numbers.count {
if i > j {
isSmallest = false
}
}
if isSmallest {
minValue = i
}
}
print("Smallest value in the list is \(minValue)")
}
findMin(numbers: list as NSArray)
My print statement returns as:
"Smallest value in the list is 0\n"
I feel like the algorithm is correct. Any ideas?
EDIT: Answered my own question
I was iterating over indices and not actual values. Thanks to one of the users in the comments. The correct code should be:
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
func findMin(numbers: NSArray) {
var minValue = numbers[0]
var isSmallest: Bool
for i in list {
isSmallest = true
for j in list {
if i > j {
isSmallest = false
}
}
if isSmallest {
minValue = i
}
}
print("Smallest value in the list is \(minValue)")
}
findMin(numbers: list as NSArray)
Simply
let list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
let minValue = list.min()
For logic use try this
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
var minValue = list[0]
for num in list {
minValue = (num < minValue) ? num : minValue
}
print("Smallest value in the list is \(minValue)")
For direct get min value by property
let list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
let minValue = list.min()
Or you could just use
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
list.min() // returns 2
If you'd like to find the min value without an extra loop, try this:
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
func findMin(numbers: NSArray) {
var minValIdx = 0
var minValue = numbers[0] as! Int
for i in 1..<numbers.count {
if (numbers[i] as! Int) < minValue {
minValue = numbers[i] as! Int
minValIdx = i
}
}
print("Smallest value in the list is \(minValue)")
}
findMin(numbers: list as NSArray)
You can use this code in Swift for manual algorithm:
let list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
var smallest = list[0]
for item in list {
if (item < smallest) {
smallest = item
}
}
print("smallest number is: \(smallest)")
And if you want Swift to do the hard work then use this:
let smallest = list.min()
print("smallest number is: \(smallest)")
here it is your solution
let numbers = [1, 6, 3, 9, 4, 6]
let min = minElement(numbers) // 1
let position = find(array, min)// it will return index
Just to throw a few more options out there, assuming you have to actually show some logic:
func min<T:Comparable>(_ elements:[T]) -> T? {
guard let first = elements[0] else {
return nil
}
return elements.reduce(first, min)
}
print(min(list))
or put it in an extension, this is essentially the definition of Array.min
extension Array where Element : Comparable {
func smallest() -> Element? {
guard let first = self.first else {
return nil
}
// Use 'Swift.min' to get to the global function since Array
// already has a min function
return reduce(first, Swift.min)
}
}
print(list.smallest())
You can use this code:
it is in C#
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
int minVal = list[0];
for (int i = 1; i < list.Length; i++)
{
if (list[i] < minVal)
{
minVal = intArray[i];
}
}
To find the minimum element in the sequence, Swift 3 have an istance method called min():
var list = [5, 4, 3, 5, 2, 50, 8, 10, 300]
let minElem = list.min()
If the sequence has no elements, returns nil.
This method can be used also for a list of floats:
let heights = [67.5, 65.7, 64.3, 61.1, 58.5, 60.3, 64.9]
let minHeight = heights.min()
You can find the official document referece here

How can I get the largest value from an integer array in a dictionary of arrays

I am trying to get the largest value in a dictionary of arrays and I need also get the key of that array.
This is how I get the largest value:
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25]
]
var largest = 0
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
}
}
}
I would use max method in your dictionary values and get the maximum value from the resulting tuple values:
if let result = interestingNumbers.max(by: {$0.value.max() ?? 0 < $1.value.max() ?? 0}),
let maxValue = result.value.max() {
print(result.key) // "Square\n"
print(result.value) // "[1, 4, 9, 16, 25]\n"
print(maxValue) // 25
}
Why don't you use a tuple to hold the largest value?
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest: (kind: String?, number: Int) = (nil, 0)
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest.number {
largest = (kind, number)
}
}
}
Which can be further simplified to:
var largest: (kind: String?, number: Int) = (nil, 0)
for (kind, numbers) in interestingNumbers {
let max = numbers.max() ?? 0
if max > largest.number {
largest = (kind, max)
}
}
Another method is to flatten the values first into a (kind, number) sequence:
let flattened = interestingNumbers
.map { (kind, numbers) in numbers.map { (kind, $0) } }
.joined()
let largest = flattened.max(by: { $0.1 < $1.1} )
print(largest)
or you can realize that only the maximum value in every array is the most important, therefore :
let largestPerKind = interestingNumbers
.map { (kind, numbers) in (kind, numbers.max() ?? 0) }
let largest = largestPerKind.max(by: { $0.1 < $1.1} )
print(largest)
You can use Swift function's for that.
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
if let value = interestingNumbers.map ({ ($0, $1.max() ?? 0) }).max(by: { $0.1 < $1.1 }) {
print(value.0, value.1) // Square 25
}
Let's go with step by step
First I have created array of tuple with type [(String, Int)], with first place it will store group and on second place it will store max value from its corresponding array.
let array = interestingNumbers.map ({ ($0, $1.max() ?? 0) })
//[("Fibonacci", 8), ("Square", 25), ("Prime", 13)]
Now find the max Int from the array of tuple.
if let value = array.max(by: { $0.1 < $1.1 }) {
print(value.0, value.1) //Will print group here it is "Square 25"
}
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
var largest_kind : String? =nil
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
largest_kind = kind
}
}
}

Repeating array in Swift

In Python I can create a repeating list like this:
>>> [1,2,3]*3
[1, 2, 3, 1, 2, 3, 1, 2, 3]
Is there a concise way to do this in Swift?
The best I can do is:
1> var r = [Int]()
r: [Int] = 0 values
2> for i in 1...3 {
3. r += [1,2,3]
4. }
5> print(r)
[1, 2, 3, 1, 2, 3, 1, 2, 3]
You can create a 2D array and then use flatMap to turn it into a 1D array:
let array = [[Int]](repeating: [1,2,3], count: 3).flatMap{$0}
If you want to have a general way of doing this, here's an extension that adds an init method and a repeating method that takes an array which makes this a bit cleaner:
extension Array {
init(repeating: [Element], count: Int) {
self.init([[Element]](repeating: repeating, count: count).flatMap{$0})
}
func repeated(count: Int) -> [Element] {
return [Element](repeating: self, count: count)
}
}
let array = [1,2,3].repeated(count: 3) // => [1, 2, 3, 1, 2, 3, 1, 2, 3]
Note that with the new initializer you can get an ambiguous method call if you use it without providing the expected type:
let array = Array(repeating: [1,2,3], count: 3) // Error: Ambiguous use of ‛init(repeating:count:)‛
Use instead:
let array = [Int](repeating: [1,2,3], count: 3) // => [1, 2, 3, 1, 2, 3, 1, 2, 3]
or
let array:[Int] = Array(repeating: [1,2,3], count: 3) // => [1, 2, 3, 1, 2, 3, 1, 2, 3]
This ambiguity can be avoided if you change the method signature to init(repeatingContentsOf: [Element], count: Int) or similar.
With Swift 5, you can create an Array extension method in order to repeat the elements of the given array into a new array. The Playground sample code below shows a possible implementation for this method:
extension Array {
func repeated(count: Int) -> Array<Element> {
assert(count > 0, "count must be greater than 0")
var result = self
for _ in 0 ..< count - 1 {
result += self
}
return result
}
}
let array = [20, 11, 87]
let newArray = array.repeated(count: 3)
print(newArray) // prints: [20, 11, 87, 20, 11, 87, 20, 11, 87]
If needed, you can also create an infix operator to perform this operation:
infix operator **
extension Array {
func repeated(count: Int) -> Array<Element> {
assert(count > 0, "count must be greater than 0")
var result = self
for _ in 0 ..< count - 1 {
result += self
}
return result
}
static func **(lhs: Array<Element>, rhs: Int) -> Array<Element> {
return lhs.repeated(count: rhs)
}
}
let array = [20, 11, 87]
let newArray = array ** 3
print(newArray) // prints: [20, 11, 87, 20, 11, 87, 20, 11, 87]
You can use modulo operations for index calculations of your base collection and functional programming for this:
let base = [1, 2, 3]
let n = 3 //number of repetitions
let r = (0..<(n*base.count)).map{base[$0%base.count]}
You can create a custom overload for the * operator, which accepts an array on the left and an integer on the right side.
func * <T>(left: [T], right: Int) -> [T] {
return (0..<(right*left.count)).map{left[$0%left.count]}
}
You can then use your function just like in python:
[1, 2, 3] * 3
// will evaluate to [1, 2, 3, 1, 2, 3, 1, 2, 3]
Solution 1:
func multiplerArray(array: [Int], time: Int) -> [Int] {
var result = [Int]()
for _ in 0..<time {
result += array
}
return result
}
Call this
print(multiplerArray([1,2,3], time: 3)) // [1, 2, 3, 1, 2, 3, 1, 2, 3]
Solution 2:
let arrays = Array(count:3, repeatedValue: [1,2,3])
// [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
var result = [Int]()
for array in arrays {
result += array
}
print(result) //[1, 2, 3, 1, 2, 3, 1, 2, 3]

Resources