I subscribe to a wonderful newsletter that, among other things, presents readers with a coding challenge every week.

Here’s this week’s question:

Given an array of people objects (where each person has a name and a number of pizza slices they’re hungry for) and a number for the number of slices that the pizza can be sliced into, return the number of pizzas you need to buy.

Example:

arr = [{ name: Joe, num: 9 }, { name: Cami, num: 3 }, { name: Cassidy, num: 4 }]
gimmePizza(arr, 8)
2 // 16 slices needed, pizzas can be sliced into 8 pieces, so 2 pizzas should be ordered

Since Rust is basically the only language I write these days (even though I write it poorly), I naturally decided to use Rust.

Here was my first attempt:

#![allow(dead_code)]
struct Person<'a> {
    name: &'a str,
    slices_requested: usize,
}
fn main() {
    let persons: Vec<Person> = vec![
        Person {
            name: "Joe",
            slices_requested: 9,
        },
        Person {
            name: "Cami",
            slices_requested: 3,
        },
        Person {
            name: "Cassidy",
            slices_requested: 4,
        },
    ];

    assert_eq!(gimme_pizza(&persons, 8), 2);
    println!("Need to order {} pizzas", gimme_pizza(&persons, 8));
}

fn gimme_pizza(persons: &[Person], slices_per_pizza: usize) -> usize {
    let mut slices_needed = 0;
    for person in persons {
        slices_needed += person.slices_requested;
    }
    if slices_needed % slices_per_pizza == 0 {
        slices_needed / slices_per_pizza
    } else {
        slices_needed / slices_per_pizza + 1
    }
}

It works fine, but those first 4 lines of the gimme_pizza function bugged me – I shouldn’t have to declare a mutable variable and set it to 0 like that. I knew there was a better way, probably using map, to make that summation a bit tighter, but I couldn’t figure out how to get it to work.

Thanks to some help from the Fediverse, I now know this is what I was reaching for:

fn gimme_pizza_using_map(persons: &[Person], slices_per_pizza: usize) -> usize {
    let slices_needed: usize = persons.iter().map(|person| person.slices_requested).sum();
    if slices_needed % slices_per_pizza == 0 {
        slices_needed / slices_per_pizza
    } else {
        slices_needed / slices_per_pizza + 1
    }
}

Alternatively, I could have used fold, another pair of Fediverse users pointed out. That would have looked like this:

fn gimme_pizza_using_fold(persons: &[Person], slices_per_pizza: usize) -> usize {
    let slices_needed: usize = persons.iter().fold(0, |running_sum, person| {
        running_sum + person.slices_requested
    });
    if slices_needed % slices_per_pizza == 0 {
        slices_needed / slices_per_pizza
    } else {
        slices_needed / slices_per_pizza + 1
    }
}

I’m not sure with I prefer… I’m guessing fold is more versatile for cases where you want to do more than summing. And I don’t love that map returns its own object type that you can only do certain things with, whereas fold is more an all-in-one approach.

Separately, I’m curious if there’s a more concise way to go from slices_needed to pizzas_needed, besides my big ole, 5-line if/else using modulo.