From WikiChip
/hmake Command - mIRC
< mirc‎ | commands
Revision as of 22:06, 16 June 2018 by Maroonbells (talk | contribs)

The /hmake command can be used to create a new hash table by a specific handle name.

A hash table is stored entirely in memory and thus it is the programmer's responsibility to save the data to a file if necessary via the /hsave command (and load it back later via the /hload command).

It's generally best to have the number of buckets be a prime number, but mIRC gives the user a large variety of choices. Instead of forcing the number of buckets to be prime, mIRC only forces the number to be odd. If [num_buckets] is an even number, mIRC will add one to the number. The default parameter for number of buckets is 100, with allowed values from 1 to 10000. Since even numbers are incremented to make them odd, the actual range is 1 to 10001 - with the default 100 incremented to 101, which is a prime number.

A hash table name is limited to 256 significant characters - any additional characters are simply ignored. In mIRC, a hash table is a much faster alternative to ini and normal text files.

Note: For most practical purposes, it's best to keep the ratio of <item count>:<maximum capacity> at 78% to maintain a good time-space tradeoff (i.e. 0.78 load factor). That means if you are planning on storing 78 items in the hash table, you should create a hash table with the size of 100 buckets. (A table of 1000 buckets is good to store up to about 780 items to maintain a maximum performance). The general equation to calculate optimal number of buckets is:

  • [#_of_buckets] = [#_of_keys_that_will_be_used] / 0.78

Linked List

Because the hash table uses chaining to resolve collisions and due to the fact mIRC does not rehash or grows the array, using a hash table with 1 bucket, the hmake command can be used to create a linked list. New items are added to the start of the chain (i.e. $hget(<table_name>, 1) will always be last item added). Additionally, changing the value or removing an item does not alter the overall order of the list.

Synopsis

/hmake [-s] <table_name> [num_buckets]

Switches

  • -s - displays a successful creation, or reports the table already exists

Parameters

  • <table_name> - The name of the table you wish to make.
  • [num_buckets] - The number of buckets to use as the table's capacity (If no number is specified, the default is 100)

Example

A basic usage for a hash table.

; call the setup once
; /abbr_setup
;
; //echo -a $abbr(lol)
;
alias abbr_setup {
  ;create the table
  hmake abbr 1000
 
  ; populate the table
  hadd abbr lol laughing out load
  hadd abbr omg oh my gosh
  hadd abbr lmao laughing my a?? off
  hadd abbr brb be right back
 
  ; ...
}
; get the abbreviation
alias abbr return $hget(abbr, $1)

Because a hash table of 1 buck is the same as a linked list, we can easily implement an almost-native stack data structure.

;/stack_example
; Output:
;   poped: DDD
;   poped: CCC
;   poped: BBB
;   poped: AAA
alias stack_example {
  ; create a linked-list
  hmake stack 1
 
  ; push items
  push stack AAA
  push stack BBB
  push stack CCC
  push stack DDD
 
  ; pop everything
  while ($pop(stack)) {
    echo -a poped: $v1
  }
 
  ; delete linked-list
  hfree stack
}
alias push {
  ; keep a counter so we keep a unique key each time
  if (!$hget($1,0).item) hadd $1 counter 1
  else hadd $1 counter $calc($hget($1, counter).data + 1)
 
  ; make it the first item
  hadd $1 key. $+ $hget($1, counter).data $2
}
alias pop {
  if ($hget($1, 1).item != counter && $hget($1, 1).data) {
    ; delete the item
    hdel $1 $hget($1, 1).item
    ; return value
    return $v1
  }
}
//hfree -sw test | hmake -s test 1 | var %i 1 | while (%i isnum 1-50) { hadd test item $+ $base(%i,10,10,3) data | inc %i } | var %n 1 | while ($hget(test,%n).item) { echo -a $ord(%n) itemname is $v1 | inc %n }
* Demonstrates how table items are accessed by $hget(table,N) in reverse order of creation if table created with 1 bucket. Changing the hmake command to use a larger number of buckets causes the items to be associated with N in a non-sequential pattern.
 
//hfree -sw test | hmake -s test | var %i 9999 , %ticks $ticks | while (%i) { var %test $+ %i data %i | dec %i } | echo 4 -a done $calc($ticks - %ticks) ticks
//hfree -sw test | hmake -s test | var %i 9999 , %ticks $ticks | while (%i) { hadd test    %i data %i | dec %i } | echo 4 -a done $calc($ticks - %ticks) ticks
* Demonstrates that it can be 10x faster to create a hashtable containing 9999 items than to create 9999 local %variables.
 
//hfree -sw test | hmake -s test 2 | var %i 1 , %a | while (%i isnum 1-999) { hadd test item $+ $base(%i,10,10,3) data | inc %i } | var %n 1 | while ($hget(test,%n).item) { var %a $sha1(%a $v1) | inc %n } | echo -a hash of item sequence %a
* Demonstrates that the number of buckets is always an odd number. An even number of buckets and even+1 arrange the items in the same sequence.
 
* If needing items to always be in a predictable sequence, you can't count on using /hsave and /hload to preserve that order. By using 1 bucket, this example creates Item $+ N as the Nth item:
//hfree -sw test | hmake -s test 1 | var %i 20 | while (%i) { hadd test item $+ %i data | dec %i } | var %N 1 | while ($hget(test,%N).item) { echo 4 -a $ord(%N) item is $hget(test,%N).item | inc %N }
* This command saves the 20 items to disk, with the 1st pair of rows being the item named Item1 and the last pair of rows being the item named Item20:
//hsave -s test test.dat | run notepad test.dat
* When you /hload this diskfile into memory, the items are loaded into the Nth item in reverse order, where the 1st item now contains the item named Item20 instead of Item1:
//hfree -w test2 | hload -sm1 test2 test.dat | echo -a the 1st item is $hget(test2,1).item
* If you save this new hashtable to disk again, you'll find the line-pairs are saved to disk in the opposite order than in test.dat, which will cause loading them into a hash table to finally be the original seqence of the 1st table:
//hsave -s test2 test2.dat | run notepad test2.dat

Compatibility

Added: mIRC v5.8
Added on: 05 Sep 2000
Note: Unless otherwise stated, this was the date of original functionality.
Further enhancements may have been made in later versions.

See also