Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save SwiftArchitect/b33d85cc06c2e1bf5a283c3be6ca5518 to your computer and use it in GitHub Desktop.
Save SwiftArchitect/b33d85cc06c2e1bf5a283c3be6ca5518 to your computer and use it in GitHub Desktop.
Swift Xcode implementation of InterviewCake 'Highest product of 3' using an `Array` extension, and a few fold faster than the accepted answer. ⚠️ Spoiler alert: this is an actual answer to the https://www.interviewcake.com/question/swift/highest-product-of-3 question, so no peeking!
//
// Array+HighestProductOfIntegers.swift
//
// Copyright © 2018 Xavier Schott
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
import Foundation
extension Array where Element == Int
{
// Single out the 3 lowest and the 3 highest numbers, then run a O(n3) algorithm on these 6 values
// Works great on very large sets
func highestProductOfIntegers() -> Double {
assert(count >= 3)
var smallPQ = [Int](repeatElement(Int.max, count: 3))
var largePQ = [Int](repeatElement(Int.min, count: 3))
for i in 0 ..< count {
// Keep an ascending array of small values by replacing the highest
if self[i] < smallPQ[2] {
smallPQ[2] = self[i]
smallPQ.sort()
}
// Keep an ascending array of large values by replacing the smallest
if self[i] > largePQ[0] {
largePQ[0] = self[i]
largePQ.sort()
}
}
// Combine the smallest and largest numbers into a single array, and run all combinations
smallPQ.append(contentsOf: largePQ)
return smallPQ.productOfIntegersN3()
}
private func productOfIntegersN3() -> Double {
let array = self
var result = -Double.greatestFiniteMagnitude
for indice0 in 0 ... count - 2 {
for indice1 in indice0 + 1 ..< count - 1 {
for indice2 in indice1 + 1 ..< count {
result = Swift.max(result, Double(array[indice0] * array[indice1] * array[indice2]))
}
}
}
return result
}
}
//
// HighestProductOfIntegersTests.swift
//
// Copyright © 2018 Xavier Schott
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
import XCTest
class HighestProductOfIntegersTests: XCTestCase {
func testHighestProductOfIntegers1to5() {
let sample = [1, 2, 3, 5, 4]
let result = sample.highestProductOfIntegers()
XCTAssertTrue(60.0 == result)
}
func testHighestProductOfIntegers0to5() {
let sample = [1, 2, 0, 3, 5, 4]
let result = sample.highestProductOfIntegers()
XCTAssertTrue(60.0 == result)
}
func testHighestProductOfIntegersSomeNegative() {
let sample:[Int] = [-10, 1, -20, 3, -5, 2]
let result = sample.highestProductOfIntegers()
XCTAssertTrue(600.0 == result)
}
func testHighestProductOfIntegersSomeNegativeAndZero() {
let sample:[Int] = [-10, 1, -20, 0, 3, -5, 2]
let result = sample.highestProductOfIntegers()
XCTAssertTrue(600.0 == result)
}
func testHighestProductOfIntegersAllNegative() {
let sample:[Int] = [-10, -20, -1, -3, -2]
let result = sample.highestProductOfIntegers()
XCTAssertTrue(-6 == result)
}
func testHighestProductOfIntegersAllNegativeAndZero() {
let sample:[Int] = [-10, -20, -1, 0, -3, -2]
let result = sample.highestProductOfIntegers()
XCTAssertTrue(0 == result)
}
func testHighestProductOfIntegersUsingSolution() {
let sample = [1, 10, -5, 1, -100]
let result = sample.highestProductOfIntegers()
XCTAssertTrue(5000.0 == result)
}
func testHighestProductOfIntegers() {
var largeArray = [Int](repeatElement(0, count: 32768)) // 0.001 sec
for i in 0 ..< largeArray.count {
largeArray[i] = Int(arc4random_uniform(65536)) - 32768 // balance positive and negative numbers
}
self.measure {
_ = largeArray.highestProductOfIntegers()
}
}
}
@SwiftArchitect
Copy link
Author

Proposed solution combines a brute-force algorithm (productOfIntegersN3) with a less than O(log n) algorithm (highestProductOfIntegers).

  • productOfIntegersN3 will only be used on the final array of 6 elements
  • the bulk of highestProductOfIntegers is linear, and is tasked to isolate the 3 lowest and 3 highest numbers in a single pass

The performance on a random set of non-ordered vales is surprisingly good, since the 2 arrays of max and min are seldom modified.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment