A regular number in mathematics is defined as one which evenly divides some power of 60. Equivalently, we can say that a regular number is one whose only prime divisors are 2, 3, and 5.
These numbers have had many applications, from helping ancient Babylonians keep time to tuning instruments according to the diatonic scale.
Given an integer N, write a program that returns, in order, the first N regular numbers.
I definitely did not get this one on my first go. After a few cracks I came up with this passable solution in swift. I didn’t think about a heap- so I guess I kind of suck? After a bit of Googling (ironic) I was there.
func generateRegularNumbers(_ n: Int) -> [Int] { let factors = [2, 3, 5] var result: [Int] = [] var heap = Set<Int>() var minHeap = Heap<Int>(sort: <) minHeap.insert(1) heap.insert(1) while result.count < n { let smallest = minHeap.remove()! result.append(smallest) for factor in factors { let next = smallest * factor if !heap.contains(next) { heap.insert(next) minHeap.insert(next) } } } return result }
// Harken back to College Days Heap Implementation struct Heap<T> { var elements: [T] = [] let sort: (T, T) -> Bool init(sort: @escaping (T, T) -> Bool) { self.sort = sort } var isEmpty: Bool { elements.isEmpty } // Teenage Mutating Ninja Swift Funcs mutating func insert(_ value: T) { elements.append(value) siftUp(from: elements.count - 1) } // Teenage Mutating Ninja Swift Funcs mutating func remove() -> T? { guard !elements.isEmpty else { return nil } elements.swapAt(0, elements.count - 1) let value = elements.removeLast() siftDown(from: 0) return value } // Recluse Teenage Mutating Ninja Swift Funcs private mutating func siftUp(from index: Int) { var child = index var parent = (child - 1) / 2 while child > 0 && sort(elements[child], elements[parent]) { elements.swapAt(child, parent) child = parent parent = (child - 1) / 2 } } private mutating func siftDown(from index: Int) { var parent = index while true { let left = 2 * parent + 1 let right = 2 * parent + 2 var candidate = parent if left < elements.count && sort(elements[left], elements[candidate]) { candidate = left } if right < elements.count && sort(elements[right], elements[candidate]) { candidate = right } if candidate == parent { return } elements.swapAt(parent, candidate) parent = candidate } } }
// Example Usage: print(generateRegularNumbers(15))