Shuffle an array

I’m trying to shuffle an array and I’m not sure what is the right way with Motoko.

This is what I have so far:

func shuffle(cards:[Card]) : [Card] {
    var currentIndex = cards.size();

    while(0 != currentIndex) {
        var randomIndex = Float.toInt(Float.floor(Math.random() * Float.fromInt(currentIndex)));
        currentIndex -= 1;
        var tempValue = cards[currentIndex];
        cards[currentIndex] := cards[randomIndex];
        cards[randomIndex] := tempValue;
        D.print(debug_show(randomIndex));
        D.print(debug_show(currentIndex));
        D.print(debug_show(tempValue.id));
};

return cards;

};

and I’m getting these errors:

Stderr:
main.mo:24.9-24.50: type error [M0073], expected mutable assignment target
main.mo:25.15-25.26: type error [M0096], expression of type
  Int
cannot produce expected type
  Nat
main.mo:25.9-25.40: type error [M0073], expected mutable assignment target

It seems I don’t know how to replace assign new values to array items and also it seems that the index of an array needs to be a Nat but I have no clue how to convert an Int to a Nat…
Math.random() generates pseudo random Floats between 0 and 1.

I wonder if the problem is that the array I’m passing to the function is immutable?
Should I use Array.tabulate to generate a mutable array from the immutable one?
Is there an easier way to copy an array?

This is going to sound silly, two things:

First,

let foo : [Card] = []; // Elements are immutable
let bar : [var Card] = []; Elements are mutable! 

Second, see below post! (edited)

Int :: Internet Computer is probably the easiest way to get a Nat from an Int, if you’re 100% sure you’ll never look at a negative one. Otherwise you’ll have to guard with a someInt >= 0 check to make sure you’re not breaking invariants.

2 Likes

@kritzcreek - thank you for pointing that out! I can’t believe I’ve managed to miss that this entire time :man_facepalming: .

1 Like

ty @kritzcreek that worked!

@Hazel

let bar : [var Card] = [];
and
var bar: [var Card] = []

returns

type error [M0091], immutable array expression cannot produce expected type [var Card/1]

The empty array with mutable elements is [var], not [].

Typically, if you use

var bar : […]

i.e. use a mutable variable for the whole array, one doesn’t generally also need the elements to be mutable.

2 Likes