feat(curriculum): daily challenges 223-229 (#66313)

This commit is contained in:
Tom
2026-03-11 04:12:51 -05:00
committed by GitHub
parent a1c5e08728
commit 79eea990ea
19 changed files with 1538 additions and 3 deletions

View File

@@ -13,7 +13,7 @@ Given a string, return the substring between the two identical characters that h
- The returned substring should exclude the matching characters.
- If two or more gaps are the same length, return the characters from the first one.
For example, given `"ABCDAC"`, return `"DA"`.
For example, given `"ABCDAC"`, return `"DA"` because:
- Only `"A"` and `"C"` repeat in the string.
- The number of characters between the two `"A"` characters is 3, and between the `"C"` characters is 2.

View File

@@ -0,0 +1,145 @@
---
id: 69a890af247de743333bd4cc
title: "Challenge 223: QR Decoder"
challengeType: 28
dashedName: challenge-223
---
# --description--
Given a 6x6 matrix (array of arrays), representing a QR code, return the string of binary data in the code.
- The QR code may be given in any rotation of 90 degree increments.
- A correctly oriented code has a 2x2 group of `1`'s (orientation markers) in the bottom-left, top-left, and top-right corners.
- The three 2x2 orientation markers are not part of the binary data.
- The binary data is read left-to-right, top-to-bottom (like a book) when the QR code is correctly oriented.
- A code will always have exactly one valid orientation.
For example, given:
```js
[
"110011",
"110011",
"000000",
"000000",
"110000",
"110001"
]
```
or given the same code with a different orientation:
```js
[
"110011",
"110011",
"000000",
"000000",
"000011",
"100011"
]
```
Return `"000000000000000000000001"`, all the binary data excluding the three 2x2 orientation markers.
# --hints--
`decodeQr(["110011", "110011", "000000", "000000", "110000", "110001"])` should return `"000000000000000000000001"`.
```js
assert.equal(decodeQr(["110011", "110011", "000000", "000000", "110000", "110001"]), "000000000000000000000001");
```
`decodeQr(["100011", "000011", "000000", "000000", "110011", "110011"])` should return `"000000000000000000000001"`.
```js
assert.equal(decodeQr(["100011", "000011", "000000", "000000", "110011", "110011"]), "000000000000000000000001");
```
`decodeQr(["110011", "111111", "010000", "110000", "110011", "110100"])` should return `"001101000011000000110100"`.
```js
assert.equal(decodeQr(["110011", "111111", "010000", "110000", "110011", "110100"]), "001101000011000000110100");
```
`decodeQr(["011011", "101011", "101000", "100010", "110011", "111011"])` should return `"010001000100010101010110"`.
```js
assert.equal(decodeQr(["011011", "101011", "101000", "100010", "110011", "111011"]), "010001000100010101010110");
```
`decodeQr(["111100", "110001", "100011", "001101", "110011", "110011"])` should return `"010000100100100101001110"`.
```js
assert.equal(decodeQr(["111100", "110001", "100011", "001101", "110011", "110011"]), "010000100100100101001110");
```
# --seed--
## --seed-contents--
```js
function decodeQr(qrCode) {
return qrCode;
}
```
# --solutions--
```js
function isOriented(code) {
const markerIndices = [
[0, 0],
[0, 1],
[0, 4],
[0, 5],
[1, 0],
[1, 1],
[1, 4],
[1, 5],
[4, 0],
[4, 1],
[5, 0],
[5, 1]
];
for(const [row, col] of markerIndices) {
if (code[row][col] !== '1') return false;
}
return true;
}
function rotate(code) {
const newCode = ['', '', '', '', '', ''];
for (let i = 0; i < 6; i++) {
for (let j = 5; j >= 0; j--) {
newCode[i] += code[j][i];
}
}
return newCode;
}
function getData(code) {
let data = '';
data += code[0].substring(2, 4)
data += code[1].substring(2, 4)
data += code[2]
data += code[3]
data += code[4].substring(2)
data += code[5].substring(2)
return data;
}
function decodeQr(qrCode) {
let code = [...qrCode];
while(!isOriented(code)) {
code = rotate(code);
}
return getData(code);
}
```

View File

@@ -0,0 +1,99 @@
---
id: 69a890af247de743333bd4cd
title: "Challenge 224: Coffee Roast Detector"
challengeType: 28
dashedName: challenge-224
---
# --description--
Given a string representing the beans used to make a cup of coffee, determine the roast of the cup.
- The given string will contain the following characters, each representing a type of bean:
- An apostrophe (`'`) is a light roast bean worth 1 point each.
- A dash (`-`) is a medium roast bean worth 2 points each.
- A period (`.`) is a dark roast bean worth 3 points each.
- The roast level is determined by the average of all the beans.
Return:
- `"Light"` if the average is less than 1.75.
- `"Medium"` if the average is 1.75 to 2.5.
- `"Dark"` if the average is greater than 2.5.
# --hints--
`detectRoast("''-''''''-'-''--''''")` should return `"Light"`.
```js
assert.equal(detectRoast("''-''''''-'-''--''''"), "Light");
```
`detectRoast(".'-''-''..'''.-.-''-")` should return `"Medium"`.
```js
assert.equal(detectRoast(".'-''-''..'''.-.-''-"), "Medium");
```
`detectRoast("--.''--'-''.--..-.--")` should return `"Medium"`.
```js
assert.equal(detectRoast("--.''--'-''.--..-.--"), "Medium");
```
`detectRoast("-...'-......-..-...-")` should return `"Dark"`.
```js
assert.equal(detectRoast("-...'-......-..-...-"), "Dark");
```
`detectRoast(".--.-..-......----.'")` should return `"Medium"`.
```js
assert.equal(detectRoast(".--.-..-......----.'"), "Medium");
```
`detectRoast("..-..-..-..-....-.-.")` should return `"Dark"`.
```js
assert.equal(detectRoast("..-..-..-..-....-.-."), "Dark");
```
`detectRoast("-'-''''''..-'.''-'.'")` should return `"Light"`.
```js
assert.equal(detectRoast("-'-''''''..-'.''-'.'"), "Light");
```
# --seed--
## --seed-contents--
```js
function detectRoast(beans) {
return beans;
}
```
# --solutions--
```js
function detectRoast(beans) {
let total = 0;
for (const bean of beans) {
if (bean === "'") total += 1;
else if (bean === "-") total += 2;
else if (bean === ".") total += 3;
}
const avg = total / beans.length;
if (avg < 1.75) return "Light";
if (avg <= 2.5) return "Medium";
return "Dark";
}
```

View File

@@ -0,0 +1,74 @@
---
id: 69a890af247de743333bd4ce
title: "Challenge 225: No Consecutive Repeats"
challengeType: 28
dashedName: challenge-225
---
# --description--
Given a string, determine if it has no repeating characters.
- A string has no repeats if it does not have the same character two or more times in a row.
# --hints--
`hasNoRepeats("hi world")` should return `true`.
```js
assert.isTrue(hasNoRepeats("hi world"));
```
`hasNoRepeats("hello world")` should return `false`.
```js
assert.isFalse(hasNoRepeats("hello world"));
```
`hasNoRepeats("abcdefghijklmnopqrstuvwxyz")` should return `true`.
```js
assert.isTrue(hasNoRepeats("abcdefghijklmnopqrstuvwxyz"));
```
`hasNoRepeats("freeCodeCamp")` should return `false`.
```js
assert.isFalse(hasNoRepeats("freeCodeCamp"));
```
`hasNoRepeats("The quick brown fox jumped over the lazy dog.")` should return `true`.
```js
assert.isTrue(hasNoRepeats("The quick brown fox jumped over the lazy dog."));
```
`hasNoRepeats("Mississippi")` should return `false`.
```js
assert.isFalse(hasNoRepeats("Mississippi"));
```
# --seed--
## --seed-contents--
```js
function hasNoRepeats(str) {
return str;
}
```
# --solutions--
```js
function hasNoRepeats(str) {
for (let i = 1; i < str.length; i++) {
if (str[i] === str[i - 1]) {
return false;
}
}
return true;
}
```

View File

@@ -0,0 +1,69 @@
---
id: 69a890af247de743333bd4cf
title: "Challenge 226: Passing Exam Count"
challengeType: 28
dashedName: challenge-226
---
# --description--
Given an array of student exam scores and the score needed to pass it, return the number of students that passed the exam.
# --hints--
`passingCount([90, 85, 75, 60, 50], 70)` should return `3`.
```js
assert.equal(passingCount([90, 85, 75, 60, 50], 70), 3);
```
`passingCount([100, 80, 75, 88, 72, 74, 79, 71, 60, 92], 75)` should return `6`.
```js
assert.equal(passingCount([100, 80, 75, 88, 72, 74, 79, 71, 60, 92], 75), 6);
```
`passingCount([79, 60, 88, 72, 74, 59, 75, 71, 80, 92], 60)` should return `9`.
```js
assert.equal(passingCount([79, 60, 88, 72, 74, 59, 75, 71, 80, 92], 60), 9);
```
`passingCount([76, 79, 80, 70, 71, 65, 79, 78, 59, 72], 85)` should return `0`.
```js
assert.equal(passingCount([76, 79, 80, 70, 71, 65, 79, 78, 59, 72], 85), 0);
```
`passingCount([84, 65, 98, 53, 58, 71, 91, 80, 92, 70, 73, 83, 86, 69, 84, 77, 72, 58, 69, 75, 66, 68, 72, 96, 90, 63, 88, 63, 80, 67], 60)` should return `27`.
```js
assert.equal(passingCount([84, 65, 98, 53, 58, 71, 91, 80, 92, 70, 73, 83, 86, 69, 84, 77, 72, 58, 69, 75, 66, 68, 72, 96, 90, 63, 88, 63, 80, 67], 60), 27);
```
# --seed--
## --seed-contents--
```js
function passingCount(scores, passingScore) {
return scores;
}
```
# --solutions--
```js
function passingCount(scores, passingScore) {
let count = 0;
for (const score of scores) {
if (score >= passingScore) {
count++;
}
}
return count;
}
```

View File

@@ -0,0 +1,69 @@
---
id: 69a890af247de743333bd4d0
title: "Challenge 227: Cooldown Time"
challengeType: 28
dashedName: challenge-227
---
# --description--
Given two timestamps, the first representing when a user finished an exam, and the second representing the current time, determine whether the user can take an exam again.
- Both timestamps will be given the format: `"YYYY-MM-DDTHH:MM:SS"`, for example `"2026-03-25T14:00:00"`. Note that the time is 24-hour clock.
- A user must wait at least 48 hours before retaking an exam.
# --hints--
`canRetake("2026-03-23T08:00:00", "2026-03-25T14:00:00")` should return `true`.
```js
assert.isTrue(canRetake("2026-03-23T08:00:00", "2026-03-25T14:00:00"));
```
`canRetake("2026-03-24T14:00:00", "2026-03-25T10:00:00")` should return `false`.
```js
assert.isFalse(canRetake("2026-03-24T14:00:00", "2026-03-25T10:00:00"));
```
`canRetake("2026-03-23T09:25:00", "2026-03-25T09:25:00")` should return `true`.
```js
assert.isTrue(canRetake("2026-03-23T09:25:00", "2026-03-25T09:25:00"));
```
`canRetake("2026-03-23T11:50:00", "2026-03-25T11:49:59")` should return `false`.
```js
assert.isFalse(canRetake("2026-03-23T11:50:00", "2026-03-25T11:49:59"));
```
# --seed--
## --seed-contents--
```js
function canRetake(finishTime, currentTime) {
return finishTime;
}
```
# --solutions--
```js
function canRetake(finishTime, currentTime) {
function parse(ts) {
const parts = ts.split(/[-T:]/).map(Number);
const [y, m, d, h, min, s] = parts;
return Date.UTC(y, m - 1, d, h, min, s);
}
const finishMs = parse(finishTime);
const currentMs = parse(currentTime);
const cooldown = 48 * 60 * 60 * 1000;
return currentMs - finishMs >= cooldown;
}
```

View File

@@ -0,0 +1,118 @@
---
id: 69a890af247de743333bd4d1
title: "Challenge 228: Movie Night"
challengeType: 28
dashedName: challenge-228
---
# --description--
Given a string for the day of the week, another string for a showtime, and an integer number of tickets, return the total cost of the movie tickets for that showing.
The given day will be one of:
- `"Monday"`
- `"Tuesday"`
- `"Wednesday"`
- `"Thursday"`
- `"Friday"`
- `"Saturday"`
- `"Sunday"`
The showtime will be given in the format `"H:MMam"` or `"H:MMpm"`. For example `"10:00am"` or `"10:00pm"`.
Return the total cost in the format `"$D.CC"` using these rules:
- Weekend (Friday - Sunday): $12.00 per ticket.
- Weekday (Monday - Thursday): $10.00 per ticket.
- Matinee (before 5:00pm): subtract $2.00 per ticket (except on Tuesdays).
- Tuesdays: all tickets are $5.00 each.
# --hints--
`getMovieNightCost("Saturday", "10:00pm", 1)` should return `"$12.00"`.
```js
assert.equal(getMovieNightCost("Saturday", "10:00pm", 1), "$12.00");
```
`getMovieNightCost("Sunday", "10:00am", 1)` should return `"$10.00"`.
```js
assert.equal(getMovieNightCost("Sunday", "10:00am", 1), "$10.00");
```
`getMovieNightCost("Tuesday", "7:20pm", 2)` should return `"$10.00"`.
```js
assert.equal(getMovieNightCost("Tuesday", "7:20pm", 2), "$10.00");
```
`getMovieNightCost("Wednesday", "5:40pm", 3)` should return `"$30.00"`.
```js
assert.equal(getMovieNightCost("Wednesday", "5:40pm", 3), "$30.00");
```
`getMovieNightCost("Monday", "11:50am", 4)` should return `"$32.00"`.
```js
assert.equal(getMovieNightCost("Monday", "11:50am", 4), "$32.00");
```
`getMovieNightCost("Friday", "4:30pm", 5)` should return `"$50.00"`.
```js
assert.equal(getMovieNightCost("Friday", "4:30pm", 5), "$50.00");
```
`getMovieNightCost("Tuesday", "11:30am", 1)` should return `"$5.00"`.
```js
assert.equal(getMovieNightCost("Tuesday", "11:30am", 1), "$5.00");
```
# --seed--
## --seed-contents--
```js
function getMovieNightCost(day, showtime, numberOfTickets) {
return day;
}
```
# --solutions--
```js
function getMovieNightCost(day, showtime, numberOfTickets) {
let price;
if (day === "Tuesday") {
price = 5;
} else {
if (["Friday", "Saturday", "Sunday"].includes(day)) {
price = 12;
} else {
price = 10;
}
const hour = parseInt(showtime.split(":")[0]);
const period = showtime.slice(-2);
let hour24 = hour;
if (period === "pm" && hour !== 12) hour24 += 12;
if (period === "am" && hour === 12) hour24 = 0;
if (hour24 < 17) {
price -= 2;
}
}
const total = price * numberOfTickets;
return `$${total.toFixed(2)}`;
}
```

View File

@@ -0,0 +1,119 @@
---
id: 69a890af247de743333bd4d2
title: "Challenge 229: Truncate the Text 2"
challengeType: 28
dashedName: challenge-229
---
# --description--
Given a string, return a new string that is truncated so that the total width of the characters does not exceed 50 units.
Each character has a specific width:
| Letters | Width |
| - | - |
| `"ilI"` | 1 |
| `"fjrt"` | 2 |
| `"abcdeghkmnopqrstuvwxyzJL"` | 3 |
| `"ABCDEFGHKMNOPQRSTUVWXYZ"` | 4 |
The table above includes all upper and lower case letters. Additionally:
- Spaces (`" "`) have a width of 2
- Periods (`"."`) have a width of 1
- If the given string is 50 units or less, return the string as-is, otherwise
- Truncate the string and add three periods at the end (`"..."`) so it's total width, including the three periods, is as close as possible to 60 units without going over.
# --hints--
`truncateText("The quick brown fox")` should return `"The quick brown f..."`.
```js
assert.equal(truncateText("The quick brown fox"), "The quick brown f...");
```
`truncateText("The silky smooth sloth")` should return `"The silky smooth s..."`.
```js
assert.equal(truncateText("The silky smooth sloth"), "The silky smooth s...");
```
`truncateText("THE LOUD BRIGHT BIRD")` should return `"THE LOUD BRIG..."`.
```js
assert.equal(truncateText("THE LOUD BRIGHT BIRD"), "THE LOUD BRIG...");
```
`truncateText("The fast striped zebra")` should return `"The fast striped z..."`.
```js
assert.equal(truncateText("The fast striped zebra"), "The fast striped z...");
```
`truncateText("The big black bear")` should return `"The big black bear"`.
```js
assert.equal(truncateText("The big black bear"), "The big black bear");
```
# --seed--
## --seed-contents--
```js
function truncateText(str) {
return str;
}
```
# --solutions--
```js
function truncateText(str) {
const MAX_WIDTH = 50;
const ELLIPSIS = "...";
const ELLIPSIS_WIDTH = 3;
const TRUNCATE_LIMIT = MAX_WIDTH - ELLIPSIS_WIDTH;
const charGroups = {
'ilI.': 1,
'fjrt ': 2,
'abcdeghkmnopqrstuvwxyzJL': 3,
'ABCDEFGHKMNOPQRSTUVWXYZ': 4
};
function getCharWidth(char) {
for (const key in charGroups) {
if (key.includes(char)) return charGroups[key];
}
return 3;
}
function stringWidth(str) {
let totalWidth = 0;
for (const char of str) {
totalWidth += getCharWidth(char);
}
return totalWidth;
}
if (stringWidth(str) <= MAX_WIDTH) return str;
let result = "";
let totalWidth = 0;
for (const char of str) {
const charWidth = getCharWidth(char);
if (totalWidth + charWidth > TRUNCATE_LIMIT) break;
result += char;
totalWidth += charWidth;
}
return result + ELLIPSIS;
}
```

View File

@@ -13,7 +13,7 @@ Given a string, return the substring between the two identical characters that h
- The returned substring should exclude the matching characters.
- If two or more gaps are the same length, return the characters from the first one.
For example, given `"ABCDAC"`, return `"DA"`.
For example, given `"ABCDAC"`, return `"DA"` because:
- Only `"A"` and `"C"` repeat in the string.
- The number of characters between the two `"A"` characters is 3, and between the `"C"` characters is 2.

View File

@@ -0,0 +1,155 @@
---
id: 69a890af247de743333bd4cc
title: "Challenge 223: QR Decoder"
challengeType: 29
dashedName: challenge-223
---
# --description--
Given a 6x6 matrix (array of arrays), representing a QR code, return the string of binary data in the code.
- The QR code may be given in any rotation of 90 degree increments.
- A correctly oriented code has a 2x2 group of `1`'s (orientation markers) in the bottom-left, top-left, and top-right corners.
- The three 2x2 orientation markers are not part of the binary data.
- The binary data is read left-to-right, top-to-bottom (like a book) when the QR code is correctly oriented.
- A code will always have exactly one valid orientation.
For example, given:
```js
[
"110011",
"110011",
"000000",
"000000",
"110000",
"110001"
]
```
or given the same code with a different orientation:
```js
[
"110011",
"110011",
"000000",
"000000",
"000011",
"100011"
]
```
Return `"000000000000000000000001"`, all the binary data excluding the three 2x2 orientation markers.
# --hints--
`decode_qr(["110011", "110011", "000000", "000000", "110000", "110001"])` should return `"000000000000000000000001"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(decode_qr(["110011", "110011", "000000", "000000", "110000", "110001"]), "000000000000000000000001")`)
}})
```
`decode_qr(["100011", "000011", "000000", "000000", "110011", "110011"])` should return `"000000000000000000000001"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(decode_qr(["100011", "000011", "000000", "000000", "110011", "110011"]), "000000000000000000000001")`)
}})
```
`decode_qr(["110011", "111111", "010000", "110000", "110011", "110100"])` should return `"001101000011000000110100"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(decode_qr(["110011", "111111", "010000", "110000", "110011", "110100"]), "001101000011000000110100")`)
}})
```
`decode_qr(["011011", "101011", "101000", "100010", "110011", "111011"])` should return `"010001000100010101010110"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(decode_qr(["011011", "101011", "101000", "100010", "110011", "111011"]), "010001000100010101010110")`)
}})
```
`decode_qr(["111100", "110001", "100011", "001101", "110011", "110011"])` should return `"010000100100100101001110"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(decode_qr(["111100", "110001", "100011", "001101", "110011", "110011"]), "010000100100100101001110")`)
}})
```
# --seed--
## --seed-contents--
```py
def decode_qr(qr_code):
return qr_code
```
# --solutions--
```py
def is_oriented(code):
marker_indices = [
(0, 0),
(0, 1),
(0, 4),
(0, 5),
(1, 0),
(1, 1),
(1, 4),
(1, 5),
(4, 0),
(4, 1),
(5, 0),
(5, 1)
]
for row, col in marker_indices:
if code[row][col] != '1':
return False
return True
def rotate(code):
new_code = ['', '', '', '', '', '']
for i in range(6):
for j in range(5, -1, -1):
new_code[i] += code[j][i]
return new_code
def get_data(code):
data = ''
data += code[0][2:4]
data += code[1][2:4]
data += code[2]
data += code[3]
data += code[4][2:]
data += code[5][2:]
return data
def decode_qr(qr_code):
code = qr_code[:]
while not is_oriented(code):
code = rotate(code)
return get_data(code)
```

View File

@@ -0,0 +1,123 @@
---
id: 69a890af247de743333bd4cd
title: "Challenge 224: Coffee Roast Detector"
challengeType: 29
dashedName: challenge-224
---
# --description--
Given a string representing the beans used to make a cup of coffee, determine the roast of the cup.
- The given string will contain the following characters, each representing a type of bean:
- An apostrophe (`'`) is a light roast bean worth 1 point each.
- A dash (`-`) is a medium roast bean worth 2 points each.
- A period (`.`) is a dark roast bean worth 3 points each.
- The roast level is determined by the average of all the beans.
Return:
- `"Light"` if the average is less than 1.75.
- `"Medium"` if the average is 1.75 to 2.5.
- `"Dark"` if the average is greater than 2.5.
# --hints--
`detect_roast("''-''''''-'-''--''''")` should return `"Light"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(detect_roast("''-''''''-'-''--''''"), "Light")`)
}})
```
`detect_roast(".'-''-''..'''.-.-''-")` should return `"Medium"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(detect_roast(".'-''-''..'''.-.-''-"), "Medium")`)
}})
```
`detect_roast("--.''--'-''.--..-.--")` should return `"Medium"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(detect_roast("--.''--'-''.--..-.--"), "Medium")`)
}})
```
`detect_roast("-...'-......-..-...-")` should return `"Dark"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(detect_roast("-...'-......-..-...-"), "Dark")`)
}})
```
`detect_roast(".--.-..-......----.'")` should return `"Medium"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(detect_roast(".--.-..-......----.'"), "Medium")`)
}})
```
`detect_roast("..-..-..-..-....-.-.")` should return `"Dark"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(detect_roast("..-..-..-..-....-.-."), "Dark")`)
}})
```
`detect_roast("-'-''''''..-'.''-'.'")` should return `"Light"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(detect_roast("-'-''''''..-'.''-'.'"), "Light")`)
}})
```
# --seed--
## --seed-contents--
```py
def detect_roast(beans):
return beans
```
# --solutions--
```py
def detect_roast(beans):
total = 0
for bean in beans:
if bean == "'":
total += 1
elif bean == "-":
total += 2
elif bean == ".":
total += 3
avg = total / len(beans)
if avg < 1.75:
return "Light"
elif avg <= 2.5:
return "Medium"
else:
return "Dark"
```

View File

@@ -0,0 +1,88 @@
---
id: 69a890af247de743333bd4ce
title: "Challenge 225: No Consecutive Repeats"
challengeType: 29
dashedName: challenge-225
---
# --description--
Given a string, determine if it has no repeating characters.
- A string has no repeats if it does not have the same character two or more times in a row.
# --hints--
`has_no_repeats("hi world")` should return `True`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertIs(has_no_repeats("hi world"), True)`)
}})
```
`has_no_repeats("hello world")` should return `False`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertIs(has_no_repeats("hello world"), False)`)
}})
```
`has_no_repeats("abcdefghijklmnopqrstuvwxyz")` should return `True`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertIs(has_no_repeats("abcdefghijklmnopqrstuvwxyz"), True)`)
}})
```
`has_no_repeats("freeCodeCamp")` should return `False`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertIs(has_no_repeats("freeCodeCamp"), False)`)
}})
```
`has_no_repeats("The quick brown fox jumped over the lazy dog.")` should return `True`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertIs(has_no_repeats("The quick brown fox jumped over the lazy dog."), True)`)
}})
```
`has_no_repeats("Mississippi")` should return `False`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertIs(has_no_repeats("Mississippi"), False)`)
}})
```
# --seed--
## --seed-contents--
```py
def has_no_repeats(s):
return s
```
# --solutions--
```py
def has_no_repeats(s):
for i in range(1, len(s)):
if s[i] == s[i-1]:
return False
return True
```

View File

@@ -0,0 +1,80 @@
---
id: 69a890af247de743333bd4cf
title: "Challenge 226: Passing Exam Count"
challengeType: 29
dashedName: challenge-226
---
# --description--
Given an array of student exam scores and the score needed to pass it, return the number of students that passed the exam.
# --hints--
`passing_count([90, 85, 75, 60, 50], 70)` should return `3`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(passing_count([90, 85, 75, 60, 50], 70), 3)`)
}})
```
`passing_count([100, 80, 75, 88, 72, 74, 79, 71, 60, 92], 75)` should return `6`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(passing_count([100, 80, 75, 88, 72, 74, 79, 71, 60, 92], 75), 6)`)
}})
```
`passing_count([79, 60, 88, 72, 74, 59, 75, 71, 80, 92], 60)` should return `9`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(passing_count([79, 60, 88, 72, 74, 59, 75, 71, 80, 92], 60), 9)`)
}})
```
`passing_count([76, 79, 80, 70, 71, 65, 79, 78, 59, 72], 85)` should return `0`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(passing_count([76, 79, 80, 70, 71, 65, 79, 78, 59, 72], 85), 0)`)
}})
```
`passing_count([84, 65, 98, 53, 58, 71, 91, 80, 92, 70, 73, 83, 86, 69, 84, 77, 72, 58, 69, 75, 66, 68, 72, 96, 90, 63, 88, 63, 80, 67], 60)` should return `27`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(passing_count([84, 65, 98, 53, 58, 71, 91, 80, 92, 70, 73, 83, 86, 69, 84, 77, 72, 58, 69, 75, 66, 68, 72, 96, 90, 63, 88, 63, 80, 67], 60), 27)`)
}})
```
# --seed--
## --seed-contents--
```py
def passing_count(scores, passing_score):
return scores
```
# --solutions--
```py
def passing_count(scores, passing_score):
count = 0
for score in scores:
if score >= passing_score:
count += 1
return count
```

View File

@@ -0,0 +1,76 @@
---
id: 69a890af247de743333bd4d0
title: "Challenge 227: Cooldown Time"
challengeType: 29
dashedName: challenge-227
---
# --description--
Given two timestamps, the first representing when a user finished an exam, and the second representing the current time, determine whether the user can take an exam again.
- Both timestamps will be given the format: `"YYYY-MM-DDTHH:MM:SS"`, for example `"2026-03-25T14:00:00"`. Note that the time is 24-hour clock.
- A user must wait at least 48 hours before retaking an exam.
# --hints--
`can_retake("2026-03-23T08:00:00", "2026-03-25T14:00:00")` should return `True`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertIs(can_retake("2026-03-23T08:00:00", "2026-03-25T14:00:00"), True)`)
}})
```
`can_retake("2026-03-24T14:00:00", "2026-03-25T10:00:00")` should return `False`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertIs(can_retake("2026-03-24T14:00:00", "2026-03-25T10:00:00"), False)`)
}})
```
`can_retake("2026-03-23T09:25:00", "2026-03-25T09:25:00")` should return `True`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertIs(can_retake("2026-03-23T09:25:00", "2026-03-25T09:25:00"), True)`)
}})
```
`can_retake("2026-03-25T11:50:00", "2026-03-23T11:49:59")` should return `False`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertIs(can_retake("2026-03-25T11:50:00", "2026-03-23T11:49:59"), False)`)
}})
```
# --seed--
## --seed-contents--
```py
def can_retake(finish_time, current_time):
return finish_time
```
# --solutions--
```py
from datetime import datetime, timedelta
def can_retake(finish_time, current_time):
fmt = "%Y-%m-%dT%H:%M:%S"
finished_dt = datetime.strptime(finish_time, fmt)
current_dt = datetime.strptime(current_time, fmt)
diff = current_dt - finished_dt
cooldown = timedelta(hours=48)
return diff >= cooldown
```

View File

@@ -0,0 +1,134 @@
---
id: 69a890af247de743333bd4d1
title: "Challenge 228: Movie Night"
challengeType: 29
dashedName: challenge-228
---
# --description--
Given a string for the day of the week, another string for a showtime, and an integer number of tickets, return the total cost of the movie tickets for that showing.
The given day will be one of:
- `"Monday"`
- `"Tuesday"`
- `"Wednesday"`
- `"Thursday"`
- `"Friday"`
- `"Saturday"`
- `"Sunday"`
The showtime will be given in the format `"H:MMam"` or `"H:MMpm"`. For example `"10:00am"` or `"10:00pm"`.
Return the total cost in the format `"$D.CC"` using these rules:
- Weekend (Friday - Sunday): $12.00 per ticket.
- Weekday (Monday - Thursday): $10.00 per ticket.
- Matinee (before 5:00pm): subtract $2.00 per ticket (except on Tuesdays).
- Tuesdays: all tickets are $5.00 each.
# --hints--
`get_movie_night_cost("Saturday", "10:00pm", 1)` should return `"$12.00"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(get_movie_night_cost("Saturday", "10:00pm", 1), "$12.00")`)
}})
```
`get_movie_night_cost("Sunday", "10:00am", 1)` should return `"$10.00"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(get_movie_night_cost("Sunday", "10:00am", 1), "$10.00")`)
}})
```
`get_movie_night_cost("Tuesday", "7:20pm", 2)` should return `"$10.00"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(get_movie_night_cost("Tuesday", "7:20pm", 2), "$10.00")`)
}})
```
`get_movie_night_cost("Wednesday", "5:40pm", 3)` should return `"$30.00"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(get_movie_night_cost("Wednesday", "5:40pm", 3), "$30.00")`)
}})
```
`get_movie_night_cost("Monday", "11:50am", 4)` should return `"$32.00"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(get_movie_night_cost("Monday", "11:50am", 4), "$32.00")`)
}})
```
`get_movie_night_cost("Friday", "4:30pm", 5)` should return `"$50.00"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(get_movie_night_cost("Friday", "4:30pm", 5), "$50.00")`)
}})
```
`get_movie_night_cost("Tuesday", "11:30am", 1)` should return `"$5.00"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(get_movie_night_cost("Tuesday", "11:30am", 1), "$5.00")`)
}})
```
# --seed--
## --seed-contents--
```py
def get_movie_night_cost(day, showtime, number_of_tickets):
return day
```
# --solutions--
```py
def get_movie_night_cost(day, showtime, number_of_tickets):
if day == "Tuesday":
price = 5
else:
if day in ["Friday", "Saturday", "Sunday"]:
price = 12
else:
price = 10
hour = int(showtime.split(":")[0])
period = showtime[-2:]
hour24 = hour
if period == "pm" and hour != 12:
hour24 += 12
if period == "am" and hour == 12:
hour24 = 0
if hour24 < 17:
price -= 2
total = price * number_of_tickets
return f"${total:.2f}"
```

View File

@@ -0,0 +1,130 @@
---
id: 69a890af247de743333bd4d2
title: "Challenge 229: Truncate the Text 2"
challengeType: 29
dashedName: challenge-229
---
# --description--
Given a string, return a new string that is truncated so that the total width of the characters does not exceed 50 units.
Each character has a specific width:
| Letters | Width |
| - | - |
| `"ilI"` | 1 |
| `"fjrt"` | 2 |
| `"abcdeghkmnopqrstuvwxyzJL"` | 3 |
| `"ABCDEFGHKMNOPQRSTUVWXYZ"` | 4 |
The table above includes all upper and lower case letters. Additionally:
- Spaces (`" "`) have a width of 2
- Periods (`"."`) have a width of 1
- If the given string is 50 units or less, return the string as-is, otherwise
- Truncate the string and add three periods at the end (`"..."`) so it's total width, including the three periods, is as close as possible to 60 units without going over.
# --hints--
`truncate_text("The quick brown fox")` should return `"The quick brown f..."`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(truncate_text("The quick brown fox"), "The quick brown f...")`)
}})
```
`truncate_text("The silky smooth sloth")` should return `truncate_text("The silky smooth sloth")`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(truncate_text("The silky smooth sloth"), truncate_text("The silky smooth sloth"))`)
}})
```
`truncate_text("THE LOUD BRIGHT BIRD")` should return `"THE LOUD BRIG..."`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(truncate_text("THE LOUD BRIGHT BIRD"), "THE LOUD BRIG...")`)
}})
```
`truncate_text("The fast striped zebra")` should return `"The fast striped z..."`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(truncate_text("The fast striped zebra"), "The fast striped z...")`)
}})
```
`truncate_text("The big black bear")` should return `"The big black bear"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(truncate_text("The big black bear"), "The big black bear")`)
}})
```
# --seed--
## --seed-contents--
```py
def truncate_text(s):
return s
```
# --solutions--
```py
def truncate_text(s):
MAX_WIDTH = 50
ELLIPSIS = "..."
ELLIPSIS_WIDTH = 3
TRUNCATE_LIMIT = MAX_WIDTH - ELLIPSIS_WIDTH
char_groups = {
"ilI.": 1,
"fjrt ": 2,
"abcdeghkmnopqrstuvwxyzJL": 3,
"ABCDEFGHKMNOPQRSTUVWXYZ": 4
}
def get_char_width(char):
for key, width in char_groups.items():
if char in key:
return width
return 3
def string_width(string):
total = 0
for char in string:
total += get_char_width(char)
return total
if string_width(s) <= MAX_WIDTH:
return s
result = ""
total_width = 0
for char in s:
char_width = get_char_width(char)
if total_width + char_width > TRUNCATE_LIMIT:
break
result += char
total_width += char_width
return result + ELLIPSIS
```

View File

@@ -894,6 +894,34 @@
{
"id": "699c8e045ee7cb94ed2322dd",
"title": "Challenge 222: Equinox Shadows"
},
{
"id": "69a890af247de743333bd4cc",
"title": "Challenge 223: QR Decoder"
},
{
"id": "69a890af247de743333bd4cd",
"title": "Challenge 224: Coffee Roast Detector"
},
{
"id": "69a890af247de743333bd4ce",
"title": "Challenge 225: No Consecutive Repeats"
},
{
"id": "69a890af247de743333bd4cf",
"title": "Challenge 226: Passing Exam Count"
},
{
"id": "69a890af247de743333bd4d0",
"title": "Challenge 227: Cooldown Time"
},
{
"id": "69a890af247de743333bd4d1",
"title": "Challenge 228: Movie Night"
},
{
"id": "69a890af247de743333bd4d2",
"title": "Challenge 229: Truncate the Text 2"
}
]
}

View File

@@ -893,6 +893,34 @@
{
"id": "699c8e045ee7cb94ed2322dd",
"title": "Challenge 222: Equinox Shadows"
},
{
"id": "69a890af247de743333bd4cc",
"title": "Challenge 223: QR Decoder"
},
{
"id": "69a890af247de743333bd4cd",
"title": "Challenge 224: Coffee Roast Detector"
},
{
"id": "69a890af247de743333bd4ce",
"title": "Challenge 225: No Consecutive Repeats"
},
{
"id": "69a890af247de743333bd4cf",
"title": "Challenge 226: Passing Exam Count"
},
{
"id": "69a890af247de743333bd4d0",
"title": "Challenge 227: Cooldown Time"
},
{
"id": "69a890af247de743333bd4d1",
"title": "Challenge 228: Movie Night"
},
{
"id": "69a890af247de743333bd4d2",
"title": "Challenge 229: Truncate the Text 2"
}
]
}

View File

@@ -13,7 +13,7 @@ const { MONGOHQ_URL } = process.env;
// Number challenges in the dev-playground blocks
// Update this if the number of challenges changes
const EXPECTED_CHALLENGE_COUNT = 222;
const EXPECTED_CHALLENGE_COUNT = 229;
// Date to set for the first challenge, second challenge will be one day later, etc...
// **DO NOT CHANGE THIS AFTER RELEASE (if seeding production - okay for local dev)**