Skip to content

Commit

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

const { AdventPlaygroundOfTheDay, FormOfTheDay } = buildAdventOfTheDay({
day: 3,
buildBuggyAdvent: adventBuggy,
referenceAdvent: isWordIncludedInLetter,
parser,
placeholderForm: '"content of the letter"\n"word"',
functionName: 'isWordIncludedInLetter',
signature: 'function isWordIncludedInLetter(letterContent: string, word: string): boolean;',
signatureExtras: [],
});

export { AdventPlaygroundOfTheDay, FormOfTheDay };

// Reference implementation

function isWordIncludedInLetter(letterContent: string, word: string): boolean {
return letterContent.includes(word);
}

// Inputs parser

function parser(answer: string): unknown[] | undefined {
const lines = answer.trim().split('\n');
if (lines.length !== 2) {
throw new Error(
`Your answer should be made of two distinct lines: one for the content of the letter and the other for the word being looked for`,
);
}
const parsedLetterContent = JSON.parse(lines[0]);
if (typeof parsedLetterContent !== 'string') {
throw new Error('The content of the letter should follow the pattern: "quoted-string"');
}
const parsedWord = JSON.parse(lines[1]);
if (typeof parsedWord !== 'string') {
throw new Error('The word should follow the pattern: "quoted-string"');
}
return [parsedLetterContent, parsedWord];
}
64 changes: 64 additions & 0 deletions website/blog/2024-12-03-advent-of-pbt-day-3/buggy.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// @ts-check

export default function advent() {
// Implementation copied from https://github.com/trekhleb/javascript-algorithms/pull/110/
const PRIME = 97;

/**
* @param {string} letterContent
* @param {string} word
* @return {boolean}
*/
return function isWordIncludedInLetter(letterContent, word) {
const wordHash = hashWord(word);
let prevSegment = null;
let currentSegmentHash = null;
for (let charIndex = 0; charIndex <= letterContent.length - word.length; charIndex += 1) {
const currentSegment = letterContent.substring(charIndex, charIndex + word.length);
if (currentSegmentHash === null) {
currentSegmentHash = hashWord(currentSegment);
} else {
currentSegmentHash = reHashWord(currentSegmentHash, prevSegment, currentSegment);
}
prevSegment = currentSegment;
if (wordHash === currentSegmentHash) {
let numberOfMatches = 0;
for (let deepCharIndex = 0; deepCharIndex < word.length; deepCharIndex += 1) {
if (word[deepCharIndex] === letterContent[charIndex + deepCharIndex]) {
numberOfMatches += 1;
}
}
if (numberOfMatches === word.length) {
return true;
}
}
}
return false;
};

/**
* @param {string} word
* @return {number}
*/
function hashWord(word) {
let hash = 0;
for (let charIndex = 0; charIndex < word.length; charIndex += 1) {
hash += word[charIndex].charCodeAt(0) * PRIME ** charIndex;
}
return hash;
}

/**
* @param {number} prevHash
* @param {string} prevWord
* @param {string} newWord
* @return {number}
*/
function reHashWord(prevHash, prevWord, newWord) {
const newWordLastIndex = newWord.length - 1;
let newHash = prevHash - prevWord[0].charCodeAt(0);
newHash /= PRIME;
newHash += newWord[newWordLastIndex].charCodeAt(0) * PRIME ** newWordLastIndex;
return newHash;
}
}
40 changes: 40 additions & 0 deletions website/blog/2024-12-03-advent-of-pbt-day-3/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
title: Advent of PBT 2024 · Day 3
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: he needs you to investigate whether the fresh new word lookup system is working as expected. Can you ensure it’s accurate, so everyone gets exactly what they deserve? 🎄🔧

<!--truncate-->

## Word Lookup in Santa's Letters

Counting the number of presents of type A, then B, by scanning all letters one after the other is a tremendous amount of work for Santa. This year, everything should be automated. So, he asked his elves to provide a quick algorithm to check if a given string is found within a letter.

The algorithm was required to take two strings:

1. The first string is the content of the letter.
2. The second string is the word Santa is looking for.

Based on these two inputs, the algorithm should return true if and only if the word can be found within the letter. If the word isn’t found, it should return false.

## Hands on

The elves implemented it quickly, but they were in a rush, and the one assigned to this task didn’t have much time. Santa isn’t confident in the result. He needs you to verify if it works, and since he knows it might be buggy, he’s asking you to report any issues.

Using the property-based testing features of fast-check, your task is to find a set of inputs (content and word) that break the elves’ implementation.

You are Santa’s last hope to ensure Christmas happens this year — don’t let him down! 🎄🔧

<AdventPlaygroundOfTheDay />

## Your answer

<FormOfTheDay />

0 comments on commit d486157

Please sign in to comment.