mirror of
https://github.com/krgamestudios/Toy.git
synced 2026-04-15 14:54:07 +10:00
Implemented quicksort in _sort()
This commit is contained in:
@@ -996,6 +996,97 @@ static int nativeSome(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments)
|
|||||||
return 1;
|
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) {
|
static int nativeToLower(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) {
|
||||||
//no arguments
|
//no arguments
|
||||||
if (arguments->count != 1) {
|
if (arguments->count != 1) {
|
||||||
@@ -1451,7 +1542,7 @@ int Toy_hookCompound(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_L
|
|||||||
{"_map", nativeMap}, //array, dictionary
|
{"_map", nativeMap}, //array, dictionary
|
||||||
{"_reduce", nativeReduce}, //array, dictionary
|
{"_reduce", nativeReduce}, //array, dictionary
|
||||||
{"_some", nativeSome}, //array, dictionary
|
{"_some", nativeSome}, //array, dictionary
|
||||||
// {"_sort", native}, //array
|
{"_sort", nativeSort}, //array
|
||||||
{"_toLower", nativeToLower}, //string
|
{"_toLower", nativeToLower}, //string
|
||||||
{"_toString", nativeToString}, //array, dictionary
|
{"_toString", nativeToString}, //array, dictionary
|
||||||
{"_toUpper", nativeToUpper}, //string
|
{"_toUpper", nativeToUpper}, //string
|
||||||
|
|||||||
@@ -1,22 +1,27 @@
|
|||||||
//polyfill the _insert function
|
import compound;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.push(tmp1);
|
fn less(a, b) {
|
||||||
return self;
|
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";
|
||||||
@@ -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
|
//test toLower
|
||||||
{
|
{
|
||||||
assert "Hello World".toLower() == "hello world", "_toLower() failed";
|
assert "Hello World".toLower() == "hello world", "_toLower() failed";
|
||||||
|
|||||||
Reference in New Issue
Block a user