Set of scripts used for various projects.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

105 lines
2.3 KiB

  1. #!/bin/sh -
  2. # Input, a file with a weight following by contents. The weight
  3. # is a number w/ a decimal point that is a weight factor that the
  4. # line will be returned. That is, the probability of a line being
  5. # selected and printed is weight / (sum of all weights).
  6. #
  7. # Sample input file:
  8. # .9 a
  9. # 1.2 b
  10. # 1.1 c
  11. #
  12. # a will be output w/ prob .9 / 3.2, b w/ prob 1.2 / 3.2 and c w/ prob 1.1 / 3.2
  13. #
  14. # Testing:
  15. # for i in $(jot 1000); do (echo .5 a; echo 1.0 b; echo 1.0 c ) | sh randomline.fudge.sh ; done | sort | uniq -c
  16. #
  17. # a P(1/5) or ~200, b and c each P(2/5) or ~400
  18. #
  19. # for i in $(jot 1000); do (echo .5 a; echo .5 b; echo .5 c; echo .5 d; echo .5 e; echo .5 f; echo .5 g; echo .5 h; echo 1.0 i ) | sh randomline.fudge.sh ; done | sort | uniq -c
  20. #
  21. # srand seed:
  22. # "dd if=/dev/random 2>/dev/null | LC_ALL=C tr -d -c 1-9 | dd bs=1 count=19 2>/dev/null" | getline seed; srand(seed)
  23. # + rand()
  24. LC_ALL=C awk '
  25. function urandom(n) {
  26. # return random [0, n)
  27. # maxn needs to be 2**(x*4), and cbs=x
  28. maxn = 4294967296
  29. if (n == 1)
  30. return 0
  31. if (n > maxn) {
  32. printf("n too large!\n") > "/dev/stderr"
  33. exit(5)
  34. }
  35. for (;;) {
  36. "dd if=/dev/random | LC_ALL=C tr -c -d 0-9a-f | dd conv=unblock cbs=8" | getline a
  37. r = ("0x" a) + 0
  38. quot = int(maxn / n) * n
  39. if (r >= quot)
  40. continue
  41. return r % n
  42. }
  43. }
  44. function getfudge(i, j) {
  45. dot = index(i, ".")
  46. if (dot == 0) {
  47. printf("invalid fudge, no dot\n") > "/dev/stderr"
  48. exit(6)
  49. }
  50. # .33
  51. precs = length(i) - dot
  52. #print "a" precs " " length(i) " " dot
  53. precsv = 1
  54. for (j = 0; j < precs; j++) {
  55. precsv = 10 * precsv
  56. }
  57. return i + 0.0
  58. }
  59. {
  60. fudge = getfudge($1) * precsv
  61. # to be slightly better, split off length of $1, then find $2 and return that
  62. $0 = substr($0, index($0, $2))
  63. if (NR == 1) {
  64. save = $0
  65. # total fraction so far
  66. runfudge = fudge
  67. # precision of total fraction
  68. runprecsv = precsv
  69. next
  70. }
  71. if (runprecsv < precsv) {
  72. runfudge = runfudge * (precsv / runprecsv)
  73. runprecsv = precsv
  74. } else {
  75. fudge = fudge * (runprecsv / precsv)
  76. }
  77. #print "f: " fudge ", precs: " precs " " precsv ", runfudge: " runfudge " " runprecsv " " (runfudge + fudge)
  78. #"jot -r 1 0 " (NR - 1) | getline a
  79. a = urandom((runfudge + fudge))
  80. #a = int(rand() * (NR))
  81. #print "a: " a ", fudge: " fudge
  82. if (a < fudge)
  83. save = $0
  84. runfudge += fudge
  85. }
  86. END { print save }'