-
Notifications
You must be signed in to change notification settings - Fork 95
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add solutions to Chapter 16 Moderate
- Loading branch information
1 parent
943d639
commit 0dbf24e
Showing
11 changed files
with
875 additions
and
0 deletions.
There are no files selected for viewing
21 changes: 21 additions & 0 deletions
21
...Chapter 16. Moderate.playground/Pages/16.1 Number Swapper.xcplaygroundpage/Contents.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import Foundation | ||
|
||
/*: | ||
16.1 Swap a number without using a temp variable | ||
*/ | ||
extension BinaryInteger { | ||
|
||
mutating func swap(x: inout Self) { | ||
self += x | ||
x = self - x | ||
self = self - x | ||
} | ||
} | ||
|
||
let y = 1 | ||
var ycopy = y | ||
let x = -1 | ||
var xcopy = x | ||
|
||
ycopy.swap(x: &xcopy) | ||
assert(ycopy == x && xcopy == y) |
36 changes: 36 additions & 0 deletions
36
...te/Chapter 16. Moderate.playground/Pages/16.20 T9 Problem.xcplaygroundpage/Contents.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import Foundation | ||
|
||
/*: | ||
16.20 On old cell phones, users typed on a numeric keypad and the phone would provide a list of words that matched these numbers. Each digit mapped to a set of 0—4 letters. Implement an algorithm to return a list of matching words, given a sequence of digits. You are provided a list of valid words (provided in whatever data strucutre you'd like). | ||
*/ | ||
|
||
let path = "/usr/share/dict/words" | ||
let url = URL(fileURLWithPath: path, isDirectory: false) | ||
let dictString = try! String(contentsOf: url, encoding: .utf8) | ||
let words = dictString.components(separatedBy: "\n").compactMap { word -> String? in | ||
let nonLetter = word.rangeOfCharacter(from: CharacterSet.letters.inverted) != nil | ||
return nonLetter ? nil : word.lowercased() | ||
} | ||
|
||
let digitsToChars: [Character: String] = ["2": "abc", "3": "def", "4": "ghi", "5": "jkl", "6": "mno", "7": "pqrs", "8": "tuv", "9": "wxyz"] | ||
|
||
let charToDigit: [Character: Character] = { | ||
digitsToChars.reduce(into: [Character: Character]()) { map, digitChars in | ||
for char in digitChars.value { | ||
map[char] = digitChars.key | ||
} | ||
} | ||
}() | ||
|
||
func digits(from: String) -> String { | ||
return from.reduce(into: "") { digits, chars in | ||
if let char = charToDigit[chars] { | ||
digits.append(char) | ||
} | ||
} | ||
} | ||
|
||
let digitsToWords = Dictionary(grouping: words, by: digits) | ||
|
||
let swift = digitsToWords["79438"]?[0] | ||
assert(swift == "swift", "\(String(describing: swift))") |
29 changes: 29 additions & 0 deletions
29
...hapter 16. Moderate.playground/Pages/16.5 Factorial Zeros.xcplaygroundpage/Contents.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import Foundation | ||
|
||
/*: | ||
16.5 Count the number of trailing zeros in n factorial | ||
*/ | ||
|
||
extension Int { | ||
|
||
func zerosInFactorial() -> Int { | ||
guard self > 0 else { return 0 } | ||
let range = (1...self) | ||
return range.reduce(0) { | ||
$1 % 5 == 0 ? $0 + 1 : $0 | ||
} | ||
} | ||
|
||
func factorial() -> Int { | ||
guard self > 0 else { return 1 } | ||
let range = (1...self) | ||
return range.reduce(1, *) | ||
} | ||
} | ||
|
||
for i in 1...20 { | ||
let s = String(i.factorial()) | ||
let trailingZerosString = s.reversed().prefix(while: { $0 == "0" }) | ||
let zerosInFactorial = i.zerosInFactorial() | ||
assert(zerosInFactorial == trailingZerosString.count, "\(i) \(zerosInFactorial) \(trailingZerosString)") | ||
} |
39 changes: 39 additions & 0 deletions
39
...er 16. Moderate.playground/Pages/16.6 Samllest Difference.xcplaygroundpage/Contents.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import Foundation | ||
|
||
/*: | ||
16.6 Return the difference between the two smallest numbers in a and b | ||
*/ | ||
extension Collection where Iterator.Element: FixedWidthInteger & SignedNumeric { | ||
|
||
func minDifference<C: Collection>(c: C) -> Iterator.Element? where C.Iterator.Element == Iterator.Element { | ||
guard !isEmpty && !c.isEmpty else { return nil } | ||
|
||
let leftC = sorted() | ||
let rightC = c.sorted(by: <) | ||
var minDiff = abs(leftC[0] - rightC[0]) | ||
var i = leftC.startIndex | ||
var k = rightC.startIndex | ||
|
||
while i != leftC.endIndex && k != rightC.endIndex { | ||
let left = leftC[i] | ||
let right = rightC[k] | ||
let absVal = abs(left - right) | ||
if absVal < minDiff { | ||
minDiff = absVal | ||
} | ||
if left <= right { | ||
i += 1 | ||
} | ||
else { | ||
k += 1 | ||
} | ||
} | ||
return minDiff | ||
} | ||
} | ||
|
||
var a = [1,3,15,11,2] | ||
var b = [23,127,235,19,8] | ||
|
||
let result = a.minDifference(c: b) | ||
assert(result ?? 0 == 3) |
61 changes: 61 additions & 0 deletions
61
...ate/Chapter 16. Moderate.playground/Pages/16.9 Operations.xcplaygroundpage/Contents.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import Foundation | ||
|
||
/*: | ||
16.9 Implement subtract, multiply, and divide using only + | ||
*/ | ||
extension FixedWidthInteger where Stride: SignedInteger { | ||
|
||
func restrictedDivide(x: Self) -> Self { | ||
var _self = self.absv | ||
let absX = x.absv | ||
let diff = absX.negate() | ||
var quotient: Self = 0 | ||
|
||
while _self >= absX { | ||
_self += diff | ||
quotient = quotient.advanced(by: 1) | ||
} | ||
let sameSign = (self < 0 && x < 0) || (self > 0 && x > 0) | ||
return sameSign ? quotient : quotient.negate() | ||
} | ||
|
||
func restrictedMultiply(x: Self) -> Self { | ||
let absX: Self = x.absv | ||
var _self: Self = 0 | ||
for _ in 0..<absX { | ||
_self += self | ||
} | ||
return x < 0 ? _self.negate() : _self | ||
} | ||
|
||
func restrictedSubtract(x: Self) -> Self { | ||
return self + x.negate() | ||
} | ||
|
||
func negate() -> Self { | ||
let diff: Self = self > 0 ? -1 : 1 | ||
var _self = self | ||
var result: Self = 0 | ||
while _self != 0 { | ||
_self += diff | ||
result += diff | ||
} | ||
return result | ||
} | ||
|
||
func restrictedSubtract2(x: Self) -> Self { | ||
return self + ~x + 1 | ||
} | ||
} | ||
|
||
var a = 35 | ||
var b = 7 | ||
|
||
for x in a...2 * a { | ||
assert(x.restrictedDivide(x: b) == x / b) | ||
assert(x.restrictedMultiply(x: b) == x * b) | ||
assert(x.restrictedSubtract(x: b) == x - b) | ||
} | ||
|
||
|
||
|
165 changes: 165 additions & 0 deletions
165
Ch 16. Moderate/Chapter 16. Moderate.playground/Sources/ArraySearching.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
// | ||
// ArraySearching.swift | ||
// | ||
// | ||
// Created by Matthew Carroll on 10/13/16. | ||
// Copyright © 2016 Third Cup lc. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
|
||
//: Similar to EnumerateGenerator, but returns the index of the element instead of a counter for the enumeration | ||
public extension Collection { | ||
|
||
func indicesElements() -> Zip2Sequence<Indices, Self> { | ||
return zip(indices, self) | ||
} | ||
} | ||
|
||
extension Zip2Sequence.Iterator: Sequence { | ||
|
||
public func makeIterator() -> Zip2Sequence.Iterator { | ||
return self | ||
} | ||
} | ||
|
||
public extension Collection { | ||
|
||
func indexElementPairs() -> Zip2Sequence<Zip2Sequence<Indices, Self>.Iterator, Zip2Sequence<Indices, Self>.Iterator> { | ||
let left = zip(indices, self).makeIterator() | ||
var right = left | ||
let _ = right.next() | ||
return zip(left, right) | ||
} | ||
|
||
func successiveElements() -> Zip2Sequence<Self, Self.SubSequence> { | ||
return zip(self, self.dropFirst()) | ||
} | ||
} | ||
|
||
public struct ElementPairsIterator<T: Sequence>: IteratorProtocol, Sequence { | ||
|
||
var iterator: T.Iterator | ||
|
||
init(sequence: T) { | ||
iterator = sequence.makeIterator() | ||
} | ||
|
||
mutating public func next() -> (T.Element, T.Element)? { | ||
guard let left = iterator.next(), let right = iterator.next() else { return nil } | ||
return (left, right) | ||
} | ||
|
||
public func makeIterator() -> ElementPairsIterator<T> { | ||
return self | ||
} | ||
} | ||
|
||
|
||
public extension Sequence { | ||
|
||
func elementPairs() -> ElementPairsIterator<Self> { | ||
return ElementPairsIterator(sequence: self) | ||
} | ||
} | ||
|
||
public extension Collection { | ||
|
||
typealias IndexElementPair = (leftIndex: Index, leftElement: Iterator.Element, rightIndex: Index, rightElement: Iterator.Element) | ||
|
||
func successiveElements(where predicate: (_ previousElement: Iterator.Element, _ element: Iterator.Element) -> Bool) -> IndexElementPair? { | ||
for (left, right) in indexElementPairs() { | ||
guard predicate(left.1, right.1) else { continue } | ||
return (left.0, left.1, right.0, right.1) | ||
} | ||
return nil | ||
} | ||
|
||
func elementPair(where predicate: (_ previousElement: Element, _ element: Element) -> Bool) -> (Element, Element)? { | ||
return elementPairs().first(where: predicate) | ||
} | ||
|
||
func elementPair2(where predicate: (_ previousElement: Element, _ element: Element) -> Bool) -> (Element, Element)? { | ||
guard !isEmpty else { return nil } | ||
var i = startIndex | ||
var k = index(after: i) | ||
while k < endIndex { | ||
let left = self[i] | ||
let right = self[k] | ||
guard predicate(left, right) else { | ||
i = k | ||
k = index(after: k) | ||
continue | ||
} | ||
return(left, right) | ||
} | ||
return nil | ||
} | ||
} | ||
|
||
public extension Collection { | ||
|
||
func unsortedRange(isUnordered: (_ left: Iterator.Element, _ right: Iterator.Element) -> Bool) -> ClosedRange<Index>? { | ||
guard let unsortedStart = successiveElements(where: isUnordered) else { return nil } | ||
|
||
var unsortedEnd = unsortedStart.leftIndex | ||
var unsortedMax = unsortedStart.leftElement | ||
let d = distance(from: startIndex, to: unsortedStart.rightIndex) | ||
|
||
for (i, x) in indicesElements().dropFirst(numericCast(d)) { | ||
if isUnordered(unsortedMax, x) { | ||
unsortedEnd = i | ||
} | ||
else { | ||
unsortedMax = x | ||
} | ||
} | ||
return unsortedStart.leftIndex...unsortedEnd | ||
} | ||
} | ||
|
||
public extension Collection { | ||
|
||
func groupBy<Key>(f: (Iterator.Element) -> Key) -> [Key: [Iterator.Element]] { | ||
var groups: [Key: [Iterator.Element]] = [:] | ||
for x in self { | ||
let key = f(x) | ||
var array = groups[key] ?? [] | ||
array.append(x) | ||
groups[key] = array | ||
} | ||
return groups | ||
} | ||
} | ||
|
||
public extension Collection where Iterator.Element: Comparable, SubSequence: Collection { | ||
|
||
func maxElementIndex() -> Index? { | ||
guard !self.isEmpty else { return nil } | ||
var prev = self[startIndex] | ||
var maxI = startIndex | ||
for (i, x) in dropFirst().indicesElements() { | ||
if x > prev { | ||
prev = x | ||
maxI = i | ||
} | ||
} | ||
return maxI | ||
} | ||
} | ||
|
||
public extension Collection where Iterator.Element: Comparable, SubSequence: Collection { | ||
|
||
func minElementIndex() -> Index? { | ||
guard !self.isEmpty else { return nil } | ||
var prev = self[startIndex] | ||
var minI = startIndex | ||
for (i, x) in dropFirst().indicesElements() { | ||
if x < prev { | ||
prev = x | ||
minI = i | ||
} | ||
} | ||
return minI | ||
} | ||
} |
Oops, something went wrong.