Skip to content

Instantly share code, notes, and snippets.

@possen
Last active November 22, 2015 18:38
Show Gist options
  • Save possen/24b1c086a4e6c94ad8d8 to your computer and use it in GitHub Desktop.
Save possen/24b1c086a4e6c94ad8d8 to your computer and use it in GitHub Desktop.
Description: Single Riffle detection, try to detct if a deck of cards has been riffled only once
//
// Description: Single Riffle detection, try to detct if a deck of cards has been riffled only once.
//
// Language: Swift 2.1 (playground)
// Author: Paul Ossenbruggen
// Date: Nov 21, 2015
//
// Uses a stack approach because it is easy to get the next element. It could be done with iterators too which
// be non destructive and might be faster, since swift copies the array a distructive approach should work.
//
import UIKit
func shuffleArray(var array : [Int]) -> [Int] {
for (index, _) in array[0..<array.count-1].enumerate() {
let randomIndex = Int(arc4random_uniform(UInt32(array.count - index))) + index
guard index != randomIndex else { continue } // swap does not like it if you swap same indexes
swap(&array[index], &array[randomIndex])
}
return array
}
// randomly pick from either half split deck the deck
func riffle(var half1 : [Int], var half2 : [Int]) -> [Int] {
var result : [Int] = []
while half1.count > 0 || half2.count > 0 {
if arc4random_uniform(UInt32(2)) == 0 && half1.count > 0 {
let half1element = half1.removeFirst()
result += [half1element]
} else if half2.count > 0 {
let half2ELement = half2.removeFirst()
result += [half2ELement]
}
}
return result
}
// this function is O(N) time. because it copies the original values, as swift usually does, it
// uses O(N) space. This is fine for a deck of cards.
func isSingleRiffle(var shuffled : [Int], var half1 : [Int], var half2 : [Int]) -> Bool{
while shuffled.count > 0 {
let shuffledTop = shuffled.removeFirst()
if shuffledTop == half1.first {
half1.removeFirst()
} else if shuffledTop == half2.first {
half2.removeFirst()
} else {
return false // not found in the order shuffle order, so return false.
}
}
return true
}
// original shuffled deck
let array = shuffleArray(Array(1...52))
let half1 = Array(array[0..<(array.count/2)])
let half2 = Array(array[(array.count/2+1)..<array.count])
// check if it is a single riffle
assert(isSingleRiffle(array, half1: half1 , half2:half2) == false, "should not be a single riffle as it is random")
// riffle the deck once.
let riffleArray = riffle(half1, half2: half2)
assert(isSingleRiffle(riffleArray, half1:half1, half2:half2) == true, "should be a single riffle")
// split deck again, compare to original halves
let newHalf1 = Array(array[0..<(riffleArray.count/2)])
let newHalf2 = Array(array[(riffleArray.count/2+1)..<array.count])
let newRiffleArray = riffle(newHalf1, half2: newHalf2)
assert(isSingleRiffle(newRiffleArray, half1:half1, half2:half2) == false, "should not be a single riffle as we sorted twice")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment