1

I'm currently learning Standard ML, just for fun; What I'm trying to do is generate a list of 3-tuples of random ints between 1 and 100. My code:

fun reload() = use "filtertest.sml";

fun getSeed() = 
  LargeInt.toInt(Time.toMicroseconds(Time.now()) mod 1000);

fun fastpower(x, 0) = 1
  | fastpower(x, n) = 
      if n mod 2 = 0 then 
        fastpower(x*x, n div 2)
      else 
        x * fastpower(x*x, n div 2);

fun getRand(seed) = 
  let
    val m = 256
    val a = 11035
    val c = 12345
  in
    (a * seed + c) mod m
  end;

fun getRandTup() = 
  let
    val a = getRand(getSeed())
    val b = getRand(a)
    val c = getRand(b)
  in
    (a, b, c)
  end;

fun sumTup(x: int, y: int, z: int) = x + y + z;

fun getFromLast(lastTup) = 
  let
    val a = getRand(sumTup(lastTup))
    val b = getRand(a)
    val c = getRand(b)
  in
    (a, b, c)
  end;

fun genTupsHelper(0, tupList) = tupList
  | genTupsHelper(n, []) = 
      genTupsHelper(n-1, getRandTup() :: [])
  | genTupsHelper(n, tupList) = 
      getFromLast(hd tupList) :: genTupsHelper(n-1, tupList);

fun genTups(n) =
  genTupsHelper(n, []);

However, when I evaluate

genTups(10) 

My output is:

- genTups(10);
val it =
  [(243,218,55),(243,218,55),(243,218,55),(243,218,55),(243,218,55),
   (243,218,55),(243,218,55),(243,218,55),(243,218,55),(85,48,73)]
  : (int * int * int) list

I don't quite understand what I'm doing wrong here. Any help would be greatly appreciated.

4
  • Changing it to the following seems to work: fun genTupsHelper(0, tupList) = tupList | genTupsHelper(n, tupList) = let val lastTuple = hd tupList val fromLast = getFromLast(lastTuple) in genTupsHelper(n-1, (fromLast :: tupList)) end; Commented Aug 22, 2022 at 17:39
  • 2
    Perhaps your seeds are all the same? Commented Aug 22, 2022 at 17:57
  • 1
    A good troubleshooting step would be to print the seeds each time you call the function to determine if they are all the same. Commented Aug 22, 2022 at 18:05
  • 1
    Since the seeds are the microseconds of the current time, they are not going to differ much if your code executes in less than 1 microsecond, which is likely. Commented Aug 23, 2022 at 14:12

1 Answer 1

0

Suggestion: use the Random structure.

val r = Random.rand();

fun getRand(a, b) =
  Random.randRange (a, b) r;

fun getTuple(a, b) =
  (getRand(a, b), getRand(a, b), getRand(a, b));

getTuple(0, 100);
(* (2, 9, 97) *)

Now, let's write a listInit function that creates a list of n length using the results of calling a function.

fun listInit(n, f) =
  let
    fun aux(s, e, f, acc) =
      if s >= e then List.rev acc
      else aux(s+1, e, f, f s :: acc)
  in
    aux(0, n, f, [])
  end;

For instance:

listInit(3, (fn i => i));
(* [0, 1, 2] *)

We could also use this to generate a list of five random tuples.

listInit(5, (fn _ => getTuple(0, 100)));
(* [(10, 26, 31), (94, 46, 38), (7, 46, 89), 
    (92, 75, 61), (14, 60, 88)] *)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.