I'm trying to to get 28 letters from an array of 9...
# getting-started
n
I'm trying to to get 28 letters from an array of 90. The array of 90 needs to be shuffled so that the set of 28 letters is virtually never the same. So this is the code I use:
Copy code
private fun shakeLetterBag(slice: IntRange): Array<Letter> {
        repository.arr.shuffle()
        return repository.arr.sliceArray(slice)
    }

    var boardLetters = MutableLiveData(repository.arr)

    fun loadTiles(): Array<Letter>? {
        boardLetters.value = shakeLetterBag(0..27)
        return boardLetters.value}
I am wondering if there is something wrong with my logic because I seem to be getting the occasional identical set, which statistically should not be the case. Any ideas? 🤔
r
Why are you accepting an int range instead of just a count? A range would imply I could pass in
33..67
and that would somehow be meaningful, but the logic suggests otherwise.
n
Hmm, well I did that because a Slice is a range, no?
Or are you saying I don't need a Slice
e
there's an obvious thread-safety issue there, but without more context we can't tell if that's relevant or not
you don't need a slice, just a count
n
This is happening in my viewModel... But thanks, I'l,l try with just a count. 🙂
e
that doesn't fix anything btw, just an observation that it's unnecessary
l
Could the lack of randomness have to do with the fact that shuffle uses a pseudo-random number generator? What happens if you use a SecureRandom to shuffle?
n
I'll have to look this up; I don't know what pseudo-random and SecureRandom mean.
l
Computers are really great at consistency, which makes generating random numbers on a computer difficult. The default Implementation of Random uses essentially a state machine. The result of this is that two runs with the same seed will produce identical results (Try creating a java.lang.random and setting the seed).
Go to play.kotlinlang.org and type in the following
Copy code
import java.util.Random

/**
 * You can edit, run, and share this code.
 * <http://play.kotlinlang.org|play.kotlinlang.org>
 */
fun main() {
    val random = Random(10273)
    repeat(20) {
        println(random.nextInt())
    }
    
    println("Resetting...")
    
    val random2 = Random(10273)
    repeat(20) {
        println(random2.nextInt())
    }
}
You’ll see that both runs print the same results.
e
I don't expect that to be the case as the default random that
shuffle()
uses is seeded once and not cloned. but you can verify by creating your own
Random
(one, not every time) and explicitly passing it to
shuffle
n
I see what you mean. What would be the best way of achieving what I need? It's a Scrabble type game with a set number of each alphabet letter. I need a fresh set of letters to play each time I load the game.
I think the problem was the Slice probably as suggested...
I originally tried it with Random but I was getting several instances of letters that only have one tile in the game...
l
Can you simply do
List(90) { it }
.shuffled()
.take(28)
?
n
Actually, that might work
l
And to be sure to not have the same entry twice, you can do a
.distinct()
before
.take()
n
thanks! 🙂
Hmm not sure why I'm getting this:
It does not seem to have shuffled them. It's just the first 28 letters of the array...
l
Can you post your code?
n
Copy code
private fun shakeLetterBag(count: Int): Array<Letter> {
        val listArr = repository.arr.toList()
        listArr
            .shuffled()
            .take(count)
        return listArr.toTypedArray()
    }
l
shuffled returns a new list. It doesn't modify the old
n
oh
l
x)
l
Basically, change the return line to
Copy code
return listArr
            .shuffled()
            .take(count).toTypedArray()
It’s a common mistake. The kotlin stdlib for lists allocates a new list for each method and returns it. It’s part of the immutability concept.
n
So you mean this?
Copy code
private fun shakeLetterBag(count: Int): Array<Letter> {
        val listArr = repository.arr.toList()
         return listArr
            .shuffled()
            .take(count).toTypedArray()
    }
l
Yep, You can also do
Copy code
private fun shakeLetterBag(count: Int): Array<Letter> {
         return repository.arr.toList()
            .shuffled()
            .take(count).toTypedArray()
    }
n
Ok phew, that worked
Many thanks to all of you!
l
K
😊 2