Skip to content

Instantly share code, notes, and snippets.

@chase-lambert
Created April 23, 2025 01:05
Show Gist options
  • Save chase-lambert/d554ecb0537a2dfbb10e9eb1adf8b617 to your computer and use it in GitHub Desktop.
Save chase-lambert/d554ecb0537a2dfbb10e9eb1adf8b617 to your computer and use it in GitHub Desktop.
rendezvous with cassidoo challenge: 25.04.21
#[derive(Debug, PartialEq)]
pub struct Ingredient<'a> {
pub name: &'a str,
pub amount: u32,
}
impl<'a> Ingredient<'a> {
fn new(name: &'a str, amount: u32) -> Self {
Self { name, amount }
}
}
pub fn calculate_ingredients<'a>(
ingredients: &'a [Ingredient],
target_servings: u32,
) -> Vec<Ingredient<'a>> {
ingredients
.iter()
.map(|ingredient| Ingredient::new(ingredient.name, ingredient.amount * target_servings))
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn calculate_ingredients_test() {
let ingredients = vec![
Ingredient::new("flour", 200),
Ingredient::new("sugar", 100),
Ingredient::new("eggs", 2),
];
let target_servings = 3;
let result = calculate_ingredients(&ingredients, target_servings);
let expected = vec![
Ingredient::new("flour", 600),
Ingredient::new("sugar", 300),
Ingredient::new("eggs", 6),
];
assert_eq!(result, expected);
}
}
@chase-lambert
Copy link
Author

chase-lambert commented Apr 24, 2025

// Zig version

const std = @import("std");
const testing = std.testing;
const Allocator = std.mem.Allocator;

pub const Ingredient = struct {
    name: []const u8,
    amount: u32,
};

pub fn calculateIngredients(allocator: Allocator, ingredients: []const Ingredient, target_servings: u8) ![]Ingredient {
    const scaled_ingredients = try allocator.alloc(Ingredient, ingredients.len);
    errdefer allocator.free(scaled_ingredients);

    for (ingredients, scaled_ingredients) |ingredient, *scaled_ingredient| {
        scaled_ingredient.* = .{
            .name = ingredient.name,
            .amount = ingredient.amount * target_servings,
        };
    }

    return scaled_ingredients;
}


// or using an iterator (no allocations!):

const IngredientScaler = struct {
    ingredients: []const Ingredient,
    target_servings: u8,
    index: usize = 0,

    pub fn next(self: *IngredientScaler) ?Ingredient {
        if (self.index >= self.ingredients.len) return null;

        const ingredient = self.ingredients[self.index];
        self.index += 1;

        return .{
            .name = ingredient.name,
            .amount = ingredient.amount * self.target_servings,
        };
    }
};

pub fn ingredientIterator(ingredients: []const Ingredient, target_servings: u8) IngredientScaler {
    return .{
        .ingredients = ingredients,
        .target_servings = target_servings,
    };
}

test "calculateIngredients test" {
    var ingredients = [_]Ingredient{
        .{ .name = "flour", .amount = 200 },
        .{ .name = "sugar", .amount = 100 },
        .{ .name = "eggs", .amount = 2 },
    };
    const target_servings = 3;

    const result = try calculateIngredients(testing.allocator, &ingredients, target_servings);
    defer testing.allocator.free(result);

    const expected = [_]Ingredient{
        .{ .name = "flour", .amount = 600 },
        .{ .name = "sugar", .amount = 300 },
        .{ .name = "eggs", .amount = 6 },
    };

    try testing.expectEqual(expected.len, result.len);
    for (expected, 0..) |exp, i| {
        try testing.expectEqualStrings(exp.name, result[i].name);
        try testing.expectEqual(exp.amount, result[i].amount);
    }
}

@chase-lambert
Copy link
Author

;; Clojure version

(defn calculate-ingredients [ingredients target-servings]
  (for [{:keys [name amount]} ingredients]
    {:name name 
     :amount (* amount target-servings)}))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment