diff --git a/website/blog/2024-12-06-advent-of-pbt-day-6/AdventOfTheDay.tsx b/website/blog/2024-12-06-advent-of-pbt-day-6/AdventOfTheDay.tsx new file mode 100644 index 00000000000..239bcb88590 --- /dev/null +++ b/website/blog/2024-12-06-advent-of-pbt-day-6/AdventOfTheDay.tsx @@ -0,0 +1,39 @@ +import adventBuggy from './buggy.mjs'; +import { buildAdventOfTheDay } from '../2024-12-01-advent-of-pbt-day-1/AdventOfTheDayBuilder'; + +const { AdventPlaygroundOfTheDay, FormOfTheDay } = buildAdventOfTheDay({ + day: 6, + buildBuggyAdvent: adventBuggy, + referenceAdvent: adventBuggy(10), // not buggy as 25**10 is far from MAX_SAFE_INTEGER + parser, + placeholderForm: '๐Ÿงบ๐ŸŽ', + functionName: 'nextBarcode', + signature: 'function nextBarcode(barcode: Unit[]): Unit[];', + signatureExtras: [ + "type Unit = 'โœ‰๏ธ'|'๐Ÿงบ'|'๐ŸŽ„'|'๐Ÿ””'|'๐Ÿ•ฏ๏ธ'|'โญ'|'๐ŸฆŒ'|'โ›„'|'๐Ÿ›ท'|'โ„๏ธ'|'๐ŸŽฟ'|'โœจ'|'๐Ÿคฉ'|'๐Ÿฅณ'|'๐ŸŽˆ'|'๐Ÿช€'|'๐ŸŽฎ'|'๐ŸŽฒ'|'โ™Ÿ๏ธ'|'๐Ÿ’'|'๐ŸŽ€'|'๐Ÿงฆ'|'๐ŸŽ…'|'๐Ÿคถ'|'๐ŸŽ';", + ], +}); + +export { AdventPlaygroundOfTheDay, FormOfTheDay }; + +// Reference implementation + +// Inputs parser + +const validBarcodeRegex = /^(โœ‰๏ธ|๐Ÿงบ|๐ŸŽ„|๐Ÿ””|๐Ÿ•ฏ๏ธ|โญ|๐ŸฆŒ|โ›„|๐Ÿ›ท|โ„๏ธ|๐ŸŽฟ|โœจ|๐Ÿคฉ|๐Ÿฅณ|๐ŸŽˆ|๐Ÿช€|๐ŸŽฎ|๐ŸŽฒ|โ™Ÿ๏ธ|๐Ÿ’|๐ŸŽ€|๐Ÿงฆ|๐ŸŽ…|๐Ÿคถ|๐ŸŽ)+$/; +function parser(answer: string): unknown[] | undefined { + const lines = answer.trim().split('\n'); + if (lines.length !== 1) { + throw new Error(`Your answer should be made of one line`); + } + if (lines[0] !== 'โœ‰๏ธ' && !validBarcodeRegex.test(lines[0])) { + throw new Error('Invalid barcode provided'); + } + const barcodeExtractorRegex = /(โœ‰๏ธ|๐Ÿงบ|๐ŸŽ„|๐Ÿ””|๐Ÿ•ฏ๏ธ|โญ|๐ŸฆŒ|โ›„|๐Ÿ›ท|โ„๏ธ|๐ŸŽฟ|โœจ|๐Ÿคฉ|๐Ÿฅณ|๐ŸŽˆ|๐Ÿช€|๐ŸŽฎ|๐ŸŽฒ|โ™Ÿ๏ธ|๐Ÿ’|๐ŸŽ€|๐Ÿงฆ|๐ŸŽ…|๐Ÿคถ|๐ŸŽ)/g; + const barcode = []; + let m: RegExpExecArray | null = null; + while ((m = barcodeExtractorRegex.exec(lines[0])) !== null) { + barcode.push(m[1]); + } + return [barcode]; +} diff --git a/website/blog/2024-12-06-advent-of-pbt-day-6/buggy.mjs b/website/blog/2024-12-06-advent-of-pbt-day-6/buggy.mjs new file mode 100644 index 00000000000..c2f5a5e2893 --- /dev/null +++ b/website/blog/2024-12-06-advent-of-pbt-day-6/buggy.mjs @@ -0,0 +1,85 @@ +// @ts-check + +export default function advent(unitPerNumericalOverride) { + /** + * @typedef {'\u{2709}\u{fe0f}'|'\u{1f9fa}'|'\u{1f384}'|'\u{1f514}'|'\u{1f56f}\u{fe0f}'|'\u{2b50}'|'\u{1f98c}'|'\u{26c4}'|'\u{1f6f7}'|'\u{2744}\u{fe0f}'|'\u{1f3bf}'|'\u{2728}'|'\u{1f929}'|'\u{1f973}'|'\u{1f388}'|'\u{1fa80}'|'\u{1f3ae}'|'\u{1f3b2}'|'\u{265f}\u{fe0f}'|'\u{1f49d}'|'\u{1f380}'|'\u{1f9e6}'|'\u{1f385}'|'\u{1f936}'|'\u{1f381}'} Unit + */ + /** + * @param {Unit[]} barcode + * @returns {Unit[]} + */ + return function nextBarcode(barcode) { + /** @type {Unit[]} */ + const units = [ + '\u{2709}\u{fe0f}', + '\u{1f9fa}', + '\u{1f384}', + '\u{1f514}', + '\u{1f56f}\u{fe0f}', + '\u{2b50}', + '\u{1f98c}', + '\u{26c4}', + '\u{1f6f7}', + '\u{2744}\u{fe0f}', + '\u{1f3bf}', + '\u{2728}', + '\u{1f929}', + '\u{1f973}', + '\u{1f388}', + '\u{1fa80}', + '\u{1f3ae}', + '\u{1f3b2}', + '\u{265f}\u{fe0f}', + '\u{1f49d}', + '\u{1f380}', + '\u{1f9e6}', + '\u{1f385}', + '\u{1f936}', + '\u{1f381}', + ]; + const base25 = '0123456789abcdefghijklmno'; + + const unitPerNumerical = typeof unitPerNumericalOverride !== 'undefined' ? unitPerNumericalOverride : 12; + const maxForNumerical = units.length ** unitPerNumerical; + const numericalVersion = []; + + // Create numerical value for current + for (let i = barcode.length; i > 0; i -= unitPerNumerical) { + const unitsForNumerical = barcode.slice(Math.max(0, i - unitPerNumerical), i); + let numerical = 0; + for (const unit of unitsForNumerical) { + numerical *= units.length; + numerical += units.indexOf(unit); + } + numericalVersion.push(numerical); + } + + // Compute next numerical value + let nextNumericalVersion = [...numericalVersion, 0]; + let cursorInNext = 0; + nextNumericalVersion[cursorInNext] += 1; + while (nextNumericalVersion[cursorInNext] >= maxForNumerical) { + nextNumericalVersion[cursorInNext] = 0; + cursorInNext += 1; + nextNumericalVersion[cursorInNext] += 1; + } + if (nextNumericalVersion[nextNumericalVersion.length - 1] === 0) { + nextNumericalVersion = nextNumericalVersion.slice(0, nextNumericalVersion.length - 1); + } + nextNumericalVersion.reverse(); + + // Translate next numerical value into a barcode + /** @type {Unit[]} */ + const next = []; + for (let numericalIndex = 0; numericalIndex !== nextNumericalVersion.length; ++numericalIndex) { + let numericalBase25 = nextNumericalVersion[numericalIndex].toString(25); + if (numericalIndex !== 0) { + numericalBase25 = numericalBase25.padStart(unitPerNumerical, '0'); + } + for (const in25 of numericalBase25) { + next.push(units[base25.indexOf(in25)]); + } + } + return next; + }; +} diff --git a/website/blog/2024-12-06-advent-of-pbt-day-6/index.md b/website/blog/2024-12-06-advent-of-pbt-day-6/index.md new file mode 100644 index 00000000000..55581031641 --- /dev/null +++ b/website/blog/2024-12-06-advent-of-pbt-day-6/index.md @@ -0,0 +1,46 @@ +--- +title: Advent of PBT 2024 ยท Day 6 +authors: [dubzzz] +tags: [advent-of-pbt, advent-of-pbt-2024] +--- + +import {AdventPlaygroundOfTheDay,FormOfTheDay} from './AdventOfTheDay'; + +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. Santa just pinged you with your next challenge: the elves have designed an algorithm to compute the next barcode for Santaโ€™s presentsโ€”a task that grows harder each year. Santa suspects their implementation might not be reliable. Can you find errors in the algorithm to ensure every present is labeled correctly? ๐ŸŽ„๐Ÿ”ง + + + +## The barcode + +Centuries ago, when Santa first began his activity, he introduced the worldโ€™s very first barcode systemโ€”becoming a true pioneer of the industry! + +Santa defined his barcode system using a specific sequence of symbols (order matters): โœ‰๏ธ, ๐Ÿงบ, ๐ŸŽ„, ๐Ÿ””, ๐Ÿ•ฏ๏ธ, โญ, ๐ŸฆŒ, โ›„, ๐Ÿ›ท, โ„๏ธ, ๐ŸŽฟ, โœจ, ๐Ÿคฉ, ๐Ÿฅณ, ๐ŸŽˆ, ๐Ÿช€, ๐ŸŽฎ, ๐ŸŽฒ, โ™Ÿ๏ธ, ๐Ÿ’, ๐ŸŽ€, ๐Ÿงฆ, ๐ŸŽ…, ๐Ÿคถ, ๐ŸŽ. + +Since day one, every present Santa delivers is labeled with a barcode following this rule: + +- The first present was labeled `['โœ‰๏ธ']`. +- The second present was `['๐Ÿงบ']`. +- The one after `['๐ŸŽ']` was `['๐Ÿงบ', 'โœ‰๏ธ']`. +- The one after `['๐Ÿงบ', 'โœ‰๏ธ']` was `['๐Ÿงบ', '๐Ÿงบ']`. +- The one after `['๐Ÿงบ', '๐ŸŽ']` was `['๐ŸŽ„', 'โœ‰๏ธ']`. +- ... + +Another rule to remember is that, apart from `['โœ‰๏ธ']`, no barcode should start with a `โœ‰๏ธ` โ€”itโ€™s the equivalent of "zero" in Santaโ€™s numerical system. + +Over time, computing the next barcode has become increasingly challenging. To save time, Santa ordered his elves to design an algorithm capable of taking an initial barcode (in the form of an array) and calculating the next one in sequence. + +## Hands on + +The elves are confident theyโ€™ve delivered the most reliable and efficient solution to Santaโ€™s request. But Santa asked you to verify their work. Your mission is to find any barcode that their algorithm mishandles and report it to Santa. As he left the room, Santa paused at the door and mentioned: _"Oh, by the way, this year Iโ€™ll probably start using the 17th bar of my barcode system... or maybe the 19th, not sure actually"_. + +Time is running out, and presents are already piling up while waiting for your checks! ๐ŸŽ„๐Ÿ”ง + + + +## Your answer + +