Skip to content

Commit

Permalink
📝 Advent of PBT, Day 23 (#5553)
Browse files Browse the repository at this point in the history
  • Loading branch information
dubzzz authored Dec 23, 2024
1 parent bf498f4 commit a1e1b43
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 0 deletions.
82 changes: 82 additions & 0 deletions website/blog/2024-12-23-advent-of-pbt-day-23/AdventOfTheDay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import adventBuggy from './buggy.mjs';
import { buildAdventOfTheDay } from '../2024-12-01-advent-of-pbt-day-1/AdventOfTheDayBuilder';

const { AdventPlaygroundOfTheDay, FormOfTheDay } = buildAdventOfTheDay({
day: 23,
buildBuggyAdvent: adventBuggy,
referenceAdvent: () => true,
buggyAdventSurcharged: (...args: Parameters<ReturnType<typeof adventBuggy>>) => {
const expected = payslipContentFor(...args);
const out = adventBuggy()(...args);
const [availableCoins, amountToBePaid] = args;
if (out === null) {
return expected === null ? true : 'not supposed to find anything';
}
if (out.reduce((acc, v) => acc + v, 0) !== amountToBePaid) {
return 'bad amount';
}
const coins = [...availableCoins];
for (const coinValue of out) {
const index = coins.indexOf(coinValue);
if (index === -1) {
return 'no such coin';
}
coins.splice(index, 1);
}
return true;
},
parser,
placeholderForm: '7?\n1,1,2,5,10',
functionName: 'payslipContentFor',
signature: 'payslipContentFor(availableCoins: Coin[], amountToBePaid: number): Coin[] | null;',
signatureExtras: ['type Coin = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;'],
});

export { AdventPlaygroundOfTheDay, FormOfTheDay };

// Reference implementation

function payslipContentFor(availableCoins, amountToBePaid) {
const coins = [...availableCoins].sort((a, b) => b - a);
function helper(target, index) {
if (target === 0) {
return [];
}
if (target < 0 || index >= coins.length) {
return null;
}
const withCurrent = helper(target - coins[index], index + 1);
if (withCurrent !== null) {
return [coins[index], ...withCurrent];
}
return helper(target, index + 1);
}
return helper(amountToBePaid, 0);
}

// Inputs parser

function parser(answer: string): unknown[] | undefined {
const lines = answer.split('\n');
if (lines.length !== 2) {
throw new Error('Expected to receive two lines one for the amount to be paid, another one for the coins');
}
if (lines[0].at(-1) !== '?') {
throw new Error(`First line must end by ?, got: ${lines[0]}.`);
}
const amount = Number(lines[0].slice(0, -1));
if (!Number.isInteger(amount) || amount < 0 || amount > 2 ** 31 - 1) {
throw new Error(`Invalid amount received, must be a positive integer value below 2**31-1, got: ${lines[0]}.`);
}
const coins: number[] =
lines[1] === ''
? []
: lines[1].split(',').map((v) => {
const n = Number(v);
if (!Number.isInteger(n) || n < 1 || n > 10) {
throw new Error(`Invalid coin value received, got: ${v}.`);
}
return n;
});
return [coins, amount];
}
35 changes: 35 additions & 0 deletions website/blog/2024-12-23-advent-of-pbt-day-23/buggy.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// @ts-check

export default function advent() {
/** @typedef {1|2|3|4|5|6|7|8|9|10} Coin */

/**
* @param {Coin[]} availableCoins
* @param {number} amountToBePaid
* @returns {Coin[] | null}
*/
return function payslipContentFor(availableCoins, amountToBePaid) {
const coins = [...availableCoins].sort((a, b) => b - a);
const memo = Array.from({ length: coins.length }, () => undefined);
function helper(target, index) {
if (target === 0) {
return [];
}
if (target < 0 || index >= coins.length) {
return null;
}
if (memo[index] !== undefined) {
return memo[index];
}
const withCurrent = helper(target - coins[index], index + 1);
if (withCurrent !== null) {
memo[index] = [coins[index], ...withCurrent];
return [coins[index], ...withCurrent];
}
const withoutCurrent = helper(target, index + 1);
memo[index] = withoutCurrent;
return withoutCurrent;
}
return helper(amountToBePaid, 0);
};
}
51 changes: 51 additions & 0 deletions website/blog/2024-12-23-advent-of-pbt-day-23/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
title: Advent of PBT 2024 · Day 23
authors: [dubzzz]
tags: [advent-of-pbt, advent-of-pbt-2024]
image: ./social.png
---

import {AdventPlaygroundOfTheDay,FormOfTheDay} from './AdventOfTheDay';
import BlueskyComments from '../2024-12-01-advent-of-pbt-day-1/BlueskyComments';

Christmas is at risk! In their rush to meet tight deadlines, Santa’s elves accidentally introduced bugs into critical algorithms. If these issues aren’t discovered in time, Christmas could be delayed for everyone worldwide!

Your mission is to troubleshoot these black-box algorithms using the power of fast-check.

The clock is ticking. This time, it’s not Santa but Emma who needs your help: she suspects her coin-payment algorithm might have bugs. Can you uncover any issues and ensure every elf gets paid on time for years to come? 🎄✨

<!--truncate-->

## Money day

In Santa's world, money works just like in ours. At the end of each month, elves and other inhabitants receive a payslip reflecting their contributions. However, Santa has a habit of delaying payments in December, claiming he needs to withdraw coins since he only pays in cash.

Last year’s drama prompted Emma, one of the elves, to take action. She designed an algorithm to ensure smooth payouts. Her algorithm works like this:

- **Input:** A list of coins Santa has in hand and the exact amount he needs to pay a given elf.
- **Output:** Either an array containing the values of the coins that sum up to the exact amount or `null` if it’s impossible to make the payment.

For example:

- If Santa has coins `[1, 1, 2, 5, 10]` and needs to pay `7`, the algorithm might return `[2, 5]`.
- If Santa has coins `[3, 4, 5]` and needs to pay `2`, it would return `null`.

## Hands on

This time, it’s not Santa calling you — it’s Emma. She’s concerned her algorithm might contain errors. If the payouts are delayed again this year, it could damage elf morale and break their motivation for next year.

Emma shared one important detail before leaving you to test her algorithm: in Santa’s world, the coins available are always `[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]`.

Your mission: Use property-based testing to check Emma’s algorithm for bugs and ensure it works flawlessly.

You’ve already saved Christmas this year; now it’s time to ensure smooth payouts for years to come! 🎄✨

<AdventPlaygroundOfTheDay />

## Your answer

<FormOfTheDay />

## Comments

<BlueskyComments url="" />
3 changes: 3 additions & 0 deletions website/blog/2024-12-23-advent-of-pbt-day-23/social.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit a1e1b43

Please sign in to comment.