use std::collections::HashMap;
use tunes::prelude::*;
use tunes::sequences;
fn main() -> anyhow::Result<()> {
println!("\n Generative Sequences: Advanced Algorithms\n");
println!("Complex pattern generators for algorithmic composition\n");
let engine = AudioEngine::new()?;
let mut comp = Composition::new(Tempo::new(110.0));
println!("1. Cellular Automaton - Rule 30 (Chaotic)\n");
println!(" Simple rules create complex patterns");
println!(" Used in Wolfram's random number generator!");
println!(" Rule 30 = 00011110 in binary\n");
let rule30 = sequences::cellular_automaton::generate(30, 8, 16, None);
for (gen_idx, generation) in rule30.iter().take(4).enumerate() {
let rhythm: Vec<usize> = generation
.iter()
.enumerate()
.filter(|(_, &v)| v == 1)
.map(|(i, _)| i)
.collect();
println!(" Generation {}: {:?}", gen_idx + 1, generation);
comp.instrument(&format!("ca30_gen{}", gen_idx), &Instrument::pluck())
.at(gen_idx as f32 * 2.0)
.drum_grid(16, 0.125, |g| g
.sound(DrumType::Kick, &rhythm));
}
println!("\n2. Cellular Automaton - Rule 90 (Sierpinski Triangle)\n");
println!(" Creates fractal patterns!");
println!(" Rule 90 = 01011010 in binary");
println!(" Generates Sierpinski fractal structure\n");
let rule90 = sequences::cellular_automaton::generate(90, 8, 16, None);
for (gen_idx, generation) in rule90.iter().take(4).enumerate() {
let rhythm: Vec<usize> = generation
.iter()
.enumerate()
.filter(|(_, &v)| v == 1)
.map(|(i, _)| i)
.collect();
println!(" Generation {}: {:?}", gen_idx + 1, generation);
comp.instrument(&format!("ca90_gen{}", gen_idx), &Instrument::synth_lead())
.at(8.0 + gen_idx as f32 * 2.0)
.drum_grid(16, 0.125, |g| g
.sound(DrumType::Snare, &rhythm));
}
println!("\n3. L-System: Algae Growth Pattern\n");
println!(" Lindenmayer system - fractal growth from rewriting rules");
println!(" Axiom: 'A'");
println!(" Rules: A → AB, B → A");
println!(" Iterations: A → AB → ABA → ABAAB → ABAABABA...\n");
let mut algae_rules = HashMap::new();
algae_rules.insert('A', "AB".to_string());
algae_rules.insert('B', "A".to_string());
let lsystem_str = sequences::lsystem::generate("A", &algae_rules, 5);
println!(" Result: {}\n", lsystem_str);
let lsystem_notes = sequences::lsystem_to_sequence(&lsystem_str);
let lsystem_freqs: Vec<f32> = lsystem_notes
.iter()
.map(|&semitones| 440.0 * 2.0f32.powf(semitones as f32 / 12.0))
.collect();
comp.instrument("lsystem", &Instrument::pluck())
.delay(Delay::new(0.375, 0.3, 0.5))
.at(16.0)
.notes(&lsystem_freqs, 0.15);
println!("4. L-System: Cantor Set (Fractal)\n");
println!(" Axiom: 'A'");
println!(" Rules: A → ABA, B → BBB");
println!(" Creates fractal rhythmic patterns\n");
let mut cantor_rules = HashMap::new();
cantor_rules.insert('A', "ABA".to_string());
cantor_rules.insert('B', "BBB".to_string());
let cantor_lsys = sequences::lsystem::generate("A", &cantor_rules, 3);
let cantor_notes = sequences::lsystem_to_sequence(&cantor_lsys);
let cantor_hits: Vec<usize> = cantor_notes
.iter()
.enumerate()
.filter(|(_, &v)| v == 0)
.map(|(i, _)| i)
.collect();
comp.track("lsystem_cantor")
.at(19.0)
.drum_grid(cantor_notes.len(), 0.125, |g| g
.sound(DrumType::Kick, &cantor_hits));
println!("\n5. Markov Chain: Probabilistic Sequence Generation\n");
println!(" Learning patterns from training data");
println!(" Each state has probabilities for next states\n");
let training_melody = vec![0, 2, 4, 2, 0, 2, 4, 5, 4, 2, 0];
println!(" Training data: {:?}", training_melody);
let transitions = sequences::build_markov_transitions(&training_melody, 1);
let markov_seq = sequences::markov::generate(&transitions, 0, 20);
println!(" Generated: {:?}\n", markov_seq);
let markov_freqs: Vec<f32> = markov_seq
.iter()
.map(|&semitones| 440.0 * 2.0f32.powf(semitones as f32 / 12.0))
.collect();
comp.instrument("markov", &Instrument::synth_lead())
.reverb(Reverb::new(0.5, 0.5, 0.3))
.at(23.0)
.notes(&markov_freqs, 0.25);
println!("6. Recamán's Sequence (Spiraling Back-and-Forth)\n");
println!(" a(0) = 0");
println!(" a(n) = a(n-1) - n if positive and new, else a(n-1) + n");
println!(" Creates beautiful melodic contours with memory\n");
let recaman = sequences::recaman::generate(24);
println!(" First 24 terms: {:?}\n", &recaman[..12]);
let recaman_freqs = sequences::normalize(&recaman, 220.0, 880.0);
comp.instrument("recaman", &Instrument::pluck())
.delay(Delay::new(0.375, 0.3, 0.6))
.at(28.0)
.notes(&recaman_freqs, 0.2);
println!("7. Van der Corput Sequence (Quasi-Random)\n");
println!(" Low-discrepancy sequence - better than random");
println!(" Fills space more evenly than random numbers");
println!(" Used in computer graphics, Monte Carlo methods\n");
let quasi_random = sequences::van_der_corput::generate(32, 2); println!(" First 16 values: {:?}\n", &quasi_random[..16]);
for (_i, &pos) in quasi_random.iter().take(32).enumerate() {
let freq = 300.0 + pos * 500.0;
let time = 33.0 + pos * 8.0;
comp.instrument("quasi", &Instrument::pluck())
.at(time)
.note(&[freq], 0.1);
}
println!("8. Full Generative Composition\n");
println!(" Combining multiple algorithms together\n");
let bass_recaman = sequences::recaman::generate(16);
let bass_freqs = sequences::normalize(&bass_recaman, 55.0, 110.0);
comp.instrument("gen_bass", &Instrument::sub_bass())
.at(42.0)
.notes(&bass_freqs, 0.5);
let melody_markov = sequences::markov::generate(&transitions, 0, 16);
let melody_freqs: Vec<f32> = melody_markov
.iter()
.map(|&s| 440.0 * 2.0f32.powf(s as f32 / 12.0))
.collect();
comp.instrument("gen_melody", &Instrument::synth_lead())
.delay(Delay::new(0.375, 0.3, 0.5))
.at(42.0)
.notes(&melody_freqs, 0.5);
let rhythm_ca = sequences::cellular_automaton::generate(30, 16, 16, None);
let ca_rhythm: Vec<usize> = rhythm_ca[0]
.iter()
.enumerate()
.filter(|(_, &v)| v == 1)
.map(|(i, _)| i)
.collect();
comp.track("gen_rhythm")
.at(42.0)
.drum_grid(16, 0.125, |g| g
.sound(DrumType::Kick, &ca_rhythm)
.sound(DrumType::Snare, &sequences::euclidean::generate(5, 16))
.sound(DrumType::HiHatClosed, &sequences::euclidean::generate(11, 16)));
let texture_lsys = sequences::lsystem::generate("A", &algae_rules, 4);
let texture_seq = sequences::lsystem_to_sequence(&texture_lsys);
let texture_freqs: Vec<f32> = texture_seq
.iter()
.map(|&s| 880.0 * 2.0f32.powf(s as f32 / 12.0))
.collect();
comp.instrument("gen_texture", &Instrument::warm_pad())
.reverb(Reverb::new(0.7, 0.6, 0.5))
.at(42.0)
.notes(&texture_freqs, 0.25);
println!("\n▶️ Playing generative sequences...\n");
println!(" Duration: ~50 seconds\n");
engine.play_mixer(&comp.into_mixer())?;
println!("\n✅ Generative Sequences Complete!\n");
println!("Key Takeaways:");
println!("• Cellular automata: Simple rules → complex patterns");
println!("• L-Systems: Fractal growth through string rewriting");
println!("• Markov chains: Learn patterns from data");
println!("• Recamán: Back-and-forth spiraling with memory");
println!("• Van der Corput: Better distribution than random\n");
println!("Generative Applications:");
println!("• Algorithmic composition systems");
println!("• Procedural game music");
println!("• Evolving soundscapes");
println!("• Non-repetitive background music");
println!("• Interactive music systems\n");
println!("Famous Rules:");
println!("Rule 30: Chaotic, used in random generation");
println!("Rule 90: Sierpinski triangle fractal");
println!("Rule 110: Turing complete!");
println!("Rule 184: Traffic flow simulation\n");
println!("Try Next:");
println!("cargo run --example mathematical_sequences");
println!("cargo run --example chaotic_sequences\n");
println!("Pro Tip:");
println!("Combine these algorithms! Use CA for rhythm,");
println!("Markov for melody, L-Systems for form,");
println!("and Recamán for bass lines!\n");
Ok(())
}