simu v 2.0


SUBMITTED BY: foxhunters

DATE: Aug. 8, 2016, 12:19 a.m.

FORMAT: Text only

SIZE: 4.2 kB

HITS: 8084

  1. #!/bin/bash
  2. # brownian.sh
  3. # Author: Mendel Cooper
  4. # Reldate: 10/26/07
  5. # License: GPL3
  6. # ----------------------------------------------------------------
  7. # This script models Brownian motion:
  8. #+ the random wanderings of tiny particles in a fluid,
  9. #+ as they are buffeted by random currents and collisions.
  10. #+ This is colloquially known as the "Drunkard's Walk."
  11. # It can also be considered as a stripped-down simulation of a
  12. #+ Galton Board, a slanted board with a pattern of pegs,
  13. #+ down which rolls a succession of marbles, one at a time.
  14. #+ At the bottom is a row of slots or catch basins in which
  15. #+ the marbles come to rest at the end of their journey.
  16. # Think of it as a kind of bare-bones Pachinko game.
  17. # As you see by running the script,
  18. #+ most of the marbles cluster around the center slot.
  19. #+ This is consistent with the expected binomial distribution.
  20. # As a Galton Board simulation, the script
  21. #+ disregards such parameters as
  22. #+ board tilt-angle, rolling friction of the marbles,
  23. #+ angles of impact, and elasticity of the pegs.
  24. # To what extent does this affect the accuracy of the simulation?
  25. # ----------------------------------------------------------------
  26. PASSES=500 # Number of particle interactions / marbles.
  27. ROWS=10 # Number of "collisions" (or horiz. peg rows).
  28. RANGE=3 # 0 - 2 output range from $RANDOM.
  29. POS=0 # Left/right position.
  30. RANDOM=$$ # Seeds the random number generator from PID
  31. #+ of script.
  32. declare -a Slots # Array holding cumulative results of passes.
  33. NUMSLOTS=21 # Number of slots at bottom of board.
  34. Initialize_Slots () { # Zero out all elements of the array.
  35. for i in $( seq $NUMSLOTS )
  36. do
  37. Slots[$i]=0
  38. done
  39. echo # Blank line at beginning of run.
  40. }
  41. Show_Slots () {
  42. echo; echo
  43. echo -n " "
  44. for i in $( seq $NUMSLOTS ) # Pretty-print array elements.
  45. do
  46. printf "%3d" ${Slots[$i]} # Allot three spaces per result.
  47. done
  48. echo # Row of slots:
  49. echo " |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|"
  50. echo " ||"
  51. echo # Note that if the count within any particular slot exceeds 99,
  52. #+ it messes up the display.
  53. # Running only(!) 500 passes usually avoids this.
  54. }
  55. Move () { # Move one unit right / left, or stay put.
  56. Move=$RANDOM # How random is $RANDOM? Well, let's see ...
  57. let "Move %= RANGE" # Normalize into range of 0 - 2.
  58. case "$Move" in
  59. 0 ) ;; # Do nothing, i.e., stay in place.
  60. 1 ) ((POS--));; # Left.
  61. 2 ) ((POS++));; # Right.
  62. * ) echo -n "Error ";; # Anomaly! (Should never occur.)
  63. esac
  64. }
  65. Play () { # Single pass (inner loop).
  66. i=0
  67. while [ "$i" -lt "$ROWS" ] # One event per row.
  68. do
  69. Move
  70. ((i++));
  71. done
  72. SHIFT=11 # Why 11, and not 10?
  73. let "POS += $SHIFT" # Shift "zero position" to center.
  74. (( Slots[$POS]++ )) # DEBUG: echo $POS
  75. # echo -n "$POS "
  76. }
  77. Run () { # Outer loop.
  78. p=0
  79. while [ "$p" -lt "$PASSES" ]
  80. do
  81. Play
  82. (( p++ ))
  83. POS=0 # Reset to zero. Why?
  84. done
  85. }
  86. # --------------
  87. # main ()
  88. Initialize_Slots
  89. Run
  90. Show_Slots
  91. # --------------
  92. exit $?
  93. # Exercises:
  94. # ---------
  95. # 1) Show the results in a vertical bar graph, or as an alternative,
  96. #+ a scattergram.
  97. # 2) Alter the script to use /dev/urandom instead of $RANDOM.
  98. # Will this make the results more random?
  99. # 3) Provide some sort of "animation" or graphic output
  100. # for each marble played.
  101. Jipe points out a set of techniques for generating random numbers within a range.
  102. # Generate random number between 6 and 30.
  103. rnumber=$((RANDOM%25+6))
  104. # Generate random number in the same 6 - 30 range,
  105. #+ but the number must be evenly divisible by 3.
  106. rnumber=$(((RANDOM%30/3+1)*3))
  107. # Note that this will not work all the time.
  108. # It fails if $RANDOM%30 returns 0.
  109. # Frank Wang suggests the following alternative:
  110. rnumber=$(( RANDOM%27/3*3+6 ))

comments powered by Disqus