This is an Advent of Code solution. Click to reveal!
The cogs are turning...
    
https://zigbin.io/d4362bClick to copy
https://zigbin.io/d4362b/runClick to copy
https://zigbin.io/d4362b/rawClick to copy
const std = @import("std");
const hash = std.crypto.hash;

const input = @embedFile("input");
var static_buf = [_]u8{0} ** 64;
var fba = std.heap.FixedBufferAllocator.init(&static_buf);
const fba_alloc = fba.allocator();

pub fn main() !void {
    std.debug.print("Part 1: {}\n", .{part1()});
    std.debug.print("Part 2: {}\n", .{part2()});
}

fn part1() usize {
    var decimal: usize = 1;
    while (true) : (decimal += 1) {
        const b = std.fmt.allocPrint(fba_alloc, "{s}{d}", .{ input[0 .. input.len - 1], decimal }) catch unreachable;
        defer fba_alloc.free(b);

        var out: [hash.Md5.digest_length]u8 = undefined;
        hash.Md5.hash(b, &out, .{});

        if (out[0] == 0 and out[1] == 0 and out[2] <= 15) {
            return decimal;
        }
    }
}

fn part2() usize {
    var decimal: usize = 1;
    while (true) : (decimal += 1) {
        const b = std.fmt.allocPrint(fba_alloc, "{s}{d}", .{ input[0 .. input.len - 1], decimal }) catch unreachable;
        defer fba_alloc.free(b);

        var out: [hash.Md5.digest_length]u8 = undefined;
        hash.Md5.hash(b, &out, .{});

        if (out[0] == 0 and out[1] == 0 and out[2] == 0) {
            return decimal;
        }
    }
}