61 lines
1.9 KiB
Rust
61 lines
1.9 KiB
Rust
use itertools::Itertools;
|
|
|
|
fn get_kolakoski_sequence(iseq: &[usize], size: &usize) -> Vec<usize> {
|
|
assert!(*size > 0);
|
|
assert!(!iseq.is_empty());
|
|
|
|
let mut kseq: Vec<usize> = Vec::default();
|
|
|
|
// create an itertor which keeps repeating the initial sequence infinitely
|
|
let repeater = iseq.iter().cloned().cycle();
|
|
|
|
// push the very first element, repeated as many times as the number
|
|
kseq.extend_from_slice(&vec![*iseq.get(0).unwrap()].repeat(*iseq.get(0).unwrap()));
|
|
|
|
//start cycling throught the initial sequence, but skip the very first one
|
|
for (k_counter, elem) in repeater.enumerate().skip(1) {
|
|
// push the given element
|
|
kseq.push(elem);
|
|
|
|
// and repeat the current element as many times
|
|
// as it's needed based on the previous elements
|
|
kseq.extend_from_slice(&vec![elem].repeat(*kseq.get(k_counter).unwrap() - 1));
|
|
|
|
// finish generation when the Kolakoski sequence has reached the given length
|
|
if kseq.len() >= *size {
|
|
break;
|
|
}
|
|
}
|
|
|
|
// truncate it as it might have more elements than needed
|
|
kseq[0..*size].to_vec()
|
|
}
|
|
|
|
fn is_kolakoski(kseq: &[usize]) -> bool {
|
|
assert!(!kseq.is_empty());
|
|
|
|
// calculate the RLE
|
|
let rle: Vec<usize> = kseq
|
|
.iter()
|
|
.batching(|it| {
|
|
it.next()
|
|
.map(|v| it.take_while_ref(|&v2| v2 == v).count() + 1)
|
|
})
|
|
.collect();
|
|
|
|
rle.iter().zip(kseq).filter(|&(a, b)| a == b).count() == rle.len()
|
|
}
|
|
|
|
fn main() {
|
|
let lengths = vec![20, 20, 30, 30];
|
|
let seqs = vec![vec![1, 2], vec![2, 1], vec![1, 3, 1, 2], vec![1, 3, 2, 1]];
|
|
|
|
for (seq, length) in seqs.iter().zip(&lengths) {
|
|
let kseq = get_kolakoski_sequence(&seq, length);
|
|
|
|
println!("Starting sequence: {:?}", seq);
|
|
println!("Kolakoski sequence: {:?}", kseq);
|
|
println!("Possible Kolakoski sequence? {:?}", is_kolakoski(&kseq));
|
|
}
|
|
}
|