r3wp [groups: 83 posts: 189283]
  • Home
  • Script library
  • AltME Archive
  • Mailing list
  • Articles Index
  • Site search
 

World: r3wp

[Core] Discuss core issues

Andreas
10-Dec-2010
[740x2]
Not really, I fear.
qsort(3) is not guaranteed to be stable.
BrianH
10-Dec-2010
[742]
I mean, mention that it works on Linux, if that is what your tests 
reveal.
Andreas
10-Dec-2010
[743x2]
(Neither is it guaranteed to be a quicksort.)
That it works on Linux is pure coincidence.
BrianH
10-Dec-2010
[745]
I ran into the problem when I was sorting words in a block and the 
bindings mattered.
Andreas
10-Dec-2010
[746]
If we want SORT to be stable, the implementation will have to abandon 
the use of qsort(3).
BrianH
10-Dec-2010
[747]
That would explain why the ticket is still not fixed. Please mention 
this in a ticket comment - it might lead to changing its status.
Andreas
10-Dec-2010
[748x2]
You can of course hack stability into qsort() by falling back to 
comparing adresses if values are the same.
Not sure if Carl likes that :)
BrianH
10-Dec-2010
[750x2]
That won't work, because we are comparing EQUAL? (maybe plus /case), 
not SAME?.
Does qsort take a comparison function? If so, it might be a error 
in that function.
Andreas
10-Dec-2010
[752]
I'm talking about the C side of things here.
BrianH
10-Dec-2010
[753]
Same here - a C function pointer.
Andreas
10-Dec-2010
[754x4]
Then I don't understand your EQUAL?/SAME? remark.
If two elements are EQUAL?, fall back to comparing their addresses 
in memory.
Won't work for linked lists, will work for arrays stored consecutively.
Sorry, missed that. Yes, qsort takes a callback used for comparison. 
Here's the decl:


void qsort(void *base, size_t nitems, size_t size, int (*compar)(const 
void *, const void*));
BrianH
10-Dec-2010
[758]
Sorry, I just got that you were talking about using <= instead of 
<.
Andreas
10-Dec-2010
[759x2]
My remark above was to the effect: if two elements are EQUAL? compare 
their INDEX? instead. This may sound ridiculous in context of REBOL's 
SORT, but it is no problem in C.
As the comparison callback gets pointers to the elements anyway.
BrianH
10-Dec-2010
[761]
I still think that you need to write this stuff in a ticket comment. 
Writing it here will have no effect - the ticket is where the real 
discussion happens, and I don't seem to understand your argument 
well enough in this case to paraphrase you there.
Andreas
10-Dec-2010
[762]
I'm writing already.
BrianH
10-Dec-2010
[763]
All :) intended, of course.
Andreas
10-Dec-2010
[764]
In any case, I find this channel more fruitful for interactive discussion.
BrianH
10-Dec-2010
[765]
True. But Carl won't see it.
Sunanda
10-Dec-2010
[766]
BrianH <And not well enough documented either. I don't really know 
how /compare works, not completely.>

Comparators and the stable-sort trick (-1, 0 +1) are documented here 
in an old change log. It never made it into the dictionary for SORT:
    http://www.rebol.com/docs/changes-2-5.html#section-72
BrianH
10-Dec-2010
[767x2]
Documentation request referencing that link added here: http://curecode.org/rebol3/ticket.rsp?id=1793
Thanks :)
Ladislav
11-Dec-2010
[769]
Re -1 0 1 - as far as I remember, I read somewhere about negative, 
0, positive?
BrianH
11-Dec-2010
[770]
That works too:

>> sort/compare [20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 
1] func [x y] [case [x < y [3] x = y [0] 'else [-4]]]
== [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20]
Gabriele
11-Dec-2010
[771x2]
Are we talking R2's sort or R3's sort here? I know for a fact that 
R2's sort is stable. Obviously you can't get a stable sort if you 
use a comparator function and you return a logic! value.
Also, the current "best" algorithm appears to be http://en.wikipedia.org/wiki/Timsort
Steeve
11-Dec-2010
[773]
We must focus on algos which are doing the fewer comarisons and are 
fast with data almost sorted (it's our common case).

in that sense, Timsort would be a good choice because it's unsing 
a combination of merge sort + insertion sort
merge sort = fewer comparisons.

insertion sort = the faster one on data already sorted and small 
subsets of data
Maxim
12-Dec-2010
[774]
yes looks pretty decent... a nice wrap up here:
http://corte.si/posts/code/timsort/index.html
Ladislav
13-Dec-2010
[775]
http://www.rebol.org/ml-display-message.r?m=rmlVPRF
Steeve
14-Dec-2010
[776x3]
Funny, I've coded "bottom-up heapsort"  last night (improved version 
of heapsort).
I give the "clean" version.
heapify: func [s start len comp /local child sav][
	;-- search terminal leaf.
	child: start
	while [2 * child < len][
		child: 2 * child
		unless (comp s/(++ child) s/:child) [-- child]
	]
	if 2 * child = len [child: len]

	;-- bottom-up, search insertion point
	while [comp s/:child s/:start][child: shift child -1]
		
	;-- bottom-up swap
	sav: s/:start
	while [child > start][
			s/:child: also sav sav: s/:child
			child: shift child -1
	]
	s/:child: sav
]

heapsort: func [serie comp /local len][
	len: length? serie
	;-- build heap
	for i shift len -1 1 -1 [heapify serie i len :comp]
	;-- sort
	for i len 1 -1 [
		swap serie at serie i
		heapify serie 1 i - 1 :comp
	]
	serie
]
>> heapsort serie func [a b][a < b]
Ladislav
14-Dec-2010
[779x2]
Is it stable, Steeve?
>> heapsort [5 1 2 4] :lesser?
== [1 2 4 5]

, while

>> heapsort [5 1 2 4] :lesser-or-equal?
** Script error: cannot compare none! with integer!
** Where: comp while heapify for heapsort
** Near: comp s/:child s/:start

, is that intended?
GrahamC
14-Dec-2010
[781]
Mindblock

a: "testing"

foreach v [ a ] [  .... ]

in .. .how to test if v is an empty? string?
Ladislav
14-Dec-2010
[782]
don't you mean:

foreach v reduce [a] [if all [string? :v empty? :v] [...]...]
GrahamC
14-Dec-2010
[783]
I didn't want to reduce first as then I can't report which one is 
empty?
Ladislav
14-Dec-2010
[784]
I do not understand
GrahamC
14-Dec-2010
[785x2]
say I have a: "testing" b: ""

how would I say .. variable b is empty?
If I reduce the block of words first, then I no longer know which 
word is empty
Ladislav
14-Dec-2010
[787]
if you have foreach v [a] [...] , then v is a word, not a string, 
so, in case you really mean it, you need something like:

if all [string? get v empty? get v]
GrahamC
14-Dec-2010
[788x2]
sounds right
thanks