Implemented quicksort in _sort()

This commit is contained in:
2023-02-13 13:31:58 +00:00
parent 9725f3c6a3
commit 16b71ba6f4
3 changed files with 139 additions and 16 deletions

View File

@@ -996,6 +996,97 @@ static int nativeSome(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
return 1;
}
static void swapLiteralsUtil(Toy_Literal* lhs, Toy_Literal* rhs) {
Toy_Literal tmp = *lhs;
*lhs = *rhs;
*rhs = tmp;
}
//https://www.youtube.com/watch?v=MZaf_9IZCrc
static void recursiveLiteralQuicksortUtil(Toy_Interpreter* interpreter, Toy_Literal* ptr, int literalCount, Toy_Literal fnCompareLiteral) {
//base case
if (literalCount <= 1) {
return;
}
int runner = 0;
//iterate through the array
for (int checker = 0; checker < literalCount - 1; checker++) {
Toy_LiteralArray arguments;
Toy_LiteralArray returns;
Toy_initLiteralArray(&arguments);
Toy_initLiteralArray(&returns);
Toy_pushLiteralArray(&arguments, ptr[literalCount - 1]); //backwards
Toy_pushLiteralArray(&arguments, ptr[checker]);
Toy_callLiteralFn(interpreter, fnCompareLiteral, &arguments, &returns);
Toy_Literal lessThan = Toy_popLiteralArray(&returns);
Toy_freeLiteralArray(&arguments);
Toy_freeLiteralArray(&returns);
if (TOY_IS_TRUTHY(lessThan)) {
swapLiteralsUtil(&ptr[runner++], &ptr[checker]);
}
Toy_freeLiteral(lessThan);
}
//"shift everything up" so the pivot is in the middle
swapLiteralsUtil(&ptr[runner], &ptr[literalCount - 1]);
//recurse on each end
recursiveLiteralQuicksortUtil(interpreter, &ptr[0], runner, fnCompareLiteral);
recursiveLiteralQuicksortUtil(interpreter, &ptr[runner + 1], literalCount - runner - 1, fnCompareLiteral);
}
static int nativeSort(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments
if (arguments->count != 2) {
interpreter->errorOutput("Incorrect number of arguments to _sort\n");
return -1;
}
//get the args
Toy_Literal fnLiteral = Toy_popLiteralArray(arguments);
Toy_Literal selfLiteral = Toy_popLiteralArray(arguments);
//parse to value if needed
Toy_Literal selfLiteralIdn = selfLiteral;
if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) {
Toy_freeLiteral(selfLiteralIdn);
}
Toy_Literal fnLiteralIdn = fnLiteral;
if (TOY_IS_IDENTIFIER(fnLiteral) && Toy_parseIdentifierToValue(interpreter, &fnLiteral)) {
Toy_freeLiteral(fnLiteralIdn);
}
//check type
if (!TOY_IS_ARRAY(selfLiteral) || !( TOY_IS_FUNCTION(fnLiteral) || TOY_IS_FUNCTION_NATIVE(fnLiteral) )) {
interpreter->errorOutput("Incorrect argument type passed to _sort\n");
Toy_freeLiteral(selfLiteral);
Toy_freeLiteral(fnLiteral);
return -1;
}
//call the quicksort util
if (TOY_IS_ARRAY(selfLiteral)) {
recursiveLiteralQuicksortUtil(interpreter, TOY_AS_ARRAY(selfLiteral)->literals, TOY_AS_ARRAY(selfLiteral)->count, fnLiteral);
}
Toy_pushLiteralArray(&interpreter->stack, selfLiteral);
Toy_freeLiteral(fnLiteral);
Toy_freeLiteral(selfLiteral);
return 1;
}
static int nativeToLower(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
//no arguments
if (arguments->count != 1) {
@@ -1451,7 +1542,7 @@ int Toy_hookCompound(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_L
{"_map", nativeMap}, //array, dictionary
{"_reduce", nativeReduce}, //array, dictionary
{"_some", nativeSome}, //array, dictionary
// {"_sort", native}, //array
{"_sort", nativeSort}, //array
{"_toLower", nativeToLower}, //string
{"_toString", nativeToString}, //array, dictionary
{"_toUpper", nativeToUpper}, //string

View File

@@ -1,22 +1,27 @@
//polyfill the _insert function
fn _insert(self, k, v) {
var tmp1 = v;
var tmp2;
for (var i = k; i < self.length(); i++) {
tmp2 = self[i];
self[i] = tmp1;
tmp1 = tmp2;
}
import compound;
self.push(tmp1);
return self;
fn less(a, b) {
return a < b;
}
var a = [1, 2, 3];
fn greater(a, b) {
return a > b;
}
a = a.insert(1, 42);
var a = [7, 2, 1, 8, 6, 3, 5, 4];
var b = [7, 2, 1, 4, 6, 3, 5, 8];
var c = [1, 2, 3, 4, 5, 6, 7, 8];
var d = [7, 2, 1, 8, 6, 3, 5, 4];
assert a == [1, 5, 2, 3], "index assignment left failed";
a = a.sort(less);
b = b.sort(less);
c = c.sort(less);
d = d.sort(greater);
assert a == [1, 2, 3, 4, 5, 6, 7, 8], "array.sort(less) failed";
assert b == [1, 2, 3, 4, 5, 6, 7, 8], "array.sort(less) with pivot high failed";
assert c == [1, 2, 3, 4, 5, 6, 7, 8], "array.sort(less) pre-sorted array failed";
assert d == [8, 7, 6, 5, 4, 3, 2, 1], "array.sort(greater) failed";
print "All good";
print "All good";

View File

@@ -228,6 +228,33 @@ import compound;
}
//test sort
{
fn less(a, b) {
return a < b;
}
fn greater(a, b) {
return a > b;
}
var a = [7, 2, 1, 8, 6, 3, 5, 4];
var b = [7, 2, 1, 4, 6, 3, 5, 8];
var c = [1, 2, 3, 4, 5, 6, 7, 8];
var d = [7, 2, 1, 8, 6, 3, 5, 4];
a = a.sort(less);
b = b.sort(less);
c = c.sort(less);
d = d.sort(greater);
assert a == [1, 2, 3, 4, 5, 6, 7, 8], "array.sort(less) failed";
assert b == [1, 2, 3, 4, 5, 6, 7, 8], "array.sort(less) with pivot high failed";
assert c == [1, 2, 3, 4, 5, 6, 7, 8], "array.sort(less) pre-sorted array failed";
assert d == [8, 7, 6, 5, 4, 3, 2, 1], "array.sort(greater) failed";
}
//test toLower
{
assert "Hello World".toLower() == "hello world", "_toLower() failed";