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",
|
"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]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
|
@ -251,6 +262,7 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"matrix",
|
"matrix",
|
||||||
"matrix-macros",
|
"matrix-macros",
|
||||||
|
"rand",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -329,6 +341,12 @@ dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.78"
|
version = "1.0.78"
|
||||||
|
@ -357,6 +375,36 @@ dependencies = [
|
||||||
"nibble_vec",
|
"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]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.10.3"
|
version = "1.10.3"
|
||||||
|
@ -491,6 +539,12 @@ version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
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]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
|
|
@ -9,3 +9,4 @@ edition = "2021"
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
matrix = { path = "../matrix" }
|
matrix = { path = "../matrix" }
|
||||||
matrix-macros = { path = "../matrix-macros" }
|
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::{vm::Vm, value::Value, unpack_args, Result, unpack_varargs};
|
||||||
use matrix_macros::native_func;
|
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 {
|
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()))
|
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) {
|
pub fn load(vm: &mut Vm) {
|
||||||
vm.load_global_fn(bin(), "bin");
|
vm.load_global_fn(bin(), "bin");
|
||||||
vm.load_global_fn(sex(), "sex");
|
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(hash(), "hash");
|
||||||
vm.load_global_fn(ord(), "ord");
|
vm.load_global_fn(ord(), "ord");
|
||||||
vm.load_global_fn(chr(), "chr");
|
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 std::{cell::RefCell, rc::Rc};
|
||||||
use matrix::{iter, vm::Vm, value::Value, Result, unpack_varargs, unpack_args};
|
use matrix::{iter, vm::Vm, value::Value, Result, unpack_varargs, unpack_args};
|
||||||
use matrix_macros::native_func;
|
use matrix_macros::native_func;
|
||||||
use crate::{error, VmArgs};
|
use crate::{error, next, VmArgs};
|
||||||
|
|
||||||
use Value as V;
|
use Value as V;
|
||||||
|
|
||||||
macro_rules! next {
|
|
||||||
($vm:expr, $frame:expr, $iter:expr) => {
|
|
||||||
$vm.run_fn($frame, $iter.clone(), vec![])
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[native_func(1)]
|
#[native_func(1)]
|
||||||
fn len(_: VmArgs, args: Vec<Value>) -> Result<Value> {
|
fn len(_: VmArgs, args: Vec<Value>) -> Result<Value> {
|
||||||
let [value] = unpack_args!(args);
|
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 error;
|
||||||
|
pub(crate) use next;
|
||||||
|
|
||||||
pub fn load(vm: &mut Vm) {
|
pub fn load(vm: &mut Vm) {
|
||||||
core::load(vm);
|
core::load(vm);
|
||||||
|
|
Loading…
Reference in a new issue