mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-03-25 14:01:44 -04:00
feat(curriculum): daily challenges 223-229 (#66313)
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
```
|
||||
@@ -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";
|
||||
}
|
||||
```
|
||||
@@ -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;
|
||||
}
|
||||
```
|
||||
@@ -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;
|
||||
}
|
||||
```
|
||||
@@ -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;
|
||||
}
|
||||
```
|
||||
@@ -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)}`;
|
||||
}
|
||||
```
|
||||
@@ -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;
|
||||
}
|
||||
```
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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"
|
||||
```
|
||||
@@ -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
|
||||
```
|
||||
@@ -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
|
||||
```
|
||||
@@ -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
|
||||
```
|
||||
@@ -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}"
|
||||
```
|
||||
@@ -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
|
||||
```
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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)**
|
||||
|
||||
Reference in New Issue
Block a user