feat(curriculum): daily challenges 63-79 (#62367)

Co-authored-by: Ilenia <26656284+ilenia-magoni@users.noreply.github.com>
This commit is contained in:
Tom
2025-09-29 22:24:17 -05:00
committed by GitHub
parent f55140c895
commit 6e01904ce6
39 changed files with 3027 additions and 7 deletions
@@ -9,9 +9,9 @@ dashedName: challenge-36
Given the current temperature of a room and a target temperature, return a string indicating how to adjust the room temperature based on these constraints:
- Return "heat" if the current temperature is below the target.
- Return "cool" if the current temperature is above the target.
- Return "hold" if the current temperature is equal to the target.
- Return `"heat"` if the current temperature is below the target.
- Return `"cool"` if the current temperature is above the target.
- Return `"hold"` if the current temperature is equal to the target.
# --hints--
@@ -0,0 +1,113 @@
---
id: 68cae5b538ff798bbd4da001
title: "Challenge 63: Battle of Words"
challengeType: 28
dashedName: challenge-63
---
# --description--
Given two sentences representing your team and an opposing team, where each word from your team battles the corresponding word from the opposing team, determine which team wins using the following rules:
- The given sentences will always contain the same number of words.
- Words are separated by a single space and will only contain letters.
- The value of each word is the sum of its letters.
- Letters `a` to `z` correspond to the values `1` through `26`. For example, `a` is `1`, and `z` is `26`.
- A capital letter doubles the value of the letter. For example, `A` is `2`, and `Z` is `52`.
- Words battle in order: the first word of your team battles the first word of the opposing team, and so on.
- A word wins if its value is greater than the opposing word's value.
- The team with more winning words is the winner.
Return `"We win"` if your team is the winner, `"We lose"` if your team loses, and `"Draw"` if both teams have the same number of wins.
# --hints--
`battle("hello world", "hello word")` should return `"We win"`.
```js
assert.equal(battle("hello world", "hello word"), "We win");
```
`battle("Hello world", "hello world")` should return `"We win"`.
```js
assert.equal(battle("Hello world", "hello world"), "We win");
```
`battle("lorem ipsum", "kitty ipsum")` should return `"We lose"`.
```js
assert.equal(battle("lorem ipsum", "kitty ipsum"), "We lose");
```
`battle("hello world", "world hello")` should return `"Draw"`.
```js
assert.equal(battle("hello world", "world hello"), "Draw");
```
`battle("git checkout", "git switch")` should return `"We win"`.
```js
assert.equal(battle("git checkout", "git switch"), "We win");
```
`battle("Cheeseburger with fries", "Cheeseburger with Fries")` should return `"We lose"`.
```js
assert.equal(battle("Cheeseburger with fries", "Cheeseburger with Fries"), "We lose");
```
`battle("We must never surrender", "Our team must win")` should return `"Draw"`.
```js
assert.equal(battle("We must never surrender", "Our team must win"), "Draw");
```
# --seed--
## --seed-contents--
```js
function battle(ourTeam, opponent) {
return ourTeam;
}
```
# --solutions--
```js
function getCharacterValue(char) {
const lowerCaseValue = char.toLowerCase().charCodeAt(0) - 96;
return char >= 'A' && char <= 'Z' ? lowerCaseValue * 2 : lowerCaseValue;
}
function getWordValue(word) {
let wordValue = 0;
for (let i=0; i<word.length; i++) {
wordValue += getCharacterValue(word[i])
}
return wordValue;
}
function battle(ourTeam, opponent) {
const myWords = ourTeam.split(' ');
const opponentWords = opponent.split(' ');
let myWins = 0, opponentWins = 0;
for (let i=0; i<myWords.length; i++) {
const myWordValue = getWordValue(myWords[i]);
const opponentWordValue = getWordValue(opponentWords[i])
if (myWordValue > opponentWordValue) myWins++;
if (opponentWordValue > myWordValue) opponentWins++;
}
if (myWins > opponentWins) return 'We win';
if (opponentWins > myWins) return 'We lose';
return 'Draw';
}
```
@@ -0,0 +1,73 @@
---
id: 68cae5b538ff798bbd4da002
title: "Challenge 64: 24 to 12"
challengeType: 28
dashedName: challenge-64
---
# --description--
Given a string representing a time of the day in the 24-hour format of `"HHMM"`, return the time in its equivalent 12-hour format of `"H:MM AM"` or `"H:MM PM"`.
- The given input will always be a four-digit string in 24-hour time format, from `"0000"` to `"2359"`.
# --hints--
`to12("1124")` should return `"11:24 AM"`.
```js
assert.equal(to12("1124"), "11:24 AM");
```
`to12("0900")` should return `"9:00 AM"`.
```js
assert.equal(to12("0900"), "9:00 AM");
```
`to12("1455")` should return `"2:55 PM"`.
```js
assert.equal(to12("1455"), "2:55 PM");
```
`to12("2346")` should return `"11:46 PM"`.
```js
assert.equal(to12("2346"), "11:46 PM");
```
`to12("0030")` should return `"12:30 AM"`.
```js
assert.equal(to12("0030"), "12:30 AM");
```
# --seed--
## --seed-contents--
```js
function to12(time) {
return time;
}
```
# --solutions--
```js
function convertHours(hours) {
if (hours === 0) return 12;
if (hours > 12) return hours - 12;
return hours;
}
function to12(time) {
const hours = parseInt(time.slice(0, 2), 10);
const minutes = time.slice(2);
const period = hours < 12 ? 'AM' : 'PM';
return `${convertHours(hours)}:${minutes} ${period}`;
}
```
@@ -0,0 +1,71 @@
---
id: 68cae5b538ff798bbd4da003
title: "Challenge 65: String Count"
challengeType: 28
dashedName: challenge-65
---
# --description--
Given two strings, determine how many times the second string appears in the first.
- The pattern string can overlap in the first string. For example, `"aaa"` contains `"aa"` twice. The first two `a`'s and the second two.
# --hints--
`count('abcdefg', 'def')` should return `1`.
```js
assert.equal(count('abcdefg', 'def'), 1);
```
`count('hello', 'world')` should return `0`.
```js
assert.equal(count('hello', 'world'), 0);
```
`count('mississippi', 'iss')` should return `2`.
```js
assert.equal(count('mississippi', 'iss'), 2);
```
`count('she sells seashells by the seashore', 'sh')` should return `3`.
```js
assert.equal(count('she sells seashells by the seashore', 'sh'), 3);
```
`count('101010101010101010101', '101')` should return `10`.
```js
assert.equal(count('101010101010101010101', '101'), 10);
```
# --seed--
## --seed-contents--
```js
function count(text, pattern) {
return text;
}
```
# --solutions--
```js
function count(text, pattern) {
let occurrences = 0;
for (let i = 0; i <= text.length - pattern.length; i++) {
if (text.slice(i, i + pattern.length) === pattern) {
occurrences++;
}
}
return occurrences;
}
```
@@ -0,0 +1,61 @@
---
id: 68cae5b538ff798bbd4da004
title: "Challenge 66: HTML Tag Stripper"
challengeType: 28
dashedName: challenge-66
---
# --description--
Given a string of HTML code, remove the tags and return the plain text content.
- The input string will contain only valid HTML.
- HTML tags may be nested.
- Remove the tags and any attributes.
For example, `'<a href="#">Click here</a>'` should return `"Click here"`.
# --hints--
`stripTags('<a href="#">Click here</a>')` should return `"Click here"`.
```js
assert.equal(stripTags('<a href="#">Click here</a>'), "Click here");
```
`stripTags('<p class="center">Hello <b>World</b>!</p>')` should return `"Hello World!"`.
```js
assert.equal(stripTags('<p class="center">Hello <b>World</b>!</p>'), "Hello World!");
```
`stripTags('<img src="cat.jpg" alt="Cat">')` should return an empty string (`""`).
```js
assert.equal(stripTags('<img src="cat.jpg" alt="Cat">'), "");
```
`stripTags('<main id="main"><section class="section">section</section><section class="section">section</section></main>')` should return `sectionsection`.
```js
assert.equal(stripTags('<main id="main"><section class="section">section</section><section class="section">section</section></main>'), "sectionsection");
```
# --seed--
## --seed-contents--
```js
function stripTags(html) {
return html;
}
```
# --solutions--
```js
function stripTags(html) {
return html.replace(/<[^>]*>/g, '');
}
```
@@ -0,0 +1,108 @@
---
id: 68cae5b538ff798bbd4da005
title: "Challenge 67: Email Validator"
challengeType: 28
dashedName: challenge-67
---
# --description--
Given a string, determine if it is a valid email address using the following constraints:
- It must contain exactly one `@` symbol.
- The local part (before the `@`):
- Can only contain letters (`a-z`, `A-Z`), digits (`0-9`), dots (`.`), underscores (`_`), or hyphens (`-`).
- Cannot start or end with a dot.
- The domain part (after the `@`):
- Must contain at least one dot.
- Must end with a dot followed by at least two letters.
- Neither the local or domain part can have two dots in a row.
# --hints--
`validate("a@b.cd")` should return `true`.
```js
assert.isTrue(validate("a@b.cd"));
```
`validate("hell.-w.rld@example.com")` should return `true`.
```js
assert.isTrue(validate("hell.-w.rld@example.com"));
```
`validate(".b@sh.rc")` should return `false`.
```js
assert.isFalse(validate(".b@sh.rc"));
```
`validate("example@test.c0")` should return `false`.
```js
assert.isFalse(validate("example@test.c0"));
```
`validate("freecodecamp.org")` should return `false`.
```js
assert.isFalse(validate("freecodecamp.org"));
```
`validate("develop.ment_user@c0D!NG.R.CKS")` should return `true`.
```js
assert.isTrue(validate("develop.ment_user@c0D!NG.R.CKS"));
```
`validate("hello.@wo.rld")` should return `false`.
```js
assert.isFalse(validate("hello.@wo.rld"));
```
`validate("hello@world..com")` should return `false`.
```js
assert.isFalse(validate("hello@world..com"));
```
`validate("git@commit@push.io")` should return `false`.
```js
assert.isFalse(validate("git@commit@push.io"));
```
# --seed--
## --seed-contents--
```js
function validate(email) {
return email;
}
```
# --solutions--
```js
function validate(email) {
if (email.includes('..')) return false;
const parts = email.split('@');
if (parts.length !== 2) return false;
const [local, domain] = parts;
if (local.startsWith('.') || local.endsWith('.')) return false;
if (!/^[a-zA-Z0-9._-]+$/.test(local)) return false;
if (!domain.includes('.')) return false;
const tld = domain.split('.').pop();
if (tld.length < 2 || !/^[a-zA-Z]+$/.test(tld)) return false;
return true;
}
```
@@ -0,0 +1,65 @@
---
id: 68cae5b538ff798bbd4da006
title: "Challenge 68: Credit Card Masker"
challengeType: 28
dashedName: challenge-68
---
# --description--
Given a string of credit card numbers, return a masked version of it using the following constraints:
- The string will contain four sets of four digits (`0-9`), with all sets being separated by a single space, or a single hyphen (`-`).
- Replace all numbers, except the last four, with an asterisk (`*`).
- Leave the remaining characters unchanged.
For example, given `"4012-8888-8888-1881"` return `"****-****-****-1881"`.
# --hints--
`mask("4012-8888-8888-1881")` should return `"****-****-****-1881"`.
```js
assert.equal(mask("4012-8888-8888-1881"), "****-****-****-1881");
```
`mask("5105 1051 0510 5100")` should return `"**** **** **** 5100"`.
```js
assert.equal(mask("5105 1051 0510 5100"), "**** **** **** 5100");
```
`mask("6011 1111 1111 1117")` should return `"**** **** **** 1117"`.
```js
assert.equal(mask("6011 1111 1111 1117"), "**** **** **** 1117");
```
`mask("2223-0000-4845-0010")` should return `"****-****-****-0010"`.
```js
assert.equal(mask("2223-0000-4845-0010"), "****-****-****-0010");
```
# --seed--
## --seed-contents--
```js
function mask(card) {
return card;
}
```
# --solutions--
```js
function mask(card) {
const split = card.split(card.includes('-') ? '-' : ' ');
return card.includes('-') ?
`****-****-****-${split[3]}` :
`**** **** **** ${split[3]}`;
}
```
@@ -0,0 +1,80 @@
---
id: 68cae5b538ff798bbd4da007
title: "Challenge 69: Missing Socks"
challengeType: 28
dashedName: challenge-69
---
# --description--
Given an integer representing the number of pairs of socks you started with, and another integer representing how many wash cycles you have gone through, return the number of complete pairs of socks you currently have using the following constraints:
- Every 2 wash cycles, you lose a single sock.
- Every 3 wash cycles, you find a single missing sock.
- Every 5 wash cycles, a single sock is worn out and must be thrown away.
- Every 10 wash cycles, you buy a pair of socks.
- You can never have less than zero total socks.
- Rules can overlap. For example, on wash cycle 10, you will lose a single sock, throw away a single sock, and buy a new pair of socks.
- Return the number of complete pairs of socks.
# --hints--
`sockPairs(2, 5)` should return `1`.
```js
assert.equal(sockPairs(2, 5), 1);
```
`sockPairs(1, 2)` should return `0`.
```js
assert.equal(sockPairs(1, 2), 0);
```
`sockPairs(5, 11)` should return `4`.
```js
assert.equal(sockPairs(5, 11), 4);
```
`sockPairs(6, 25)` should return `3`.
```js
assert.equal(sockPairs(6, 25), 3);
```
`sockPairs(1, 8)` should return `0`.
```js
assert.equal(sockPairs(1, 8), 0);
```
# --seed--
## --seed-contents--
```js
function sockPairs(pairs, cycles) {
return pairs;
}
```
# --solutions--
```js
function sockPairs(pairs, cycles) {
let socks = pairs * 2;
for (let i = 1; i <= cycles; i++) {
if (i % 2 === 0) socks -= 1;
if (i % 3 === 0) socks += 1;
if (i % 5 === 0) socks -= 1;
if (i % 10 === 0) socks += 2;
if (socks < 0) socks = 0;
}
return Math.floor(socks / 2);
}
```
@@ -0,0 +1,77 @@
---
id: 68cae5b538ff798bbd4da008
title: "Challenge 70: HTML Attribute Extractor"
challengeType: 28
dashedName: challenge-70
---
# --description--
Given a string of a valid HTML element, return the attributes of the element using the following criteria:
- You will only be given one element.
- Attributes will be in the format: `attribute="value"`.
- Return an array of strings with each attribute property and value, separated by a comma, in this format: `["attribute1, value1", "attribute2, value2"]`.
- Return attributes in the order they are given.
- If no attributes are found, return an empty array.
# --hints--
`extractAttributes('<span class="red"></span>')` should return `["class, red"]`.
```js
assert.deepEqual(extractAttributes('<span class="red"></span>'), ["class, red"]);
```
`extractAttributes('<meta charset="UTF-8" />')` should return `["charset, UTF-8"]`.
```js
assert.deepEqual(extractAttributes('<meta charset="UTF-8" />'), ["charset, UTF-8"]);
```
`extractAttributes("<p>Lorem ipsum dolor sit amet</p>")` should return `[]`.
```js
assert.deepEqual(extractAttributes("<p>Lorem ipsum dolor sit amet</p>"), []);
```
`extractAttributes('<input name="email" type="email" required="true" />')` should return `["name, email", "type, email", "required, true"]`.
```js
assert.deepEqual(extractAttributes('<input name="email" type="email" required="true" />'), ["name, email", "type, email", "required, true"]);
```
`extractAttributes('<button id="submit" class="btn btn-primary">Submit</button>')` should return `["id, submit", "class, btn btn-primary"]`.
```js
assert.deepEqual(extractAttributes('<button id="submit" class="btn btn-primary">Submit</button>'), ["id, submit", "class, btn btn-primary"]);
```
# --seed--
## --seed-contents--
```js
function extractAttributes(element) {
return element;
}
```
# --solutions--
```js
function extractAttributes(element) {
const regex = /(\w[\w-]*)="([^"]*)"/g;
const result = [];
let match;
while ((match = regex.exec(element)) !== null) {
const attr = match[1];
const val = match[2];
result.push(`${attr}, ${val}`);
}
return result;
}
```
@@ -0,0 +1,62 @@
---
id: 68cae5b538ff798bbd4da009
title: "Challenge 71: Tip Calculator"
challengeType: 28
dashedName: challenge-71
---
# --description--
Given the price of your meal and a custom tip percent, return an array with three tip values; 15%, 20%, and the custom amount.
- Prices will be given in the format: `"$N.NN"`.
- Custom tip percents will be given in this format: `"25%"`.
- Return amounts in the same `"$N.NN"` format, rounded to two decimal places.
For example, given a `"$10.00"` meal price, and a `"25%"` custom tip value, return `["$1.50", "$2.00", "$2.50"]`.
# --hints--
`calculateTips("$10.00", "25%")` should return `["$1.50", "$2.00", "$2.50"]`.
```js
assert.deepEqual(calculateTips("$10.00", "25%"), ["$1.50", "$2.00", "$2.50"]);
```
`calculateTips("$89.67", "26%")` should return `["$13.45", "$17.93", "$23.31"]`.
```js
assert.deepEqual(calculateTips("$89.67", "26%"), ["$13.45", "$17.93", "$23.31"]);
```
`calculateTips("$19.85", "9%")` should return `["$2.98", "$3.97", "$1.79"]`.
```js
assert.deepEqual(calculateTips("$19.85", "9%"), ["$2.98", "$3.97", "$1.79"]);
```
# --seed--
## --seed-contents--
```js
function calculateTips(mealPrice, customTip) {
return mealPrice;
}
```
# --solutions--
```js
function calculateTips(mealPrice, customTip) {
const meal = parseFloat(mealPrice.slice(1));
const customPercent = parseFloat(customTip.slice(0, -1));
const tips = [15, 20, customPercent];
return tips.map(percent => {
const amount = (meal * percent / 100).toFixed(2);
return `$${amount}`;
});
}
```
@@ -0,0 +1,76 @@
---
id: 68cae5b538ff798bbd4da00a
title: "Challenge 72: Thermostat Adjuster 2"
challengeType: 28
dashedName: challenge-72
---
# --description--
Given the current temperature of a room in Fahrenheit and a target temperature in Celsius, return a string indicating how to adjust the room temperature based on these constraints:
- Return `"Heat: X degrees Fahrenheit"` if the current temperature is below the target. With `X` being the number of degrees in Fahrenheit to heat the room to reach the target, rounded to 1 decimal place.
- Return `"Cool: X degrees Fahrenheit"` if the current temperature is above the target. With `X` being the number of degrees in Fahrenheit to cool the room to reach the target, rounded to 1 decimal place.
- Return `"Hold"` if the current temperature is equal to the target.
To convert Celsius to Fahrenheit, multiply the Celsius temperature by 1.8 and add 32 to the result (`F = (C * 1.8) + 32`).
# --hints--
`adjustThermostat(32, 0)` should return `"Hold"`.
```js
assert.equal(adjustThermostat(32, 0), "Hold");
```
`adjustThermostat(70, 25)` should return `"Heat: 7.0 degrees Fahrenheit"`.
```js
assert.equal(adjustThermostat(70, 25), "Heat: 7.0 degrees Fahrenheit");
```
`adjustThermostat(72, 18)` should return `"Cool: 7.6 degrees Fahrenheit"`.
```js
assert.equal(adjustThermostat(72, 18), "Cool: 7.6 degrees Fahrenheit");
```
`adjustThermostat(212, 100)` should return `"Hold"`.
```js
assert.equal(adjustThermostat(212, 100), "Hold");
```
`adjustThermostat(59, 22)` should return `"Heat: 12.6 degrees Fahrenheit"`.
```js
assert.equal(adjustThermostat(59, 22), "Heat: 12.6 degrees Fahrenheit");
```
# --seed--
## --seed-contents--
```js
function adjustThermostat(currentF, targetC) {
return currentF;
}
```
# --solutions--
```js
function adjustThermostat(currentF, targetC) {
const targetF = targetC * 1.8 + 32;
const diff = Math.abs(targetF - currentF).toFixed(1);
if (currentF < targetF) {
return `Heat: ${diff} degrees Fahrenheit`;
} else if (currentF > targetF) {
return `Cool: ${diff} degrees Fahrenheit`;
} else {
return "Hold"
}
}
```
@@ -0,0 +1,87 @@
---
id: 68d2ba1468508398389487ce
title: "Challenge 73: Speak Wisely, You Must"
challengeType: 28
dashedName: challenge-73
---
# --description--
Given a sentence, return a version of it that sounds like advice from a wise teacher using the following rules:
- Words are separated by a single space.
- Find the first occurrence of one of the following words in the sentence: `"have"`, `"must"`, `"are"`, `"will"`, `"can"`.
- Move all words before and including that word to the end of the sentence and:
- Preserve the order of the words when you move them.
- Make them all lowercase.
- And add a comma and space before them.
- Capitalize the first letter of the new first word of the sentence.
- All given sentences will end with a single punctuation mark. Keep the original punctuation of the sentence and move it to the end of the new sentence.
- Return the new sentence, make sure there's a single space between each word and no spaces at the beginning or end of the sentence.
For example, given `"You must speak wisely."` return `"Speak wisely, you must."`
# --hints--
`wiseSpeak("You must speak wisely.")` should return `"Speak wisely, you must."`
```js
assert.equal(wiseSpeak("You must speak wisely."), "Speak wisely, you must.");
```
`wiseSpeak("You can do it!")` should return `"Do it, you can!"`
```js
assert.equal(wiseSpeak("You can do it!"), "Do it, you can!");
```
`wiseSpeak("Do you think you will complete this?")` should return `"Complete this, do you think you will?"`
```js
assert.equal(wiseSpeak("Do you think you will complete this?"), "Complete this, do you think you will?");
```
`wiseSpeak("All your base are belong to us.")` should return `"Belong to us, all your base are."`
```js
assert.equal(wiseSpeak("All your base are belong to us."), "Belong to us, all your base are.");
```
`wiseSpeak("You have much to learn.")` should return `"Much to learn, you have."`
```js
assert.equal(wiseSpeak("You have much to learn."), "Much to learn, you have.");
```
# --seed--
## --seed-contents--
```js
function wiseSpeak(sentence) {
return sentence;
}
```
# --solutions--
```js
function wiseSpeak(sentence) {
const triggers = ["have", "must", "are", "will", "can"];
const punctuation = sentence[sentence.length - 1];
const words = sentence.split(" ");
const triggerIndex = words.findIndex(w => triggers.includes(w));
const toMove = words.slice(0, triggerIndex + 1).map(w => w.toLowerCase());
const remaining = words.slice(triggerIndex + 1);
const newStart = remaining.map((w, i) => {
return i === 0 ? w[0].toUpperCase() + w.slice(1) :
i === remaining.length - 1 ? w.slice(0, w.length - 1) : w;
})
return newStart.join(" ") + ", " + toMove.join(" ") + punctuation;
}
```
@@ -0,0 +1,54 @@
---
id: 68d2ba1468508398389487cf
title: "Challenge 74: Favorite Songs"
challengeType: 28
dashedName: challenge-74
---
# --description--
Remember iPods? The first model came out 24 years ago today, on Oct. 23, 2001.
Given an array of song objects representing your iPod playlist, return an array with the titles of the two most played songs, with the most played song first.
- Each object will have a `"title"` property (string), and a `"plays"` property (integer).
# --hints--
`favoriteSongs([{"title": "Sync or Swim", "plays": 3}, {"title": "Byte Me", "plays": 1}, {"title": "Earbud Blues", "plays": 2} ])` should return `["Sync or Swim", "Earbud Blues"]`.
```js
assert.deepEqual(favoriteSongs([{"title": "Sync or Swim", "plays": 3}, {"title": "Byte Me", "plays": 1}, {"title": "Earbud Blues", "plays": 2} ]), ["Sync or Swim", "Earbud Blues"]);
```
`favoriteSongs([{"title": "Skip Track", "plays": 98}, {"title": "99 Downloads", "plays": 99}, {"title": "Clickwheel Love", "plays": 100} ])` should return `["Clickwheel Love", "99 Downloads"]`.
```js
assert.deepEqual(favoriteSongs([{"title": "Skip Track", "plays": 98}, {"title": "99 Downloads", "plays": 99}, {"title": "Clickwheel Love", "plays": 100} ]), ["Clickwheel Love", "99 Downloads"]);
```
`favoriteSongs([{"title": "Song A", "plays": 42}, {"title": "Song B", "plays": 99}, {"title": "Song C", "plays": 75} ])` should return `["Song B", "Song C"]`.
```js
assert.deepEqual(favoriteSongs([{"title": "Song A", "plays": 42}, {"title": "Song B", "plays": 99}, {"title": "Song C", "plays": 75} ]), ["Song B", "Song C"]);
```
# --seed--
## --seed-contents--
```js
function favoriteSongs(playlist) {
return playlist;
}
```
# --solutions--
```js
function favoriteSongs(playlist) {
const sorted = [...playlist].sort((a, b) => b.plays - a.plays);
return sorted.slice(0, 2).map(song => song.title);
}
```
@@ -0,0 +1,107 @@
---
id: 68d2ba1468508398389487d0
title: "Challenge 75: Missile Strike"
challengeType: 28
dashedName: challenge-75
---
# --description--
Given a 2D array representing the location of your ship in the ocean, and an array with the coordinates (`[row, column]`) of a missile strike, return `"Hit"`, `"Miss"`, or `"Sunk"` using the following rules:
- The given 2D array will contain exactly one unsunk ship.
- Each cell in the 2D array will contain one of the following values:
- `"-"`: Water (no ship).
- `"O"`: A part of your ship that has not been struck.
- `"X"`: A part of your ship that has already been struck.
- If the strike hits the water, return `"Miss"`.
- If the strike hits your ship, but at least one other part of the ship remains unstruck, return `"Hit"`.
- If the strike hits the last unstruck part of your ship, return `"Sunk"`.
For example, given:
```json
[
[ "-", "X"],
[ "-", "X"],
[ "-", "O"]
]
```
And `[2, 1]` for the coordinates of the missile strike, return `"Sunk"` because it hit the last unstruck part of your ship.
# --hints--
`strike([[ "-", "X"], [ "-", "X"], [ "-", "O"]], [2, 1])` should return `"Sunk"`.
```js
assert.equal(strike([[ "-", "X"], [ "-", "X"], [ "-", "O"]], [2, 1]), "Sunk");
```
`strike([[ "-", "X"], [ "-", "X"], [ "-", "O"]], [2, 0])` should return `"Miss"`.
```js
assert.equal(strike([[ "-", "X"], [ "-", "X"], [ "-", "O"]], [2, 0]), "Miss");
```
`strike([[ "-", "X"], [ "-", "O"], [ "-", "O"]], [1, 1])` should return `"Hit"`.
```js
assert.equal(strike([[ "-", "X"], [ "-", "O"], [ "-", "O"]], [1, 1]), "Hit");
```
`strike([[ "-", "-", "-"], [ "X", "O", "X"], [ "-", "-", "-"]], [1, 2])` should return `"Hit"`.
```js
assert.equal(strike([[ "-", "-", "-"], [ "X", "O", "X"], [ "-", "-", "-"]], [1, 2]), "Hit");
```
`strike([[ "-", "-", "-"], [ "-", "-", "-"], [ "O", "X", "X"]], [2, 0])` should return `"Sunk"`.
```js
assert.equal(strike([[ "-", "-", "-"], [ "-", "-", "-"], [ "O", "X", "X"]], [2, 0]), "Sunk");
```
`strike([[ "-", "-", "-"], [ "-", "-", "-"], [ "O", "X", "X"]], [1, 2])` should return `"Miss"`.
```js
assert.equal(strike([[ "-", "-", "-"], [ "-", "-", "-"], [ "O", "X", "X"]], [1, 2]), "Miss");
```
# --seed--
## --seed-contents--
```js
function strike(map, coordinates) {
return map;
}
```
# --solutions--
```js
function strike(map, coordinates) {
const [row, col] = coordinates;
const target = map[row][col];
if (target === "-") {
return "Miss";
}
if (target === "O") {
for (let r = 0; r < map.length; r++) {
for (let c = 0; c < map[r].length; c++) {
if ((r !== row || c !== col) && map[r][c] === "O") {
return "Hit";
}
}
}
return "Sunk";
}
return "Hit";
}
```
@@ -0,0 +1,65 @@
---
id: 68d30845cc08266018fc46bc
title: "Challenge 76: Complementary DNA"
challengeType: 28
dashedName: challenge-76
---
# --description--
Given a string representing a DNA sequence, return its complementary strand using the following rules:
- DNA consists of the letters `"A"`, `"C"`, `"G"`, and `"T"`.
- The letters `"A"` and `"T"` complement each other.
- The letters `"C"` and `"G"` complement each other.
For example, given `"ACGT"`, return `"TGCA"`.
# --hints--
`complementaryDNA("ACGT")` should return `"TGCA"`.
```js
assert.equal(complementaryDNA("ACGT"), "TGCA");
```
`complementaryDNA("ATGCGTACGTTAGC")` should return `"TACGCATGCAATCG"`.
```js
assert.equal(complementaryDNA("ATGCGTACGTTAGC"), "TACGCATGCAATCG");
```
`complementaryDNA("GGCTTACGATCGAAG")` should return `"CCGAATGCTAGCTTC"`.
```js
assert.equal(complementaryDNA("GGCTTACGATCGAAG"), "CCGAATGCTAGCTTC");
```
`complementaryDNA("GATCTAGCTAGGCTAGCTAG")` should return `"CTAGATCGATCCGATCGATC"`.
```js
assert.equal(complementaryDNA("GATCTAGCTAGGCTAGCTAG"), "CTAGATCGATCCGATCGATC");
```
# --seed--
## --seed-contents--
```js
function complementaryDNA(strand) {
return strand;
}
```
# --solutions--
```js
function complementaryDNA(strand) {
const complements = { A: "T", T: "A", C: "G", G: "C" };
return strand
.split("")
.map(c => complements[c])
.join("");
}
```
@@ -0,0 +1,77 @@
---
id: 68d30845cc08266018fc46bd
title: "Challenge 77: Duration Formatter"
challengeType: 28
dashedName: challenge-77
---
# --description--
Given an integer number of seconds, return a string representing the same duration in the format `"H:MM:SS"`, where `"H"` is the number of hours, `"MM"` is the number of minutes, and `"SS"` is the number of seconds. Return the time using the following rules:
- Seconds: Should always be two digits.
- Minutes: Should omit leading zeros when they aren't needed. Use `"0"` if the duration is less than one minute.
- Hours: Should be included only if they're greater than zero.
# --hints--
`format(500)` should return `"8:20"`.
```js
assert.equal(format(500), "8:20");
```
`format(4000)` should return `"1:06:40"`.
```js
assert.equal(format(4000), "1:06:40");
```
`format(1)` should return `"0:01"`.
```js
assert.equal(format(1), "0:01");
```
`format(5555)` should return `"1:32:35"`.
```js
assert.equal(format(5555), "1:32:35");
```
`format(99999)` should return `"27:46:39"`.
```js
assert.equal(format(99999), "27:46:39");
```
# --seed--
## --seed-contents--
```js
function format(seconds) {
return seconds;
}
```
# --solutions--
```js
function format(seconds) {
const h = Math.floor(seconds / 3600);
const m = Math.floor((seconds % 3600) / 60);
const s = seconds % 60;
const secondsStr = s.toString().padStart(2, "0");
const minutesStr = m.toString();
if (h > 0) {
const hoursStr = h.toString();
return `${hoursStr}:${minutesStr.padStart(2, "0")}:${secondsStr}`;
} else {
return `${minutesStr}:${secondsStr}`;
}
}
```
@@ -0,0 +1,61 @@
---
id: 68d30845cc08266018fc46be
title: "Challenge 78: Integer Sequence"
challengeType: 28
dashedName: challenge-78
---
# --description--
Given a positive integer, return a string with all of the integers from `1` up to, and including, the given number, in numerical order.
For example, given `5`, return `"12345"`.
# --hints--
`sequence(5)` should return `"12345"`.
```js
assert.equal(sequence(5), "12345");
```
`sequence(10)` should return `"12345678910"`.
```js
assert.equal(sequence(10), "12345678910");
```
`sequence(1)` should return `"1"`.
```js
assert.strictEqual(sequence(1), "1");
```
`sequence(27)` should return `"123456789101112131415161718192021222324252627"`.
```js
assert.equal(sequence(27), "123456789101112131415161718192021222324252627");
```
# --seed--
## --seed-contents--
```js
function sequence(n) {
return n;
}
```
# --solutions--
```js
function sequence(n) {
let result = "";
for (let i = 1; i <= n; i++) {
result += i;
}
return result;
}
```
@@ -0,0 +1,98 @@
---
id: 68d30fc57588d97fd3027b30
title: "Challenge 79: Navigator"
challengeType: 28
dashedName: challenge-79
---
# --description--
On October 28, 1994, Netscape Navigator was released, helping millions explore the early web.
Given an array of browser commands you executed on Netscape Navigator, return the current page you are on after executing all the commands using the following rules:
- You always start on the `"Home"` page, which will not be included in the commands array.
- Valid commands are:
- `"Visit Page"`: Where `"Page"` is the name of the page you are visiting. For example, `"Visit About"` takes you to the `"About"` page. When you visit a new page, make sure to discard any forward history you have.
- `"Back"`: Takes you to the previous page in your history or stays on the current page if there isn't one.
- `"Forward"`: Takes you forward in the history to the page you came from or stays on the current page if there isn't one.
For example, given `["Visit About Us", "Back", "Forward"]`, return `"About Us"`.
# --hints--
`navigate(["Visit About Us", "Back", "Forward"])` should return `"About Us"`.
```js
assert.equal(navigate(["Visit About Us", "Back", "Forward"]), "About Us");
```
`navigate(["Forward"])` should return `"Home"`.
```js
assert.equal(navigate(["Forward"]), "Home");
```
`navigate(["Back"])` should return `"Home"`.
```js
assert.equal(navigate(["Back"]), "Home");
```
`navigate(["Visit About Us", "Visit Gallery"])` should return `"Gallery"`.
```js
assert.equal(navigate(["Visit About Us", "Visit Gallery"]), "Gallery");
```
`navigate(["Visit About Us", "Visit Gallery", "Back", "Back"])` should return `"Home"`.
```js
assert.equal(navigate(["Visit About Us", "Visit Gallery", "Back", "Back"]), "Home");
```
`navigate(["Visit About", "Visit Gallery", "Back", "Visit Contact", "Forward"])` should return `"Contact"`.
```js
assert.equal(navigate(["Visit About", "Visit Gallery", "Back", "Visit Contact", "Forward"]), "Contact");
```
`navigate(["Visit About Us", "Visit Visit Us", "Forward", "Visit Contact Us", "Back"])` should return `"Visit Us"`.
```js
assert.equal(navigate(["Visit About Us", "Visit Visit Us", "Forward", "Visit Contact Us", "Back"]), "Visit Us");
```
# --seed--
## --seed-contents--
```js
function navigate(commands) {
return commands;
}
```
# --solutions--
```js
function navigate(commands) {
const history = ["Home"];
let currentPageIndex = 0;
for (const command of commands) {
if (command.startsWith("Visit")) {
history.splice(currentPageIndex + 1);
history.push(command.slice(6));
currentPageIndex++;
} else if(command === "Back" && currentPageIndex > 0) {
currentPageIndex--;
} else if (command === "Forward" && currentPageIndex < history.length - 1) {
currentPageIndex++;
}
}
return history[currentPageIndex];
}
```
@@ -9,9 +9,9 @@ dashedName: challenge-36
Given the current temperature of a room and a target temperature, return a string indicating how to adjust the room temperature based on these constraints:
- Return "heat" if the current temperature is below the target.
- Return "cool" if the current temperature is above the target.
- Return "hold" if the current temperature is equal to the target.
- Return `"heat"` if the current temperature is below the target.
- Return `"cool"` if the current temperature is above the target.
- Return `"hold"` if the current temperature is equal to the target.
# --hints--
@@ -0,0 +1,129 @@
---
id: 68cae5b538ff798bbd4da001
title: "Challenge 63: Battle of Words"
challengeType: 29
dashedName: challenge-63
---
# --description--
Given two sentences representing your team and an opposing team, where each word from your team battles the corresponding word from the opposing team, determine which team wins using the following rules:
- The given sentences will always contain the same number of words.
- Words are separated by a single space and will only contain letters.
- The value of each word is the sum of its letters.
- Letters `a` to `z` correspond to the values `1` through `26`. For example, `a` is `1`, and `z` is `26`.
- A capital letter doubles the value of the letter. For example, `A` is `2`, and `Z` is `52`.
- Words battle in order: the first word of your team battles the first word of the opposing team, and so on.
- A word wins if its value is greater than the opposing word's value.
- The team with more winning words is the winner.
Return `"We win"` if your team is the winner, `"We lose"` if your team loses, and `"Draw"` if both teams have the same number of wins.
# --hints--
`battle("hello world", "hello word")` should return `"We win"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(battle("hello world", "hello word"), "We win")`)
}})
```
`battle("Hello world", "hello world")` should return `"We win"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(battle("Hello world", "hello world"), "We win")`)
}})
```
`battle("lorem ipsum", "kitty ipsum")` should return `"We lose"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(battle("lorem ipsum", "kitty ipsum"), "We lose")`)
}})
```
`battle("hello world", "world hello")` should return `"Draw"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(battle("hello world", "world hello"), "Draw")`)
}})
```
`battle("git checkout", "git switch")` should return `"We win"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(battle("git checkout", "git switch"), "We win")`)
}})
```
`battle("Cheeseburger with fries", "Cheeseburger with Fries")` should return `"We lose"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(battle("Cheeseburger with fries", "Cheeseburger with Fries"), "We lose")`)
}})
```
`battle("We must never surrender", "Our team must win")` should return `"Draw"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(battle("We must never surrender", "Our team must win"), "Draw")`)
}})
```
# --seed--
## --seed-contents--
```py
def battle(our_team, opponent):
return our_team
```
# --solutions--
```py
def get_word_value(word):
value = 0
for char in word:
val = ord(char.lower()) - ord('a') + 1
if char.isupper():
val *= 2
value += val
return value
def battle(our_team, opponent):
my_wins = 0
opp_wins = 0
for my_word, opp_word in zip(our_team.split(), opponent.split()):
my_val = get_word_value(my_word)
opp_val = get_word_value(opp_word)
if my_val > opp_val:
my_wins += 1
elif opp_val > my_val:
opp_wins += 1
if my_wins > opp_wins:
return "We win"
elif opp_wins > my_wins:
return "We lose"
else:
return "Draw"
```
@@ -0,0 +1,88 @@
---
id: 68cae5b538ff798bbd4da002
title: "Challenge 64: 24 to 12"
challengeType: 29
dashedName: challenge-64
---
# --description--
Given a string representing a time of the day in the 24-hour format of `"HHMM"`, return the time in its equivalent 12-hour format of `"H:MM AM"` or `"H:MM PM"`.
- The given input will always be a four-digit string in 24-hour time format, from `"0000"` to `"2359"`.
# --hints--
`to_12("1124")` should return `"11:24 AM"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(to_12("1124"), "11:24 AM")`)
}})
```
`to_12("0900")` should return `"9:00 AM"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(to_12("0900"), "9:00 AM")`)
}})
```
`to_12("1455")` should return `"2:55 PM"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(to_12("1455"), "2:55 PM")`)
}})
```
`to_12("2346")` should return `"11:46 PM"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(to_12("2346"), "11:46 PM")`)
}})
```
`to_12("0030")` should return `"12:30 AM"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(to_12("0030"), "12:30 AM")`)
}})
```
# --seed--
## --seed-contents--
```py
def to_12(time):
return time
```
# --solutions--
```py
def convert_hours(hours):
if hours == 0:
return 12
elif hours > 12:
return hours - 12
else:
return hours
def to_12(time):
hours = int(time[:2])
minutes = time[2:]
period = "AM" if hours < 12 else "PM"
return f"{convert_hours(hours)}:{minutes} {period}"
```
@@ -0,0 +1,84 @@
---
id: 68cae5b538ff798bbd4da003
title: "Challenge 65: String Count"
challengeType: 29
dashedName: challenge-65
---
# --description--
Given two strings, determine how many times the second string appears in the first.
- The pattern string can overlap in the first string. For example, `"aaa"` contains `"aa"` twice. The first two `a`'s and the second two.
# --hints--
`count('abcdefg', 'def')` should return `1`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(count('abcdefg', 'def'), 1)`)
}})
```
`count('hello', 'world')` should return `0`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(count('hello', 'world'), 0)`)
}})
```
`count('mississippi', 'iss')` should return `2`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(count('mississippi', 'iss'), 2)`)
}})
```
`count('she sells seashells by the seashore', 'sh')` should return `3`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(count('she sells seashells by the seashore', 'sh'), 3)`)
}})
```
`count('101010101010101010101', '101')` should return `10`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(count('101010101010101010101', '101'), 10)`)
}})
```
# --seed--
## --seed-contents--
```py
def count(text, parameter):
return text
```
# --solutions--
```py
def count(text, pattern):
if not pattern:
return 0
occurrences = 0
for i in range(len(text) - len(pattern) + 1):
if text[i:i+len(pattern)] == pattern:
occurrences += 1
return occurrences
```
@@ -0,0 +1,72 @@
---
id: 68cae5b538ff798bbd4da004
title: "Challenge 66: HTML Tag Stripper"
challengeType: 29
dashedName: challenge-66
---
# --description--
Given a string of HTML code, remove the tags and return the plain text content.
- The input string will contain only valid HTML.
- HTML tags may be nested.
- Remove the tags and any attributes.
For example, `'<a href="#">Click here</a>'` should return `"Click here"`.
# --hints--
`strip_tags('<a href="#">Click here</a>')` should return `"Click here"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(strip_tags('<a href="#">Click here</a>'), "Click here")`)
}})
```
`strip_tags('<p class="center">Hello <b>World</b>!</p>')` should return `"Hello World!"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(strip_tags('<p class="center">Hello <b>World</b>!</p>'), "Hello World!")`)
}})
```
`strip_tags('<img src="cat.jpg" alt="Cat">')` should return an empty string (`""`).
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(strip_tags('<img src="cat.jpg" alt="Cat">'), "")`)
}})
```
`strip_tags('<main id="main"><section class="section">section</section><section class="section">section</section></main>')` should return `sectionsection`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(strip_tags('<main id="main"><section class="section">section</section><section class="section">section</section></main>'), "sectionsection")`)
}})
```
# --seed--
## --seed-contents--
```py
def strip_tags(html):
return html
```
# --solutions--
```py
import re
def strip_tags(html):
return re.sub(r'<[^>]*>', '', html)
```
@@ -0,0 +1,141 @@
---
id: 68cae5b538ff798bbd4da005
title: "Challenge 67: Email Validator"
challengeType: 29
dashedName: challenge-67
---
# --description--
Given a string, determine if it is a valid email address using the following constraints:
- It must contain exactly one `@` symbol.
- The local part (before the `@`):
- Can only contain letters (`a-z`, `A-Z`), digits (`0-9`), dots (`.`), underscores (`_`), or hyphens (`-`).
- Cannot start or end with a dot.
- The domain part (after the `@`):
- Must contain at least one dot.
- Must end with a dot followed by at least two letters.
- Neither the local or domain part can have two dots in a row.
# --hints--
`validate("a@b.cd")` should return `True`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertIs(validate("a@b.cd"), True)`)
}})
```
`validate("hell.-w.rld@example.com")` should return `True`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertIs(validate("hell.-w.rld@example.com"), True)`)
}})
```
`validate(".b@sh.rc")` should return `False`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertIs(validate(".b@sh.rc"), False)`)
}})
```
`validate("example@test.c0")` should return `False`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertIs(validate("example@test.c0"), False)`)
}})
```
`validate("freecodecamp.org")` should return `False`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertIs(validate("freecodecamp.org"), False)`)
}})
```
`validate("develop.ment_user@c0D!NG.R.CKS")` should return `True`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertIs(validate("develop.ment_user@c0D!NG.R.CKS"), True)`)
}})
```
`validate("hello.@wo.rld")` should return `False`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertIs(validate("hello.@wo.rld"), False)`)
}})
```
`validate("hello@world..com")` should return `False`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertIs(validate("hello@world..com"), False)`)
}})
```
`validate("git@commit@push.io")` should return `False`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertIs(validate("git@commit@push.io"), False)`)
}})
```
# --seed--
## --seed-contents--
```py
def validate(email):
return email
```
# --solutions--
```py
import re
def validate(email):
if '..' in email:
return False
parts = email.split('@')
if len(parts) != 2:
return False
local, domain = parts
if local.startswith('.') or local.endswith('.'):
return False
if not re.match(r'^[a-zA-Z0-9._-]+$', local):
return False
if '.' not in domain:
return False
tld = domain.split('.')[-1]
if len(tld) < 2 or not tld.isalpha():
return False
return True
```
@@ -0,0 +1,76 @@
---
id: 68cae5b538ff798bbd4da006
title: "Challenge 68: Credit Card Masker"
challengeType: 29
dashedName: challenge-68
---
# --description--
Given a string of credit card numbers, return a masked version of it using the following constraints:
- The string will contain four sets of four digits (`0-9`), with all sets being separated by a single space, or a single hyphen (`-`).
- Replace all numbers, except the last four, with an asterisk (`*`).
- Leave the remaining characters unchanged.
For example, given `"4012-8888-8888-1881"` return `"****-****-****-1881"`.
# --hints--
`mask("4012-8888-8888-1881")` should return `"****-****-****-1881"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(mask("4012-8888-8888-1881"), "****-****-****-1881")`)
}})
```
`mask("5105 1051 0510 5100")` should return `"**** **** **** 5100"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(mask("5105 1051 0510 5100"), "**** **** **** 5100")`)
}})
```
`mask("6011 1111 1111 1117")` should return `"**** **** **** 1117"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(mask("6011 1111 1111 1117"), "**** **** **** 1117")`)
}})
```
`mask("2223-0000-4845-0010")` should return `"****-****-****-0010"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(mask("2223-0000-4845-0010"), "****-****-****-0010")`)
}})
```
# --seed--
## --seed-contents--
```py
def mask(card):
return card
```
# --solutions--
```py
def mask(card):
if '-' in card:
split = card.split('-')
return f"****-****-****-{split[3]}"
else:
split = card.split(' ')
return f"**** **** **** {split[3]}"
```
@@ -0,0 +1,97 @@
---
id: 68cae5b538ff798bbd4da007
title: "Challenge 69: Missing Socks"
challengeType: 29
dashedName: challenge-69
---
# --description--
Given an integer representing the number of pairs of socks you started with, and another integer representing how many wash cycles you have gone through, return the number of complete pairs of socks you currently have using the following constraints:
- Every 2 wash cycles, you lose a single sock.
- Every 3 wash cycles, you find a single missing sock.
- Every 5 wash cycles, a single sock is worn out and must be thrown away.
- Every 10 wash cycles, you buy a pair of socks.
- You can never have less than zero total socks.
- Rules can overlap. For example, on wash cycle 10, you will lose a single sock, throw away a single sock, and buy a new pair of socks.
- Return the number of complete pairs of socks.
# --hints--
`sock_pairs(2, 5)` should return `1`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(sock_pairs(2, 5), 1)`)
}})
```
`sock_pairs(1, 2)` should return `0`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(sock_pairs(1, 2), 0)`)
}})
```
`sock_pairs(5, 11)` should return `4`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(sock_pairs(5, 11), 4)`)
}})
```
`sock_pairs(6, 25)` should return `3`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(sock_pairs(6, 25), 3)`)
}})
```
`sock_pairs(1, 8)` should return `0`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(sock_pairs(1, 8), 0)`)
}})
```
# --seed--
## --seed-contents--
```py
def sock_pairs(pairs, cycles):
return pairs
```
# --solutions--
```py
def sock_pairs(pairs, cycles):
socks = pairs * 2
for i in range(1, cycles + 1):
if i % 2 == 0:
socks -= 1
if i % 3 == 0:
socks += 1
if i % 5 == 0:
socks -= 1
if i % 10 == 0:
socks += 2
if socks < 0:
socks = 0
return socks // 2
```
@@ -0,0 +1,83 @@
---
id: 68cae5b538ff798bbd4da008
title: "Challenge 70: HTML Attribute Extractor"
challengeType: 29
dashedName: challenge-70
---
# --description--
Given a string of a valid HTML element, return the attributes of the element using the following criteria:
- You will only be given one element.
- Attributes will be in the format: `attribute="value"`.
- Return an array of strings with each attribute property and value, separated by a comma, in this format: `["attribute1, value1", "attribute2, value2"]`.
- Return attributes in the order they are given.
- If no attributes are found, return an empty array.
# --hints--
`extract_attributes('<span class="red"></span>')` should return `["class, red"]`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(extract_attributes('<span class="red"></span>'), ["class, red"])`)
}})
```
`extract_attributes('<meta charset="UTF-8" />')` should return `["charset, UTF-8"]`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(extract_attributes('<meta charset="UTF-8" />'), ["charset, UTF-8"])`)
}})
```
`extract_attributes("<p>Lorem ipsum dolor sit amet</p>")` should return `[]`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(extract_attributes("<p>Lorem ipsum dolor sit amet</p>"), [])`)
}})
```
`extract_attributes('<input name="email" type="email" required="true" />')` should return `["name, email", "type, email", "required, true"]`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(extract_attributes('<input name="email" type="email" required="true" />'), ["name, email", "type, email", "required, true"])`)
}})
```
`extract_attributes('<button id="submit" class="btn btn-primary">Submit</button>')` should return `["id, submit", "class, btn btn-primary"]`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(extract_attributes('<button id="submit" class="btn btn-primary">Submit</button>'), ["id, submit", "class, btn btn-primary"])`)
}})
```
# --seed--
## --seed-contents--
```py
def extract_attributes(element):
return element
```
# --solutions--
```py
import re
def extract_attributes(element):
pattern = r'([\w-]+)="([^"]*)"'
matches = re.findall(pattern, element)
return [f"{attr}, {val}" for attr, val in matches]
```
@@ -0,0 +1,68 @@
---
id: 68cae5b538ff798bbd4da009
title: "Challenge 71: Tip Calculator"
challengeType: 29
dashedName: challenge-71
---
# --description--
Given the price of your meal and a custom tip percent, return an array with three tip values; 15%, 20%, and the custom amount.
- Prices will be given in the format: `"$N.NN"`.
- Custom tip percents will be given in this format: `"25%"`.
- Return amounts in the same `"$N.NN"` format, rounded to two decimal places.
For example, given a `"$10.00"` meal price, and a `"25%"` custom tip value, return `["$1.50", "$2.00", "$2.50"]`.
# --hints--
`calculate_tips("$10.00", "25%")` should return `["$1.50", "$2.00", "$2.50"]`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(calculate_tips("$10.00", "25%"), ["$1.50", "$2.00", "$2.50"])`)
}})
```
`calculate_tips("$89.67", "26%")` should return `["$13.45", "$17.93", "$23.31"]`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(calculate_tips("$89.67", "26%"), ["$13.45", "$17.93", "$23.31"])`)
}})
```
`calculate_tips("$19.85", "9%")` should return `["$2.98", "$3.97", "$1.79"]`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(calculate_tips("$19.85", "9%"), ["$2.98", "$3.97", "$1.79"])`)
}})
```
# --seed--
## --seed-contents--
```py
def calculate_tips(meal_price, custom_tip):
return meal_price
```
# --solutions--
```py
def calculate_tips(meal_price, custom_tip):
meal = float(meal_price[1:])
custom_percent = float(custom_tip[:-1])
tips_percent = [15, 20, custom_percent]
tips = [f"${meal * p / 100:.2f}" for p in tips_percent]
return tips
```
@@ -0,0 +1,88 @@
---
id: 68cae5b538ff798bbd4da00a
title: "Challenge 72: Thermostat Adjuster 2"
challengeType: 29
dashedName: challenge-72
---
# --description--
Given the current temperature of a room in Fahrenheit and a target temperature in Celsius, return a string indicating how to adjust the room temperature based on these constraints:
- Return `"Heat: X degrees Fahrenheit"` if the current temperature is below the target. With `X` being the number of degrees in Fahrenheit to heat the room to reach the target, rounded to 1 decimal place.
- Return `"Cool: X degrees Fahrenheit"` if the current temperature is above the target. With `X` being the number of degrees in Fahrenheit to cool the room to reach the target, rounded to 1 decimal place.
- Return `"Hold"` if the current temperature is equal to the target.
To convert Celsius to Fahrenheit, multiply the Celsius temperature by 1.8 and add 32 to the result (`F = (C * 1.8) + 32`).
# --hints--
`adjust_thermostat(32, 0)` should return `"Hold"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(adjust_thermostat(32, 0), "Hold")`)
}})
```
`adjust_thermostat(70, 25)` should return `"Heat: 7.0 degrees Fahrenheit"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(adjust_thermostat(70, 25), "Heat: 7.0 degrees Fahrenheit")`)
}})
```
`adjust_thermostat(72, 18)` should return `"Cool: 7.6 degrees Fahrenheit"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(adjust_thermostat(72, 18), "Cool: 7.6 degrees Fahrenheit")`)
}})
```
`adjust_thermostat(212, 100)` should return `"Hold"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(adjust_thermostat(212, 100), "Hold")`)
}})
```
`adjust_thermostat(59, 22)` should return `"Heat: 12.6 degrees Fahrenheit"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(adjust_thermostat(59, 22), "Heat: 12.6 degrees Fahrenheit")`)
}})
```
# --seed--
## --seed-contents--
```py
def adjust_thermostat(current_f, target_c):
return current_f
```
# --solutions--
```py
def adjust_thermostat(current_f, target_c):
target_f = (target_c * 1.8) + 32
diff = round(abs(target_f - current_f), 1)
if current_f < target_f:
return f"Heat: {diff} degrees Fahrenheit"
elif current_f > target_f:
return f"Cool: {diff} degrees Fahrenheit"
else:
return "Hold"
```
@@ -0,0 +1,98 @@
---
id: 68d2ba1468508398389487ce
title: "Challenge 73: Speak Wisely, You Must"
challengeType: 29
dashedName: challenge-73
---
# --description--
Given a sentence, return a version of it that sounds like advice from a wise teacher using the following rules:
- Words are separated by a single space.
- Find the first occurrence of one of the following words in the sentence: `"have"`, `"must"`, `"are"`, `"will"`, `"can"`.
- Move all words before and including that word to the end of the sentence and:
- Preserve the order of the words when you move them.
- Make them all lowercase.
- And add a comma and space before them.
- Capitalize the first letter of the new first word of the sentence.
- All given sentences will end with a single punctuation mark. Keep the original punctuation of the sentence and move it to the end of the new sentence.
- Return the new sentence, make sure there's a single space between each word and no spaces at the beginning or end of the sentence.
For example, given `"You must speak wisely."` return `"Speak wisely, you must."`
# --hints--
`wise_speak("You must speak wisely.")` should return `"Speak wisely, you must."`
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(wise_speak("You must speak wisely."), "Speak wisely, you must.")`)
}})
```
`wise_speak("You can do it!")` should return `"Do it, you can!"`
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(wise_speak("You can do it!"), "Do it, you can!")`)
}})
```
`wise_speak("Do you think you will complete this?")` should return `"Complete this, do you think you will?"`
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(wise_speak("Do you think you will complete this?"), "Complete this, do you think you will?")`)
}})
```
`wise_speak("All your base are belong to us.")` should return `"Belong to us, all your base are."`
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(wise_speak("All your base are belong to us."), "Belong to us, all your base are.")`)
}})
```
`wise_speak("You have much to learn.")` should return `"Much to learn, you have."`
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(wise_speak("You have much to learn."), "Much to learn, you have.")`)
}})
```
# --seed--
## --seed-contents--
```py
def wise_speak(sentence):
return sentence
```
# --solutions--
```py
def wise_speak(sentence):
triggers = ["have", "must", "are", "will", "can"]
punctuation = sentence[-1]
words = sentence[:-1].split(" ")
index = next(i for i, w in enumerate(words) if w in triggers)
to_move = [w.lower() for w in words[:index + 1]]
remaining = words[index + 1:]
if remaining:
remaining[0] = remaining[0][0].upper() + remaining[0][1:]
return " ".join(remaining) + ", " + " ".join(to_move) + punctuation
```
@@ -0,0 +1,61 @@
---
id: 68d2ba1468508398389487cf
title: "Challenge 74: Favorite Songs"
challengeType: 29
dashedName: challenge-74
---
# --description--
Remember iPods? The first model came out 24 years ago today, on Oct. 23, 2001.
Given an array of song objects representing your iPod playlist, return an array with the titles of the two most played songs, with the most played song first.
- Each object will have a `"title"` property (string), and a `"plays"` property (integer).
# --hints--
`favorite_songs([{"title": "Sync or Swim", "plays": 3}, {"title": "Byte Me", "plays": 1}, {"title": "Earbud Blues", "plays": 2} ])` should return `["Sync or Swim", "Earbud Blues"]`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(favorite_songs([{"title": "Sync or Swim", "plays": 3}, {"title": "Byte Me", "plays": 1}, {"title": "Earbud Blues", "plays": 2} ]), ["Sync or Swim", "Earbud Blues"])`)
}})
```
`favorite_songs([{"title": "Skip Track", "plays": 98}, {"title": "99 Downloads", "plays": 99}, {"title": "Clickwheel Love", "plays": 100} ])` should return `["Clickwheel Love", "99 Downloads"]`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(favorite_songs([{"title": "Skip Track", "plays": 98}, {"title": "99 Downloads", "plays": 99}, {"title": "Clickwheel Love", "plays": 100} ]), ["Clickwheel Love", "99 Downloads"])`)
}})
```
`favorite_songs([{"title": "Song A", "plays": 42}, {"title": "Song B", "plays": 99}, {"title": "Song C", "plays": 75} ])` should return `["Song B", "Song C"]`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(favorite_songs([{"title": "Song A", "plays": 42}, {"title": "Song B", "plays": 99}, {"title": "Song C", "plays": 75} ]), ["Song B", "Song C"])`)
}})
```
# --seed--
## --seed-contents--
```py
def favorite_songs(playlist):
return playlist
```
# --solutions--
```py
def favorite_songs(playlist):
sorted_songs = sorted(playlist, key=lambda x: x["plays"], reverse=True)
return [song["title"] for song in sorted_songs[:2]]
```
@@ -0,0 +1,118 @@
---
id: 68d2ba1468508398389487d0
title: "Challenge 75: Missile Strike"
challengeType: 29
dashedName: challenge-75
---
# --description--
Given a 2D array representing the location of your ship in the ocean, and an array with the coordinates (`[row, column]`) of a missile strike, return `"Hit"`, `"Miss"`, or `"Sunk"` using the following rules:
- The given 2D array will contain exactly one unsunk ship.
- Each cell in the 2D array will contain one of the following values:
- `"-"`: Water (no ship).
- `"O"`: A part of your ship that has not been struck.
- `"X"`: A part of your ship that has already been struck.
- If the strike hits the water, return `"Miss"`.
- If the strike hits your ship, but at least one other part of the ship remains unstruck, return `"Hit"`.
- If the strike hits the last unstruck part of your ship, return `"Sunk"`.
For example, given:
```json
[
[ "-", "X"],
[ "-", "X"],
[ "-", "O"]
]
```
And `[2, 1]` for the coordinates of the missile strike, return `"Sunk"` because it hit the last unstruck part of your ship.
# --hints--
`strike([[ "-", "X"], [ "-", "X"], [ "-", "O"]], [2, 1])` should return `"Sunk"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(strike([[ "-", "X"], [ "-", "X"], [ "-", "O"]], [2, 1]), "Sunk")`)
}})
```
`strike([[ "-", "X"], [ "-", "X"], [ "-", "O"]], [2, 0])` should return `"Miss"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(strike([[ "-", "X"], [ "-", "X"], [ "-", "O"]], [2, 0]), "Miss")`)
}})
```
`strike([[ "-", "X"], [ "-", "O"], [ "-", "O"]], [1, 1])` should return `"Hit"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(strike([[ "-", "X"], [ "-", "O"], [ "-", "O"]], [1, 1]), "Hit")`)
}})
```
`strike([[ "-", "-", "-"], [ "X", "O", "X"], [ "-", "-", "-"]], [1, 2])` should return `"Hit"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(strike([[ "-", "-", "-"], [ "X", "O", "X"], [ "-", "-", "-"]], [1, 2]), "Hit")`)
}})
```
`strike([[ "-", "-", "-"], [ "-", "-", "-"], [ "O", "X", "X"]], [2, 0])` should return `"Sunk"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(strike([[ "-", "-", "-"], [ "-", "-", "-"], [ "O", "X", "X"]], [2, 0]), "Sunk")`)
}})
```
`strike([[ "-", "-", "-"], [ "-", "-", "-"], [ "O", "X", "X"]], [1, 2])` should return `"Miss"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(strike([[ "-", "-", "-"], [ "-", "-", "-"], [ "O", "X", "X"]], [1, 2]), "Miss")`)
}})
```
# --seed--
## --seed-contents--
```py
def strike(map, coordinates):
return map
```
# --solutions--
```py
def strike(map, coordinates):
row, col = coordinates
target = map[row][col]
if target == "-":
return "Miss"
if target == "O":
for r in range(len(map)):
for c in range(len(map[r])):
if (r != row or c != col) and map[r][c] == "O":
return "Hit"
return "Sunk"
return "Hit"
```
@@ -0,0 +1,72 @@
---
id: 68d30845cc08266018fc46bc
title: "Challenge 76: Complementary DNA"
challengeType: 29
dashedName: challenge-76
---
# --description--
Given a string representing a DNA sequence, return its complementary strand using the following rules:
- DNA consists of the letters `"A"`, `"C"`, `"G"`, and `"T"`.
- The letters `"A"` and `"T"` complement each other.
- The letters `"C"` and `"G"` complement each other.
For example, given `"ACGT"`, return `"TGCA"`.
# --hints--
`complementary_dna("ACGT")` should return `"TGCA"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(complementary_dna("ACGT"), "TGCA")`)
}})
```
`complementary_dna("ATGCGTACGTTAGC")` should return `"TACGCATGCAATCG"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(complementary_dna("ATGCGTACGTTAGC"), "TACGCATGCAATCG")`)
}})
```
`complementary_dna("GGCTTACGATCGAAG")` should return `"CCGAATGCTAGCTTC"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(complementary_dna("GGCTTACGATCGAAG"), "CCGAATGCTAGCTTC")`)
}})
```
`complementary_dna("GATCTAGCTAGGCTAGCTAG")` should return `"CTAGATCGATCCGATCGATC"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(complementary_dna("GATCTAGCTAGGCTAGCTAG"), "CTAGATCGATCCGATCGATC")`)
}})
```
# --seed--
## --seed-contents--
```py
def complementary_dna(strand):
return strand
```
# --solutions--
```py
def complementary_dna(strand):
complements = { "A": "T", "T": "A", "C": "G", "G": "C" }
return "".join(complements[n] for n in strand)
```
@@ -0,0 +1,89 @@
---
id: 68d30845cc08266018fc46bd
title: "Challenge 77: Duration Formatter"
challengeType: 29
dashedName: challenge-77
---
# --description--
Given an integer number of seconds, return a string representing the same duration in the format `"H:MM:SS"`, where `"H"` is the number of hours, `"MM"` is the number of minutes, and `"SS"` is the number of seconds. Return the time using the following rules:
- Seconds: Should always be two digits.
- Minutes: Should omit leading zeros when they aren't needed. Use `"0"` if the duration is less than one minute.
- Hours: Should be included only if they're greater than zero.
# --hints--
`format(500)` should return `"8:20"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(format(500), "8:20")`)
}})
```
`format(4000)` should return `"1:06:40"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(format(4000), "1:06:40")`)
}})
```
`format(1)` should return `"0:01"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(format(1), "0:01")`)
}})
```
`format(5555)` should return `"1:32:35"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(format(5555), "1:32:35")`)
}})
```
`format(99999)` should return `"27:46:39"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(format(99999), "27:46:39")`)
}})
```
# --seed--
## --seed-contents--
```py
def format(seconds):
return seconds
```
# --solutions--
```py
def format(seconds):
h = seconds // 3600
m = (seconds % 3600) // 60
s = seconds % 60
seconds_str = f"{s:02d}"
minutes_str = str(m)
if h > 0:
hours_str = str(h)
return f"{hours_str}:{minutes_str.zfill(2)}:{seconds_str}"
else:
return f"{minutes_str}:{seconds_str}"
```
@@ -0,0 +1,70 @@
---
id: 68d30845cc08266018fc46be
title: "Challenge 78: Integer Sequence"
challengeType: 29
dashedName: challenge-78
---
# --description--
Given a positive integer, return a string with all of the integers from `1` up to, and including, the given number, in numerical order.
For example, given `5`, return `"12345"`.
# --hints--
`sequence(5)` should return `"12345"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(sequence(5), "12345")`)
}})
```
`sequence(10)` should return `"12345678910"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(sequence(10), "12345678910")`)
}})
```
`sequence(1)` should return `"1"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(sequence(1), "1")`)
}})
```
`sequence(27)` should return `"123456789101112131415161718192021222324252627"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(sequence(27), "123456789101112131415161718192021222324252627")`)
}})
```
# --seed--
## --seed-contents--
```py
def sequence(n):
return n
```
# --solutions--
```py
def sequence(n):
result = ""
for i in range(1, n + 1):
result += str(i)
return result
```
@@ -0,0 +1,115 @@
---
id: 68d30fc57588d97fd3027b30
title: "Challenge 79: Navigator"
challengeType: 29
dashedName: challenge-79
---
# --description--
On October 28, 1994, Netscape Navigator was released, helping millions explore the early web.
Given an array of browser commands you executed on Netscape Navigator, return the current page you are on after executing all the commands using the following rules:
- You always start on the `"Home"` page, which will not be included in the commands array.
- Valid commands are:
- `"Visit Page"`: Where `"Page"` is the name of the page you are visiting. For example, `"Visit About"` takes you to the `"About"` page. When you visit a new page, make sure to discard any forward history you have.
- `"Back"`: Takes you to the previous page in your history or stays on the current page if there isn't one.
- `"Forward"`: Takes you forward in the history to the page you came from or stays on the current page if there isn't one.
For example, given `["Visit About Us", "Back", "Forward"]`, return `"About Us"`.
# --hints--
`navigate(["Visit About Us", "Back", "Forward"])` should return `"About Us"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(navigate(["Visit About Us", "Back", "Forward"]), "About Us")`)
}})
```
`navigate(["Forward"])` should return `"Home"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(navigate(["Forward"]), "Home")`)
}})
```
`navigate(["Back"])` should return `"Home"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(navigate(["Back"]), "Home")`)
}})
```
`navigate(["Visit About Us", "Visit Gallery"])` should return `"Gallery"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(navigate(["Visit About Us", "Visit Gallery"]), "Gallery")`)
}})
```
`navigate(["Visit About Us", "Visit Gallery", "Back", "Back"])` should return `"Home"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(navigate(["Visit About Us", "Visit Gallery", "Back", "Back"]), "Home")`)
}})
```
`navigate(["Visit About", "Visit Gallery", "Back", "Visit Contact", "Forward"])` should return `"Contact"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(navigate(["Visit About", "Visit Gallery", "Back", "Visit Contact", "Forward"]), "Contact")`)
}})
```
`navigate(["Visit About Us", "Visit Visit Us", "Forward", "Visit Contact Us", "Back"])` should return `"Visit Us"`.
```js
({test: () => { runPython(`
from unittest import TestCase
TestCase().assertEqual(navigate(["Visit About Us", "Visit Visit Us", "Forward", "Visit Contact Us", "Back"]), "Visit Us")`)
}})
```
# --seed--
## --seed-contents--
```py
def navigate(commands):
return commands
```
# --solutions--
```py
def navigate(commands):
history = ["Home"]
current_index = 0
for command in commands:
if command.startswith("Visit "):
history = history[:current_index + 1]
history.append(command[6:])
current_index += 1
elif command == "Back" and current_index > 0:
current_index -= 1
elif command == "Forward" and current_index < len(history) - 1:
current_index += 1
return history[current_index]
```
@@ -254,6 +254,74 @@
{
"id": "68c497f3aaefc9fd9f1b0e26",
"title": "Challenge 62: Hex to Decimal"
},
{
"id": "68cae5b538ff798bbd4da001",
"title": "Challenge 63: Battle of Words"
},
{
"id": "68cae5b538ff798bbd4da002",
"title": "Challenge 64: 24 to 12"
},
{
"id": "68cae5b538ff798bbd4da003",
"title": "Challenge 65: String Count"
},
{
"id": "68cae5b538ff798bbd4da004",
"title": "Challenge 66: HTML Tag Stripper"
},
{
"id": "68cae5b538ff798bbd4da005",
"title": "Challenge 67: Email Validator"
},
{
"id": "68cae5b538ff798bbd4da006",
"title": "Challenge 68: Credit Card Masker"
},
{
"id": "68cae5b538ff798bbd4da007",
"title": "Challenge 69: Missing Socks"
},
{
"id": "68cae5b538ff798bbd4da008",
"title": "Challenge 70: HTML Attribute Extractor"
},
{
"id": "68cae5b538ff798bbd4da009",
"title": "Challenge 71: Tip Calculator"
},
{
"id": "68cae5b538ff798bbd4da00a",
"title": "Challenge 72: Thermostat Adjuster 2"
},
{
"id": "68d2ba1468508398389487ce",
"title": "Challenge 73: Speak Wisely, You Must"
},
{
"id": "68d2ba1468508398389487cf",
"title": "Challenge 74: Favorite Songs"
},
{
"id": "68d2ba1468508398389487d0",
"title": "Challenge 75: Missile Strike"
},
{
"id": "68d30845cc08266018fc46bc",
"title": "Challenge 76: Complementary DNA"
},
{
"id": "68d30845cc08266018fc46bd",
"title": "Challenge 77: Duration Formatter"
},
{
"id": "68d30845cc08266018fc46be",
"title": "Challenge 78: Integer Sequence"
},
{
"id": "68d30fc57588d97fd3027b30",
"title": "Challenge 79: Navigator"
}
]
}
@@ -253,6 +253,74 @@
{
"id": "68c497f3aaefc9fd9f1b0e26",
"title": "Challenge 62: Hex to Decimal"
},
{
"id": "68cae5b538ff798bbd4da001",
"title": "Challenge 63: Battle of Words"
},
{
"id": "68cae5b538ff798bbd4da002",
"title": "Challenge 64: 24 to 12"
},
{
"id": "68cae5b538ff798bbd4da003",
"title": "Challenge 65: String Count"
},
{
"id": "68cae5b538ff798bbd4da004",
"title": "Challenge 66: HTML Tag Stripper"
},
{
"id": "68cae5b538ff798bbd4da005",
"title": "Challenge 67: Email Validator"
},
{
"id": "68cae5b538ff798bbd4da006",
"title": "Challenge 68: Credit Card Masker"
},
{
"id": "68cae5b538ff798bbd4da007",
"title": "Challenge 69: Missing Socks"
},
{
"id": "68cae5b538ff798bbd4da008",
"title": "Challenge 70: HTML Attribute Extractor"
},
{
"id": "68cae5b538ff798bbd4da009",
"title": "Challenge 71: Tip Calculator"
},
{
"id": "68cae5b538ff798bbd4da00a",
"title": "Challenge 72: Thermostat Adjuster 2"
},
{
"id": "68d2ba1468508398389487ce",
"title": "Challenge 73: Speak Wisely, You Must"
},
{
"id": "68d2ba1468508398389487cf",
"title": "Challenge 74: Favorite Songs"
},
{
"id": "68d2ba1468508398389487d0",
"title": "Challenge 75: Missile Strike"
},
{
"id": "68d30845cc08266018fc46bc",
"title": "Challenge 76: Complementary DNA"
},
{
"id": "68d30845cc08266018fc46bd",
"title": "Challenge 77: Duration Formatter"
},
{
"id": "68d30845cc08266018fc46be",
"title": "Challenge 78: Integer Sequence"
},
{
"id": "68d30fc57588d97fd3027b30",
"title": "Challenge 79: Navigator"
}
]
}
@@ -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 = 62;
const EXPECTED_CHALLENGE_COUNT = 79;
// 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)**