https://kotlinlang.org logo
#getting-started
Title
# getting-started
n

Nat Strangerweather

06/03/2022, 5:24 PM
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

Ruckus

06/03/2022, 5:37 PM
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

Nat Strangerweather

06/03/2022, 5:40 PM
Hmm, well I did that because a Slice is a range, no?
Or are you saying I don't need a Slice
e

ephemient

06/03/2022, 5:42 PM
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

Nat Strangerweather

06/03/2022, 5:44 PM
This is happening in my viewModel... But thanks, I'l,l try with just a count. 🙂
e

ephemient

06/03/2022, 5:49 PM
that doesn't fix anything btw, just an observation that it's unnecessary
l

Landry Norris

06/03/2022, 5:55 PM
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

Nat Strangerweather

06/03/2022, 6:08 PM
I'll have to look this up; I don't know what pseudo-random and SecureRandom mean.
l

Landry Norris

06/03/2022, 6:14 PM
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

ephemient

06/03/2022, 6:21 PM
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

Nat Strangerweather

06/03/2022, 6:23 PM
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

Louis Gautier

06/03/2022, 7:12 PM
Can you simply do
List(90) { it }
.shuffled()
.take(28)
?
n

Nat Strangerweather

06/03/2022, 7:24 PM
Actually, that might work
l

Louis Gautier

06/03/2022, 7:26 PM
And to be sure to not have the same entry twice, you can do a
.distinct()
before
.take()
n

Nat Strangerweather

06/03/2022, 7:31 PM
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

Landry Norris

06/03/2022, 7:41 PM
Can you post your code?
n

Nat Strangerweather

06/03/2022, 7:41 PM
Copy code
private fun shakeLetterBag(count: Int): Array<Letter> {
        val listArr = repository.arr.toList()
        listArr
            .shuffled()
            .take(count)
        return listArr.toTypedArray()
    }
l

Landry Norris

06/03/2022, 7:42 PM
shuffled returns a new list. It doesn't modify the old
n

Nat Strangerweather

06/03/2022, 7:42 PM
oh
l

Louis Gautier

06/03/2022, 7:42 PM
x)
l

Landry Norris

06/03/2022, 7:42 PM
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

Nat Strangerweather

06/03/2022, 7:45 PM
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

Louis Gautier

06/03/2022, 7:46 PM
Yep, You can also do
Copy code
private fun shakeLetterBag(count: Int): Array<Letter> {
         return repository.arr.toList()
            .shuffled()
            .take(count).toTypedArray()
    }
n

Nat Strangerweather

06/03/2022, 7:46 PM
Ok phew, that worked
Many thanks to all of you!
l

Louis Gautier

06/03/2022, 7:47 PM
K
😊 2
2 Views