Shuffling a String in Swift

Scramble String in Swift

I found a good solution to this. There was a guy who made a single file MD5-converter without any third party libraries named MD5 Digest

Then this library can be used like this

let input = "0bb0fca0-1e89-429f-901a-1413894d9f59"
let md5 = input.utf8.md5
print(md5)

this gives the result:

4a89b58cb43b3eecd289c1d093b48bd0

This is exactly what I wanted, something that can be re-created, but still makes a result based on the string I sent in that the user can't connect to the string being sent in.

Leetcode Q. 1528. Shuffle String

Its a one to one hashing not a index based hashing which you were doing in above code below is the updated correct version of your code:-

class Solution {
func restoreString(_ s: String, _ indices: [Int]) -> String {
var newString = s.map{ String($0) }
var y = ""
var count = 0
var dict = [Int:String]()
var z = 0

while count < newString.count {
dict[indices[count]] = newString[count]
count += 1
}

while z < indices.count {
y.append(dict[z]!)
z += 1
}
print(dict)

return y
}
}

Issue with shuffling an array of strings per 1 day in SwiftUI

try this:

ForEach(isNewDay() ? words.shuffled() : words, id: \.self) { word in  // <-- here
Text(word) // <-- here

How do I shuffle an array in Swift?

This answer details how to shuffle with a fast and uniform algorithm (Fisher-Yates) in Swift 4.2+ and how to add the same feature in the various previous versions of Swift. The naming and behavior for each Swift version matches the mutating and nonmutating sorting methods for that version.

Swift 4.2+

shuffle and shuffled are native starting Swift 4.2. Example usage:

let x = [1, 2, 3].shuffled()
// x == [2, 3, 1]

let fiveStrings = stride(from: 0, through: 100, by: 5).map(String.init).shuffled()
// fiveStrings == ["20", "45", "70", "30", ...]

var numbers = [1, 2, 3, 4]
numbers.shuffle()
// numbers == [3, 2, 1, 4]

Swift 4.0 and 4.1

These extensions add a shuffle() method to any mutable collection (arrays and unsafe mutable buffers) and a shuffled() method to any sequence:

extension MutableCollection {
/// Shuffles the contents of this collection.
mutating func shuffle() {
let c = count
guard c > 1 else { return }

for (firstUnshuffled, unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
// Change `Int` in the next line to `IndexDistance` in < Swift 4.1
let d: Int = numericCast(arc4random_uniform(numericCast(unshuffledCount)))
let i = index(firstUnshuffled, offsetBy: d)
swapAt(firstUnshuffled, i)
}
}
}

extension Sequence {
/// Returns an array with the contents of this sequence, shuffled.
func shuffled() -> [Element] {
var result = Array(self)
result.shuffle()
return result
}
}

Same usage as in Swift 4.2 examples above.


Swift 3

These extensions add a shuffle() method to any mutable collection and a shuffled() method to any sequence:

extension MutableCollection where Indices.Iterator.Element == Index {
/// Shuffles the contents of this collection.
mutating func shuffle() {
let c = count
guard c > 1 else { return }

for (firstUnshuffled , unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) {
// Change `Int` in the next line to `IndexDistance` in < Swift 3.2
let d: Int = numericCast(arc4random_uniform(numericCast(unshuffledCount)))
guard d != 0 else { continue }
let i = index(firstUnshuffled, offsetBy: d)
self.swapAt(firstUnshuffled, i)
}
}
}

extension Sequence {
/// Returns an array with the contents of this sequence, shuffled.
func shuffled() -> [Iterator.Element] {
var result = Array(self)
result.shuffle()
return result
}
}

Same usage as in Swift 4.2 examples above.


Swift 2

(obsolete language: you can't use Swift 2.x to publish on iTunes Connect starting July 2018)

extension MutableCollectionType where Index == Int {
/// Shuffle the elements of `self` in-place.
mutating func shuffleInPlace() {
// empty and single-element collections don't shuffle
if count < 2 { return }

for i in startIndex ..< endIndex - 1 {
let j = Int(arc4random_uniform(UInt32(count - i))) + i
guard i != j else { continue }
swap(&self[i], &self[j])
}
}
}

extension CollectionType {
/// Return a copy of `self` with its elements shuffled.
func shuffle() -> [Generator.Element] {
var list = Array(self)
list.shuffleInPlace()
return list
}
}

Usage:

[1, 2, 3].shuffle()
// [2, 3, 1]

let fiveStrings = 0.stride(through: 100, by: 5).map(String.init).shuffle()
// ["20", "45", "70", "30", ...]

var numbers = [1, 2, 3, 4]
numbers.shuffleInPlace()
// [3, 2, 1, 4]

Swift 1.2

(obsolete language: you can't use Swift 1.x to publish on iTunes Connect starting July 2018)

shuffle as a mutating array method

This extension will let you shuffle a mutable Array instance in place:

extension Array {
mutating func shuffle() {
if count < 2 { return }
for i in 0..<(count - 1) {
let j = Int(arc4random_uniform(UInt32(count - i))) + i
swap(&self[i], &self[j])
}
}
}
var numbers = [1, 2, 3, 4, 5, 6, 7, 8]
numbers.shuffle() // e.g., numbers == [6, 1, 8, 3, 2, 4, 7, 5]

shuffled as a non-mutating array method

This extension will let you retrieve a shuffled copy of an Array instance:

extension Array {
func shuffled() -> [T] {
if count < 2 { return self }
var list = self
for i in 0..<(list.count - 1) {
let j = Int(arc4random_uniform(UInt32(list.count - i))) + i
swap(&list[i], &list[j])
}
return list
}
}
let numbers = [1, 2, 3, 4, 5, 6, 7, 8]
let mixedup = numbers.shuffled() // e.g., mixedup == [6, 1, 8, 3, 2, 4, 7, 5]

Shuffle/Randomize Questions from an Array with no Repetition (SWIFT)

You seem to be shuffling the list every time you call updateQuestion which seems to be the issue here. You are only supposed to call the shuffle once and iterate through the questions one by one. To fix the issue remove the shuffle from updateQuestion and add it in viewDidLoad or just call it once in updateQuestion based on a condition like this:

if questionNumber == 1 {
allQuestions.list.shuffle()
}

How to shuffle text from array without repeating a word and going through the whole array? (Swift)

If I understood it correctly you shouldn't shuffle your collection every time you call nextFruit. Just shuffle it once before iterating your collection. The simplest solution in my opinion is to store the index of the current fruit. In your next fruit method check if the index is equal to zero and if true shuffle your fruits. Get the fruit at the current index and increment it. If the index is equal to the number of fruits just reset it to zero. Something like:

struct Fruit {
let id: Int
let fruit: Character
let name: String
}

Playground testing:

var fruitOptions = [
Fruit(id: 1, fruit:"quot;, name: "KIWI"),
Fruit(id: 2, fruit:"quot;, name: "APPLE"),
Fruit(id: 3, fruit:"quot;, name: "PEAR"),
Fruit(id: 4, fruit:"quot;, name: "ORANGE"),
Fruit(id: 5, fruit:"quot;, name: "STRAWBERRY"),
Fruit(id: 6, fruit:"quot;, name: "WATERMELON"),
Fruit(id: 7, fruit:"quot;, name: "GRAPES"),
Fruit(id: 8, fruit:"quot;, name: "BANANA"),
Fruit(id: 9, fruit:"quot;, name: "CHERRY")]

var index = 0

func nextFruit() {
if index == 0 { fruitOptions.shuffle() }
print(fruitOptions[index])
index += 1
if index == fruitOptions.count {
print("end of fruits")
index = 0
}
}


nextFruit()
nextFruit()
nextFruit()
nextFruit()
nextFruit()
nextFruit()
nextFruit()
nextFruit()
nextFruit()
nextFruit()
nextFruit()
nextFruit()
nextFruit()

This will print:

Fruit(id: 5, fruit: "quot;, name: "STRAWBERRY")

Fruit(id: 2, fruit: "quot;, name: "APPLE")

Fruit(id: 4, fruit: "quot;, name: "ORANGE")

Fruit(id: 9, fruit: "quot;, name: "CHERRY")

Fruit(id: 3, fruit: "quot;, name: "PEAR")

Fruit(id: 6, fruit: "quot;, name: "WATERMELON")

Fruit(id: 8, fruit: "quot;, name: "BANANA")

Fruit(id: 1, fruit: "quot;, name: "KIWI")

Fruit(id: 7, fruit: "quot;, name: "GRAPES")

end of fruits

Fruit(id: 2, fruit: "quot;, name: "APPLE")

Fruit(id: 3, fruit: "quot;, name: "PEAR")

Fruit(id: 1, fruit: "quot;, name: "KIWI")

Fruit(id: 4, fruit: "quot;, name: "ORANGE")

Shuffle array swift 3

count returns an IndexDistance which is the type describing
the distance between two collection indices. IndexDistance is
required to be a SignedInteger, but need not be an Int and can
be different from Index. Therefore it is not possible to create
the range 0..<count - 1.

A solution is to use startIndex and endIndex instead of 0 and count:

extension MutableCollection where Index == Int {
/// Shuffle the elements of `self` in-place.
mutating func shuffle() {
// empty and single-element collections don't shuffle
if count < 2 { return }

for i in startIndex ..< endIndex - 1 {
let j = Int(arc4random_uniform(UInt32(endIndex - i))) + i
if i != j {
swap(&self[i], &self[j])
}
}
}
}

Another advantage is that this also works correctly with array slices
(where the index of the first element is not necessarily zero).

Note that according to the new "Swift API Design Guidelines",
shuffle() is the "proper" name for a mutating shuffle method,
and shuffled() for the non-mutating counterpart which returns an array:

extension Collection {
/// Return a copy of `self` with its elements shuffled
func shuffled() -> [Iterator.Element] {
var list = Array(self)
list.shuffle()
return list
}
}

Update: A (even more general) Swift 3 version has been added to
How do I shuffle an array in Swift? in the meantime.


For Swift 4 (Xcode 9) one has to replace the call to the swap()
function by a call to the swapAt() method of the collection.
Also the restriction on the Index type is no longer needed:

extension MutableCollection {
/// Shuffle the elements of `self` in-place.
mutating func shuffle() {
for i in indices.dropLast() {
let diff = distance(from: i, to: endIndex)
let j = index(i, offsetBy: numericCast(arc4random_uniform(numericCast(diff))))
swapAt(i, j)
}
}
}

See SE-0173 Add MutableCollection.swapAt(_:_:) for more information about swapAt.


As of Swift 4.2 (Xcode 10, currently in beta), with the implementation of
SE-0202 Random Unification,
shuffle() and shuffled() are part of the Swift standard library.



Related Topics



Leave a reply



Submit