Skip to content

Commit

Permalink
📝 Advent Of PBT, Day 6 (#5489)
Browse files Browse the repository at this point in the history
  • Loading branch information
dubzzz authored Dec 6, 2024
1 parent dd5cad1 commit 5873f96
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 0 deletions.
39 changes: 39 additions & 0 deletions website/blog/2024-12-06-advent-of-pbt-day-6/AdventOfTheDay.tsx
Original file line number Diff line number Diff line change
@@ -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];
}
85 changes: 85 additions & 0 deletions website/blog/2024-12-06-advent-of-pbt-day-6/buggy.mjs
Original file line number Diff line number Diff line change
@@ -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;
};
}
46 changes: 46 additions & 0 deletions website/blog/2024-12-06-advent-of-pbt-day-6/index.md
Original file line number Diff line number Diff line change
@@ -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? 🎄🔧

<!--truncate-->

## 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! 🎄🔧

<AdventPlaygroundOfTheDay />

## Your answer

<FormOfTheDay />

0 comments on commit 5873f96

Please sign in to comment.