mIRC Home    About    Download    Register    News    Help

Print Thread
Page 1 of 2 1 2
#43507 22/08/03 07:34 AM
Joined: Dec 2002
Posts: 196
T
Vogon poet
OP Offline
Vogon poet
T
Joined: Dec 2002
Posts: 196
Instead of using $read files, maybe $rand(aa,bz) or something like that should work too.

It will show anything between aa and bz, eg ab bd bg ak etc.

That would be nice apart from numbers.


trenzterra
AustNet #trenzterra and #w
Head Scripter @ http://trenzterra.uni.cc
#43508 22/08/03 08:50 AM
Joined: Dec 2002
Posts: 1,321
H
Hoopy frood
Offline
Hoopy frood
H
Joined: Dec 2002
Posts: 1,321
In order to overcome the limitation posed by $rand's failure to pick the first choice as often as it should, use $randletter instead:
Code:

alias randletter {
  [color:#006600]
  ;  Make sure the first character of each of the inputs are letters.
  ;  [/color]
  if $$1 !isletter || $$2 !isletter {
  [color:#006600]
    ;  Echo an appropriate error message patterned after mIRC's own error messages.
    ;  [/color]
    echo $color(info) -esti * Invalid parameters: $randletter
  [color:#006600]
    ;  Halt the script in the error condition
    ;  [/color]
    halt
  }
  [color:#006600]
  ;  Start with a known non-letter.
  ;  [/color]
  var %rand = 33
  [color:#006600]
  ;  Repeatedly pick random characters until one is in the range specified and a letter.
  ;  [/color]
  while $chr(%rand) !isletter { 
  [color:#006600]
    ;  Find a random value in the range specified (plus one for error correction).
    ;  [/color]
    var %rand = $rand($asc($1), $calc($asc($2) + 1)) }
  [color:#006600]
    ;  Correct for the $rand error, if necessary, if $2 is overshot by 1.
    ;  [/color]
    if %rand == $calc($asc($2) + 1) {
  [color:#006600]
      ;  Return the first character of the range if we overshoot.
      ;  [/color]
      return $1 
    }
  [color:#006600]
    ;  Repeat until a valid letter is found.  [/color]
  }
  [color:#006600]
  ;  Return the character found.
  ;  [/color]
  return $chr(%rand)
}

//echo -a * $randletter(a,b) $+ $randletter(A,z) $+ $randletter(A,Z) $+ $randletter(a,z)


DALnet: #HelpDesk and #m[color:#FF0000]IR[color:#EEEE00]C
#43509 22/08/03 03:48 PM
Joined: Feb 2003
Posts: 2,812
Hoopy frood
Offline
Hoopy frood
Joined: Feb 2003
Posts: 2,812
What trenzterra was asking for is an alias that can choose double-digit letters, like AA through BZ, as you might find in a card index or spread sheet.

I dont see any problem with the consistancy a random letter or number is chosen by $rand. The following experiment tests the consistancy that $rand chooses a random letter from 'a' through 'z'.

The Code:
//var %n = 2600 | WHILE %n { hinc -m rand $r(a,z) | dec %n }

The Results, with 2600 loops (each letter should average 100 hits):
a 121, b 94, c 92, d 99, e 85, f 103, g 104, h 88, i 99, j 95, k 94, l 115, m 91,
n 99, o 101, p 118, q 105, r 95, s 96, t 92, u 93, v 107, w 99, x 110, y 102, z 103.

The Results, with 260000 loops:
a 10147, b 10130, c 10028, d 9815, e 9974, f 10080, g 9947, h 9983, i 9812,
j 9846, k 9965, l 9697, m 10057, n 10129, o 9964, p 10063, q 10054, r 10015,
s 10026, t 10016, u 10104, v 10028, w 9999, x 10009, y 10124, z 9988.

If anything, $rand is more likely to pick the first letter the most, not the least.
Otherwise, it's completely even distribution.

- Raccoon


Well. At least I won lunch.
Good philosophy, see good in bad, I like!
#43510 22/08/03 06:09 PM
Joined: Dec 2002
Posts: 343
D
Pan-dimensional mouse
Offline
Pan-dimensional mouse
D
Joined: Dec 2002
Posts: 343
Maybe $rand could be extended so it would work like the below.

$rand(a,z,1,999,A,Z,5,9) would return the same thing as below.

$rand(a,z) $+ $rand(1,999) $+ $rand(A,Z) $+ $rand(5,9)

#43511 22/08/03 06:18 PM
Joined: Jan 2003
Posts: 2,523
Q
Hoopy frood
Offline
Hoopy frood
Q
Joined: Jan 2003
Posts: 2,523
These incosistencies are apparent when you use $rand(number1,number2). In this case, the edge numbers appear half as often. I didn't know $rand(letter1,letter2) isn't affected, neither did Hammer probably.


/.timerQ 1 0 echo /.timerQ 1 0 $timer(Q).com
#43512 22/08/03 06:36 PM
Joined: Feb 2003
Posts: 2,812
Hoopy frood
Offline
Hoopy frood
Joined: Feb 2003
Posts: 2,812
Oh wow, I had no idea about that bug... but it's true!

Guess I'll be using something like this until it's fixed...

/r2 { :1 | if ($r($calc($1 -1),$calc($2 +1)) isnum $+($1,-,$2)) return $ifmatch | goto 1 }

does the trick... at nearly 1/3rd the speed.


Well. At least I won lunch.
Good philosophy, see good in bad, I like!
#43513 22/08/03 07:09 PM
Joined: Dec 2002
Posts: 343
D
Pan-dimensional mouse
Offline
Pan-dimensional mouse
D
Joined: Dec 2002
Posts: 343
That's an old bug I remember. $rand(1,3) will have 1 come about 25% of the time. 2 will come up 50% of the time. And 3 will come up 25% of the time.

If this ever does get fixed, do you think it would be worth it to have "$rand(1,10,a,z)" to replace "$rand(1,10) $rand(a,z)"? I was going to say "$rand(1,10) $+ $rand(a,z)" but then it's hard separating it since you don't know where the space should be all the time.

#43514 22/08/03 07:47 PM
Joined: Feb 2003
Posts: 2,812
Hoopy frood
Offline
Hoopy frood
Joined: Feb 2003
Posts: 2,812
There are many different ways I would write a $rand function.
The difficulty is to preserve backward compatibility since $rand already exists.
If I didn't have to worry about that though, here are some of the ways I might do it.

1. Each parameter is a single character or range of characters to be selected randomly from.
The result will be a single character picked from the list.

$rand(0-9,A-F) which would generate a random hexidecimal character.
$rand(0-9,A-Z,a-z,_,^,`,\,|,[,],{,},-) which would generate a random nickname character.
$rand(0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,...etc) which would do the same.

2. Or like a regular expression class. Even include the []'s to help with backward compatibility.

$rand([][0-9A-Za-z_^`|{}\-]) generates a single nickname character.
$rand([][0-9A-Za-z_^`|{}\-]{9}) generates a string of 9 nickname characters.
$rand([][0-9A-Za-z_^`|{}\-]{1,9}) generates a string of $r(1,9) nickname characters.
Perhaps additional parameters could each have different ranges of characters.
$rand([][A-Za-z_^`|{}\], [][0-9A-Za-z_^`|{}\-]{8}) generates a real random nick. (no numbers or '-' for first character)

3. Dice roll syntex. Perhaps it's own $roll identifier.
$roll(5d20+4) == $calc($r(1,20) + $r(1,20) + $r(1,20) + $r(1,20) + $r(1,20) + 4)
There are too many varying roll syntex that exist, so I'll leave it with this simple example.

Just some of the ideas I had in mind anyway.


Well. At least I won lunch.
Good philosophy, see good in bad, I like!
#43515 22/08/03 07:57 PM
Joined: Dec 2002
Posts: 343
D
Pan-dimensional mouse
Offline
Pan-dimensional mouse
D
Joined: Dec 2002
Posts: 343
That seems complex and would probably break compatibility.

I would think "$rand(1,9,A,Z)" returning the same as "$rand(1,9) $rand(A,Z)" would be enough or a first step. Since it gets rid of the extra $rand identifiers. And "$remove($rand(1,9,A,Z),$chr(32))" would return it without the spaces inbetween.

#43516 22/08/03 08:11 PM
Joined: Dec 2002
Posts: 2,962
S
Hoopy frood
Offline
Hoopy frood
S
Joined: Dec 2002
Posts: 2,962
I think just support for what the original poster asked for would be fine, all that other stuff is largely unnecessary.

Slightly off-topic here but this alias is marginally faster than yours plus it can take letters (and it doesn't use a nasty goto).

Code:
my_rand {
  if ($+($1,$2) !isnum) return $rand($1,$2)
  if ($rand($1,$calc($2 + 1)) <= $2) return $ifmatch
  return $1
}


Spelling mistakes, grammatical errors, and stupid comments are intentional.
#43517 22/08/03 09:19 PM
Joined: Feb 2003
Posts: 2,812
Hoopy frood
Offline
Hoopy frood
Joined: Feb 2003
Posts: 2,812
very cleaver.

$my_rand(1,100) == $rand(1,101)
if (101) then 1

since both are chosen only half the number of times they ought to be, their combined effort evens the odds... and no wasted mis-fires.

very cleaver indeed.


Well. At least I won lunch.
Good philosophy, see good in bad, I like!
#43518 22/08/03 11:06 PM
Joined: Jan 2003
Posts: 2,523
Q
Hoopy frood
Offline
Hoopy frood
Q
Joined: Jan 2003
Posts: 2,523
does the trick... at nearly 1/3rd the speed.
Compared to what? I kinda lost you there.

Hammer's algorithm is faster (constant-time), as it takes advantage of the fact that edge numbers appear exactly half as often. Here's the r2 alias that implements this algorithm:

alias r2 if $rand($1,$calc($2 + 1)) <= $2 { return $ifmatch } | return $1

Your method could fix any edge-numbers problem, this one can only fix the current $rand().


/.timerQ 1 0 echo /.timerQ 1 0 $timer(Q).com
#43519 22/08/03 11:37 PM
Joined: Dec 2002
Posts: 2,809
C
Hoopy frood
Offline
Hoopy frood
C
Joined: Dec 2002
Posts: 2,809
Someone should just make a dll to use mt_rand.

#43520 22/08/03 11:55 PM
Joined: Feb 2003
Posts: 2,812
Hoopy frood
Offline
Hoopy frood
Joined: Feb 2003
Posts: 2,812
>>does the trick... at nearly 1/3rd the speed.
>Compared to what? I kinda lost you there.

My $r2 function compared to mIRC's $rand function. my $r2 is 3x slower than $rand.
I meant to phrase that "but at 1/3rd the speed."

>Hammer's algorithm is faster (constant-time), as it takes advantage of the fact that edge numbers appear exactly half as often. Here's the r2 alias that implements this algorithm:

I didn't completly deceminate the method he was using, because I was too busy disproving any bug with $rand(a,z). I do see now that his example, though it didn't support numbers, used the same logic as starbuck's-- so I shout praise in hammer's direction too.

> alias r2 if $rand($1,$calc($2 + 1)) <= $2 { return $ifmatch } | return $1
> Your method could fix any edge-numbers problem, this one can only fix the current $rand().

Agreed. But that's all we want to do, is fix the edge problem... isn't it?
And that looks exactly like starbuck's code, sans bounds checking for letters.

All I was doing is saluting starbuck's example.
I'm sorry I missed the method behind hammer's code.


Well. At least I won lunch.
Good philosophy, see good in bad, I like!
#43521 23/08/03 12:25 AM
Joined: Jan 2003
Posts: 2,523
Q
Hoopy frood
Offline
Hoopy frood
Q
Joined: Jan 2003
Posts: 2,523
Oops, by the time I submitted my reply, starbucks and you had replied. I read the 2 replies only after I submitted. This is what happens when I do other things in the middle of the "preview post"...


/.timerQ 1 0 echo /.timerQ 1 0 $timer(Q).com
#43522 23/08/03 10:18 AM
Joined: Dec 2002
Posts: 1,321
H
Hoopy frood
Offline
Hoopy frood
H
Joined: Dec 2002
Posts: 1,321
[color:00007F]qwerty[/color]:
I did know letters are unaffected, though I didn't really remember it until someone mentioned it; however, since I was using the the $asc() value of the letters, I had to take into account the edge number problem, which is why I did it the way I did. As I mentioned to you on EFnet, I did it this way to allow case sensitivity and omit intervening [\]^_` between upper and lower case (ASCII 91-96). $rand will allow $rand(A,Z) or $rand(a,z) but not $rand(A,z).

Raccoon:
It does not support number only because he did not ask for it to do so. That is why I specifically checked !isletter instead of !isalnum. Removing the check simplifies the code and you can specify any kind of range you wish, including not only letters but also punctuation or high ASCII as well. Here are my original results as posted to this forum for reference.

As far as the portion of the code to double (or more) the letters, I left that as an exercise for the poster for specific reasons.
  • There was no intented use specified and I can easily visualize ways this sort of thing can be used maliciously.
  • There would need to be some sort of formatting design decisions made which are not evident in the original post. For example, how will it handle $rand(a,ZZZZZ) or $rand(zzzz,a). Note that both are "backwards" in addition to being of differing lengths. Thus, they are interpretable in multiple ways, none of which were expressed in the original post.
  • No data validation was mentioned, which is why I only included the sole check indicated by that post. As I left it, it is possible to specify a backward range. Since $!rand(15,1) works (even though $!rand(z,a) doesn't) and my method converts to ASCII first, my version can handle backward ranges.
  • On another, more careful, reading of the original post, the first character of the first parameter is the lower bound and the first character of the second parameter is the upper bound for that character position in the result string. This would be simple enough to accomplish in an alias that wraps $randletter(), passing it $mid($1,%i,1) and $mid($2,%i,1) if you assume (or correct for, as below) that $1 and $2 will be of equal length; again, though, you might need data validation for each loop iteration.
    Code:
    
    alias multirand {
      var %result, %1 = $left($1,$len($$2)), %2 = $left($2,$len(%1)), %i = 1, %limit = $calc($len(%1) + 1)
      while %i &lt; %limit { var %result = $+(%result,$randletter($mid(%1,%i,1),$mid(%2,%i,1))), %i = %i + 1 }
      return %result
    }

    //echo -a * $multirand(aa,bz) $multirand(aaa,bft)
    * at bdj
  • Perhaps I erred in allowing upper-case letters to be mixed with lower-case letters and should have just $lower()'d the input, since that is how it was presented in the original suggestion.
These are my reasons for leaving the scripted reply in the state I did. The omissions were intentional.

Personally, if I were the one designing it, I would change the format entirely and use $multirand(<valid characters (ranges allowed)>, [length]) where $mutlirand(0-9A-Za-z,3) might return g3A, and the length parameter is optional, defaulting to 1. This would be even simpler to implement, since you just have two loops, the outer loop builds the string and var %re = /([ $+ $1 $+ ])/), then the inner loop is a simple while $regex($rand(%low,%high), %re) == 0 { continue } and then build %result = $+(%result,$regml(1)). The error checking and determining %low and %high would take longer to write than the actual meat of the code. This method will probably be slower, though, since it calls $regex.

If you've made it this far, kudos and cookies are at the table on the left. I hope I haven't left any questions you had about my code or the reasons behind it unaddressed.


DALnet: #HelpDesk and #m[color:#FF0000]IR[color:#EEEE00]C
#43523 23/08/03 01:46 PM
Joined: Jan 2003
Posts: 2,523
Q
Hoopy frood
Offline
Hoopy frood
Q
Joined: Jan 2003
Posts: 2,523
however, since I was using the the $asc() value of the letters, I had to take into account the edge number problem, which is why I did it the way I did.

You're right of course. Even though I did see $asc() in your code, I accidentally thought you were using $rand(letter1,letter2) (it's amazing how stupid mistakes I can make sometimes, isn't it).


/.timerQ 1 0 echo /.timerQ 1 0 $timer(Q).com
#43524 23/08/03 02:07 PM
Joined: Dec 2002
Posts: 196
T
Vogon poet
OP Offline
Vogon poet
T
Joined: Dec 2002
Posts: 196
Since you asked for the syntax, I will gladly post it.

$rand(zz,a) will show a letter from a to zz.

$rand(a,zz) will do the same too.

It would be good to have case sensitive too, and have ZZ superior to zz.

As another poster suggested, $rand(a,zz,2,33) etc is quite a good idea I reckon.


trenzterra
AustNet #trenzterra and #w
Head Scripter @ http://trenzterra.uni.cc
#43525 23/08/03 02:40 PM
Joined: Dec 2002
Posts: 2,985
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 2,985
If you have one case superior to the other then the result is not random, is it?

#43526 23/08/03 02:46 PM
Joined: Dec 2002
Posts: 1,541
L
Hoopy frood
Offline
Hoopy frood
L
Joined: Dec 2002
Posts: 1,541
what Id like to see is something like this:

$rand(1-100,151-200) where it picks a random number between 1 and 200 ignoring numbers 101 thru 150.


Those who fail history are doomed to repeat it
Page 1 of 2 1 2

Link Copied to Clipboard