big-brain
big-brain copied to clipboard
feat: Implement `Highest` `Picker` for picking highest, then first tying, score
… first tying, score
Awesome, both sound good. I'll see what I can get done in a day or two.
If you have any thoughts on how to reduce the allocation count, please suggest them. I'm a little uncertain about how reduce
would help here. I guess you can track the winning value in the accumulator, but that seems less readable. Feels a bit like a premature optimization, but maybe I'm wrong and just haven't hit any specific performance issues in my usage yet.
pickers run very often, so I think this is a worthwhile place to optimize a bit. You can do it with reduce, or you can do it with a variable. The algorithms would just be something like:
let mut highest: Option<(FloatOrd, &Choice)> = None;
for choice in choices {
if let Some((curr_value, curr_choice)) = highest {
let val = choice.calculate(scores);
if val > curr_value {
highest = Some((val, &choice));
}
} else {
highest = (choice.calculate(scores), &choice);
}
}
return highest.map(|(_, choice)| choice)
Or something like that. I didn't try it myself. And honestly, I find this more readable than chaining iterators.
OK, so you'd prefer something more imperative and less functional? I can do that. Looking at the above, it looks like you may have copy-pasted my code and forgot to edit out the copy-paste? That or you did the same calculation twice, just in different styles. :) Sorry, not trying to be obtuse, going through some apartment remodel/repair drama and my brain is a bit fried right now.
yes, sorry. I copy-pasted it so I could refer to it while I wrote mine.
You can also write yours with reduce
, and the logic would ultimately be the same. Initialize the accumulator with None
, and go from there. The body of the reduce function would probably look exactly like the iterator body above.
I've got a fold
version of this which looks like
impl Picker for MaxScore {
fn pick<'a>(&self, choices: &'a [Choice], scores: &Query<&Score>) -> Option<&'a Choice> {
let mut max_score = 0f32;
choices.iter().fold(None, |acc, choice| {
let score = choice.calculate(scores);
if score <= max_score {
return acc;
}
max_score = score;
Some(choice)
})
}
}
@will-hart do you want to just PR that one, since it's already done?
Yeah, I'm fine with whichever. Sorry I didn't get to it quicker--dealing with an apartment remodel from hell and it's been on tomorrow's todo list for a few days now. Can still probably get to it tomorrow, but if you've got an equivalent PR then this one can be closed.
Just glad to have this implemented. :)
Ouch that sounds stressful @ndarilek . I don't want to step on your toes but I'm happy to make a PR