Stridable Protocol - swift

I am trying to convert the following Swift 2.3 code:
//Example usage:
//(0 ..< 778).binarySearch { $0 < 145 } // 145
extension CollectionType where Index: RandomAccessIndexType {
/// Finds such index N that predicate is true for all elements up to
/// but not including the index N, and is false for all elements
/// starting with index N.
/// Behavior is undefined if there is no such N.
func binarySearch(predicate: Generator.Element -> Bool)
-> Index {
var low = startIndex
var high = endIndex
while low != high {
let mid = low.advancedBy(low.distanceTo(high) / 2)
if predicate(self[mid]) {
low = mid.advancedBy(1)
} else {
high = mid
}
}
return low
}
}
into Swift 3 as follows:
//Example usage:
//(0 ..< 778).binarySearch { $0 < 145 } // 145
extension Collection where Index: Strideable {
/// Finds such index N that predicate is true for all elements up to
/// but not including the index N, and is false for all elements
/// starting with index N.
/// Behavior is undefined if there is no such N.
func binarySearch(predicate: (Generator.Element) -> Bool)
-> Index {
var low = startIndex
var high = endIndex
while low != high {
let mid = low.advanced(by: low.distance(to: high) / 2)
if predicate(self[mid]) {
low = mid.advanced(to: 1)
} else {
high = mid
}
}
return low
}
}
The error
Binary operator '/' cannot be applied to operands of type 'self.Index.Stride' and 'Int'
is thrown at let mid = low.advanced(by: low.distance(to: high) / 2)
Any help on how to fix it?

In Swift 3, "Collections move their index", compare
A New Model for Collections and Indices on Swift evolution. In particular, you don't call advancedBy() on an index,
but an index() method on the collection to advance indices.
So your method would be implemented in Swift 3 as
extension RandomAccessCollection {
func binarySearch(predicate: (Iterator.Element) -> Bool) -> Index {
var low = startIndex
var high = endIndex
while low != high {
let mid = index(low, offsetBy: distance(from: low, to: high)/2)
if predicate(self[mid]) {
low = index(after: mid)
} else {
high = mid
}
}
return low
}
}
The same method would also compile (and work) as an extension of the
more general Collection type, but – as Vadim Yelagin correctly remarked,
is very inefficient if the index/offset calculations cannot be done in
constant time.

Related

Finding indices of array elements that add up to a target number. What would be a way to optimize my solution?

I'm practicing this problem
Given an array of integers nums and an integer target, return indices
of the two numbers such that they add up to target.
You may assume that each input would have exactly one solution, and
you may not use the same element twice.
You can return the answer in any order.
and came up with
class Solution {
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
var indices = [Int]()
for (firstIndex, firstNum) in nums.enumerated() {
for (secondIndex, secondNum) in nums.enumerated() {
if firstNum + secondNum == target && firstIndex != secondIndex {
indices = [firstIndex, secondIndex]
}
}
}
return indices
}
}
However, it has quadratic time complexity because of the nested for-in loops. What would be a good way to optimize this to run in linear time?
Here's an idea that results in a O(n) time ans space solution.
Have a hashtable that maps elements to their indices.
As you iterate through the input array check whether target - element is in the hashtable already. If so, return the indices of the current element and target - element in the hashtable.
If not, add current element as key and its index as value to the hashtable.
Using #user1984 comment your solution should look like this:
class Solution {
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
var indices = [Int]()
var dictionary: [Int: Int] = [:]
for (index, num) in nums.enumerated()
{
let diff = target - num
if let index2 = dictionary[diff] {
return [index2, index]
}
else {
dictionary[num] = index
}
}
return []
}
}
There are several approaches (depending on your requirements and time/space constraints)
final class Solution {
// Time Complexity: O(n * (n - 1) / 2) = O(n^2)
// Auxiliary Space: O(1)
func twoSum1(_ nums: [Int], _ target: Int) -> [Int] {
for firstIndex in nums.indices {
for secondIndex in (firstIndex + 1)..<nums.count {
if nums[firstIndex] + nums[secondIndex] == target {
return [firstIndex, secondIndex]
}
}
}
return []
}
// Time Complexity: O(n log n).
// Auxiliary Space: O(n). Can be O(1) if do in-place sort
func twoSum2(_ nums: [Int], _ target: Int) -> [Int] {
let sorted = nums.sorted()
var left = 0
var right = nums.count - 1
while left < right {
if sorted[left] + sorted[right] == target {
return [left, right]
} else if sorted[left] + sorted[right] < target {
left += 1
} else {
right -= 1
}
}
return []
}
// Time Complexity: O(n). (Amortized)
// Auxiliary Space: O(n).
func twoSum3(_ nums: [Int], _ target: Int) -> [Int] {
var differences = [Int: Int]()
for (index, element) in nums.enumerated() {
let difference = target - element
if let dIndex = differences[difference] {
return [index, dIndex]
}
differences[element] = index
}
return []
}
static func test() {
// Given
let nums = [1, 5, 4, 3, 7, 9, -3]
let target = 7
let solution = Solution()
let expectedResult = [2, 3]
// When
let result1 = solution.twoSum1(nums, target)
let result2 = solution.twoSum2(nums, target)
let result3 = solution.twoSum3(nums, target)
// Then
assert(Set(result1) == Set(expectedResult))
assert(Set(result2) == Set(expectedResult))
assert(Set(result3) == Set(expectedResult))
}
}

Prime factorization with return being a string

I am trying to solve the following coding challenge:
Given a positive number n > 1 find the prime factor decomposition of n. The result will be a string with the following form:
"(p1xxn1)(p2xxn2)...(pkxxnk)"
with the p(i) in increasing order and n(i) empty if n(i) is 1.
Example: n = 86240 should return "(2xx5)(5)(7xx2)(11)"
I believe I have figured out how to find the prime factors of a number... my problem is that I have no idea how to convert them into the form required by the question (i.e., a string where p(i) is in increasing order). I tried to convert an integer array containing the prime factors into some sort of array of tuples containing factors p and n, but I have been struggling fruitlessly for several hours.
Here is what I have so far:
func factors(_ number: Int) -> String {
var changedNumber = number
var numberArr = [Int]()
while changedNumber >= 2 {
for i in 2...changedNumber {
if changedNumber % i == 0 {
numberArr.append(i)
changedNumber /= i
break
}
}
}
}
Any insight or resources would be greatly appreciated.
func factors(_ number: Int) -> String
I think it’s a mistake to make this return the String directly. It violates the separation of responsibilities, and makes this hard to reuse.
Imagine elsewhere in a codebase that uses this function, there might be a function which tries to parse the string result of this back into an array to use it in some other way. It may sound ridiculous, but a large number of the questions we get on here are about people trying to build systems to accept silly input from other systems that they should just change instead!
Here's what I would suggest:
func primeFactorization(of value: Int) -> (factor: Int, exponent: Int) {
...
}
func format(_ primeFactors: [(factor: Int, exponent: Int)]) -> String {
return primeFactors
.map { $0.exponent == 1 ? "(\($0.factor))" : "(\($0.factor)xx\($0.exponent))" }
.joined()
}
So you can then do:
let factorization = primeFactorization(of: 86240)
// Which results in: [
// (factor: 2, exponent: 5),
// (factor: 2, exponent: 1),
// (factor: 7, exponent: 2),
// (factor: 11, exponent: 1),
// ]
// Which you can then format as this one question wants:
format(factorization) // => "(2xx5)(5)(7xx2)(11)"
For extra points, you could generify the first function into an extension on BinaryInteger, which would let you be able to write something like 86240.primeFactorization().
Just make your function group the numbers and then use each sub collection count when creating your string:
func factors(_ number: Int) -> String {
var changedNumber = number
var numberArr: [[Int]] = []
while changedNumber >= 2 {
for i in 2...changedNumber {
if changedNumber.isMultiple(of: i) {
if numberArr.last?.last == i {
numberArr[numberArr.count-1].append(i)
} else {
numberArr.append([i])
}
changedNumber /= i
break
}
}
}
return numberArr.reduce(into: "") {
if let last = $1.last {
if $1.count == 1 {
$0 += "(" + String(last) + ")"
} else {
$0 += "(" + String(last) + "xx\($1.count))"
}
}
}
}
print(factors(86240)) // (2xx5)(5)(7xx2)(11)
There's lots of ways to handle this. Here's one, off the top of my head:
Write an extension to Int that has the following functions
func isPrime() -> Bool
func nextPrime() -> Int.
First check to see if the input number n is prime. If it is, return the result as "(nxxx1)" and you're done.
Define a struct primeFactor:
struct PrimeFactor {
let value: Int
var count: Int
}
Create an array of PrimeFactors.
func primeFactorsString(of value: String) -> String {
var primeFactors = [PrimeFactor]()
var currentPrime = 1
var remainder = value
guard !value.isPrime() else { return "(\(value)xx1)" }
while remainder > 1 {
currentPrime = currentPrime.nextPrime()
if remainder % currentPrime == 0 {
let newPrimeFactor = PrimeFactor(value: currentPrime, count: 1)
remainder /= currentPrime
while remainder % currentPrime == 0 {
newPrimeFactor.count = newPrimeFactor.count + 1
remainder /= currentPrime
}
primeFactors.append(newPrimeFactor)
}
}
// Now loop through your array of primeFactors and build your output string.
return primeFactors.map { "(\($0.value)xx\($0.count))".joined()

Custom Index for Linked List in Swift

Custom Index Type for Linked List
Swift 5.0, Xcode 10.3
I recently implemented a doubly linked list type in Swift. When I set out to make it, my goal was to give users most of the same ease of use as using an Array, but with the algorithmic complexities associated with doubly linked lists. With this goal in mind, I decided one of the primary ways I would achieve this would be making the Node type an implementation detail; out of sight and out of mind for the user. I also decided that LinkedList must be implemented as a struct so to provide support proper immutability/mutability.
Deciding on the semantics for the LinkedList type and its private Node type was quite tricky though. This was mainly due to LinkedList being a struct and Node being a class. Because of this, whenever a copy of a LinkedList value was made, mutating the copied linked list would also mutate the initial variable. For example, under the described circumstances, this would occur:
let list1 = LinkedList([1, 2, 3])
var list2 = list1
list2.append(4) // Mutates both list1 and list2
print(list1)
// Prints "[1, 2, 3, 4]"
This was, for obvious reasons, unintended and required me to put thought into the behaviour and semantics associated with making a copy of a LinkedList and mutation thereof. To combat this, in the only two mutating defined on LinkedList that were made accessible to the user, I checked whether or not the head node of the list was known to be uniquely referenced or not. If it was, the mutation would go under way as normal. But if it wasn't, a function would create a copy of all the nodes in list before mutating them. This would prevent mutating operations on an instance of LinkedList from affecting any other instance. This check before mutation effectively implemented copy-on-write semantics for LinkedList's nodes. With this, the previous example perform as expected:
let list1 = LinkedList([1, 2, 3])
var list2 = list1
list2.append(4) // Nodes are copied
print(list1)
// Prints "[1, 2, 3]"
print(list2)
// Prints "[1, 2, 3, 4]"
This seemed to provide a fix to the problem of shared references to nodes and their mutation therein quite nicely. Unfortunately, to my chagrin, I then realized that I had not tied up all of my loose ends. This is where I am currently stuck. To this point in time, my custom index type, LinkedList.Index, has been defined as following:
extension LinkedList: Collection {
//...
public struct Index: Comparable {
fileprivate weak var node: Node?
fileprivate var offset: Int
fileprivate init(node: Node?, offset: Int) {
self.node = node
self.offset = offset
}
public static func ==(lhs: Index, rhs: Index) -> Bool {
return lhs.offset == rhs.offset
}
public static func <(lhs: Index, rhs: Index) -> Bool {
return lhs.offset < rhs.offset
}
}
}
Let me break down some of the decisions I made while constructing this... Firstly, the offset property was put in to allow for comparison with other indices and to provide the ability to check if an index was within the bounds of a list. Secondly, the node property was essential to giving each Index actual meaning and usefulness. This meant that both index(after:) and index(before:) could rely on the node property's next and previous properties to provide their respective desired indices in O(1) time. To me, this in it of itself is seems to be a requirement for an index type of a linked list implementation. Presently, I do not think there is any way to circumvent this requirement of associating each index with its respective node. In testing, I also came across a bug wherein the list's node were being copied too frequently and also not being deallocated by ARC. I realized this was because of a strong reference being held to nodes by Index. To combat that, I made node a weak reference.
Before I state the problem I am having, here is my current code for LinkedList:
public struct LinkedList<Element> {
private var headNode: Node?
private var tailNode: Node?
public private(set) var count: Int = 0
public init() { }
}
//MARK: - LinkedList Node
extension LinkedList {
fileprivate class Node {
public var value: Element
public var next: Node?
public weak var previous: Node?
public init(value: Element) {
self.value = value
}
}
}
//MARK: - Initializers
public extension LinkedList {
private init(_ nodeChain: NodeChain?) {
guard let chain = nodeChain else {
return
}
headNode = chain.head
tailNode = chain.tail
count = chain.count
}
init<S>(_ sequence: S) where S: Sequence, S.Element == Element {
if let linkedList = sequence as? LinkedList<Element> {
self = linkedList
} else {
self = LinkedList(NodeChain(of: sequence))
}
}
}
//MARK: NodeChain
extension LinkedList {
private struct NodeChain {
let head: Node!
let tail: Node!
private(set) var count: Int
// Creates a chain of nodes from a sequence. Returns `nil` if the sequence is empty.
init?<S>(of sequence: S) where S: Sequence, S.Element == Element {
var iterator = sequence.makeIterator()
guard let firstValue = iterator.next() else {
return nil
}
var currentNode = Node(value: firstValue)
head = currentNode
count = 1
while let nextElement = iterator.next() {
let nextNode = Node(value: nextElement)
currentNode.next = nextNode
nextNode.previous = currentNode
currentNode = nextNode
count += 1
}
tail = currentNode
}
}
}
//MARK: - Copy Nodes
extension LinkedList {
private mutating func copyNodes(settingNodeAt index: Index, to value: Element) {
var currentIndex = startIndex
var currentNode = Node(value: currentIndex == index ? value : currentIndex.node!.value)
let newHeadNode = currentNode
currentIndex = self.index(after: currentIndex)
while currentIndex < endIndex {
let nextNode = Node(value: currentIndex == index ? value : currentIndex.node!.value)
currentNode.next = nextNode
nextNode.previous = currentNode
currentNode = nextNode
currentIndex = self.index(after: currentIndex)
}
headNode = newHeadNode
tailNode = currentNode
}
#discardableResult
private mutating func copyNodes(removing range: Range<Index>) -> Range<Index> {
var currentIndex = startIndex
while range.contains(currentIndex) {
currentIndex = index(after: currentIndex)
}
guard let headValue = currentIndex.node?.value else {
self = LinkedList()
return endIndex..<endIndex
}
var currentNode = Node(value: headValue)
let newHeadNode = currentNode
var newCount = 1
var removedRange: Range<Index> = Index(node: currentNode, offset: 0)..<Index(node: currentNode, offset: 0)
currentIndex = index(after: currentIndex)
while currentIndex < endIndex {
guard !range.contains(currentIndex) else {
currentIndex = index(after: currentIndex)
continue
}
let nextNode = Node(value: currentIndex.node!.value)
if currentIndex == range.upperBound {
removedRange = Index(node: nextNode, offset: newCount)..<Index(node: nextNode, offset: newCount)
}
currentNode.next = nextNode
nextNode.previous = currentNode
currentNode = nextNode
newCount += 1
currentIndex = index(after: currentIndex)
}
if currentIndex == range.upperBound {
removedRange = Index(node: nil, offset: newCount)..<Index(node: nil, offset: newCount)
}
headNode = newHeadNode
tailNode = currentNode
count = newCount
return removedRange
}
}
//MARK: - Computed Properties
public extension LinkedList {
var head: Element? {
return headNode?.value
}
var tail: Element? {
return tailNode?.value
}
}
//MARK: - Sequence Conformance
extension LinkedList: Sequence {
public typealias Element = Element
public __consuming func makeIterator() -> Iterator {
return Iterator(node: headNode)
}
public struct Iterator: IteratorProtocol {
private var currentNode: Node?
fileprivate init(node: Node?) {
currentNode = node
}
public mutating func next() -> Element? {
guard let node = currentNode else {
return nil
}
currentNode = node.next
return node.value
}
}
}
//MARK: - Collection Conformance
extension LinkedList: Collection {
public var startIndex: Index {
return Index(node: headNode, offset: 0)
}
public var endIndex: Index {
return Index(node: nil, offset: count)
}
public var first: Element? {
return head
}
public var isEmpty: Bool {
return count == 0
}
public func index(after i: Index) -> Index {
precondition(i.offset != endIndex.offset, "LinkedList index is out of bounds")
return Index(node: i.node?.next, offset: i.offset + 1)
}
public struct Index: Comparable {
fileprivate weak var node: Node?
fileprivate var offset: Int
fileprivate init(node: Node?, offset: Int) {
self.node = node
self.offset = offset
}
public static func ==(lhs: Index, rhs: Index) -> Bool {
return lhs.offset == rhs.offset
}
public static func <(lhs: Index, rhs: Index) -> Bool {
return lhs.offset < rhs.offset
}
}
}
//MARK: - MutableCollection Conformance
extension LinkedList: MutableCollection {
public subscript(position: Index) -> Element {
get {
precondition(position.offset != endIndex.offset, "Index out of range")
guard let node = position.node else {
preconditionFailure("LinkedList index is invalid")
}
return node.value
}
set {
precondition(position.offset != endIndex.offset, "Index out of range")
// Copy-on-write semantics for nodes
if !isKnownUniquelyReferenced(&headNode) {
copyNodes(settingNodeAt: position, to: newValue)
} else {
position.node?.value = newValue
}
}
}
}
//MARK: LinkedList Specific Operations
public extension LinkedList {
mutating func prepend(_ newElement: Element) {
replaceSubrange(startIndex..<startIndex, with: CollectionOfOne(newElement))
}
mutating func prepend<S>(contentsOf newElements: __owned S) where S: Sequence, S.Element == Element {
replaceSubrange(startIndex..<startIndex, with: newElements)
}
#discardableResult
mutating func popFirst() -> Element? {
if isEmpty {
return nil
}
return removeFirst()
}
#discardableResult
mutating func popLast() -> Element? {
guard isEmpty else {
return nil
}
return removeLast()
}
}
//MARK: - BidirectionalCollection Conformance
extension LinkedList: BidirectionalCollection {
public var last: Element? {
return tail
}
public func index(before i: Index) -> Index {
precondition(i.offset != startIndex.offset, "LinkedList index is out of bounds")
if i.offset == count {
return Index(node: tailNode, offset: i.offset - 1)
}
return Index(node: i.node?.previous, offset: i.offset - 1)
}
}
//MARK: - RangeReplaceableCollection Conformance
extension LinkedList: RangeReplaceableCollection {
public mutating func append<S>(contentsOf newElements: __owned S) where S: Sequence, Element == S.Element {
replaceSubrange(endIndex..<endIndex, with: newElements)
}
public mutating func replaceSubrange<S, R>(_ subrange: R, with newElements: __owned S) where S: Sequence, R: RangeExpression, Element == S.Element, Index == R.Bound {
var range = subrange.relative(to: indices)
precondition(range.lowerBound >= startIndex && range.upperBound <= endIndex, "Subrange bounds are out of range")
// If range covers all elements and the new elements are a LinkedList then set references to it
if range.lowerBound == startIndex, range.upperBound == endIndex, let linkedList = newElements as? LinkedList {
self = linkedList
return
}
var newElementsCount = 0
// There are no new elements, so range indicates deletion
guard let nodeChain = NodeChain(of: newElements) else {
// If there is nothing in the removal range
// This also covers the case that the linked list is empty because this is the only possible range
guard range.lowerBound != range.upperBound else {
return
}
// Deletion range spans all elements
if range.lowerBound == startIndex && range.upperBound == endIndex {
headNode = nil
tailNode = nil
count = 0
return
}
// Copy-on-write semantics for nodes and remove elements in range
guard isKnownUniquelyReferenced(&headNode) else {
copyNodes(removing: range)
return
}
// Update count after mutation to preserve startIndex and endIndex validity
defer {
count = count - (range.upperBound.offset - range.lowerBound.offset)
}
// Move head up if deletion starts at start index
if range.lowerBound == startIndex {
// Can force unwrap node since the upperBound is not the end index
headNode = range.upperBound.node!
headNode!.previous = nil
// Move tail back if deletion ends at end index
} else if range.upperBound == endIndex {
// Can force unwrap since lowerBound index must have an associated element
tailNode = range.lowerBound.node!.previous
tailNode!.next = nil
// Deletion range is in the middle of the linked list
} else {
// Can force unwrap all bound nodes since they both must have elements
range.upperBound.node!.previous = range.lowerBound.node!.previous
range.lowerBound.node!.previous!.next = range.upperBound.node!
}
return
}
// Obtain the count of the new elements from the node chain composed from them
newElementsCount = nodeChain.count
// Replace entire content of list with new elements
if range.lowerBound == startIndex && range.upperBound == endIndex {
headNode = nodeChain.head
tailNode = nodeChain.tail
count = nodeChain.count
return
}
// Copy-on-write semantics for nodes before mutation
if !isKnownUniquelyReferenced(&headNode) {
range = copyNodes(removing: range)
}
// Update count after mutation to preserve startIndex and endIndex validity
defer {
count += nodeChain.count - (range.upperBound.offset - range.lowerBound.offset)
}
// Prepending new elements
guard range.upperBound != startIndex else {
headNode?.previous = nodeChain.tail
nodeChain.tail.next = headNode
headNode = nodeChain.head
return
}
// Appending new elements
guard range.lowerBound != endIndex else {
tailNode?.next = nodeChain.head
nodeChain.head.previous = tailNode
tailNode = nodeChain.tail
return
}
if range.lowerBound == startIndex {
headNode = nodeChain.head
}
if range.upperBound == endIndex {
tailNode = nodeChain.tail
}
range.lowerBound.node!.previous!.next = nodeChain.head
range.upperBound.node!.previous = nodeChain.tail
}
}
//MARK: - ExpressibleByArrayLiteral Conformance
extension LinkedList: ExpressibleByArrayLiteral {
public typealias ArrayLiteralElement = Element
public init(arrayLiteral elements: ArrayLiteralElement...) {
self.init(elements)
}
}
//MARK: - CustomStringConvertible Conformance
extension LinkedList: CustomStringConvertible {
public var description: String {
return "[" + lazy.map { "\($0)" }.joined(separator: ", ") + "]"
}
}
Note: if/when I do update my code, the up-to-date version can be found here.
My Problem
The current problem I am experiencing is with Index instances. When an index is provided either to a method, as is the case currently, the method has no way of knowing and checking whether or not that index/node belongs to that specific LinkedList instance. That allows for bugs such as this:
let immutableList: LinkedList = [1, 2, 3, 4]
var mutableList: LinkedList = [5, 6, 7, 8]
let immutableIndex = immutableList.index(after: immutableList.startIndex)
mutableList[immutableIndex] = 0
print("Immutable List:", immutableList)
print("Mutable List:", mutableList)
// Prints:
// Immutable List: [1, 0, 3, 4]
// Mutable List: [5, 6, 7, 8]
All methods that deal with Index must have a way to confirm that the index they are dealing with contains a node owned by the current LinkedList instance, though I have no idea how I would be able to do this.
Furthermore, indices' offset invalidate after mutation to their node's parent list, thus causing absurd situations like this wherein the indices are said to be equal:
var list: LinkedList = [1, 2, 3, 4]
let idx1 = list.index(list.startIndex, offsetBy: 2) // Index to node with value of 3 and offset of 2
list.remove(at: list.index(before: idx1))
print(list)
// Prints: "[1, 3, 4]"
let idx2 = list.index(before: list.endIndex) // Index to node with value of 4 and offset of 2
print(idx1 == idx2)
// Prints: "true"
print(Array(list[idx1...idx2]))
// Prints: "[3]"
In the previous example, because, upon mutation of a LinkedList, instances of its indices' offsets are not updated, though they still have a weak reference to their associated node, many unintended consequences and incorrect behaviour can arise.
When creating the Index type initially, I was hard pressed to find similar examples to mine online and as a result I am not totally sure whether things like startIndex and endIndex and how index(before:) and index(after:) handle them are the optimal/proper way. I am looking for input on how I can go about fixing all of these problems brought on by LinkedList.Index and properly implement it. Any and all input is appreciated!
Let's address the second problem first:
Furthermore, indices' offset invalidate after mutation to their node's parent list, thus causing absurd situations ...
That is to be expected with all collections. From Collections:
Saved indices may become invalid as a result of mutating operations.
Using an invalidated index is undefined behavior, and anything can happen: An unexpected result, a fatal error, ... Here is a simple example for Swift strings:
var s = "a🇩🇪bcd"
let i = s.firstIndex(of: "🇩🇪")!
s.remove(at: s.startIndex) // invalidates `i`
s.remove(at: i)
print(s) // \360cd
Now the first (main?) problem:
... the method has no way of knowing and checking whether or not that index/node belongs to that specific LinkedList instance.
Quoting from Collections again:
You can pass only valid indices to collection operations. You can find a complete set of a collection’s valid indices by starting with the collection’s startIndex property and finding every successor up to, and including, the endIndex property. All other values of the Index type, such as the startIndex property of a different collection, are invalid indices for this collection.
In your case
mutableList[immutableIndex] = 0
immutableIndex is not a valid index for mutableList, so this is again undefined behavior. A user of your library can not expect that this does anything sensible.
A possible way to protect against this misuse could be to store in the LinkedList.Index a (weak) pointer to the head node of the linked list, and verify that owner in the accessor methods (subscripts).

Swift Extension and 'Element' explicit initialization

I wonder if is there any other way to explicitly initialize an Element object in a Swift extension ?
For example I would like to do this but non-nominal type 'Element' does not support explicit initialization
extension Array where Element: Numeric {
func findDuplicate() -> Int {
guard self.count > 0 else { return -1 }
let sum = self.reduce(0, +)
let expectedSum = Element((self.count - 1) * self.count / 2)
return sum - expectedSum
}
}
Of course if I remove the forced Element casting in the expectedSum assignment and let the compiler use an Int I obtain an error comparing sum (Element) and expectedSum (Int)
I can easily have my extension working with where Element == Int but of course this is no more generic in this way.
Any hints?
Conversion of an integer to a Numeric type is done with init?(exactly:). Taking Leo's suggestions into account:
extension Array where Element: Numeric {
func findDuplicate() -> Element? {
guard !isEmpty else { return nil }
let sum = self.reduce(0, +)
guard let expectedSum = Element(exactly: (count - 1) * count / 2) else { return nil }
return sum - expectedSum
}
}
On the other hand, this seems to be a programming task that
is specifically about integers, and then it might make more sense
to restrict the element type to BinaryInteger (and use Int
for the intermediate calculations to avoid overflow):
extension Array where Element: BinaryInteger {
func findDuplicate() -> Element? {
guard !isEmpty else { return nil }
let sum = Int(reduce(0, +))
let expectedSum = (count - 1) * count / 2
return Element(sum - expectedSum)
}
}
or even Element == Int.

Find digit sum of a number in Swift

Does anyone know how to get the sum of all the digits in a number in Swift?
For example using the number 845 would result in 17
update: Swift 5 or later We can use then new Character property wholeNumberValue:
let string = "845"
let sum = string.compactMap{$0.wholeNumberValue}.reduce(0, +)
print(sum) // 17
let integer = 845
let sumInt = String(integer).compactMap{$0.wholeNumberValue}.reduce(0, +)
print(sumInt) // 17
Here is a solution that uses simple integer arithmetic only:
func digitSum(var n : Int) -> Int {
var sum = 0
while n > 0 {
sum += n % 10 // Add least significant digit ...
n /= 10 // ... and remove it from the number.
}
return sum
}
println(digitSum(845)) // 17
Update for Swift 3/4:
func digitSum(_ n : Int) -> Int {
var n = n
var sum = 0
while n > 0 {
sum += n % 10 // Add least significant digit ...
n /= 10 // ... and remove it from the number.
}
return sum
}
print(digitSum(845)) // 17
Another implementation, just for fun:
func digitSum(_ n : Int) -> Int {
return sequence(state: n) { (n: inout Int) -> Int? in
defer { n /= 10 }
return n > 0 ? n % 10 : nil
}.reduce(0, +)
}
The recursive solution in Swift 3!
func digitSum(of number: Int) -> Int {
if(number < 10) {
return number
} else {
return (number % 10) + digitSum(of: (number/10))
}
}
For the sake of completeness, and for those who would like to see or understand a math-based approach, here's a real-number function based technique ported to Swift.
This is not the most efficient way to tally the digits of an integer in Swift. I don't recommend using it. I would personally use #LeoLDbus map/reduce answer to the question, because it is so cool and illustrates a powerful set of Swift features yet short, or #MartinR integer mod/divide answer, due to its utter simplicity and relative speed of integer arithmetic .
Cocoa and UIKit have the requisite math methods, so you'll probably need to import one of those packages.
func sumDigits(var i : Int) -> Int {
var sum = 0
var nDigits = floor(log10(Double(i))) + 1
for var r = nDigits; r > 0; r-- {
var p = pow(10, r - 1)
var d = floor(Double(i) / p)
sum += Int(d)
i -= Int(d * p)
}
return sum
}
for swift4, try below function:
func sumDigits(num: Int) -> Int {
return String(num).compactMap { Int(String($0)) }.reduce(0, +)
}
Split it into two pieces:
digits
public extension UnsignedInteger {
/// The digits that make up this number.
/// - Parameter radix: The base the result will use.
func digits(radix: Self = 10) -> [Self] {
sequence(state: self) { quotient in
guard quotient > 0
else { return nil }
let division = quotient.quotientAndRemainder(dividingBy: radix)
quotient = division.quotient
return division.remainder
}
.reversed()
}
}
XCTAssertEqual(
(867_5309 as UInt).digits(),
[8,6,7, 5,3,0,9]
)
XCTAssertEqual(
(0x00_F0 as UInt).digits(radix: 0b10),
[1,1,1,1, 0,0,0,0]
)
XCTAssertEqual(
(0xA0_B1_C2_D3_E4_F5 as UInt).digits(radix: 0x10),
[10,0, 11,1, 12,2, 13,3, 14,4, 15,5]
)
XCTAssertEqual(
(0o00707 as UInt).digits(radix: 0o10),
[0b111, 0, 0b111]
)
sum
public extension Sequence where Element: AdditiveArithmetic {
var sum: Element? { reduce(+) }
}
public extension Sequence {
/// The first element of the sequence.
/// - Note: `nil` if the sequence is empty.
var first: Element? {
var iterator = makeIterator()
return iterator.next()
}
/// - Returns: `nil` If the sequence has no elements, instead of an "initial result".
func reduce(
_ getNextPartialResult: (Element, Element) throws -> Element
) rethrows -> Element? {
guard let first = first
else { return nil }
return try dropFirst().reduce(first, getNextPartialResult)
}
}
XCTAssertEqual([1, 2, 3].sum, 6)
XCTAssertEqual([0.5, 1, 1.5].sum, 3)
XCTAssertNil([CGFloat]().sum)