Data update
This commit is contained in:
parent
35bcdeebf8
commit
74c69a0df6
2427 changed files with 31826 additions and 3468 deletions
|
|
@ -0,0 +1,38 @@
|
|||
100 dim array(15)
|
||||
110 a = 0
|
||||
120 b = ubound(array)
|
||||
130 randomize timer
|
||||
140 for i = a to b
|
||||
150 array(i) = rnd(1)*1000
|
||||
160 next i
|
||||
170 print "unsort ";
|
||||
180 for i = a to b
|
||||
190 print using "####";array(i);
|
||||
200 if i = b then print ""; else print ", ";
|
||||
210 next i
|
||||
220 quicksort(array(),a,b)
|
||||
230 print : print " sort ";
|
||||
240 for i = a to b
|
||||
250 print using "####";array(i);
|
||||
260 if i = b then print ""; else print ", ";
|
||||
270 next i
|
||||
280 print
|
||||
290 end
|
||||
300 sub quicksort(array(),l,r)
|
||||
310 size = r-l+1
|
||||
320 if size < 2 then return
|
||||
330 i = l
|
||||
340 j = r
|
||||
350 pivot = array(l+int(size/2))
|
||||
360 rem repeat
|
||||
370 while array(i) < pivot
|
||||
380 i = i+1
|
||||
390 wend
|
||||
400 while pivot < array(j)
|
||||
410 j = j-1
|
||||
420 wend
|
||||
430 if i <= j then temp = array(i) : array(i) = array(j) : array(j) = temp : i = i+1 : j = j-1
|
||||
440 if i <= j then goto 360
|
||||
450 if l < j then quicksort(array(),l,j)
|
||||
460 if i < r then quicksort(array(),i,r)
|
||||
470 end sub
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
MODULE qsort_mod
|
||||
|
||||
IMPLICIT NONE
|
||||
|
||||
TYPE group
|
||||
INTEGER :: order ! original order of unsorted data
|
||||
REAL :: VALUE ! values to be sorted by
|
||||
END TYPE group
|
||||
|
||||
CONTAINS
|
||||
|
||||
RECURSIVE SUBROUTINE QSort(a,na)
|
||||
|
||||
! DUMMY ARGUMENTS
|
||||
INTEGER, INTENT(in) :: nA
|
||||
TYPE (group), DIMENSION(nA), INTENT(in out) :: A
|
||||
|
||||
! LOCAL VARIABLES
|
||||
INTEGER :: left, right
|
||||
REAL :: random
|
||||
REAL :: pivot
|
||||
TYPE (group) :: temp
|
||||
INTEGER :: marker
|
||||
|
||||
IF (nA > 1) THEN
|
||||
|
||||
CALL random_NUMBER(random)
|
||||
pivot = A(INT(random*REAL(nA-1))+1)%VALUE ! Choice a random pivot (not best performance, but avoids worst-case)
|
||||
left = 1
|
||||
right = nA
|
||||
! Partition loop
|
||||
DO
|
||||
IF (left >= right) EXIT
|
||||
DO
|
||||
IF (A(right)%VALUE <= pivot) EXIT
|
||||
right = right - 1
|
||||
END DO
|
||||
DO
|
||||
IF (A(left)%VALUE >= pivot) EXIT
|
||||
left = left + 1
|
||||
END DO
|
||||
IF (left < right) THEN
|
||||
temp = A(left)
|
||||
A(left) = A(right)
|
||||
A(right) = temp
|
||||
END IF
|
||||
END DO
|
||||
|
||||
IF (left == right) THEN
|
||||
marker = left + 1
|
||||
ELSE
|
||||
marker = left
|
||||
END IF
|
||||
|
||||
CALL QSort(A(:marker-1),marker-1)
|
||||
CALL QSort(A(marker:),nA-marker+1) WARNING CAN GO BEYOND END OF ARRAY DO NOT USE THIS IMPLEMENTATION
|
||||
|
||||
END IF
|
||||
|
||||
END SUBROUTINE QSort
|
||||
|
||||
END MODULE qsort_mod
|
||||
|
||||
! Test Qsort Module
|
||||
PROGRAM qsort_test
|
||||
USE qsort_mod
|
||||
IMPLICIT NONE
|
||||
|
||||
INTEGER, PARAMETER :: nl = 10, nc = 5, l = nc*nl, ns=33
|
||||
TYPE (group), DIMENSION(l) :: A
|
||||
INTEGER, DIMENSION(ns) :: seed
|
||||
INTEGER :: i
|
||||
REAL :: random
|
||||
CHARACTER(LEN=80) :: fmt1, fmt2
|
||||
! Using the Fibonacci sequence to initialize seed:
|
||||
seed(1) = 1 ; seed(2) = 1
|
||||
DO i = 3,ns
|
||||
seed(i) = seed(i-1)+seed(i-2)
|
||||
END DO
|
||||
! Formats of the outputs
|
||||
WRITE(fmt1,'(A,I2,A)') '(', nc, '(I5,2X,F6.2))'
|
||||
WRITE(fmt2,'(A,I2,A)') '(3x', nc, '("Ord. Num.",3x))'
|
||||
PRINT *, "Unsorted Values:"
|
||||
PRINT fmt2,
|
||||
CALL random_SEED(put = seed)
|
||||
DO i = 1, l
|
||||
CALL random_NUMBER(random)
|
||||
A(i)%VALUE = NINT(1000*random)/10.0
|
||||
A(i)%order = i
|
||||
IF (MOD(i,nc) == 0) WRITE (*,fmt1) A(i-nc+1:i)
|
||||
END DO
|
||||
PRINT *
|
||||
CALL QSort(A,l)
|
||||
PRINT *, "Sorted Values:"
|
||||
PRINT fmt2,
|
||||
DO i = nc, l, nc
|
||||
IF (MOD(i,nc) == 0) WRITE (*,fmt1) A(i-nc+1:i)
|
||||
END DO
|
||||
STOP
|
||||
END PROGRAM qsort_test
|
||||
|
|
@ -1,21 +1,21 @@
|
|||
def quickSort(arr):
|
||||
less = []
|
||||
pivotList = []
|
||||
more = []
|
||||
if len(arr) <= 1:
|
||||
return arr
|
||||
else:
|
||||
pivot = arr[0]
|
||||
for i in arr:
|
||||
if i < pivot:
|
||||
less.append(i)
|
||||
elif i > pivot:
|
||||
more.append(i)
|
||||
else:
|
||||
pivotList.append(i)
|
||||
less = quickSort(less)
|
||||
more = quickSort(more)
|
||||
return less + pivotList + more
|
||||
def quick_sort(sequence):
|
||||
lesser = []
|
||||
equal = []
|
||||
greater = []
|
||||
if len(sequence) <= 1:
|
||||
return sequence
|
||||
pivot = sequence[0]
|
||||
for element in sequence:
|
||||
if element < pivot:
|
||||
lesser.append(element)
|
||||
elif element > pivot:
|
||||
greater.append(element)
|
||||
else:
|
||||
equal.append(element)
|
||||
lesser = quick_sort(lesser)
|
||||
greater = quick_sort(greater)
|
||||
return lesser + equal + greater
|
||||
|
||||
|
||||
a = [4, 65, 2, -31, 0, 99, 83, 782, 1]
|
||||
a = quickSort(a)
|
||||
a = quick_sort(a)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#| Recursive, single-thread, single-pass, quicksort implementation
|
||||
multi quicksort(@unsorted where @unsorted.elems < 2) { @unsorted }
|
||||
multi quicksort(@unsorted) {
|
||||
my $pivot = @unsorted.pick;
|
||||
my %class{Order} is default([]) = @unsorted.classify: * cmp $pivot;
|
||||
|samewith(%class{Less}), |%class{Same}, |samewith(%class{More})
|
||||
#| Recursive, single-thread, random pivot, single-pass, quicksort implementation
|
||||
multi quicksort(\a where a.elems < 2) { a }
|
||||
multi quicksort(\a, \pivot = a.pick) {
|
||||
my %prt{Order} is default([]) = a.classify: * cmp pivot;
|
||||
|samewith(%prt{Less}), |%prt{Same}, |samewith(%prt{More})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
#| 7-Line, recursive, parallel, single-pass, quicksort implementation
|
||||
multi seven-line-quicksort-parallel(@unsorted where @unsorted.elems < 2) { @unsorted }
|
||||
multi seven-line-quicksort-parallel(@unsorted) {
|
||||
my $pivot = @unsorted.pick;
|
||||
my %partitions{Order} is default([]) = @unsorted.classify( * cmp $pivot );
|
||||
my Promise $less = start { samewith(%partitions{Less}) }
|
||||
my $more = samewith(%partitions{More});
|
||||
await $less andthen |$less.result, |%partitions{Same}, |$more;
|
||||
#| Recursive, parallel, random pivot, single-pass, quicksort implementation
|
||||
multi quicksort-parallel-naive(\a where a.elems < 2) { a }
|
||||
multi quicksort-parallel-naive(\a, \pivot = a.pick) {
|
||||
my %prt{Order} is default([]) = a.classify: * cmp pivot;
|
||||
my Promise $less = start { samewith(%prt{Less}) }
|
||||
my $more = samewith(%prt{More});
|
||||
await $less andthen |$less.result, |%prt{Same}, |$more;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,22 @@
|
|||
constant $BATCH-SIZE = 2**10;
|
||||
my atomicint $worker = $*KERNEL.cpu-cores;
|
||||
#| Recursive, parallel, tuned, single-pass, quicksort implementation
|
||||
proto quicksort-parallel(| --> Positional) {*}
|
||||
multi quicksort-parallel(@unsorted where @unsorted.elems < 2) { @unsorted }
|
||||
multi quicksort-parallel(@unsorted) {
|
||||
# separate unsorted input into Order Less, Same and More compared to a random $pivot
|
||||
my $pivot = @unsorted.pick;
|
||||
my %partitions{Order} is default([]) = @unsorted.classify( * cmp $pivot );
|
||||
#| Recursive, parallel, batch tuned, single-pass, quicksort implementation
|
||||
sub quicksort-parallel(@a, $batch = 2**9) {
|
||||
return @a if @a.elems < 2;
|
||||
|
||||
# atomically decide if we sort the Less partition on a new thread
|
||||
my $less = ⚛$worker > 0 &&
|
||||
%partitions{Less}.elems > $BATCH-SIZE
|
||||
?? (
|
||||
$worker⚛--;
|
||||
start {
|
||||
LEAVE $worker⚛++;
|
||||
samewith(%partitions{Less})
|
||||
}
|
||||
)
|
||||
!! samewith(%partitions{Less});
|
||||
# separate unsorted input into Order Less, Same and More compared to a random $pivot
|
||||
my $pivot = @a.pick;
|
||||
my %prt{Order} is default([]) = @a.classify( * cmp $pivot );
|
||||
|
||||
# decide if we sort the Less partition on a new thread
|
||||
my $less = %prt{Less}.elems >= $batch
|
||||
?? start { samewith(%prt{Less}, $batch) }
|
||||
!! samewith(%prt{Less}, $batch);
|
||||
|
||||
# meanwhile use current thread for sorting the More partition
|
||||
my $more = samewith(%partitions{More});
|
||||
my $more = samewith(%prt{More}, $batch);
|
||||
|
||||
# if we went parallel, we need to await the result
|
||||
await $less andthen $less = $less.result if $less ~~ Promise;
|
||||
|
||||
# concat all sorted partitions into a list and return
|
||||
|$less, |%partitions{Same}, |$more;
|
||||
|$less, |%prt{Same}, |$more;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
say "x" x 10 ~ " Testing " ~ "x" x 10;
|
||||
use Test;
|
||||
my @functions-under-test = &quicksort, &quicksort-parallel-naive, &quicksort-parallel;
|
||||
my @testcases =
|
||||
() => (),
|
||||
<a>.List => <a>.List,
|
||||
<a a> => <a a>,
|
||||
<a b> => <a b>,
|
||||
<b a> => <a b>,
|
||||
("b", "a", 3) => (3, "a", "b"),
|
||||
<h b a c d f e g> => <a b c d e f g h>,
|
||||
(2, 3, 1, 4, 5) => (1, 2, 3, 4, 5),
|
||||
<a 🎮 3 z 4 🐧> => <a 🎮 3 z 4 🐧>.sort
|
||||
;
|
||||
my @implementations = &quicksort, &seven-line-quicksort-parallel, &quicksort-parallel;
|
||||
plan @testcases.elems * @implementations.elems;
|
||||
for @implementations -> &fun {
|
||||
;
|
||||
|
||||
plan @testcases.elems * @functions-under-test.elems;
|
||||
for @functions-under-test -> &fun {
|
||||
say &fun.name;
|
||||
is-deeply &fun(.key), .value, .key ~ " => " ~ .value for @testcases;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,28 @@
|
|||
my $elem-length = 8;
|
||||
my @large of Str = ('a'..'z').roll($elem-length).join xx 10 * $worker * $BATCH-SIZE;
|
||||
say "x" x 11 ~ " Benchmarking " ~ "x" x 11;
|
||||
use Benchmark;
|
||||
my $runs = 5;
|
||||
my $elems = 10 * Kernel.cpu-cores * 2**10;
|
||||
my @unsorted of Str = ('a'..'z').roll(8).join xx $elems;
|
||||
my UInt $l-batch = 2**13;
|
||||
my UInt $m-batch = 2**11;
|
||||
my UInt $s-batch = 2**9;
|
||||
my UInt $t-batch = 2**7;
|
||||
|
||||
say "Benchmarking by sorting {@large.elems} strings of size $elem-length - using batches of $BATCH-SIZE strings and $worker workers.";
|
||||
my @benchmark = gather for @implementations -> &fun {
|
||||
&fun(@large);
|
||||
take (&fun.name => now - ENTER now);
|
||||
say "elements: $elems, runs: $runs, cpu-cores: {Kernel.cpu-cores}, large/medium/small/tiny-batch: $l-batch/$m-batch/$s-batch/$t-batch";
|
||||
|
||||
my %results = timethese $runs, {
|
||||
single-thread => { quicksort(@unsorted) },
|
||||
parallel-naive => { quicksort-parallel-naive(@unsorted) },
|
||||
parallel-tiny-batch => { quicksort-parallel(@unsorted, $t-batch) },
|
||||
parallel-small-batch => { quicksort-parallel(@unsorted, $s-batch) },
|
||||
parallel-medium-batch => { quicksort-parallel(@unsorted, $m-batch) },
|
||||
parallel-large-batch => { quicksort-parallel(@unsorted, $l-batch) },
|
||||
}, :statistics;
|
||||
|
||||
my @metrics = <mean median sd>;
|
||||
my $msg-row = "%.4f\t" x @metrics.elems ~ '%s';
|
||||
|
||||
say @metrics.join("\t");
|
||||
for %results.kv -> $name, %m {
|
||||
say sprintf($msg-row, %m{@metrics}, $name);
|
||||
}
|
||||
say @benchmark;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn quickSort(comptime T: type, arr: []T, comptime compareFn: fn (T, T) bool) void {
|
||||
if (arr.len < 2) return;
|
||||
|
||||
const pivot_index = partition(T, arr, compareFn);
|
||||
quickSort(T, arr[0..pivot_index], compareFn);
|
||||
quickSort(T, arr[pivot_index + 1 .. arr.len], compareFn);
|
||||
}
|
||||
|
||||
fn partition(comptime T: type, arr: []T, comptime compareFn: fn (T, T) bool) usize {
|
||||
const pivot_index = arr.len / 2;
|
||||
const last_index = arr.len - 1;
|
||||
|
||||
std.mem.swap(T, &arr[pivot_index], &arr[last_index]);
|
||||
|
||||
var store_index: usize = 0;
|
||||
for (arr[0 .. arr.len - 1]) |*elem_ptr| {
|
||||
if (compareFn(elem_ptr.*, arr[last_index])) {
|
||||
std.mem.swap(T, elem_ptr, &arr[store_index]);
|
||||
store_index += 1;
|
||||
}
|
||||
}
|
||||
|
||||
std.mem.swap(T, &arr[store_index], &arr[last_index]);
|
||||
return store_index;
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn main() void {
|
||||
const print = std.debug.print;
|
||||
|
||||
var arr = [_]i16{ 4, 65, 2, -31, 0, 99, 2, 83, 782, 1 };
|
||||
print("Before: {any}\n\n", .{arr});
|
||||
|
||||
print("Sort numbers in ascending order.\n", .{});
|
||||
quickSort(i16, &arr, struct {
|
||||
fn sortFn(left: i16, right: i16) bool {
|
||||
return left < right;
|
||||
}
|
||||
}.sortFn);
|
||||
print("After: {any}\n\n", .{arr});
|
||||
|
||||
print("Sort numbers in descending order.\n", .{});
|
||||
quickSort(i16, &arr, struct {
|
||||
fn sortFn(left: i16, right: i16) bool {
|
||||
return left > right;
|
||||
}
|
||||
}.sortFn);
|
||||
print("After: {any}\n\n", .{arr});
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn quicksort(comptime t: type, arr: []t) void {
|
||||
if (arr.len < 2) return;
|
||||
var pivot = arr[@as(usize, @intFromFloat(@floor(@as(f64, @floatFromInt(arr.len)) / 2)))];
|
||||
var left: usize = 0;
|
||||
var right: usize = arr.len - 1;
|
||||
|
||||
while (left <= right) {
|
||||
while (arr[left] < pivot) {
|
||||
left += 1;
|
||||
}
|
||||
while (arr[right] > pivot) {
|
||||
right -= 1;
|
||||
}
|
||||
if (left <= right) {
|
||||
const tmp = arr[left];
|
||||
arr[left] = arr[right];
|
||||
arr[right] = tmp;
|
||||
left += 1;
|
||||
right -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
quicksort(t, arr[0 .. right + 1]);
|
||||
quicksort(t, arr[left..]);
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
const LIST_TYPE = i16;
|
||||
var arr: [10]LIST_TYPE = [_]LIST_TYPE{ 4, 65, 2, -31, 0, 99, 2, 83, 782, 1 };
|
||||
var i: usize = 0;
|
||||
|
||||
while (i < arr.len) : (i += 1) {
|
||||
std.debug.print("{d} ", .{arr[i]});
|
||||
}
|
||||
std.debug.print("\n", .{});
|
||||
|
||||
i = 0;
|
||||
quicksort(LIST_TYPE, &arr);
|
||||
while (i < arr.len) : (i += 1) {
|
||||
std.debug.print("{d} ", .{arr[i]});
|
||||
}
|
||||
std.debug.print("\n", .{});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue