Pseudo-random numbers/Middle-square method: Difference between revisions

From Rosetta Code
Content added Content deleted
No edit summary
(add task to arm assemble raspberry pi)
Line 97: Line 97:
{{output}}
{{output}}
<lang applescript>{959861, 333139, 981593, 524817, 432883}</lang>
<lang applescript>{959861, 333139, 981593, 524817, 432883}</lang>

=={{header|ARM Assembly}}==
{{works with|as|Raspberry Pi <br> or android 32 bits with application Termux}}
<lang ARM Assembly>
/* ARM assembly Raspberry PI or android with termux */
/* program pRandom.s */
/* REMARK 1 : this program use routines in a include file
see task Include a file language arm assembly
for the routine affichageMess conversion10
see at end of this program the instruction include */
/* for constantes see task include a file in arm assembly */
/************************************/
/* Constantes */
/************************************/
.include "../constantes.inc"
/*********************************/
/* Initialized data */
/*********************************/
.data
sMessResult: .asciz " @ \n"
szCarriageReturn: .asciz "\n"

iSeed: .int 675248
/*********************************/
/* UnInitialized data */
/*********************************/
.bss
sZoneConv: .skip 24
/*********************************/
/* code section */
/*********************************/
.text
.global main
main: @ entry of program

ldr r0,iAdriSeed
ldr r3,[r0]
mov r2,#5
1:
mov r0,r3
bl computePseudo
mov r3,r0
ldr r1,iAdrsZoneConv
bl conversion10 @ call décimal conversion
ldr r0,iAdrsMessResult
ldr r1,iAdrsZoneConv @ insert conversion in message
bl strInsertAtCharInc
bl affichageMess @ display message
subs r2,r2,#1
bgt 1b
100: @ standard end of the program
mov r0, #0 @ return code
mov r7, #EXIT @ request to exit program
svc #0 @ perform the system call
iAdrszCarriageReturn: .int szCarriageReturn
iAdrsMessResult: .int sMessResult
iAdrsZoneConv: .int sZoneConv
iAdriSeed: .int iSeed
/***************************************************/
/* compute pseudo random number */
/***************************************************/
/* r0 contains the number */
computePseudo:
push {r1-r2,lr} @ save registers
mov r2,r0
umull r0,r1,r2,r2
ldr r2,idiv
bl division32R
ldr r2,idiv2
bl division32R
mov r0,r2
pop {r1-r2,pc} @ restaur registers
idiv: .int 1000
idiv2: .int 1000000
/***************************************************/
/* division number 64 bits in 2 registers by number 32 bits */
/***************************************************/
/* r0 contains lower part dividende */
/* r1 contains upper part dividende */
/* r2 contains divisor */
/* r0 return lower part quotient */
/* r1 return upper part quotient */
/* r2 return remainder */
division32R:
push {r3-r9,lr} @ save registers
mov r6,#0 @ init upper upper part remainder !!
mov r7,r1 @ init upper part remainder with upper part dividende
mov r8,r0 @ init lower part remainder with lower part dividende
mov r9,#0 @ upper part quotient
mov r4,#0 @ lower part quotient
mov r5,#32 @ bits number
1: @ begin loop
lsl r6,#1 @ shift upper upper part remainder
lsls r7,#1 @ shift upper part remainder
orrcs r6,#1
lsls r8,#1 @ shift lower part remainder
orrcs r7,#1
lsls r4,#1 @ shift lower part quotient
lsl r9,#1 @ shift upper part quotient
orrcs r9,#1
@ divisor sustract upper part remainder
subs r7,r2
sbcs r6,#0 @ and substract carry
bmi 2f @ négative ?
@ positive or equal
orr r4,#1 @ 1 -> right bit quotient
b 3f
2: @ negative
orr r4,#0 @ 0 -> right bit quotient
adds r7,r2 @ and restaur remainder
adc r6,#0
3:
subs r5,#1 @ decrement bit size
bgt 1b @ end ?
mov r0,r4 @ lower part quotient
mov r1,r9 @ upper part quotient
mov r2,r7 @ remainder
100: @ function end
pop {r3-r9,lr} @ restaur registers
bx lr
/***************************************************/
/* ROUTINES INCLUDE */
/***************************************************/
.include "../affichage.inc"
</lang>
<pre>
959861
333139
981593
524817
432883
</pre>
=={{header|AWK}}==
=={{header|AWK}}==
<lang AWK>
<lang AWK>

Revision as of 16:08, 6 April 2022

Task
Pseudo-random numbers/Middle-square method
You are encouraged to solve this task according to the task description, using any language you may know.
Middle-square_method Generator
The Method

To generate a sequence of n-digit pseudorandom numbers, an n-digit starting value is created and squared, producing a 2n-digit number. If the result has fewer than 2n digits, leading zeroes are added to compensate. The middle n digits of the result would be the next number in the sequence and returned as the result. This process is then repeated to generate more numbers.

Pseudo code
var seed = 675248
function random()
    var s = str(seed * seed) 'str: turn a number into string
    do while not len(s) = 12
        s = "0" + s          'add zeroes before the string
    end do
    seed = val(mid(s, 4, 6)) 'mid: string variable, start, length
                             'val: turn a string into number
    return seed
end function
Middle-square method use
for i = 1 to 5
    print random()
end for
Task
  • Generate a class/set of functions that generates pseudo-random

numbers (6 digits) as shown above.

  • Show the first five integers generated with the seed 675248 as shown above.
  • Show your output here, on this page.


Ada

<lang Ada>with Ada.Text_IO; use Ada.Text_IO;

procedure Main is

  type long is range 0 .. 2**64;
  Seed : long := 675_248;
  function random return long is
  begin
     Seed := Seed * Seed / 1_000 rem 1_000_000;
     return Seed;
  end random;

begin

  for I in 1 .. 5 loop
     Put (long'Image (random));
  end loop;
  New_Line;

end Main;</lang>

Output:
 959861 333139 981593 524817 432883

ALGOL 68

Uses (long) integers. <lang algol68>BEGIN # generate random numbers by the middle-square method #

   INT seed := 675248;
   # returns the next middle-square random number #
   PROC ms random = INT: seed := SHORTEN( ( ( LONG INT( seed ) * LONG INT( seed ) ) OVER 1000 ) MOD 1 000 000 );
   # test the ms random procedure #
   FOR i TO 5 DO
       print( ( " ", whole( ms random, 0 ) ) )
   OD

END</lang>

Output:
 959861 333139 981593 524817 432883

AppleScript

<lang applescript>on newGenerator(n, seed)

   script generator
       property seed : missing value
       property p1 : 10 ^ (n div 2)
       property p2 : 10 ^ n
       
       on getRandom()
           set seed to seed * seed div p1 mod p2
           return seed div 1
       end getRandom
   end script
   
   set generator's seed to seed mod (10 ^ n)
   return generator

end newGenerator

local generator, output set generator to newGenerator(6, 675248) set output to {} repeat 5 times

   set end of output to generator's getRandom()

end repeat return output</lang>

Output:

<lang applescript>{959861, 333139, 981593, 524817, 432883}</lang>

ARM Assembly

Works with: as version Raspberry Pi
or android 32 bits with application Termux

<lang ARM Assembly> /* ARM assembly Raspberry PI or android with termux */ /* program pRandom.s */

/* REMARK 1 : this program use routines in a include file 
  see task Include a file language arm assembly 
  for the routine affichageMess conversion10 
  see at end of this program the instruction include */

/* for constantes see task include a file in arm assembly */ /************************************/ /* Constantes */ /************************************/ .include "../constantes.inc"

/*********************************/ /* Initialized data */ /*********************************/ .data sMessResult: .asciz " @ \n" szCarriageReturn: .asciz "\n"

iSeed: .int 675248 /*********************************/ /* UnInitialized data */ /*********************************/ .bss sZoneConv: .skip 24 /*********************************/ /* code section */ /*********************************/ .text .global main main: @ entry of program

   ldr r0,iAdriSeed
   ldr r3,[r0]
   mov r2,#5

1:

   mov r0,r3
   bl computePseudo
   mov r3,r0
   ldr r1,iAdrsZoneConv
   bl conversion10               @ call décimal conversion
   ldr r0,iAdrsMessResult
   ldr r1,iAdrsZoneConv          @ insert conversion in message
   bl strInsertAtCharInc
   bl affichageMess              @ display message
   subs r2,r2,#1
   bgt 1b

100: @ standard end of the program

   mov r0, #0                    @ return code
   mov r7, #EXIT                 @ request to exit program
   svc #0                        @ perform the system call

iAdrszCarriageReturn: .int szCarriageReturn iAdrsMessResult: .int sMessResult iAdrsZoneConv: .int sZoneConv iAdriSeed: .int iSeed /***************************************************/ /* compute pseudo random number */ /***************************************************/ /* r0 contains the number */ computePseudo:

   push {r1-r2,lr}           @ save registers 
   mov r2,r0
   umull r0,r1,r2,r2
   ldr r2,idiv
   bl division32R
   ldr r2,idiv2
   bl division32R
   mov r0,r2
   pop {r1-r2,pc}            @ restaur registers

idiv: .int 1000 idiv2: .int 1000000 /***************************************************/ /* division number 64 bits in 2 registers by number 32 bits */ /***************************************************/ /* r0 contains lower part dividende */ /* r1 contains upper part dividende */ /* r2 contains divisor */ /* r0 return lower part quotient */ /* r1 return upper part quotient */ /* r2 return remainder */ division32R:

   push {r3-r9,lr}    @ save registers
   mov r6,#0          @ init upper upper part remainder  !!
   mov r7,r1          @ init upper part remainder with upper part dividende
   mov r8,r0          @ init lower part remainder with lower part dividende
   mov r9,#0          @ upper part quotient 
   mov r4,#0          @ lower part quotient
   mov r5,#32         @ bits number

1: @ begin loop

   lsl r6,#1          @ shift upper upper part remainder
   lsls r7,#1         @ shift upper  part remainder
   orrcs r6,#1        
   lsls r8,#1         @ shift lower  part remainder
   orrcs r7,#1
   lsls r4,#1         @ shift lower part quotient
   lsl r9,#1          @ shift upper part quotient
   orrcs r9,#1
                      @ divisor sustract  upper  part remainder
   subs r7,r2
   sbcs  r6,#0        @ and substract carry
   bmi 2f             @ négative ?
   
                      @ positive or equal
   orr r4,#1          @ 1 -> right bit quotient
   b 3f

2: @ negative

   orr r4,#0          @ 0 -> right bit quotient
   adds r7,r2         @ and restaur remainder
   adc  r6,#0 

3:

   subs r5,#1         @ decrement bit size 
   bgt 1b             @ end ?
   mov r0,r4          @ lower part quotient
   mov r1,r9          @ upper part quotient
   mov r2,r7          @ remainder

100: @ function end

   pop {r3-r9,lr}     @ restaur registers
   bx lr  

/***************************************************/ /* ROUTINES INCLUDE */ /***************************************************/ .include "../affichage.inc" </lang>

959861
 333139
 981593
 524817
 432883

AWK

<lang AWK>

  1. syntax: GAWK -f PSEUDO-RANDOM_NUMBERS_MIDDLE-SQUARE_METHOD.AWK

BEGIN {

   seed = 675248
   srand(seed)
   for (i=1; i<=5; i++) {
     printf("%2d: %s\n",i,main())
   }
   exit(0)

} function main( s) {

   s = seed ^ 2
   while (length(s) < 12) {
     s = "0" s
   }
   seed = substr(s,4,6)
   return(seed)

} </lang>

Output:
 1: 959861
 2: 333139
 3: 981593
 4: 524817
 5: 432883

C

<lang c>#include<stdio.h> long long seed; long long random(){

       seed = seed * seed / 1000 % 1000000;
       return seed;

} int main(){

       seed = 675248;
       for(int i=1;i<=5;i++)
               printf("%lld\n",random());
       return 0;

}</lang>

Output:

959861 333139 981593 524817 432883

C++

<lang cpp>#include <exception>

  1. include <iostream>

using ulong = unsigned long;

class MiddleSquare { private:

   ulong state;
   ulong div, mod;

public:

   MiddleSquare() = delete;
   MiddleSquare(ulong start, ulong length) {
       if (length % 2) throw std::invalid_argument("length must be even");
       div = mod = 1;
       for (ulong i=0; i<length/2; i++) div *= 10;
       for (ulong i=0; i<length; i++) mod *= 10;
       state = start % mod;
   }
   
   ulong next() { 
       return state = state * state / div % mod;
   }

};

int main() {

   MiddleSquare msq(675248, 6);
   for (int i=0; i<5; i++)
       std::cout << msq.next() << std::endl;
   return 0;

}</lang>

Output:
959861
333139
981593
524817
432883

CLU

<lang clu>middle_square = cluster is seed, next

   rep = null
   own state: int
   
   seed = proc (s: int)
       state := s
   end seed
   
   next = proc () returns (int)
       state := (state ** 2) / 1000 // 1000000
       return(state)
   end next

end middle_square

start_up = proc ()

   po: stream := stream$primary_output()
   middle_square$seed(675248)
   for i: int in int$from_to(1, 5) do
       stream$putl(po, int$unparse(middle_square$next()))
   end

end start_up</lang>

Output:
959861
333139
981593
524817
432883

COBOL

<lang cobol> IDENTIFICATION DIVISION.

      PROGRAM-ID. MIDDLE-SQUARE.
      
      DATA DIVISION.
      WORKING-STORAGE SECTION.
      01 STATE.
         03 SEED         PIC 9(6) VALUE 675248.
         03 SQUARE       PIC 9(12).
         03 FILLER       REDEFINES SQUARE.
            05 FILLER    PIC 9(3).
            05 NEXT-SEED PIC 9(6).
            05 FILLER    PIC 9(3).
      
      PROCEDURE DIVISION.
      BEGIN.
          PERFORM SHOW-NUM 5 TIMES.
          STOP RUN.
      
      SHOW-NUM.
          PERFORM MAKE-RANDOM.
          DISPLAY SEED.
      
      MAKE-RANDOM.
          MULTIPLY SEED BY SEED GIVING SQUARE.
          MOVE NEXT-SEED TO SEED.</lang>
Output:
959861
333139
981593
524817
432883

F#

<lang fsharp> // Pseudo-random numbers/Middle-square method. Nigel Galloway: January 5th., 2022 Seq.unfold(fun n->let n=n*n%1000000000L/1000L in Some(n,n)) 675248L|>Seq.take 5|>Seq.iter(printfn "%d") </lang>

Output:
959861
333139
981593
524817
432883

Factor

Translation of: Phix
Works with: Factor version 0.99 2021-06-02

<lang factor>USING: kernel math namespaces prettyprint ;

SYMBOL: seed 675248 seed set-global

rand ( -- n ) seed get sq 1000 /i 1000000 mod dup seed set ;

5 [ rand . ] times</lang>

Output:
959861
333139
981593
524817
432883

Forth

Works with: gforth version 0.7.3

The loop keeps the seed on top of the stack. <lang forth>: next-random dup * 1000 / 1000000 mod ;

5-random-num 5 0 do next-random dup . loop ;

675248 5-random-num</lang>

Output:
959861 333139 981593 524817 432883  ok


FreeBASIC

<lang freebasic>Dim Shared seed As Integer = 675248 Dim i As Integer Declare Function Rand As Integer For i = 1 To 5 Print Rand Next i Sleep

Function Rand As Integer Dim s As String s = Str(seed ^ 2) Do While Len(s) <> 12 s = "0" + s Loop seed = Val(Mid(s, 4, 6)) Rand = seed End Function </lang>

Go

<lang go>package main

import "fmt"

func random(seed int) int {

   return seed * seed / 1e3 % 1e6

}

func main() {

   seed := 675248
   for i := 1; i <= 5; i++ {
       seed = random(seed)
       fmt.Println(seed)
   }

}</lang>

Output:
959861
333139
981593
524817
432883

Haskell

<lang haskell>findPseudoRandom :: Int -> Int findPseudoRandom seed =

  let square = seed * seed
      squarestr = show square
      enlarged = replicate ( 12 - length squarestr ) '0' ++ squarestr
  in read $ take 6 $ drop 3 enlarged

solution :: [Int] solution = tail $ take 6 $ iterate findPseudoRandom 675248</lang>

Output:
[959861,333139,981593,524817,432883]

J

<lang j>(_6{._3}.])&.:(10&#.^:_1)@(*~) ^: (>:i.6) 675248</lang>

Output:
959861 333139 981593 524817 432883 387691

jq

Works with gojq, the Go implementation of jq

The proposed PRNG hardly deserves the name and so this entry avoids it. <lang jq># Input: a positive integer

  1. Output: the "middle-square"

def middle_square:

 (tostring|length) as $len
 | (. * .)
 | tostring
 | (3*length/4|ceil) as $n
 | .[ -$n : $len-$n]
 | if length == 0 then 0 else tonumber end;
  1. Input: a positive integer
  2. Output: middle_square, applied recursively

def middle_squares:

 middle_square | ., middle_squares;

limit(5; 675248 | middle_squares)</lang>

Output:

As expected.

Julia

<lang julia>const seed = [675248]

function random()

   s = string(seed[] * seed[], pad=12) # turn a number into string, pad to 12 digits
   seed[] = parse(Int, s[begin+3:end-3]) # take middle of number string, parse to Int
   return seed[]

end

  1. Middle-square method use

for i = 1:5

   println(random())

end

</lang>

Output:
959861
333139
981593
524817
432883

Nim

Translation of: Raku

<lang nim>proc rand:int =

 var seed {.global.} = 675248
 seed = int(seed*seed) div 1000 mod 1000000
 return seed 

for _ in 1..5: echo rand()</lang>

Output:
959861
333139
981593
524817
432883

Perl

<lang perl>#!/usr/bin/perl

use strict; # https://rosettacode.org/wiki/Pseudo-random_numbers/Middle-square_method use warnings;

sub msq

 {
 use feature qw( state );
 state $seed = 675248;
 $seed = sprintf "%06d", $seed ** 2 / 1000 % 1e6;
 }

print msq, "\n" for 1 .. 5;</lang>

Output:
959861
333139
981593
524817
432883

Phix

You don't actually have to use strings, but should you so desire the commented-out line gives exactly the same results. Output matches Python.

with javascript_semantics
integer seed = 675248
function random()
    seed = remainder(floor(seed*seed/1000),1e6)
--  seed = to_integer(sprintf("%012d",seed*seed)[4..9])
    return seed
end function
for i=1 to 5 do
    ?random()
end for

PureBasic

<lang PureBasic>Procedure.i MSRandom()

 Static.i seed=675248
 seed = (seed*seed/1000)%1000000
 ProcedureReturn seed

EndProcedure

If OpenConsole()

 For i=1 To 5 : PrintN(Str(i)+": "+Str(MSRandom())) : Next
 Input()

EndIf</lang>

Output:
1: 959861
2: 333139
3: 981593
4: 524817
5: 432883

Python

<lang python>seed = 675248 def random():

   global seed
   s = str(seed ** 2)
   while len(s) != 12:
       s = "0" + s
   seed = int(s[3:9])
   return seed

for i in range(0,5):

   print(random())

</lang>

Output:
959861
333139
981593
524817
432883

Raku

<lang perl6>sub msq {

   state $seed = 675248;
   $seed = $seed² div 1000 mod 1000000;

}

say msq() xx 5;</lang>

Output:
(959861 333139 981593 524817 432883)

Red

Translation of: Phix

<lang rebol>Red[] seed: 675248 rand: does [seed: to-integer (seed * 1.0 * seed / 1000) % 1000000]  ; multiply by 1.0 to avoid integer overflow (32-bit) loop 5 [print rand]</lang>

Output:
959861
333139
981593
524817
432883

Ruby

<lang ruby>def middle_square (seed)

 return to_enum(__method__, seed) unless block_given?
 s = seed.digits.size
 loop { yield seed = (seed*seed).to_s.rjust(s*2, "0")[s/2, s].to_i }

end

puts middle_square(675248).take(5)</lang>

Output:
959861
333139
981593
524817
432883

Sidef

<lang ruby>class MiddleSquareMethod(seed, k = 1000) {

   method next {
       seed = (seed**2 // k % k**2)
   }

}

var obj = MiddleSquareMethod(675248) say 5.of { obj.next }</lang>

Output:
[959861, 333139, 981593, 524817, 432883]

UNIX Shell

Works with: zsh

<lang bash>seed=675248 random(){

       seed=`expr $seed \* $seed / 1000 % 1000000`
       return seed

} for ((i=1;i<=5;i++)); do

       random
       echo $?

done</lang>

Output:

The same as Python's

VBA

See Visual Basic

Visual Basic

Translation of: FreeBASIC
Works with: Visual Basic version 5
Works with: Visual Basic version 6

<lang vb>Option Explicit Dim seed As Long Sub Main()

   Dim i As Integer
   seed = 675248
   For i = 1 To 5
       Debug.Print Rand
   Next i

End Sub Function Rand() As Variant

   Dim s As String
   s = CStr(seed ^ 2)
   Do While Len(s) <> 12
       s = "0" + s
   Loop
   seed = Val(Mid(s, 4, 6))
   Rand = seed

End Function</lang>

Output:

As expected.

Wren

<lang ecmascript>var random = Fn.new { |seed| ((seed * seed)/1e3).floor % 1e6 }

var seed = 675248 for (i in 1..5) System.print(seed = random.call(seed))</lang>

Output:
959861
333139
981593
524817
432883

XPL0

<lang XPL0>real Seed; func Random; [Seed:= Floor(Mod(Seed*Seed/1e3, 1e6)); return fix(Seed); ];

int N; [Seed:= 675248.; for N:= 1 to 5 do

   [IntOut(0, Random);  ChOut(0, ^ )];

]</lang>

Output:
959861 333139 981593 524817 432883