Suppose we have an array:
let arr: [u8; 10] = [1,2,3,4,5,6,7,8,9,10];
Is there a function in Rust to choose N random elements from it without repetitions? Equivalent to python's random.sample function.
You can use choose_multiple:
use rand::prelude::*;
fn main() {
let mut rng = rand::thread_rng();
let arr: [u8; 10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let sample: Vec<_> = arr.choose_multiple (&mut rng, 3).collect();
println!("{:?}", sample);
}
Playground
You can use sample for getting a sample over indexes, then just iterate and get those from the original array:
use rand::prelude::*;
use rand::seq::index::sample;
fn main() {
let mut rng = rand::thread_rng();
let arr: [u8; 10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let sample: Vec<u8> = sample(&mut rng, arr.len(), 3)
.iter()
.map(|i| arr[i])
.collect();
}
Playground
Related
I am solving the n queens problem.
I use an array of 1..=n to represent the position of the queen, and then keep finding the next permutation until I judge that this permutation is a solution.
/// Returns a bool value indicating whether the next permutation exists
pub fn next_permutation(arrange: &mut [usize]) -> bool {
let last_ascending = match arrange.windows(2).rposition(|w| w[0] < w[1]) {
Some(i) => i,
None => {
arrange.reverse();
return false;
}
};
let swap_with = arrange[last_ascending + 1..]
.binary_search_by(|n| usize::cmp(&arrange[last_ascending], n).then(Ordering::Less))
.unwrap_err();
arrange.swap(last_ascending, last_ascending + swap_with);
arrange[last_ascending + 1..].reverse();
true
}
pub fn is_solution(arrange: &[usize]) -> bool {
let iter = arrange.iter().enumerate();
iter.clone().all(|(i, &j)| {
iter.clone()
.filter(|&(c, _)| c != i)
.all(|(p, &q)| i as isize - j as isize != p as isize - q as isize && i as usize + j != p as usize + q)
})
}
Now my problem is that the next_permutation function does not quite meet my needs.
For example [1, 2, 3, 4, 5], the next permutation is [1, 2, 3, 5, 4], this results in a lot of wasted judgment.
It can be found that [1, 2, _, _, _] does not meet the requirements , the next permutation to check should be say [1, 3, 2, 4, 5].
How do I optimize the next_permutation function to implement this process?
I want to get the indices that would sort a Vec in Rust. Effectively, I want argsort() from numpy.
For example:
let v = vec![1, 7, 4, 2];
let i = argsort(&v);
assert_eq!(i, &[0, 3, 2, 1]);
Not sure if there's something pre-made for this, but its simple enough to implement yourself with .sort_by_key():
pub fn argsort<T: Ord>(data: &[T]) -> Vec<usize> {
let mut indices = (0..data.len()).collect::<Vec<_>>();
indices.sort_by_key(|&i| &data[i]);
indices
}
See it working on the playground.
I have encountered a problem that looks simple but is actually difficult. It appears to be a subset of a combined algorithm. is there a faster and more direct algorithm?
/// split the group {v1} to {n} parts
///
/// For example:
/// Group(here represented by an array):
/// [1, 2, 3, 4]
/// split Group to 2 part, got:
/// [[1], [2, 3, 4]]
/// [[1, 2], [3, 4]]
/// [[1, 3], [2, 4]]
/// [[1, 4], [2, 3]]
/// [[1, 2, 3], [4]]
fn split_group(v1: Vec<i32>, n: i32) -> Vec<Vec<Vec<i32>>> {
unimplemented!()
}
fn main() {
let mut v1 = vec![1, 2, 3, 4];
let v2 = split_group(v1, 2);
assert_eq!(
v2,
vec![
vec![vec![1], vec![2, 3, 4]],
vec![vec![1, 2], vec![3, 4]],
vec![vec![1, 3], vec![2, 4]],
vec![vec![1, 4], vec![2, 3]],
vec![vec![1, 2, 3], vec![4]],
]
);
}
Here is a solution derived from this answer linked by #MBo.
The recursive function fills K parts with N values.
The lastfilled parameter helps to avoid duplicates - it provides an increasing sequence of leading (smallest) elements of every part.
The empty parameter is intended to avoid empty parts.
use std::cmp;
pub fn genp(parts: &mut Vec<Vec<usize>>, mut empty: usize, n: usize, k: usize, m: usize, lastfilled: Option<usize>) {
if m == n {
return println!("{:?}", parts);
}
let mut start = 0;
if n - m == empty {
start = k - empty;
}
let max = match lastfilled {
None => 1,
Some(lastfilled) => lastfilled + 2,
};
for i in start..cmp::min(k, max) {
parts[i].push(m);
if parts[i].len() == 1 {
empty -= 1;
}
genp(parts, empty, n, k, m+1, cmp::max(Some(i), lastfilled));
parts[i].pop();
if parts[i].is_empty() {
empty += 1;
}
}
}
pub fn split_group(v1: Vec<i32>, k: usize) {
let mut parts: Vec<Vec<usize>> = Vec::new();
for _ in 0..k {
parts.push(Vec::new());
}
genp(&mut parts, k, v1.len(), k, 0, None);
}
fn main() {
let v1 = vec![1, 2, 3, 4];
split_group(v1, 2);
}
[[0, 1, 2], [3]]
[[0, 1, 3], [2]]
[[0, 1], [2, 3]]
[[0, 2, 3], [1]]
[[0, 2], [1, 3]]
[[0, 3], [1, 2]]
[[0], [1, 2, 3]]
Is it possible to index columns in a Rust ndarray matrix using a Vec rather than a Slice object? The only documentation I can find pertains to slicing using contiguous columns
Specifically, I am trying to implement something like the following code in Python:
x = np.array([[1,2,3,4,5,6], [7,8,9,10,11,12]])
idx = [0,1,2,4]
x[:, idx]
The outcome of x[:, idx] would be the subset of the matrix containing all rows and only columns described in idx, i.e., [0,1,2,4].
I am currently using ndarray (as the title suggests) but I cannot find a way to subset on non-contiguous slices. For instance, you can pass ndarray, which can take a Slice with a start, stop and an index, but I cannot find a way to pass a list of columns that cannot be described using a Slice object.
For instance:
#[macro_use]
extern crate ndarray;
fn main() {
let mut x = array![[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]];
let idx = vec![0, 1, 2, 4];
// The following works as expected
let y = x.slice(s![.., 0..2]);
println!("{:?}", y);
// This is conceptually what I would like to do but
// It does not work.
let y = x.slice(s![.., idx]);
}
The analogue of "advanced indexing" in Numpy is the ArrayBase::select() method:
use ndarray::{array, Axis};
fn main() {
let x = array![[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12]];
let idx = vec![0, 1, 2, 4];
println!("{}", x.select(Axis(1), &idx));
}
producing the output
[[1, 2, 3, 5],
[7, 8, 9, 11]]
Note that the resulting array is a copy of the selected elements (just as it is in Numpy). Depending on your use case, you may not need the copy; it's possible you can make do with just iterating over idx and using x.slice(s![.., i]) for all i in idx.
Let's say I have a list with 10 numbers:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
I would like my program to slice every 3 numbers, for example:
[1,2,3]
[4,5,6]
[7,8,9]
How can I do it?
Grateful
For example, with n = 3,
package main
import "fmt"
func main() {
list := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
for a, n := list, 3; len(a) >= n; a = a[n:] {
slice := a[:n]
fmt.Println(slice)
}
}
Output:
[1 2 3]
[4 5 6]
[7 8 9]
you could make a something like this (sorry for pseudo code)
array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
while (array){
list = ""
for($i=1;$i -le 3;$i++){
list.add = array[$i]
remove from array the array[$i]
}
your list now here (list)
}
you could ask the first 3 values and after that you remove it