sort n rand
This commit is contained in:
parent
158bcae00d
commit
4438116264
5 changed files with 181 additions and 8 deletions
54
Cargo.lock
generated
54
Cargo.lock
generated
|
@ -181,6 +181,17 @@ dependencies = [
|
|||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
|
@ -251,6 +262,7 @@ dependencies = [
|
|||
"anyhow",
|
||||
"matrix",
|
||||
"matrix-macros",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -329,6 +341,12 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.78"
|
||||
|
@ -357,6 +375,36 @@ dependencies = [
|
|||
"nibble_vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.3"
|
||||
|
@ -491,6 +539,12 @@ version = "0.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
|
|
@ -9,3 +9,4 @@ edition = "2021"
|
|||
anyhow = "1"
|
||||
matrix = { path = "../matrix" }
|
||||
matrix-macros = { path = "../matrix-macros" }
|
||||
rand = "0.8"
|
||||
|
|
|
@ -2,7 +2,8 @@ use std::hash::{DefaultHasher, Hash, Hasher};
|
|||
|
||||
use matrix::{vm::Vm, value::Value, unpack_args, Result, unpack_varargs};
|
||||
use matrix_macros::native_func;
|
||||
use crate::{VmArgs, error};
|
||||
use rand::Rng;
|
||||
use crate::{VmArgs, next, error};
|
||||
|
||||
|
||||
fn to_radix(r: i64, mut n: i64) -> String {
|
||||
|
@ -162,6 +163,116 @@ fn str(_: VmArgs, args: Vec<Value>) -> Result<Value> {
|
|||
Ok(Value::String(format!("{value}").into()))
|
||||
}
|
||||
|
||||
fn partition(list: &mut [Value], lo: usize, hi: usize) -> (usize, usize) {
|
||||
let pivot = list[(lo + hi) / 2].clone();
|
||||
let mut lt = lo;
|
||||
let mut eq = lo;
|
||||
let mut gt = hi;
|
||||
|
||||
while eq <= gt {
|
||||
if list[eq] < pivot {
|
||||
list.swap(eq, lt);
|
||||
lt += 1;
|
||||
eq += 1;
|
||||
} else if list[eq] > pivot {
|
||||
list.swap(eq, gt);
|
||||
gt -= 1;
|
||||
} else {
|
||||
eq += 1;
|
||||
}
|
||||
}
|
||||
|
||||
(lt, gt)
|
||||
}
|
||||
|
||||
fn quicksort(list: &mut [Value], lo: usize, hi: usize) {
|
||||
if lo < hi {
|
||||
let (lt, gt) = partition(list, lo, hi);
|
||||
if lt > 0 {
|
||||
quicksort(list, lo, lt - 1);
|
||||
}
|
||||
quicksort(list, gt + 1, hi);
|
||||
}
|
||||
}
|
||||
|
||||
#[native_func(1)]
|
||||
fn sort(_: VmArgs, args: Vec<Value>) -> Result<Value> {
|
||||
let [value] = unpack_args!(args);
|
||||
let Value::List(mut list) = value else {
|
||||
return error!("sort requires a list")
|
||||
};
|
||||
let hi = list.len() - 1;
|
||||
quicksort(list.as_mut(), 0, hi);
|
||||
Ok(Value::List(list))
|
||||
}
|
||||
|
||||
#[native_func(0)]
|
||||
fn rand(_: VmArgs, _: Vec<Value>) -> Result<Value> {
|
||||
let mut rng = rand::thread_rng();
|
||||
Ok(Value::Float(rng.gen()))
|
||||
}
|
||||
|
||||
#[native_func(0..)]
|
||||
fn rand_range(_: VmArgs, args: Vec<Value>) -> Result<Value> {
|
||||
use Value as V;
|
||||
let ([], varargs) = unpack_varargs!(args);
|
||||
let (min, max, step) = match varargs.as_slice() {
|
||||
[V::Int(max)] => {
|
||||
(0, *max, 1)
|
||||
},
|
||||
[V::Int(min), V::Int(max)] => {
|
||||
(*min, *max, 1)
|
||||
},
|
||||
[V::Int(min), V::Int(max), V::Int(step)] => {
|
||||
(*min, *max, *step)
|
||||
},
|
||||
_ => return error!("rand_range takes 1 to 3 [Int]'s")
|
||||
};
|
||||
if max <= min {
|
||||
return Ok(Value::Int(min))
|
||||
}
|
||||
let count = ((max - 1 - min) / step) + 1;
|
||||
let rng = (rand::thread_rng().gen::<u32>() % (count as u32)) as i64;
|
||||
let i = min + (rng * step);
|
||||
Ok(Value::Int(i))
|
||||
}
|
||||
|
||||
#[native_func(2)]
|
||||
fn rand_int(_: VmArgs, args: Vec<Value>) -> Result<Value> {
|
||||
use Value as V;
|
||||
let (min, max) = match args.as_slice() {
|
||||
[V::Int(min), V::Int(max)] => {
|
||||
(*min, *max + 1)
|
||||
},
|
||||
_ => return error!("rand_int takes 2 [Int]'s")
|
||||
};
|
||||
if max <= min {
|
||||
return Ok(Value::Int(min))
|
||||
}
|
||||
|
||||
let count = max - min;
|
||||
let rng = (rand::thread_rng().gen::<u32>() % (count as u32)) as i64;
|
||||
let i = min + rng;
|
||||
Ok(Value::Int(i))
|
||||
}
|
||||
|
||||
#[native_func(1)]
|
||||
fn rand_in((vm, frame): VmArgs, args: Vec<Value>) -> Result<Value> {
|
||||
let [iter] = unpack_args!(args);
|
||||
let iter = iter.into_iter_fn()?;
|
||||
let mut vals = Vec::new();
|
||||
loop {
|
||||
let val = next!(vm, frame, iter)?;
|
||||
if val == Value::Nil { break }
|
||||
vals.push(val);
|
||||
}
|
||||
if vals.is_empty() {
|
||||
return Ok(Value::Nil)
|
||||
}
|
||||
let idx = rand::thread_rng().gen::<usize>() % vals.len();
|
||||
Ok(vals[idx].clone())
|
||||
}
|
||||
|
||||
pub fn load(vm: &mut Vm) {
|
||||
vm.load_global_fn(bin(), "bin");
|
||||
vm.load_global_fn(sex(), "sex");
|
||||
|
@ -178,4 +289,10 @@ pub fn load(vm: &mut Vm) {
|
|||
vm.load_global_fn(hash(), "hash");
|
||||
vm.load_global_fn(ord(), "ord");
|
||||
vm.load_global_fn(chr(), "chr");
|
||||
|
||||
vm.load_global_fn(sort(), "sort");
|
||||
vm.load_global_fn(rand(), "rand");
|
||||
vm.load_global_fn(rand_range(), "rand_range");
|
||||
vm.load_global_fn(rand_int(), "rand_int");
|
||||
vm.load_global_fn(rand_in(), "rand_in");
|
||||
}
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
use std::{cell::RefCell, rc::Rc};
|
||||
use matrix::{iter, vm::Vm, value::Value, Result, unpack_varargs, unpack_args};
|
||||
use matrix_macros::native_func;
|
||||
use crate::{error, VmArgs};
|
||||
use crate::{error, next, VmArgs};
|
||||
|
||||
use Value as V;
|
||||
|
||||
macro_rules! next {
|
||||
($vm:expr, $frame:expr, $iter:expr) => {
|
||||
$vm.run_fn($frame, $iter.clone(), vec![])
|
||||
};
|
||||
}
|
||||
|
||||
#[native_func(1)]
|
||||
fn len(_: VmArgs, args: Vec<Value>) -> Result<Value> {
|
||||
let [value] = unpack_args!(args);
|
||||
|
|
|
@ -14,7 +14,14 @@ macro_rules! error {
|
|||
};
|
||||
}
|
||||
|
||||
macro_rules! next {
|
||||
($vm:expr, $frame:expr, $iter:expr) => {
|
||||
$vm.run_fn($frame, $iter.clone(), vec![])
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use error;
|
||||
pub(crate) use next;
|
||||
|
||||
pub fn load(vm: &mut Vm) {
|
||||
core::load(vm);
|
||||
|
|
Loading…
Reference in a new issue