View Issue Details

IDProjectCategoryView StatusLast Update
0000560LDMudEfunspublic2010-02-13 03:40
ReporterLargo Assigned To 
PrioritynormalSeverityfeatureReproducibilityalways
Status newResolutionopen 
Summary0000560: new efun to randomize array contents
DescriptionHey guys,

I've written a small new efun named randomize_array() to replace some of these constructs with sort_array() to achieve an array randomization. Maybe you're interested in it, patch is attached.
Additional InformationNote that small p_int -> size_t change in array.h: It's not needed by the patch, but using size_t in this place made more sense to me.
Tagsldmud-extensions
Attached Files
shuffle_array.diff (3,442 bytes)   
Index: version.sh
===================================================================
--- version.sh	(Revision 2394)
+++ version.sh	(Arbeitskopie)
@@ -17,7 +17,7 @@
 # A timestamp, to be used by bumpversion and other scripts.
 # It can be used, for example, to 'touch' this file on every build, thus
 # forcing revision control systems to add it on every checkin automatically.
-version_stamp="2007-10-14 12:18:07"
+version_stamp="So 17. Aug 14:55:45 CEST 2008"
 
 # The version number information
 version_micro=716
Index: array.c
===================================================================
--- array.c	(Revision 2394)
+++ array.c	(Arbeitskopie)
@@ -69,6 +69,7 @@
 #include "mempools.h"
 #include "mstrings.h"
 #include "object.h"
+#include "random.h"
 #include "stdstrings.h"
 #include "simulate.h"
 #include "svalue.h"
@@ -2806,6 +2807,55 @@
     return sp;
 } /* f_transpose_array() */
 
+/*-------------------------------------------------------------------------*/
+svalue_t *
+f_shuffle_array (svalue_t *sp)
+
+/* EFUN shuffle_array()
+ *
+ *   mixed *shuffle_array (mixed *arr);
+ *
+ * shuffle_array ( ({1,2,3}) )
+ *              => ({3,1,2})
+ *              => ({2,3,1})
+ *              => ...
+ *
+ * shuffle_array() applied to an array results in an array of
+ * randomly arranged elements.
+ */
+
+{
+    vector_t *v;  /* Input vector */
+    vector_t *w;  /* Output vector */
+    size_t size;  /* size of <v> */
+    size_t i;
+    svalue_t *pos, *next, tmp;
+
+    /* Get and test the arguments */
+    v = sp->u.vec;
+
+    if ( (size = VEC_SIZE(v)) < 2)
+        return sp;
+
+    /* Allocate and fill the result vector */
+    w = slice_array(v, 0, size - 1);
+    free_array(v);
+
+    /* shuffle the array elements */
+    for (pos = w->item, i = size; i-- > 0; ++pos)
+    {
+        next = w->item + random_number(size - i);
+        tmp = *next;
+        transfer_svalue_no_free(next, pos);
+        transfer_svalue_no_free(pos, &tmp);
+    }
+
+    /* Clean up and return the result */
+    put_array(sp, w);
+
+    return sp;
+} /* f_shuffle_array() */
+
 /*=========================================================================*/
 
 /* EFUN unique_array()
Index: array.h
===================================================================
--- array.h	(Revision 2394)
+++ array.h	(Arbeitskopie)
@@ -60,7 +60,7 @@
  */
 
 struct vector_s {
-    p_int size;        /* Number of contained elements */
+    size_t size;       /* Number of contained elements */
     p_int ref;         /* Number of references */
 #ifdef DEBUG
     p_int extra_ref;   /* Second refcount, used to check .ref. */
@@ -119,6 +119,7 @@
 extern svalue_t *v_sort_array(svalue_t *sp, int num_arg);
 extern svalue_t *x_map_array(svalue_t *sp, int num_arg);
 extern svalue_t *f_transpose_array(svalue_t *sp);
+extern svalue_t *f_shuffle_array(svalue_t *sp);
 
 extern svalue_t *v_filter_objects(svalue_t *sp, int num_arg);
 extern svalue_t *v_map_objects(svalue_t *sp, int num_arg);
Index: func_spec
===================================================================
--- func_spec	(Revision 2394)
+++ func_spec	(Arbeitskopie)
@@ -437,6 +437,7 @@
 mixed  *map_objects(mixed *, string, ...);
 mixed  *sort_array(mixed *,string|closure, ...);
 mixed  *transpose_array(mixed *);
+mixed  *shuffle_array(mixed *);
 mixed  *unique_array(mixed *, string|closure, ...);
 
 mixed   filter(mapping|mixed *|string, string|closure|mapping, ...);
shuffle_array.diff (3,442 bytes)   
External Data (URL)

Activities

fufu

2008-08-14 03:23

manager   ~0000757

I have no objection to this per se, but this is easy to implement with an sefun like this:

mixed *shuffle_array(mixed *a)
{
    a = copy(a);
    for (int i = sizeof(a); i; ) {
        int j = random(i--);
        mixed t = a[i];
        a[i] = a[j];
        a[j] = t;
    }
    return a;
}

I prefer the name shuffle_array (or maybe just shuffle). Also, the algorithm in the patch isn't quite correct - random_number(size) should be random_number(size - i) for fair shuffling.

Largo

2008-08-17 07:03

reporter   ~0000759

alright, useful or not, I adapted the patch to solve the issues.

zesstra

2009-10-08 07:40

administrator   ~0001516

I am not sure, if we should it as efun, because it does seem to be used so regularly or to be time-critical.
But it might well be useful, I know a few places in our mudlib, which do a similar thing. Maybe we can include a collection of contributed sefuns?
Either directly in the driver or in a 'unofficial ldmud extensions' (which could be in LPC as well as in C)?

zesstra

2010-02-13 03:40

administrator   ~0001719

For now I added the patch to http://github.com/zesstra/ldmud-extensions in hope that people find it there.

Issue History

Date Modified Username Field Change
2008-08-13 14:45 Largo New Issue
2008-08-13 14:45 Largo File Added: randomize_array.diff
2008-08-14 03:23 fufu Note Added: 0000757
2008-08-17 07:02 Largo File Added: shuffle_array.diff
2008-08-17 07:03 Largo Note Added: 0000759
2008-08-17 08:54 fufu File Deleted: randomize_array.diff
2008-08-17 08:54 fufu File Deleted: shuffle_array.diff
2008-08-17 08:55 Largo File Added: shuffle_array.diff
2009-10-08 07:40 zesstra Note Added: 0001516
2010-02-13 03:40 zesstra Note Added: 0001719
2010-02-15 17:57 zesstra Tag Attached: ldmud-extensions