Skip to content

Commit 3e5f5cc

Browse files
authored
feat(curriculum): daily challenges 279-294 (freeCodeCamp#67227)
1 parent aa6df83 commit 3e5f5cc

35 files changed

Lines changed: 2965 additions & 1 deletion
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
---
2+
id: 69f35a5bb823ed620fcb7cb8
3+
title: "Challenge 279: Longest Domino Chain"
4+
challengeType: 28
5+
dashedName: challenge-279
6+
---
7+
8+
# --description--
9+
10+
Given a 2D array representing a set of dominoes, return the longest valid chain.
11+
12+
- Each domino is a pair of numbers from 0–6, e.g. `[3, 2]`.
13+
- A chain is valid when the second number of each domino matches the first number of the next.
14+
- The first number of the first domino and the second number of the last one don't need to match anything.
15+
- Any domino can be flipped, so `[3, 2]` can be played as `[2, 3]`.
16+
- There is always exactly one longest valid chain.
17+
18+
For example, given `[[1, 2], [4, 5], [2, 3]]`, return `[[1, 2], [2, 3]]`.
19+
20+
# --hints--
21+
22+
`getLongestChain([[1, 2], [4, 5], [2, 3]])` should return `[[1, 2], [2, 3]]`.
23+
24+
```js
25+
const chain = JSON.stringify(getLongestChain([[1, 2], [4, 5], [2, 3]]));
26+
const result1 = JSON.stringify([[1, 2], [2, 3]]);
27+
const result2 = JSON.stringify([[3, 2], [2, 1]]);
28+
assert.isTrue(chain === result1 || chain === result2);
29+
```
30+
31+
`getLongestChain([[2, 1], [4, 3], [5, 3]])` should return `[[4, 3], [3, 5]]`.
32+
33+
```js
34+
const chain = JSON.stringify(getLongestChain([[2, 1], [4, 3], [5, 3]]));
35+
const result1 = JSON.stringify([[4, 3], [3, 5]]);
36+
const result2 = JSON.stringify([[5, 3], [3, 4]]);
37+
assert.isTrue(chain === result1 || chain === result2);
38+
```
39+
40+
`getLongestChain([[1, 2], [3, 4], [2, 3], [4, 0]])` should return `[[1, 2], [2, 3], [3, 4], [4, 0]]`.
41+
42+
```js
43+
const chain = JSON.stringify(getLongestChain([[1, 2], [3, 4], [2, 3], [4, 0]]));
44+
const result1 = JSON.stringify([[1, 2], [2, 3], [3, 4], [4, 0]]);
45+
const result2 = JSON.stringify([[0, 4], [4, 3], [3, 2], [2, 1]]);
46+
assert.isTrue(chain === result1 || chain === result2);
47+
```
48+
49+
`getLongestChain([[6, 6], [6, 1], [1, 1], [0, 3], [2, 3], [4, 1], [5, 6]])` should return `[[4, 1], [1, 1], [1, 6], [6, 6], [6, 5]]`.
50+
51+
```js
52+
const chain = JSON.stringify(getLongestChain([[6, 6], [6, 1], [1, 1], [0, 3], [2, 3], [4, 1], [5, 6]]));
53+
const result1 = JSON.stringify([[4, 1], [1, 1], [1, 6], [6, 6], [6, 5]]);
54+
const result2 = JSON.stringify([[5, 6], [6, 6], [6, 1], [1, 1], [1, 4]]);
55+
assert.isTrue(chain === result1 || chain === result2);
56+
```
57+
58+
`getLongestChain([[0, 4], [3, 3], [0, 3], [5, 6], [4, 5], [4, 2], [5, 5], [1, 2], [4, 4]])` should return `[[3, 3], [3, 0], [0, 4], [4, 4], [4, 5], [5, 5], [5, 6]]`.
59+
60+
```js
61+
const chain = JSON.stringify(getLongestChain([[0, 4], [3, 3], [0, 3], [5, 6], [4, 5], [4, 2], [5, 5], [1, 2], [4, 4]]));
62+
const result1 = JSON.stringify([[3, 3], [3, 0], [0, 4], [4, 4], [4, 5], [5, 5], [5, 6]]);
63+
const result2 = JSON.stringify([[6, 5], [5, 5], [5, 4], [4, 4], [4, 0], [0, 3], [3, 3]]);
64+
assert.isTrue(chain === result1 || chain === result2);
65+
```
66+
67+
# --seed--
68+
69+
## --seed-contents--
70+
71+
```js
72+
function getLongestChain(dominoes) {
73+
74+
return dominoes;
75+
}
76+
```
77+
78+
# --solutions--
79+
80+
```js
81+
function getLongestChain(dominoes) {
82+
function search(chain, remaining) {
83+
let best = chain;
84+
const last = chain[chain.length - 1][1];
85+
86+
for (let i = 0; i < remaining.length; i++) {
87+
const [a, b] = remaining[i];
88+
const rest = remaining.filter((_, j) => j !== i);
89+
90+
if (a === last) {
91+
const result = search([...chain, [a, b]], rest);
92+
if (result.length > best.length) best = result;
93+
}
94+
if (b === last && a !== b) {
95+
const result = search([...chain, [b, a]], rest);
96+
if (result.length > best.length) best = result;
97+
}
98+
}
99+
return best;
100+
}
101+
102+
let best = [];
103+
for (let i = 0; i < dominoes.length; i++) {
104+
const [a, b] = dominoes[i];
105+
const rest = dominoes.filter((_, j) => j !== i);
106+
107+
const r1 = search([[a, b]], rest);
108+
if (r1.length > best.length) best = r1;
109+
110+
if (a !== b) {
111+
const r2 = search([[b, a]], rest);
112+
if (r2.length > best.length) best = r2;
113+
}
114+
}
115+
return best;
116+
}
117+
```
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
id: 69f35a5bb823ed620fcb7cb9
3+
title: "Challenge 280: Mongo ID Date"
4+
challengeType: 28
5+
dashedName: challenge-280
6+
---
7+
8+
# --description--
9+
10+
Given a MongoDB ID string, return its creation time as an ISO 8601 string.
11+
12+
- A MongoDB ID is a 24-character hex string. The first 8 characters represent a Unix timestamp (in seconds) encoded as a base-16 integer.
13+
14+
For example, `"6a094b50bcf86cd799439011"` has a timestamp of `"6a094b50"` in hex, which is `1778994000` in decimal, representing a creation time of `"2026-05-17T05:00:00.000Z"`.
15+
16+
# --hints--
17+
18+
`mongoIdToDate("6a094b50bcf86cd799439011")` should return `"2026-05-17T05:00:00.000Z"`.
19+
20+
```js
21+
assert.equal(mongoIdToDate("6a094b50bcf86cd799439011"), "2026-05-17T05:00:00.000Z");
22+
```
23+
24+
`mongoIdToDate("695344eb1f4a4c1123042128")` should return `"2025-12-30T03:20:11.000Z"`.
25+
26+
```js
27+
assert.equal(mongoIdToDate("695344eb1f4a4c1123042128"), "2025-12-30T03:20:11.000Z");
28+
```
29+
30+
`mongoIdToDate("386da62df34123ac54617e56")` should return `"2000-01-01T07:01:01.000Z"`.
31+
32+
```js
33+
assert.equal(mongoIdToDate("386da62df34123ac54617e56"), "2000-01-01T07:01:01.000Z");
34+
```
35+
36+
`mongoIdToDate("69f571c3d7711807afd3dd55")` should return `"2026-05-02T03:38:43.000Z"`.
37+
38+
```js
39+
assert.equal(mongoIdToDate("69f571c3d7711807afd3dd55"), "2026-05-02T03:38:43.000Z");
40+
```
41+
42+
`mongoIdToDate("68adce01c0e1144d0a90295a")` should return `"2025-08-26T15:08:49.000Z"`.
43+
44+
```js
45+
assert.equal(mongoIdToDate("68adce01c0e1144d0a90295a"), "2025-08-26T15:08:49.000Z");
46+
```
47+
48+
# --seed--
49+
50+
## --seed-contents--
51+
52+
```js
53+
function mongoIdToDate(id) {
54+
55+
return id;
56+
}
57+
```
58+
59+
# --solutions--
60+
61+
```js
62+
function mongoIdToDate(id) {
63+
const timestamp = parseInt(id.slice(0, 8), 16);
64+
return new Date(timestamp * 1000).toISOString();
65+
}
66+
```
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
---
2+
id: 69f35a5bb823ed620fcb7cba
3+
title: "Challenge 281: Bingo Range"
4+
challengeType: 28
5+
dashedName: challenge-281
6+
---
7+
8+
# --description--
9+
10+
Given a bingo letter, return the number range associated with that letter.
11+
12+
| Letter | Number Range |
13+
| - | - |
14+
| `"B"` | 1-15 |
15+
| `"I"` | 16-30 |
16+
| `"N"` | 31-45 |
17+
| `"G"` | 46-60 |
18+
| `"O"` | 61-75 |
19+
20+
Return an array with all numbers in the range from smallest to largest.
21+
22+
# --hints--
23+
24+
`getBingoRange("B")` should return `[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]`.
25+
26+
```js
27+
assert.deepEqual(getBingoRange("B"), [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
28+
```
29+
30+
`getBingoRange("I")` should return `[16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]`.
31+
32+
```js
33+
assert.deepEqual(getBingoRange("I"), [16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]);
34+
```
35+
36+
`getBingoRange("N")` should return `[31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45]`.
37+
38+
```js
39+
assert.deepEqual(getBingoRange("N"), [31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45]);
40+
```
41+
42+
`getBingoRange("G")` should return `[46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]`.
43+
44+
```js
45+
assert.deepEqual(getBingoRange("G"), [46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]);
46+
```
47+
48+
`getBingoRange("O")` should return `[61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75]`.
49+
50+
```js
51+
assert.deepEqual(getBingoRange("O"), [61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75]);
52+
```
53+
54+
# --seed--
55+
56+
## --seed-contents--
57+
58+
```js
59+
function getBingoRange(letter) {
60+
61+
return letter;
62+
}
63+
```
64+
65+
# --solutions--
66+
67+
```js
68+
function getBingoRange(letter) {
69+
const ranges = { B: [1, 15], I: [16, 30], N: [31, 45], G: [46, 60], O: [61, 75] };
70+
const [start, end] = ranges[letter];
71+
return Array.from({ length: end - start + 1 }, (_, i) => start + i);
72+
}
73+
```
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
---
2+
id: 69f35a5bb823ed620fcb7cbb
3+
title: "Challenge 282: Sleep Debt"
4+
challengeType: 28
5+
dashedName: challenge-282
6+
---
7+
8+
# --description--
9+
10+
Given an array of hours slept each night leading up to today, and a target number of hours per night, return how many hours of sleep you need tonight to eliminate your sleep debt.
11+
12+
- Include tonight's hours in the total time needed to catch up.
13+
- If you've slept enough to cover tonight's target or more, return `0`.
14+
15+
# --hints--
16+
17+
`sleepDebt([6, 6, 6, 6, 6, 6], 8)` should return `20`.
18+
19+
```js
20+
assert.equal(sleepDebt([6, 6, 6, 6, 6, 6], 8), 20);
21+
```
22+
23+
`sleepDebt([6, 7, 8, 4, 8, 6], 7)` should return `10`.
24+
25+
```js
26+
assert.equal(sleepDebt([6, 7, 8, 4, 8, 6], 7), 10);
27+
```
28+
29+
`sleepDebt([10, 10, 9, 10, 9, 11], 9)` should return `4`.
30+
31+
```js
32+
assert.equal(sleepDebt([10, 10, 9, 10, 9, 11], 9), 4);
33+
```
34+
35+
`sleepDebt([8, 7, 6, 7, 6, 8], 6)` should return `0`.
36+
37+
```js
38+
assert.equal(sleepDebt([8, 7, 6, 7, 6, 8], 6), 0);
39+
```
40+
41+
`sleepDebt([8, 9, 10, 9, 10, 7], 7)` should return `0`.
42+
43+
```js
44+
assert.equal(sleepDebt([8, 9, 10, 9, 10, 7], 7), 0);
45+
```
46+
47+
# --seed--
48+
49+
## --seed-contents--
50+
51+
```js
52+
function sleepDebt(hoursSlept, targetHours) {
53+
54+
return hoursSlept;
55+
}
56+
```
57+
58+
# --solutions--
59+
60+
```js
61+
function sleepDebt(hoursSlept, targetHours) {
62+
const debt = (hoursSlept.length + 1) * targetHours - hoursSlept.reduce((sum, h) => sum + h, 0);
63+
return Math.max(0, debt);
64+
}
65+
```
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
id: 69f35a5bb823ed620fcb7cbc
3+
title: "Challenge 283: String Zipper"
4+
challengeType: 28
5+
dashedName: challenge-283
6+
---
7+
8+
# --description--
9+
10+
Given two strings, return a new string that interleaves their characters one at a time. If one string is longer, append the remaining characters at the end.
11+
12+
Begin with the first character of the first string.
13+
14+
# --hints--
15+
16+
`zipStrings("abc", "123")` should return `"a1b2c3"`.
17+
18+
```js
19+
assert.equal(zipStrings("abc", "123"), "a1b2c3");
20+
```
21+
22+
`zipStrings("acegikmoqsuwy", "bdfhjlnprtvxz")` should return `"abcdefghijklmnopqrstuvwxyz"`.
23+
24+
```js
25+
assert.equal(zipStrings("acegikmoqsuwy", "bdfhjlnprtvxz"), "abcdefghijklmnopqrstuvwxyz");
26+
```
27+
28+
`zipStrings("day", "night")` should return `"dnaiyght"`.
29+
30+
```js
31+
assert.equal(zipStrings("day", "night"), "dnaiyght");
32+
```
33+
34+
`zipStrings("python", "javascript")` should return `"pjyatvhaosncript"`.
35+
36+
```js
37+
assert.equal(zipStrings("python", "javascript"), "pjyatvhaosncript");
38+
```
39+
40+
`zipStrings("feCdCm", "reoeap")` should return `"freeCodeCamp"`.
41+
42+
```js
43+
assert.equal(zipStrings("feCdCm", "reoeap"), "freeCodeCamp");
44+
```
45+
46+
# --seed--
47+
48+
## --seed-contents--
49+
50+
```js
51+
function zipStrings(a, b) {
52+
53+
return a;
54+
}
55+
```
56+
57+
# --solutions--
58+
59+
```js
60+
function zipStrings(a, b) {
61+
let result = '';
62+
const len = Math.max(a.length, b.length);
63+
for (let i = 0; i < len; i++) {
64+
if (i < a.length) result += a[i];
65+
if (i < b.length) result += b[i];
66+
}
67+
return result;
68+
}
69+
```

0 commit comments

Comments
 (0)