use serde_json::Value;
use crate::sequence::Sequence;
pub(crate) struct OeisSeq {
data: Vec<i128>,
}
impl Sequence for OeisSeq {
fn infer(seq: &[i128]) -> Option<Self> {
let url = format!(
"https://oeis.org/search?q={:?}&fmt=json",
seq.iter()
.map(|x| x.to_string())
.collect::<Vec<_>>()
.join(",")
);
let response = reqwest::blocking::get(url).unwrap();
let body = response.text().unwrap();
let json: Value = serde_json::from_str(&body).unwrap();
let Value::Array(arr) = json else {
return None;
};
let first = arr.first().unwrap();
let Value::Object(obj) = first else {
return None;
};
let Value::String(name) = obj.get("data")? else {
return None;
};
let data = name
.split(',')
.map(|x| {
x.parse()
.unwrap_or_else(|_| panic!("unable to parse {:?} as integer", x))
})
.collect();
Some(OeisSeq { data })
}
fn generate(&self, seq: &[i128], end: i128) -> Vec<i128> {
let start_idx = (0..self.data.len())
.find(|idx| self.data[*idx..*idx + seq.len()] == *seq)
.unwrap_or_else(|| panic!("Sequence not found in data. Sequence: {:?}. Data: {:?}",
seq, self.data));
let mut seq = Vec::new();
let mut terminated = false;
for x in &self.data[start_idx..] {
if *x >= end {
terminated = true;
break;
}
seq.push(*x);
}
if !terminated {
panic!(
"OEIS sequence is incomplete and terminates with an value less than the upper bound of {:?}. OEIS sequence: {:?}",
end, seq
);
}
seq
}
}