mIRC Home    About    Download    Register    News    Help

Print Thread
shuffle a list to join channels #239884 30/11/12 01:11 AM
Joined: Apr 2010
Posts: 59
A
ascription Offline OP
Babel fish
OP Offline
Babel fish
A
Joined: Apr 2010
Posts: 59
Hello Forum,

Notwithstanding my recent threads in the 'Feature Suggestions' forum, I have a challenge for you.

I would like to join 3 channels in a random order. The trivial solution is to enumerate the possible orders of the list, and pick a random integer 1..6. [untested]

Code:
var %rand0 $rand(1,6)
if (%rand0 == 1)
  join A B C
elseif (%rand0 == 2)
  join A C B
elseif (%rand0 == 3)
  join B A C
elseif (%rand0 == 4)
  join B C A
elseif (%rand0 == 5)
  join C A B
elseif (%rand0 == 6)
  join C B A

But this is unwieldy, and inconvenient for a list of 4 channels, let alone 5 channels with 120 permutations or 6 with 720.

How do you shuffle a list in MSL?

Re: shuffle a list to join channels [Re: ascription] #239885 30/11/12 03:32 AM
Joined: Oct 2012
Posts: 164
D
Deega Offline
Vogon poet
Offline
Vogon poet
D
Joined: Oct 2012
Posts: 164
Theres probably a better solution but...
Code:
  var %chans = #1 #2 #3 #4 #5 #6
  var %a,%b
  while %chans { var %a = $gettok(%chans,$r(1,$numtok(%chans,32)),32),%b = $addtok(%b,%a,44),%chans = $remtok(%chans,%a,1,32) }
  Join %b


Re: shuffle a list to join channels [Re: ascription] #239892 02/12/12 06:20 AM
Joined: Oct 2003
Posts: 3,918
A
argv0 Offline
Hoopy frood
Offline
Hoopy frood
A
Joined: Oct 2003
Posts: 3,918
You can use /filter -a to sort a hidden window. Presumably you're not hardcoding the channels, so they're coming from a list anyway, which means you can /filter from some "channels.txt" input file.

Code:
alias filtersort.rand { return $calc($rand(0,2) - 1) }
alias joinrand { 
  var %i = 1, %channels = ""
  window -h @joinrand
  filter -afw channels.txt @joinrand filtersort.rand *
  while ($line(@joinrand,%i)) {
    %channels = $addtok(%channels,$v1,44)
    inc %i
  }
  join %channels
  window -c @joinrand
}


- argv[0] on EFnet #mIRC
- "Life is a pointer to an integer without a cast"
Re: shuffle a list to join channels [Re: argv0] #239895 02/12/12 09:11 AM
Joined: Dec 2002
Posts: 339
D
drum Offline
Fjord artisan
Offline
Fjord artisan
D
Joined: Dec 2002
Posts: 339
Originally Posted By: argv0
You can use /filter -a to sort a hidden window. Presumably you're not hardcoding the channels, so they're coming from a list anyway, which means you can /filter from some "channels.txt" input file.


This is sort of a cool trick, but it won't give you a uniform distribution. (For example, the first channel in the list will be more likely to appear first after the "sort" than other channels.) I wouldn't recommend this method if you're looking for unbiased results.

Re: shuffle a list to join channels [Re: drum] #239902 03/12/12 12:20 AM
Joined: Oct 2003
Posts: 3,918
A
argv0 Offline
Hoopy frood
Offline
Hoopy frood
A
Joined: Oct 2003
Posts: 3,918
Originally Posted By: drum
but it won't give you a uniform distribution.


How is this any different from any use of $rand in mIRC? You're pointing out a flaw with mIRC's random number generator, not with the methodology.

Do you have a better solution?


- argv[0] on EFnet #mIRC
- "Life is a pointer to an integer without a cast"
Re: shuffle a list to join channels [Re: argv0] #239903 03/12/12 01:25 AM
Joined: Dec 2002
Posts: 339
D
drum Offline
Fjord artisan
Offline
Fjord artisan
D
Joined: Dec 2002
Posts: 339
Originally Posted By: argv0
Originally Posted By: drum
but it won't give you a uniform distribution.


How is this any different from any use of $rand in mIRC? You're pointing out a flaw with mIRC's random number generator, not with the methodology.


No, it's not an issue with $rand. It's because sorting algorithms work on the assumption that if A comes before B, and B comes before C, then A must come before C. However that isn't true with $filtersort.rand. I can't really get into more detail that than without knowing the exact algorithm that mIRC uses for sorting with /filter, but I ran a trial with your method and there was a clear bias.

Quote:
Do you have a better solution?


Deega's method (or any method not relying on a sorting algorithm) is fine.

Re: shuffle a list to join channels [Re: drum] #239939 06/12/12 01:11 PM
Joined: Apr 2010
Posts: 59
A
ascription Offline OP
Babel fish
OP Offline
Babel fish
A
Joined: Apr 2010
Posts: 59
I didn't state whether I needed "uniform" random numbers, or just shake it up a little. But it wouldn't be long until I encountered Mr. Drum's concerns in other applications, especially something like cryptography.

If the $rand routine is uniform, Mr. Argv0's solution will be skewed. Otherwise, both are skewed and you might need to implement your own.

MSL only has one data structure, hash tables, just like PHP. But according to the docs, entries can be accessed with integer indices, therefore a random item can be used and removed.

I tinkered around with hash tables a bit; I haven't used them much. I'm having problems accessing the data associated with an item, but the script is successful this far.
Code:
alias test {
  if (!$hget(testhash)) hmake testhash
  var %k 5
  while (%k) {
    hadd -s testhash item $+ %k data $+ %k
    dec %k
  }
  echo -s size: $hget(testhash, 0).item
  while ($hget(testhash, 0).item) {
    var %r $rand(1, $hget(testhash, 0).item)
    var %i $hget(testhash, %r).item
    var %d %hget(testhash, %r).data
    var %d2 %hget(testhash, %r)
    var %d3 %hget(testhash, %i).data
    var %d4 %hget(testhash, %i)
    echo -s r %r i %i d %d %d2 %d3 %d4
    hdel testhash %i
  }
  echo -s testhash
  hfree testhash
}

The expected output is:
Code:
size: 5
r 4 i item3 d data3
r 4 i item1 d data1
r 3 i item2 d data2
r 1 i item4 d data4
r 1 i item5 d data5
testhash

But the observed output is:
Code:
size: 5
r 4 i item3 d
r 4 i item1 d
r 3 i item2 d
r 1 i item4 d
r 1 i item5 d
testhash

Any ideas?

Re: shuffle a list to join channels [Re: ascription] #239940 06/12/12 01:40 PM
Joined: Dec 2002
Posts: 339
D
drum Offline
Fjord artisan
Offline
Fjord artisan
D
Joined: Dec 2002
Posts: 339
You accidentally used %hget in a few places instead of $hget. That method should work otherwise.

Re: shuffle a list to join channels [Re: drum] #239946 08/12/12 08:07 AM
Joined: Apr 2010
Posts: 59
A
ascription Offline OP
Babel fish
OP Offline
Babel fish
A
Joined: Apr 2010
Posts: 59
That is rather subtle. I want a hammer that is less easy to drop on my foot. Not to mix metaphors.

Replacing the script command:
Code:
    echo -s r %r i %i d %d d2 %d2 d3 %d3 d4 %d4

Gives the output:
Code:
size: 5
r 5 i item1 d data1 d2 d3 5 d4 data1
r 3 i item2 d data2 d2 d3 4 d4 data2
r 2 i item5 d data5 d2 d3 3 d4 data5
r 2 i item3 d data3 d2 d3 2 d4 data3
r 1 i item4 d data4 d2 d3 1 d4 data4
testhash

That means that "$hget(testhash, %r).data" and "$hget(testhash, %i)" do what I want but "$hget(testhash, %r)" and "$hget(testhash, %i).data" don't.

Why is there a "$gettok(.., 44)" in Deega's solution? Would Join operate correctly on more channels than the network target max?