what the difference of keys and values in dictionary of swift - swift

I'm trying the tutor of swift, and found the question.
I need to use optional values to keys and then unwrap it, however the values don't to be done so.But why?
Don't know why to use "kinds" rather than kind in the closure, but the one before that used number rather than numbers ,and how can I use numbers to get same result?
let interestingnumbers = [
"prime": [2,3,5,7,9,11,21],
"fibonacci": [1,23,5,32,4,123,11],
"dadgadfgh":[1,2,4,5,43,6,576,12],
"square": [1243325,123,455,1111],
]
var thekind:String?
var max=0
for (kinds,numbers) in interestingnumbers{
for kind in kinds{
for number in numbers{
if number>max {
max=number
thekind = kinds // I don't know why here should use "kinds" rather than kind, but the one before that used number rather than numbers ,and how can I use numbers to get same result?
}
}
}
}
print(max,thekind!)
//this is a fault code
let interestingnumbers = [
"prime": [2,3,5,7,9,11,21],
"fibonacci": [1,23,5,32,4,123,11],
"dadgadfgh":[1,2,4,5,43,6,576,12],
"square": [1243325,123,455,1111],
]
var thekind:String
var max=0
for (kinds,numbers) in interestingnumbers{
for kind in kinds{
for number in numbers{
if number>max {
max=number
thekind = kinds
}
}
}
}
print(max,thekind)
//and i tried this also
let interestingnumbers = [
"prime": [2,3,5,7,9,11,21],
"fibonacci": [1,23,5,32,4,123,11],
"dadgadfgh":[1,2,4,5,43,6,576,12],
"square": [1243325,123,455,1111],
]
var thekind:String?
var max:Int? //also [:Int]?
for (kinds,numbers) in interestingnumbers{
for kind in kinds{
for number in numbers{
if number>max {
max=numbers
thekind = kinds
}
}
}
}
print(max,thekind!)

a) "I need to use optional values to keys and then unwrap it, however the values don't to be done so.But why?"
This is not true. You can initialize thekind string variable with an empty string the same way you did with your integer type max setting its initial value to zero.
b) "Don't know why to use "kinds" rather than kind in the closure, but the one before that used number rather than numbers ,and how can I use numbers to get same result?"
You are unnecessarily iterating each character of your dictionary keys. Thats why you are assigning kinds String instead of kind Character.
let interestingnumbers = [
"prime": [2,3,5,7,9,11,21],
"fibonacci": [1,23,5,32,4,123,11],
"dadgadfgh":[1,2,4,5,43,6,576,12],
"square": [1243325,123,455,1111],
]
var thekind: String = ""
var max = 0
for (key, numbers) in interestingnumbers {
for number in numbers {
if number > max {
max = number
thekind = key
}
}
}
print(max, thekind) // "1243325 square\n"
Just for fun the functional approach:
// result is a tuple (kind and max)
// reduce iterates every key value pair
// $0 is the accumulated which in this case it is used to hold the max value and the corresponding key
// $1 is the current key,value pair (kind, numbers)
let (kind, max) = interestingnumbers.reduce(into: ("",0)) {
// here we check if the current value has a maximum value and if it is greater than $0.1 (the resulting tuple maxValue)
if let maxValue = $1.value.max(), maxValue > $0.1 {
// if true assign a new tuple to the result with the new key and the new maximum value
$0 = ($1.key, maxValue)
}
}
print(kind, max) // "square 1243325\n"

Swift's standard library doesn't have this flatMap overload, which makes things easy.
// (key: "square", value: 1243325)
interestingNumbers.flatMap().max(by: \.value)
public extension Dictionary where Value: Sequence {
/// Flatten value sequences,
/// pairing each value element with its original key.
func flatMap() -> [(key: Key, value: Value.Element)] {
flatMap { key, value in value.map { (key, $0) } }
}
}
public extension Sequence {
func max<Comparable: Swift.Comparable>(
by getComparable: (Element) throws -> Comparable
) rethrows -> Element? {
try self.max {
try getComparable($0) < getComparable($1)
}
}
}

Related

Swift get decimal value for String characters

Is it possible to get the decimal value for String characters in Swift?
something like:
let words:String = "1 ring to rule them all"
var value:Int = 0
for i in 0..<words.count {
let char = words[words.index(words.startIndex,offsetBy:i)]
value += Int(char.decimal)
}
where the first character in "1 ring to rule them all" is 49. Possible?
you could try this:
let words = "1 ring to rule them all"
var value: Int = 0
for i in 0..<words.count {
let char = words[words.index(words.startIndex,offsetBy:i)]
if let val = char.asciiValue {
print("----> char: \(char) val: \(val)") // char and its "decimal" value
value += Int(val)
}
}
print("\n----> value: \(value) \n") // meaningless total value
ok, looks like this is the way:
let characterString = "蜇"
let scalars = characterString.unicodeScalars
let ui32:UInt32 = scalars[scalars.startIndex].value
If you want to add up the Unicode values associated with a string, it would be:
var value = 0
for character in string {
for scalar in character.unicodeScalars {
value += Int(scalar.value)
}
}
Or, alternatively:
let value = string
.flatMap { $0.unicodeScalars }
.compactMap { $0.value }
.reduce(0, +)
While the above adds the values, as requested, if you are trying to get a numeric representation for a string, you might consider using hashValue, or checksum, or CRC, or the like. Simply summing the values will not be able to detect, for example, character transpositions. It just depends upon your use-case for this numeric representation of your string.

Flip and Mirror numbers

I have just picked up an interview question from the Internet and practicing with Swift.
Question is as follows:
Given an input of an array of string, verify if, turned 180 degrees, it is the "same".
For instance:
[1, 6, 0, 9, 1] => return true
[1, 7, 1] => return false
I have come up with the following approach which I put mirroring numbers in the dictionary and check whether or not if any number in the given array do not match with dictionary numbers.
It seems it works with basic test cases, but I wonder if I am missing anything ?
func checkRotation (nums : [Int]) -> Bool
{
var dict = [Int : Int]()
dict = [0:0, 1:1, 2:5, 5:2, 6:9, 8:8, 9:6]
for n in nums
{
guard let exist = dict[n] else
{
return false
}
}
return true
}
extension Collection where Element == Int {
func isFlipMirrored() -> Bool {
let mirrors = [0:0, 1:1, 6:9, 8:8, 9:6]
return zip(self, self.reversed()) // Create tuples of each element and its opposite
.allSatisfy { // Return whether all of them match the rule:
mirrors[$0] == $1 // That the element matches its opposite's mirror
}
}
}
This isn't as efficient as it could be, but it's very simple and to the point. It just verifies that each element of the sequence is the same as the mirrored elements in the reverse order.
It could be more efficient to only check the first half of the elements, but it's a pretty minor optimization that requires extra conditionals, so I'm not sure if it would really be faster for reasonably small N. You'd need to profile before complicating the code too much.
Of course, just because it's not actually slower (i.e. I haven't profiled it to know), that doesn't mean that an interviewer won't baulk at the fact that this code makes redundant checks. There are a lot of misunderstandings about performance, and they all seem to show up in interview questions. So, let's make the interviewer happy and only check the first half of the list against the last half.
extension Collection where Element == Int {
func isFlipMirrored() -> Bool {
let mirrors = [0:0, 1:1, 6:9, 8:8, 9:6]
// May test one more thing than we technically have to, but fewer conditionals
let midpoint = count / 2 + 1
return zip(self.prefix(midpoint), // Create tuples of the left-half of the list,
self.reversed().prefix(midpoint)) // and the right half
.allSatisfy { // Return whether all of them match the rule:
mirrors[$0] == $1 // that the element matches its opposite's mirror
}
}
}
I have some issues with your code, which I've annotated below:
func checkRotation /* Why the space here? */ (nums /* Why the space here? */ : [Int]) -> Bool
{ // Brackets like this aren't Swift's code style
// Dict is a horrible name. I can see that it's a dictionary. What is it a dict *of*?!
var dict = [Int : Int]() // Why is this a `var` variable, that's assigned an empty initial value
dict = [0:0, 1:1, 2:5, 5:2, 6:9, 8:8, 9:6] // only to be immediately overwritten?
for n in nums // This should be a `contains(_:)` call, rather than explicit enumeration
{
// If you're not using a `contains(_:)` check, you should at least use a `where` clause on the for loop
guard let exist = dict[n] else // "exist" is a bad variable name, and it's not even used. Replace this with a `dict[n] != nil` check.
{
return false
}
}
return true
}
Here is how I would write it in a similar way:
func checkRotation(nums: [Int]) -> Bool {
let mirroredDigits = [0:0, 1:1, 2:5, 5:2, 6:9, 8:8, 9:6]
for n in nums where mirroredDigits[n] == nil {
return false
}
return true
}
You can try
func checkRotation (nums : [Int]) -> Bool
{
var dict = [0:0, 1:1, 2:5, 5:2, 6:9, 8:8, 9:6]
return nums.filter{ dict[$0] != nil }.count == nums.count
}
Or
func checkRotation (nums : [Int]) -> Bool
{
var dict = [0:0, 1:1, 2:5, 5:2, 6:9, 8:8, 9:6]
return nums.compactMap{ dict[$0]}.count == nums.count
}
To know if array is convertible, you need to
traverse items upto index N/2 (including middle one for odd-length array)
check whether all items belong to dictionary
check that dict[nums[i]] == nums[N-i-1]
I don't know Swift, but Python example should look very close:
def isconv(lst):
dict = {0:0, 1:1, 2:5, 5:2, 6:9, 8:8, 9:6}
N = len(lst)
for i in range((N + 1) // 2):
if (lst[i] not in dict) or (dict[lst[i]] != lst[N - 1 - i]):
return False
return True
print(isconv([1,6,0,9,1]))
print(isconv([5,5,2,2]))
print(isconv([1,6,0,6,1]))
print(isconv([1,4,1]))
>>True
>>True
>>False
>>False
My approach would be to use prefix to limit the data set and enumerated to enumerate over indexes and values simultaneously. Throw in lazy so you don't make lots of array copies and only process what's relevant.
extension Array where Element == Int {
func isMirrored() -> Bool {
let flipped = [0:0, 1:1, 2:5, 5:2, 6:9, 8:8, 9:6]
return lazy // means we won't make 3 copies of arrays
.prefix((count + 1) / 2) // stops the enumeration at the midway point
.enumerated() // enumerates over (index, value)
.allSatisfy { (index, value) in // verify all elements meet the criteria below
// make sure each reversed element matches it's flipped value
// Note you don't have to explicitly check for nil, since
// '==' works on Optional<Int>
return flipped[value] == self[count - index - 1]
}
}
}
[1, 6, 0, 9, 1].isMirrored()
[1, 7, 1].isMirrored()

Finding the largest number in a [String: [Int]] Swift dictionary

I am new in Swift.
I have an error with this code and I can't find any answer on this site.
I print largest number but I want to print largest number's kind.
let interestingNumbers = [
"Prime": [2,3,5,7,11,13],
"Fibonacci": [1,1,2,3,5,8,13],
"Square": [1,4,9,16,25,36]
]
var largestNumber = 0
for (kind, numbers) in interestingNumbers {
for x in numbers {
for y in kind {
if x > largestNumber {
largestNumber = x
}
}
}
}
print("the largest number is = \(largestNumber)")
Try this instead:
var largestNumber = 0
var largestNumberKind: String!
for (kind, numbers) in interestingNumbers {
for x in numbers {
if x > largestNumber {
largestNumber = x
largertNumberKind = kind
}
}
}
print("the largest number is = \(largestNumber)")
print("the largest number kind is = \(largestNumberKind)")
Regarding your original code:
you were only keeping track of the largest number, losing the kind info you wanted. The largestNumberKind variable I added does just that.
looping over the kind: String didn't make any sense (the for y in kind line). Your outside loop already iterates a key at a time, so such inner loop is pointless.
There is nothing wrong with Paulo's approach (with some minor corrections; see comments there), but this is a reasonable problem to explore more functional approaches that don't require looping and mutation.
For example, we can just flatten each kind to its maximum element (or Int.min if it's empty), then take the kind with the highest max:
interestingNumbers
.map { (kind: $0, maxValue: $1.max() ?? .min) } // Map each kind to its max value
.max { $0.maxValue < $1.maxValue }? // Find the kind with the max value
.kind // Return the kind
This does create a slight edge condition that I don't love. If you evaluate the following:
let interestingNumbers = [
"ImaginaryReals": [],
"Smallest": [Int.min],
]
It's not well defined here which will be returned. Clearly the correct answer is "Smallest," but it's kind of order-dependent. With a little more thought (and code) we can fix this. The problem is that we are taking a little shortcut by treating an empty list as having an Int.min maximum (this also prevents our system from working for things like Float, so that's sad). So let's fix that. Let's be precise. The max of an empty list is nil. We want to drop those elements.
We can use a modified version of mapValues (which is coming in Swift 4 I believe). We'll make flatMapValues:
extension Dictionary {
func flatMapValues<T>(_ transform: (Value) throws -> T?) rethrows -> [Key: T] {
var result: [Key: T] = [:]
for (key, value) in self {
if let newValue = try transform(value) {
result[key] = newValue
}
}
return result
}
}
And with that, we can be totally precise, even with empty lists in the mix:
interestingNumbers
.flatMapValues { $0.max() }
.max { $0.1 < $1.1 }?
.key
Again, nothing wrong with Paulo's approach if you find it clear, but there are other ways of thinking about the problem.
BTW, the equivalent version that iterates would look like this:
var largestNumber: Int? = nil
var largestNumberKind: String? = nil
for (kind, numbers) in interestingNumbers {
for x in numbers {
if largestNumber == nil || largestNumber! < x {
largestNumber = x
largestNumberKind = kind
}
}
}

Iterating based on a variable number of inner loops

In the below code I am trying to go through all possible combination of alphabets for number of characters which are runtime variable.
The purpose of this code is to build a kind of password cracker, which basically brute-force guess the string. I want to use loop, because I will be able to break the loop as soon as the correct combination is hit thus saving on time and resources which otherwise will be required if I try to build an array of all possible combinations in first step.
I have a static code which works for a string 5 characters long but in reality my string could be any length. How can I make my code work with any length of string?
let len = textField.text?.characters.count //Length of string
let charRange = "abcdefghijklmnopqrstuvwxyz" //Allowed characterset
for char1 in charRange.characters {
for char2 in charRange.characters {
for char3 in charRange.characters {
for char4 in charRange.characters {
for char5 in charRange.characters {
// Do whatever with all possible combinations
}
}
}
}
}
I think I have to utilize for totalChars in 1...len { somehow but can't figure out how the for loops are going to be created dynamically?
Idea: form the string using an array of indices into your alphabet; each time increment the indices.
[0, 0, 0] -> [1, 0, 0] -> [2, 0, 0] ->
[0, 1, 0] -> [1, 1, 0] -> [2, 1, 0] ->
[0, 2, 0] -> [1, 2, 0] -> [2, 2, 0] ->
[0, 0, 1] ... [2, 2, 2]
Here's an example using a length of 3 and an alphabet of abcd
let len = 3
let alphabet = "abcd".characters.map({ String($0) })
var allStrings = [String]()
let maxIndex = alphabet.endIndex
var indicies = Array(count: len, repeatedValue: 0)
outerLoop: while (true) {
// Generate string from indicies
var string = ""
for i in indicies {
let letter = alphabet[i]
string += letter
}
allStrings.append(string)
print("Adding \(string)")
// Increment the index
indicies[0] += 1
var idx = 0
// If idx overflows then (idx) = 0 and (idx + 1) += 1 and try next
while (indicies[idx] == maxIndex) {
// Reset current
indicies[idx] = 0
// Increment next (as long as we haven't hit the end done)
idx += 1
if (idx >= alphabet.endIndex - 1) {
print("Breaking outer loop")
break outerLoop
}
indicies[idx] += 1
}
}
print("All Strings: \(allStrings)")
As suggested by Martin R, you can use recursion
This is the function
func visit(alphabet:[Character], combination:[Character], inout combinations:[String], length: Int) {
guard length > 0 else {
combinations.append(String(combination))
return
}
alphabet.forEach {
visit(alphabet, combination: combination + [$0], combinations: &combinations, length: length - 1)
}
}
The helper function
func combinations(alphabet: String, length: Int) -> [String] {
var combinations = [String]()
visit([Character](alphabet.characters), combination: [Character](), combinations: &combinations, length: length)
return combinations
}
Test
Now if you want every combination of 3 chars, and you want "ab" as alphabet then
combinations("ab", length: 3) // ["aaa", "aab", "aba", "abb", "baa", "bab", "bba", "bbb"]
Duplicates
Please note that if you insert duplicates into your alphabet, you'll get duplicate elements into the result.
Time complexity
The visit function is invoked as many times as the nodes into a perfect k-ary tree with height h where:
k: the number of elements into the alphabet param
h: the length param
Such a tree has
nodes. And this is the exact number of times the function will be invoked.
Space complexity
Theoretically The max number of stack frames allocated at the same time to execute visit is length.
However since the Swift compiler does implement the Tail Call Optimization the number of allocated stack frames is only 1.
Finally we must consider that combinations will be as big as the number of results: alphabet^length
So the time complexity is the max of length and elements into the result.
And it is O(length + alphabet^length)
Update
It turns out you want a brute force password breaker so.
func find(alphabet:[Character], combination:[Character] = [Character](), length: Int, check: (keyword:String) -> Bool) -> String? {
guard length > 0 else {
let keyword = String(combination)
return check(keyword: keyword) ? keyword : nil
}
for char in alphabet {
if let keyword = find(alphabet, combination: combination + [char], length: length - 1, check: check) {
return keyword
}
}
return nil
}
The last param check is a closure to verify if the current word is the correct password. You will put your logic here and the find will stop as soon as the password is found.
Example
find([Character]("tabcdefghil".characters), length: 3) { (keyword) -> Bool in
return keyword == "cat" // write your code to verify the password here
}
Alternative to recursion; loop radix representation of incremental (repeated) traversing of your alphabet
An alternative to recursion is to loop over an numeral representation of your alphabet, using a radix representative for the different number of letters. A limitation with this method is that the String(_:,radix:) initializer allows at most base36 numbers (radix 36), i.e., you can at most perform your "password cracking" with a set of characters with a unique count <=36.
Help function
// help function to use to pad incremental alphabeth cycling to e.g. "aa..."
let padToTemplate: (str: String, withTemplate: String) -> String = {
return $0.characters.count < $1.characters.count
? String($1.characters.suffixFrom($0.characters.endIndex)) + $0
: $0
}
Main radix brute-force password checking method
// attempt brute-force attempts to crack isCorrectPassword closure
// for a given alphabet, suspected word length and for a maximum number of
// attempts, optionally with a set starting point
func bruteForce(isCorrectPassword: (String) -> Bool, forAlphabet alphabet: [Character], forWordLength wordLength: Int, forNumberOfAttempts numAttempts: Int, startingFrom start: Int = 0) -> (Int, String?) {
// remove duplicate characters (but preserve order)
var exists: [Character:Bool] = [:]
let uniqueAlphabet = Array(alphabet.filter { return exists.updateValue(true, forKey: $0) == nil })
// limitation: allows at most base36 radix
guard case let radix = uniqueAlphabet.count
where radix < 37 else {
return (-1, nil)
}
// begin brute-force attempts
for i in start..<start+numAttempts {
let baseStr = String(i, radix: radix).characters
.flatMap { Int(String($0), radix: radix) }
.map { String(uniqueAlphabet[$0]) }
.joinWithSeparator("")
// construct attempt of correct length
let attempt = padToTemplate(str: baseStr,
withTemplate: String(count: wordLength, repeatedValue: alphabet.first!))
// log
//print(i, attempt)
// test attempt
if isCorrectPassword(attempt) { return (i, attempt) }
}
return (start+numAttempts, nil) // next to test
}
Example usage
Example usage #1
// unknown content closure
let someHashBashing : (String) -> Bool = {
return $0 == "ask"
}
// setup alphabet
let alphabet = [Character]("abcdefghijklmnopqrstuvwxyz".characters)
// any success for 500 attempts?
if case (let i, .Some(let password)) =
bruteForce(someHashBashing, forAlphabet: alphabet,
forWordLength: 3, forNumberOfAttempts: 500) {
print("Password cracked: \(password) (attempt \(i))")
} /* Password cracked: ask (attempt 478) */
Example usage #2 (picking up one failed "batch" with another)
// unknown content closure
let someHashBashing : (String) -> Bool = {
return $0 == "axk"
}
// setup alphabet
let alphabet = [Character]("abcdefghijklmnopqrstuvwxyz".characters)
// any success for 500 attempts?
let firstAttempt = bruteForce(someHashBashing, forAlphabet: alphabet,
forWordLength: 3, forNumberOfAttempts: 500)
if let password = firstAttempt.1 {
print("Password cracked: \(password) (attempt \(firstAttempt.0))")
}
// if not, try another 500?
else {
if case (let i, .Some(let password)) =
bruteForce(someHashBashing, forAlphabet: alphabet,
forWordLength: 3, forNumberOfAttempts: 500,
startingFrom: firstAttempt.0) {
print("Password cracked: \(password) (attempt \(i))")
} /* Password cracked: axk (attempt 608) */
}

How to access the next key in a Swift dictionary?

I have this code
for (k, v) in myDict {
println(k)
}
How do I access the next key in the dictionary (e.g. myDict[k + 1])?
Thanks in advance!
There is no such thing as "the next key"; dictionaries have no order.
Since, however, you are iterating through the dictionary...
for (k, v) in myDict {
println(k)
}
I'm going to assume that what you mean is: how can I know, on this iteration, what k would be on the next iteration?
A simple solution would be to coerce the dictionary to an array (of key-value tuples):
let arr = Array(myDict)
Now you have something with integer indexes. So you can enumerate it like this:
let arr = Array(myDict)
for (ix, (k,v)) in enumerate(arr) {
println("This key is \(k)")
if ix < arr.count-1 {
println("The next key is \(arr[ix+1].0)")
}
}
The truth is, of course, that you can enumerate a dictionary directly, but indexes are not integers, so they are a little harder to work with. Martin R is also showing an approach illustrating that point.
I don't know if this is what you are looking for, but you can
iterate through a dictionary in a "similar" way as iterating
through an array by using the DictionaryIndex<Key, Value> as an index:
let dict = [ "foo" : 1, "bar" : 2, "baz" : 3]
for idx in indices(dict) {
let (k, v) = dict[idx]
println("Current key: \(k), current value: \(v)")
let nextIdx = idx.successor()
if nextIdx != dict.endIndex {
let (k1, v1) = dict[nextIdx]
println("Next key: \(k1), next value: \(v1)")
}
}
Sample output:
Current key: bar, current value: 2
Next key: baz, next value: 3
Current key: baz, current value: 3
Next key: foo, next value: 1
Current key: foo, current value: 1
A possible solution is to create Generator which returns the current and previous values in a sequence. For this you need a custom Generator which will return a tuple, containing the previous and current values from a sequence, from next:
struct PairGenerator<Base: GeneratorType> : GeneratorType {
typealias ElementPair = (previousElement: Base.Element, currentElement: Base.Element)
private var base: Base
private var previousElement: Base.Element?
init(_ base: Base) {
self.base = base
}
mutating func next() -> ElementPair? {
if previousElement == nil { previousElement = base.next() }
let currentElement = base.next()
// Since `base.next()` returns `nil` when the end of the sequence
// is reached, we need to check `previousElement` and `currentElement `
// aren't `nil`. If either of them are, `nil` will be returned to signal
// there aren't any pairs left.
if let prev = previousElement, curr = currentElement {
previousElement = currentElement
return (prev, curr)
}
return nil
}
}
The PairGenerator is then stored in a PairSequence, which conforms to SequenceType; this means you can iterate over it in a for loop.
struct PairSequence<Base: SequenceType> : SequenceType {
let generator: PairGenerator<Base.Generator>
init(_ base: Base) {
generator = PairGenerator(base.generate())
}
func generate() -> PairGenerator<Base.Generator> {
return generator
}
}
Now you need a function which will create a PairSequence from an object that conforms to SequenceType:
func pairs<Seq: SequenceType>(base: Seq) -> PairSequence<Seq> {
return PairSequence(base)
}
Finally, you can use this like so:
let myDict = ["1": 1, "2": 2, "3": 3, "4": 4]
let values = Array(myDict.values).sorted(<)
for (prev, curr) in pairs(values) {
println("\(prev), \(curr)")
}
// Prints:
// 1, 2
// 2, 3
// 3, 4
You could use pairs(myDict), but like #Martin R and #matt said - Dictionaries don't have an order so you may not get the results in the order you expected.
For more information on SequenceType and GeneratorType, I'd recommend looking at Playing With Swift and Generators In Swift.
Or, as #Martin R pointed out in his comment, you could use:
for (prev, curr) in zip(values, dropFirst(values)) {
println("\(prev), \(curr)")
}