mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-04-11 07:00:41 -04:00
chore(i18n,learn): processed translations (#54848)
This commit is contained in:
committed by
GitHub
parent
d137a037e6
commit
7e1823dcf0
@@ -26,7 +26,7 @@ Here's an example:
|
||||
|
||||
# --instructions--
|
||||
|
||||
حان الوقت لأخذ استراحة من Camper Cat و مقابلة الزميل camper Zersiax (@zersiax), بطل ال accessibility و مستخدم لتقنية قارئ الشاشة (screen reader). To hear a clip of his screen reader in action, add an `audio` element after the `p` element. Include the `controls` attribute. Then place a `source` element inside the `audio` tags with the `src` attribute set to `https://s3.amazonaws.com/freecodecamp/screen-reader.mp3` and `type` attribute set to `"audio/mpeg"`.
|
||||
حان الوقت لأخذ استراحة من Camper Cat و مقابلة الزميل camper Zersiax (@zersiax), بطل ال accessibility و مستخدم لتقنية قارئ الشاشة (screen reader). To hear a clip of his screen reader in action, add an `audio` element after the `p` element. Include the `controls` attribute. Then place a `source` element inside the `audio` tags with the `src` attribute set to `https://cdn.freecodecamp.org/curriculum/applied-accessibility/screen-reader.mp3` and `type` attribute set to `"audio/mpeg"`.
|
||||
|
||||
**Note:** The audio clip may sound fast and be difficult to understand, but that is a normal speed for screen reader users.
|
||||
|
||||
@@ -70,7 +70,7 @@ The value for the `src` attribute on the `source` tag should match the link in t
|
||||
```js
|
||||
assert(
|
||||
$('source').attr('src') ===
|
||||
'https://s3.amazonaws.com/freecodecamp/screen-reader.mp3'
|
||||
'https://cdn.freecodecamp.org/curriculum/applied-accessibility/screen-reader.mp3'
|
||||
);
|
||||
```
|
||||
|
||||
@@ -108,7 +108,7 @@ assert($('source').attr('type') === 'audio/mpeg');
|
||||
<main>
|
||||
<p>A sound clip of Zersiax's screen reader in action.</p>
|
||||
<audio controls>
|
||||
<source src="https://s3.amazonaws.com/freecodecamp/screen-reader.mp3" type="audio/mpeg"/>
|
||||
<source src="https://cdn.freecodecamp.org/curriculum/applied-accessibility/screen-reader.mp3" type="audio/mpeg"/>
|
||||
</audio>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
@@ -93,7 +93,7 @@ assert($('.profile-name').css('flex-direction') == 'column');
|
||||
}
|
||||
</style>
|
||||
<header>
|
||||
<img src="https://freecodecamp.s3.amazonaws.com/quincy-twitter-photo.jpg" alt="Quincy Larson's profile picture" class="profile-thumbnail">
|
||||
<img src="https://cdn.freecodecamp.org/curriculum/legacy-css-flexbox/quincy-twitter-photo.jpg" alt="Quincy Larson's profile picture" class="profile-thumbnail">
|
||||
<div class="profile-name">
|
||||
<h3>Quincy Larson</h3>
|
||||
<h4>@ossia</h4>
|
||||
@@ -186,7 +186,7 @@ assert($('.profile-name').css('flex-direction') == 'column');
|
||||
}
|
||||
</style>
|
||||
<header>
|
||||
<img src="https://freecodecamp.s3.amazonaws.com/quincy-twitter-photo.jpg" alt="Quincy Larson's profile picture" class="profile-thumbnail">
|
||||
<img src="https://cdn.freecodecamp.org/curriculum/legacy-css-flexbox/quincy-twitter-photo.jpg" alt="Quincy Larson's profile picture" class="profile-thumbnail">
|
||||
<div class="profile-name">
|
||||
<h3>Quincy Larson</h3>
|
||||
<h4>@ossia</h4>
|
||||
|
||||
@@ -102,7 +102,7 @@ assert(code.match(/footer\s*?{[^}]*?flex-direction:\s*?row;/g));
|
||||
}
|
||||
</style>
|
||||
<header>
|
||||
<img src="https://freecodecamp.s3.amazonaws.com/quincy-twitter-photo.jpg" alt="Quincy Larson's profile picture" class="profile-thumbnail">
|
||||
<img src="https://cdn.freecodecamp.org/curriculum/legacy-css-flexbox/quincy-twitter-photo.jpg" alt="Quincy Larson's profile picture" class="profile-thumbnail">
|
||||
<div class="profile-name">
|
||||
<h3>Quincy Larson</h3>
|
||||
<h4>@ossia</h4>
|
||||
@@ -198,7 +198,7 @@ assert(code.match(/footer\s*?{[^}]*?flex-direction:\s*?row;/g));
|
||||
}
|
||||
</style>
|
||||
<header>
|
||||
<img src="https://freecodecamp.s3.amazonaws.com/quincy-twitter-photo.jpg" alt="Quincy Larson's profile picture" class="profile-thumbnail">
|
||||
<img src="https://cdn.freecodecamp.org/curriculum/legacy-css-flexbox/quincy-twitter-photo.jpg" alt="Quincy Larson's profile picture" class="profile-thumbnail">
|
||||
<div class="profile-name">
|
||||
<h3>Quincy Larson</h3>
|
||||
<h4>@ossia</h4>
|
||||
|
||||
@@ -95,7 +95,7 @@ assert($('.follow-btn').css('align-items') == 'center');
|
||||
}
|
||||
</style>
|
||||
<header>
|
||||
<img src="https://freecodecamp.s3.amazonaws.com/quincy-twitter-photo.jpg" alt="Quincy Larson's profile picture" class="profile-thumbnail">
|
||||
<img src="https://cdn.freecodecamp.org/curriculum/legacy-css-flexbox/quincy-twitter-photo.jpg" alt="Quincy Larson's profile picture" class="profile-thumbnail">
|
||||
<div class="profile-name">
|
||||
<h3>Quincy Larson</h3>
|
||||
<h4>@ossia</h4>
|
||||
@@ -190,7 +190,7 @@ assert($('.follow-btn').css('align-items') == 'center');
|
||||
}
|
||||
</style>
|
||||
<header>
|
||||
<img src="https://freecodecamp.s3.amazonaws.com/quincy-twitter-photo.jpg" alt="Quincy Larson's profile picture" class="profile-thumbnail">
|
||||
<img src="https://cdn.freecodecamp.org/curriculum/legacy-css-flexbox/quincy-twitter-photo.jpg" alt="Quincy Larson's profile picture" class="profile-thumbnail">
|
||||
<div class="profile-name">
|
||||
<h3>Quincy Larson</h3>
|
||||
<h4>@ossia</h4>
|
||||
|
||||
@@ -98,7 +98,7 @@ assert(
|
||||
}
|
||||
</style>
|
||||
<header>
|
||||
<img src="https://freecodecamp.s3.amazonaws.com/quincy-twitter-photo.jpg" alt="Quincy Larson's profile picture" class="profile-thumbnail">
|
||||
<img src="https://cdn.freecodecamp.org/curriculum/legacy-css-flexbox/quincy-twitter-photo.jpg" alt="Quincy Larson's profile picture" class="profile-thumbnail">
|
||||
<div class="profile-name">
|
||||
<h3>Quincy Larson</h3>
|
||||
<h4>@ossia</h4>
|
||||
@@ -192,7 +192,7 @@ assert(
|
||||
}
|
||||
</style>
|
||||
<header>
|
||||
<img src="https://freecodecamp.s3.amazonaws.com/quincy-twitter-photo.jpg" alt="Quincy Larson's profile picture" class="profile-thumbnail">
|
||||
<img src="https://cdn.freecodecamp.org/curriculum/legacy-css-flexbox/quincy-twitter-photo.jpg" alt="Quincy Larson's profile picture" class="profile-thumbnail">
|
||||
<div class="profile-name">
|
||||
<h3>Quincy Larson</h3>
|
||||
<h4>@ossia</h4>
|
||||
|
||||
@@ -0,0 +1,887 @@
|
||||
---
|
||||
id: 5e44413e903586ffb414c94e
|
||||
title: Build a Budget App Project
|
||||
challengeType: 23
|
||||
forumTopicId: 462361
|
||||
dashedName: build-a-budget-app-project
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Complete the `Category` class. It should be able to instantiate objects based on different budget categories like *food*, *clothing*, and *entertainment*. When objects are created, they are passed in the name of the category. The class should have an instance variable called `ledger` that is a list. The class should also contain the following methods:
|
||||
|
||||
- A `deposit` method that accepts an amount and description. If no description is given, it should default to an empty string. The method should append an object to the ledger list in the form of `{"amount": amount, "description": description}`.
|
||||
- A `withdraw` method that is similar to the `deposit` method, but the amount passed in should be stored in the ledger as a negative number. If there are not enough funds, nothing should be added to the ledger. This method should return `True` if the withdrawal took place, and `False` otherwise.
|
||||
- A `get_balance` method that returns the current balance of the budget category based on the deposits and withdrawals that have occurred.
|
||||
- A `transfer` method that accepts an amount and another budget category as arguments. The method should add a withdrawal with the amount and the description "Transfer to [Destination Budget Category]". The method should then add a deposit to the other budget category with the amount and the description "Transfer from [Source Budget Category]". If there are not enough funds, nothing should be added to either ledgers. This method should return `True` if the transfer took place, and `False` otherwise.
|
||||
- A `check_funds` method that accepts an amount as an argument. It returns `False` if the amount is greater than the balance of the budget category and returns `True` otherwise. This method should be used by both the `withdraw` method and `transfer` method.
|
||||
|
||||
When the budget object is printed it should display:
|
||||
|
||||
- A title line of 30 characters where the name of the category is centered in a line of `*` characters.
|
||||
- A list of the items in the ledger. Each line should show the description and amount. The first 23 characters of the description should be displayed, then the amount. The amount should be right aligned, contain two decimal places, and display a maximum of 7 characters.
|
||||
- A line displaying the category total.
|
||||
|
||||
Here is an example usage:
|
||||
|
||||
```py
|
||||
food = Category("Food")
|
||||
food.deposit(1000, "deposit")
|
||||
food.withdraw(10.15, "groceries")
|
||||
food.withdraw(15.89, "restaurant and more food for dessert")
|
||||
clothing = Category("Clothing")
|
||||
food.transfer(50, clothing)
|
||||
print(food)
|
||||
```
|
||||
|
||||
And here is an example of the output:
|
||||
|
||||
```bash
|
||||
*************Food*************
|
||||
initial deposit 1000.00
|
||||
groceries -10.15
|
||||
restaurant and more foo -15.89
|
||||
Transfer to Clothing -50.00
|
||||
Total: 923.96
|
||||
```
|
||||
|
||||
Besides the `Category` class, create a function (outside of the class) called `create_spend_chart` that takes a list of categories as an argument. It should return a string that is a bar chart.
|
||||
|
||||
The chart should show the percentage spent in each category passed in to the function. The percentage spent should be calculated only with withdrawals and not with deposits. Down the left side of the chart should be labels 0 - 100. The "bars" in the bar chart should be made out of the "o" character. The height of each bar should be rounded down to the nearest 10. The horizontal line below the bars should go two spaces past the final bar. Each category name should be written vertically below the bar. There should be a title at the top that says "Percentage spent by category".
|
||||
|
||||
This function will be tested with up to four categories.
|
||||
|
||||
Look at the example output below very closely and make sure the spacing of the output matches the example exactly.
|
||||
|
||||
```bash
|
||||
Percentage spent by category
|
||||
100|
|
||||
90|
|
||||
80|
|
||||
70|
|
||||
60| o
|
||||
50| o
|
||||
40| o
|
||||
30| o
|
||||
20| o o
|
||||
10| o o o
|
||||
0| o o o
|
||||
----------
|
||||
F C A
|
||||
o l u
|
||||
o o t
|
||||
d t o
|
||||
h
|
||||
i
|
||||
n
|
||||
g
|
||||
```
|
||||
|
||||
# --hints--
|
||||
|
||||
The `deposit` method should create a specific object in the ledger instance variable.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/budget.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import budget
|
||||
from importlib import reload
|
||||
|
||||
reload(budget)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.food = budget.Category("Food")
|
||||
|
||||
def test_deposit(self):
|
||||
self.food.deposit(900, "deposit")
|
||||
actual = self.food.ledger[0]
|
||||
expected = {"amount": 900, "description": "deposit"}
|
||||
self.assertEqual(actual, expected, 'Expected "deposit" method to create a specific object in the ledger instance variable.')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Calling the `deposit` method with no description should create a blank description.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/budget.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import budget
|
||||
from importlib import reload
|
||||
|
||||
reload(budget)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.food = budget.Category("Food")
|
||||
|
||||
def test_deposit_no_description(self):
|
||||
self.food.deposit(45.56)
|
||||
actual = self.food.ledger[0]
|
||||
expected = {"amount": 45.56, "description": ""}
|
||||
self.assertEqual(actual, expected, 'Expected calling "deposit" method with no description to create a blank description.')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `withdraw` method should create a specific object in the `ledger` instance variable.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/budget.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import budget
|
||||
from importlib import reload
|
||||
|
||||
reload(budget)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.food = budget.Category("Food")
|
||||
|
||||
def test_withdraw(self):
|
||||
self.food.deposit(900, "deposit")
|
||||
self.food.withdraw(45.67, "milk, cereal, eggs, bacon, bread")
|
||||
actual = self.food.ledger[1]
|
||||
expected = {"amount": -45.67, "description": "milk, cereal, eggs, bacon, bread"}
|
||||
self.assertEqual(actual, expected, 'Expected "withdraw" method to create a specific object in the ledger instance variable.')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Calling the `withdraw` method with no description should create a blank description.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/budget.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import budget
|
||||
from importlib import reload
|
||||
|
||||
reload(budget)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.food = budget.Category("Food")
|
||||
|
||||
def test_withdraw_no_description(self):
|
||||
self.food.deposit(900, "deposit")
|
||||
good_withdraw = self.food.withdraw(45.67)
|
||||
actual = self.food.ledger[1]
|
||||
expected = {"amount": -45.67, "description": ""}
|
||||
self.assertEqual(actual, expected, 'Expected "withdraw" method with no description to create a blank description.')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `withdraw` method should return `True` if the withdrawal took place.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/budget.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import budget
|
||||
from importlib import reload
|
||||
|
||||
reload(budget)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.food = budget.Category("Food")
|
||||
|
||||
def test_withdraw_no_description(self):
|
||||
self.food.deposit(900, "deposit")
|
||||
good_withdraw = self.food.withdraw(45.67)
|
||||
self.assertEqual(good_withdraw, True, 'Expected "withdraw" method to return "True".')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Calling `food.deposit(900, "deposit")` and `food.withdraw(45.67, "milk, cereal, eggs, bacon, bread")` should return a balance of `854.33`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/budget.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import budget
|
||||
from importlib import reload
|
||||
|
||||
reload(budget)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.food = budget.Category("Food")
|
||||
|
||||
def test_get_balance(self):
|
||||
self.food.deposit(900, "deposit")
|
||||
self.food.withdraw(45.67, "milk, cereal, eggs, bacon, bread")
|
||||
actual = self.food.get_balance()
|
||||
expected = 854.33
|
||||
self.assertEqual(actual, expected, 'Expected balance to be 854.33')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Calling the `transfer` method on a category object should create a specific ledger item in that category object.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/budget.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import budget
|
||||
from importlib import reload
|
||||
|
||||
reload(budget)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.food = budget.Category("Food")
|
||||
self.entertainment = budget.Category("Entertainment")
|
||||
|
||||
def test_transfer(self):
|
||||
self.food.deposit(900, "deposit")
|
||||
self.food.withdraw(45.67, "milk, cereal, eggs, bacon, bread")
|
||||
transfer_amount = 20
|
||||
good_transfer = self.food.transfer(transfer_amount, self.entertainment)
|
||||
actual = self.food.ledger[2]
|
||||
expected = {"amount": -transfer_amount, "description": "Transfer to Entertainment"}
|
||||
self.assertEqual(actual, expected, 'Expected "transfer" method to create a specific ledger item in food object.')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `transfer` method should return `True` if the transfer took place.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/budget.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import budget
|
||||
from importlib import reload
|
||||
|
||||
reload(budget)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.food = budget.Category("Food")
|
||||
self.entertainment = budget.Category("Entertainment")
|
||||
|
||||
def test_transfer(self):
|
||||
self.food.deposit(900, "deposit")
|
||||
self.food.withdraw(45.67, "milk, cereal, eggs, bacon, bread")
|
||||
transfer_amount = 20
|
||||
good_transfer = self.food.transfer(transfer_amount, self.entertainment)
|
||||
self.assertEqual(good_transfer, True, 'Expected "transfer" method to return "True".')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Calling `transfer` on a category object should reduce the balance in the category object.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/budget.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import budget
|
||||
from importlib import reload
|
||||
|
||||
reload(budget)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.food = budget.Category("Food")
|
||||
self.entertainment = budget.Category("Entertainment")
|
||||
|
||||
def test_transfer(self):
|
||||
self.food.deposit(900, "deposit")
|
||||
self.food.withdraw(45.67, "milk, cereal, eggs, bacon, bread")
|
||||
transfer_amount = 20
|
||||
food_balance_before = self.food.get_balance()
|
||||
good_transfer = self.food.transfer(transfer_amount, self.entertainment)
|
||||
food_balance_after = self.food.get_balance()
|
||||
self.assertEqual(food_balance_before - food_balance_after, transfer_amount, 'Expected "transfer" method to reduce balance in food object.')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `transfer` method should increase the balance of the category object passed as its argument.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/budget.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import budget
|
||||
from importlib import reload
|
||||
|
||||
reload(budget)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.food = budget.Category("Food")
|
||||
self.entertainment = budget.Category("Entertainment")
|
||||
|
||||
def test_transfer(self):
|
||||
self.food.deposit(900, "deposit")
|
||||
self.food.withdraw(45.67, "milk, cereal, eggs, bacon, bread")
|
||||
transfer_amount = 20
|
||||
entertainment_balance_before = self.entertainment.get_balance()
|
||||
good_transfer = self.food.transfer(transfer_amount, self.entertainment)
|
||||
entertainment_balance_after = self.entertainment.get_balance()
|
||||
self.assertEqual(entertainment_balance_after - entertainment_balance_before, transfer_amount, 'Expected "transfer" method to increase balance in entertainment object.')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `transfer` method should create a specific ledger item in the category object passed as its argument.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/budget.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import budget
|
||||
from importlib import reload
|
||||
|
||||
reload(budget)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.food = budget.Category("Food")
|
||||
self.entertainment = budget.Category("Entertainment")
|
||||
|
||||
def test_transfer(self):
|
||||
self.food.deposit(900, "deposit")
|
||||
self.food.withdraw(45.67, "milk, cereal, eggs, bacon, bread")
|
||||
transfer_amount = 20
|
||||
good_transfer = self.food.transfer(transfer_amount, self.entertainment)
|
||||
actual = self.entertainment.ledger[0]
|
||||
expected = {"amount": transfer_amount, "description": "Transfer from Food"}
|
||||
self.assertEqual(actual, expected, 'Expected "transfer" method to create a specific ledger item in entertainment object.')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `check_funds` method should return `False` if the amount passed to the method is greater than the category balance.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/budget.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import budget
|
||||
from importlib import reload
|
||||
|
||||
reload(budget)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.food = budget.Category("Food")
|
||||
|
||||
def test_check_funds(self):
|
||||
self.food.deposit(10, "deposit")
|
||||
actual = self.food.check_funds(20)
|
||||
expected = False
|
||||
self.assertEqual(actual, expected, 'Expected "check_funds" method to be False')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `check_funds` method should return `True` if the amount passed to the method is not greater than the category balance.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/budget.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import budget
|
||||
from importlib import reload
|
||||
|
||||
reload(budget)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.food = budget.Category("Food")
|
||||
|
||||
def test_check_funds(self):
|
||||
self.food.deposit(10, "deposit")
|
||||
actual = self.food.check_funds(10)
|
||||
expected = True
|
||||
self.assertEqual(actual, expected, 'Expected "check_funds" method to be True')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `withdraw` method should return `False` if the withdrawal didn't take place.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/budget.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import budget
|
||||
from importlib import reload
|
||||
|
||||
reload(budget)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.food = budget.Category("Food")
|
||||
|
||||
def test_withdraw_no_funds(self):
|
||||
self.food.deposit(100, "deposit")
|
||||
good_withdraw = self.food.withdraw(100.10)
|
||||
self.assertEqual(good_withdraw, False, 'Expected "withdraw" method to return "False".')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `transfer` method should return `False` if the transfer didn't take place.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/budget.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import budget
|
||||
from importlib import reload
|
||||
|
||||
reload(budget)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.food = budget.Category("Food")
|
||||
self.entertainment = budget.Category("Entertainment")
|
||||
|
||||
def test_transfer_no_funds(self):
|
||||
self.food.deposit(100, "deposit")
|
||||
good_transfer = self.food.transfer(200, self.entertainment)
|
||||
self.assertEqual(good_transfer, False, 'Expected "transfer" method to return "False".')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Printing a `Category` instance should give a different string representation of the object.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/budget.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import budget
|
||||
from importlib import reload
|
||||
|
||||
reload(budget)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.food = budget.Category("Food")
|
||||
self.entertainment = budget.Category("Entertainment")
|
||||
|
||||
def test_to_string(self):
|
||||
self.food.deposit(900, "deposit")
|
||||
self.food.withdraw(45.67, "milk, cereal, eggs, bacon, bread")
|
||||
self.food.transfer(20, self.entertainment)
|
||||
actual = str(self.food)
|
||||
expected = "*************Food*************\\ndeposit 900.00\\nmilk, cereal, eggs, bac -45.67\\nTransfer to Entertainme -20.00\\nTotal: 834.33"
|
||||
self.assertEqual(actual, expected, 'Expected different string representation of object.')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`create_spend_chart` should print a different chart representation. Check that all spacing is exact.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/budget.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import budget
|
||||
from importlib import reload
|
||||
|
||||
reload(budget)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.food = budget.Category("Food")
|
||||
self.entertainment = budget.Category("Entertainment")
|
||||
self.business = budget.Category("Business")
|
||||
|
||||
def test_create_spend_chart(self):
|
||||
self.food.deposit(900, "deposit")
|
||||
self.entertainment.deposit(900, "deposit")
|
||||
self.business.deposit(900, "deposit")
|
||||
self.food.withdraw(105.55)
|
||||
self.entertainment.withdraw(33.40)
|
||||
self.business.withdraw(10.99)
|
||||
actual = budget.create_spend_chart([self.business, self.food, self.entertainment])
|
||||
expected = "Percentage spent by category\\n100| \\n 90| \\n 80| \\n 70| o \\n 60| o \\n 50| o \\n 40| o \\n 30| o \\n 20| o o \\n 10| o o \\n 0| o o o \\n ----------\\n B F E \\n u o n \\n s o t \\n i d e \\n n r \\n e t \\n s a \\n s i \\n n \\n m \\n e \\n n \\n t "
|
||||
self.assertEqual(actual, expected, 'Expected different chart representation. Check that all spacing is exact.')
|
||||
`);
|
||||
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Category:
|
||||
pass
|
||||
|
||||
def create_spend_chart(categories):
|
||||
pass
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```py
|
||||
class Category:
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.ledger = []
|
||||
self.balance = 0
|
||||
self.spent = 0
|
||||
|
||||
def __str__(self):
|
||||
first_line = f'{self.name.center(30, "*")}\n'
|
||||
lines = ''
|
||||
total = f'Total: {format(self.balance, ".2f")}'
|
||||
|
||||
for n in range(len(self.ledger)):
|
||||
descr = self.ledger[n]["description"][:23]
|
||||
am = format(float(self.ledger[n]["amount"]), ".2f")[:7]
|
||||
lines = lines + f'{descr:<23}{am:>7}\n'
|
||||
|
||||
return f'{first_line}{lines}{total}'
|
||||
|
||||
def deposit(self, amount, description=''):
|
||||
self.ledger.append({
|
||||
'amount': float(amount),
|
||||
'description': description
|
||||
})
|
||||
self.balance = self.balance + float(amount)
|
||||
|
||||
def withdraw(self, amount, description=''):
|
||||
if self.check_funds(amount):
|
||||
self.ledger.append({
|
||||
'amount': -float(amount),
|
||||
'description': description
|
||||
})
|
||||
self.balance = self.balance - float(amount)
|
||||
self.spent = self.spent + float(amount)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def get_balance(self):
|
||||
return self.balance
|
||||
|
||||
def transfer(self, amount, category):
|
||||
if self.check_funds(amount):
|
||||
# withdraw
|
||||
self.ledger.append({
|
||||
'amount': -float(amount),
|
||||
'description': f'Transfer to {category.name}'
|
||||
})
|
||||
self.balance = self.balance - float(amount)
|
||||
# deposit
|
||||
category.deposit(amount, f'Transfer from {self.name}')
|
||||
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def check_funds(self, amount):
|
||||
if float(amount) > self.balance:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
|
||||
def create_spend_chart(categories):
|
||||
total_expenses = 0
|
||||
obj = {}
|
||||
col1 = []
|
||||
str = []
|
||||
final_str = 'Percentage spent by category\n'
|
||||
label_max_length = 0
|
||||
label_strings = []
|
||||
|
||||
for category in categories:
|
||||
total_expenses = total_expenses + category.spent
|
||||
obj[category.name] = {'expenses': category.spent}
|
||||
obj[category.name]['label'] = list(category.name)
|
||||
if len(obj[category.name]['label']) > label_max_length:
|
||||
label_max_length = len(obj[category.name]['label'])
|
||||
|
||||
for category in categories:
|
||||
obj[category.name]['percent'] = (
|
||||
(category.spent / total_expenses * 100) // 10) * 10
|
||||
obj[category.name]['column'] = []
|
||||
for i in range(0, 110, 10):
|
||||
if obj[category.name]['percent'] >= i:
|
||||
obj[category.name]['column'].insert(0, 'o')
|
||||
else:
|
||||
obj[category.name]['column'].insert(0, ' ')
|
||||
|
||||
for i in range(0, 110, 10):
|
||||
col1.insert(0, i)
|
||||
|
||||
for i in range(11):
|
||||
str.append("")
|
||||
for key in obj:
|
||||
str[i] += (f'{obj[key]["column"][i]} ')
|
||||
final_str += f'{col1[i]:>3}| {str[i]}\n'
|
||||
final_str += f' {"-"*(1+3*len(obj))}\n '
|
||||
|
||||
for i in range(label_max_length):
|
||||
label_strings.append(' ')
|
||||
for k in obj:
|
||||
if len(obj[k]['label']) < label_max_length:
|
||||
obj[k]['label'].extend(
|
||||
f'{" "*(label_max_length-len(obj[k]["label"]))}')
|
||||
|
||||
label_strings[i] += f'{obj[k]["label"][i]} '
|
||||
if i < label_max_length - 1:
|
||||
label_strings[i] += '\n '
|
||||
final_str += label_strings[i]
|
||||
|
||||
print(final_str)
|
||||
return (final_str)
|
||||
|
||||
```
|
||||
@@ -0,0 +1,869 @@
|
||||
---
|
||||
id: 5e444147903586ffb414c94f
|
||||
title: Build a Polygon Area Calculator Project
|
||||
challengeType: 23
|
||||
forumTopicId: 462363
|
||||
dashedName: build-a-polygon-area-calculator-project
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
In this project you will use object oriented programming to create a `Rectangle` class and a `Square` class. The `Square` class should be a subclass of `Rectangle`, and inherit its methods and attributes.
|
||||
|
||||
## Rectangle class
|
||||
|
||||
When a Rectangle object is created, it should be initialized with `width` and `height` attributes. The class should also contain the following methods:
|
||||
|
||||
- `set_width`
|
||||
- `set_height`
|
||||
- `get_area`: Returns area (`width * height`)
|
||||
- `get_perimeter`: Returns perimeter (`2 * width + 2 * height`)
|
||||
- `get_diagonal`: Returns diagonal (`(width ** 2 + height ** 2) ** .5`)
|
||||
- `get_picture`: Returns a string that represents the shape using lines of "\*". The number of lines should be equal to the height and the number of "\*" in each line should be equal to the width. There should be a new line (`\n`) at the end of each line. If the width or height is larger than 50, this should return the string: "Too big for picture.".
|
||||
- `get_amount_inside`: Takes another shape (square or rectangle) as an argument. Returns the number of times the passed in shape could fit inside the shape (with no rotations). For instance, a rectangle with a width of 4 and a height of 8 could fit in two squares with sides of 4.
|
||||
|
||||
Additionally, if an instance of a `Rectangle` is represented as a string, it should look like: `Rectangle(width=5, height=10)`
|
||||
|
||||
## Square class
|
||||
|
||||
The `Square` class should be a subclass of `Rectangle`. When a `Square` object is created, a single side length is passed in. The `__init__` method should store the side length in both the `width` and `height` attributes from the `Rectangle` class.
|
||||
|
||||
The `Square` class should be able to access the `Rectangle` class methods but should also contain a `set_side` method. If an instance of a `Square` is represented as a string, it should look like: `Square(side=9)`
|
||||
|
||||
Additionally, the `set_width` and `set_height` methods on the `Square` class should set both the width and height.
|
||||
|
||||
## Usage example
|
||||
|
||||
```py
|
||||
rect = Rectangle(10, 5)
|
||||
print(rect.get_area())
|
||||
rect.set_height(3)
|
||||
print(rect.get_perimeter())
|
||||
print(rect)
|
||||
print(rect.get_picture())
|
||||
|
||||
sq = Square(9)
|
||||
print(sq.get_area())
|
||||
sq.set_side(4)
|
||||
print(sq.get_diagonal())
|
||||
print(sq)
|
||||
print(sq.get_picture())
|
||||
|
||||
rect.set_height(8)
|
||||
rect.set_width(16)
|
||||
print(rect.get_amount_inside(sq))
|
||||
```
|
||||
|
||||
That code should return:
|
||||
|
||||
```bash
|
||||
50
|
||||
26
|
||||
Rectangle(width=10, height=3)
|
||||
**********
|
||||
**********
|
||||
**********
|
||||
|
||||
81
|
||||
5.656854249492381
|
||||
Square(side=4)
|
||||
****
|
||||
****
|
||||
****
|
||||
****
|
||||
|
||||
8
|
||||
```
|
||||
|
||||
# --hints--
|
||||
|
||||
The `Square` class should be a subclass of the `Rectangle` class.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
|
||||
def test_subclass(self):
|
||||
actual = issubclass(shape_calculator.Square, shape_calculator.Rectangle)
|
||||
expected = True
|
||||
self.assertEqual(actual, expected, 'Expected Square class to be a subclass of the Rectangle class.')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `Square` class should be a distinct class from the `Rectangle` class.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
|
||||
def test_distinct_classes(self):
|
||||
actual = shape_calculator.Square is not shape_calculator.Rectangle
|
||||
expected = True
|
||||
self.assertEqual(actual, expected, 'Expected Square class to be a distinct class from the Rectangle class.')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
A square object should be an instance of the `Square` class and the `Rectangle` class.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.sq = shape_calculator.Square(5)
|
||||
|
||||
def test_square_is_square_and_rectangle(self):
|
||||
actual = isinstance(self.sq, shape_calculator.Square) and isinstance(self.sq, shape_calculator.Rectangle)
|
||||
expected = True
|
||||
self.assertEqual(actual, expected, 'Expected square object to be an instance of the Square class and the Rectangle class.')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The string representation of `Rectangle(3, 6)` should be `Rectangle(width=3, height=6)`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.rect = shape_calculator.Rectangle(3, 6)
|
||||
|
||||
def test_rectangle_string(self):
|
||||
actual = str(self.rect)
|
||||
expected = "Rectangle(width=3, height=6)"
|
||||
self.assertEqual(actual, expected, 'Expected string representation of rectangle to be "Rectangle(width=3, height=6)"')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The string representation of `Square(5)` should be `Square(side=5)`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.sq = shape_calculator.Square(5)
|
||||
|
||||
def test_square_string(self):
|
||||
actual = str(self.sq)
|
||||
expected = "Square(side=5)"
|
||||
self.assertEqual(actual, expected, 'Expected string representation of square to be "Square(side=5)"')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`Rectangle(3, 6).get_area()` should return `18`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.rect = shape_calculator.Rectangle(3, 6)
|
||||
|
||||
def test_area(self):
|
||||
actual = self.rect.get_area()
|
||||
expected = 18
|
||||
self.assertEqual(actual, expected, 'Expected area of rectangle to be 18')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`Square(5).get_area()` should return `25`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.sq = shape_calculator.Square(5)
|
||||
|
||||
def test_area(self):
|
||||
actual = self.sq.get_area()
|
||||
expected = 25
|
||||
self.assertEqual(actual, expected, 'Expected area of square to be 25')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`Rectangle(3, 6).get_perimeter()` should return `18`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.rect = shape_calculator.Rectangle(3, 6)
|
||||
|
||||
def test_perimeter(self):
|
||||
actual = self.rect.get_perimeter()
|
||||
expected = 18
|
||||
self.assertEqual(actual, expected, 'Expected perimeter of rectangle to be 18')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`Square(5).get_perimeter()` should return `20`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.sq = shape_calculator.Square(5)
|
||||
|
||||
def test_perimeter(self):
|
||||
actual = self.sq.get_perimeter()
|
||||
expected = 20
|
||||
self.assertEqual(actual, expected, 'Expected perimeter of square to be 20')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`Rectangle(3, 6).get_diagonal()` should return `6.708203932499369`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.rect = shape_calculator.Rectangle(3, 6)
|
||||
|
||||
def test_diagonal(self):
|
||||
actual = self.rect.get_diagonal()
|
||||
expected = 6.708203932499369
|
||||
self.assertEqual(actual, expected, 'Expected diagonal of rectangle to be 6.708203932499369')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`Square(5).get_diagonal()` should return `7.0710678118654755`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.sq = shape_calculator.Square(5)
|
||||
|
||||
def test_diagonal(self):
|
||||
actual = self.sq.get_diagonal()
|
||||
expected = 7.0710678118654755
|
||||
self.assertEqual(actual, expected, 'Expected diagonal of square to be 7.0710678118654755')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
An instance of the `Rectangle` class should have a different string representation after setting new values.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.rect = shape_calculator.Rectangle(3, 6)
|
||||
|
||||
def test_set_attributes(self):
|
||||
self.rect.set_width(7)
|
||||
self.rect.set_height(8)
|
||||
actual = str(self.rect)
|
||||
expected = "Rectangle(width=7, height=8)"
|
||||
self.assertEqual(actual, expected, 'Expected string representation of rectangle after setting new values to be "Rectangle(width=7, height=8)"')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
An instance of the `Square` class should have a different string representation after setting new values by using `.set_side()`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.sq = shape_calculator.Square(5)
|
||||
|
||||
def test_set_attributes(self):
|
||||
self.sq.set_side(2)
|
||||
actual = str(self.sq)
|
||||
expected = "Square(side=2)"
|
||||
self.assertEqual(actual, expected, 'Expected string representation of square after setting new values to be "Square(side=2)"')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
An instance of the `Square` class should have a different string representation after setting new values by using `.set_width()` or `set_height()`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.sq = shape_calculator.Square(5)
|
||||
|
||||
def test_set_attributes(self):
|
||||
self.sq.set_height(2)
|
||||
actual = str(self.sq)
|
||||
expected = "Square(side=2)"
|
||||
self.assertEqual(actual, expected, 'Expected string representation of square after setting new values to be "Square(side=2)"')
|
||||
self.sq.set_width(4)
|
||||
actual = str(self.sq)
|
||||
expected = "Square(side=4)"
|
||||
self.assertEqual(actual, expected, 'Expected string representation of square after setting width to be "Square(side=4)"')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `.get_picture()` method should return a different string representation of a `Rectangle` instance.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.rect = shape_calculator.Rectangle(3, 6)
|
||||
|
||||
def test_rectangle_picture(self):
|
||||
self.rect.set_width(7)
|
||||
self.rect.set_height(3)
|
||||
actual = self.rect.get_picture()
|
||||
expected = "*******\\n*******\\n*******\\n"
|
||||
self.assertEqual(actual, expected, 'Expected rectangle picture to be different.')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `.get_picture()` method should return a different string representation of a `Square` instance.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.sq = shape_calculator.Square(5)
|
||||
|
||||
def test_square_picture(self):
|
||||
self.sq.set_side(2)
|
||||
actual = self.sq.get_picture()
|
||||
expected = "**\\n**\\n"
|
||||
self.assertEqual(actual, expected, 'Expected square picture to be different.')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The `.get_picture()` method should return the string `Too big for picture.` if the `width` or `height` attributes are larger than `50`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.rect = shape_calculator.Rectangle(3, 6)
|
||||
|
||||
def test_big_picture(self):
|
||||
self.rect.set_width(51)
|
||||
self.rect.set_height(3)
|
||||
actual = self.rect.get_picture()
|
||||
expected = "Too big for picture."
|
||||
self.assertEqual(actual, expected, 'Expected message: "Too big for picture."')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`Rectangle(15,10).get_amount_inside(Square(5))` should return `6`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.rect = shape_calculator.Rectangle(3, 6)
|
||||
self.sq = shape_calculator.Square(5)
|
||||
|
||||
def test_get_amount_inside(self):
|
||||
self.rect.set_height(10)
|
||||
self.rect.set_width(15)
|
||||
actual = self.rect.get_amount_inside(self.sq)
|
||||
expected = 6
|
||||
self.assertEqual(actual, expected, 'Expected "get_amount_inside" to return 6.')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`Rectangle(4,8).get_amount_inside(Rectangle(3, 6))` should return `1`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.rect = shape_calculator.Rectangle(3, 6)
|
||||
|
||||
def test_get_amount_inside_two_rectangles(self):
|
||||
rect2 = shape_calculator.Rectangle(4, 8)
|
||||
actual = rect2.get_amount_inside(self.rect)
|
||||
expected = 1
|
||||
self.assertEqual(actual, expected, 'Expected "get_amount_inside" to return 1.')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`Rectangle(2,3).get_amount_inside(Rectangle(3, 6))` should return `0`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/shape_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py',`
|
||||
import unittest
|
||||
import shape_calculator
|
||||
from importlib import reload
|
||||
reload(shape_calculator)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def setUp(self):
|
||||
self.rect = shape_calculator.Rectangle(3, 6)
|
||||
|
||||
def test_get_amount_inside_none(self):
|
||||
rect2 = shape_calculator.Rectangle(2, 3)
|
||||
actual = rect2.get_amount_inside(self.rect)
|
||||
expected = 0
|
||||
self.assertEqual(actual, expected, 'Expected "get_amount_inside" to return 0.')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
from importlib import reload
|
||||
import test_module
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
class Rectangle:
|
||||
pass
|
||||
|
||||
class Square:
|
||||
pass
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```py
|
||||
class Rectangle:
|
||||
def __init__(self, width, height):
|
||||
self.width = width
|
||||
self.height = height
|
||||
|
||||
def __str__(self):
|
||||
return f'Rectangle(width={self.width}, height={self.height})'
|
||||
|
||||
def set_width(self, width):
|
||||
self.width = width
|
||||
|
||||
def set_height(self, height):
|
||||
self.height = height
|
||||
|
||||
def get_area(self):
|
||||
area = self.width * self.height
|
||||
return area
|
||||
|
||||
def get_perimeter(self):
|
||||
perimeter = self.width * 2 + self.height * 2
|
||||
return perimeter
|
||||
|
||||
def get_diagonal(self):
|
||||
diagonal = (self.width ** 2 + self.height ** 2) ** 0.5
|
||||
return diagonal
|
||||
|
||||
def get_picture(self):
|
||||
if self.width < 50 and self.height < 50:
|
||||
picture = f'{"*"*self.width}\n'*self.height
|
||||
return picture
|
||||
else:
|
||||
return 'Too big for picture.'
|
||||
|
||||
def get_amount_inside(self, polygon):
|
||||
h_number = self.height // polygon.height
|
||||
w_number = self.width // polygon.width
|
||||
repetition = h_number * w_number
|
||||
return repetition
|
||||
|
||||
|
||||
class Square(Rectangle):
|
||||
def __init__(self, side):
|
||||
self.width = side
|
||||
self.height = side
|
||||
|
||||
def __str__(self):
|
||||
return f'Square(side={self.width})'
|
||||
|
||||
def set_width(self, side):
|
||||
self.width = side
|
||||
self.height = side
|
||||
|
||||
def set_height(self, side):
|
||||
self.height = side
|
||||
self.width = side
|
||||
|
||||
def set_side(self,side):
|
||||
self.width = side
|
||||
self.height = side
|
||||
|
||||
```
|
||||
@@ -0,0 +1,300 @@
|
||||
---
|
||||
id: 5e44414f903586ffb414c950
|
||||
title: Build a Probability Calculator Project
|
||||
challengeType: 23
|
||||
forumTopicId: 462364
|
||||
dashedName: build-a-probability-calculator-project
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Suppose there is a hat containing 5 blue balls, 4 red balls, and 2 green balls. What is the probability that a random draw of 4 balls will contain at least 1 red ball and 2 green balls? While it would be possible to calculate the probability using advanced mathematics, an easier way is to write a program to perform a large number of experiments to estimate an approximate probability.
|
||||
|
||||
For this project, you will write a program to determine the approximate probability of drawing certain balls randomly from a hat.
|
||||
|
||||
First, create a `Hat` class in `main.py`. The class should take a variable number of arguments that specify the number of balls of each color that are in the hat. For example, a class object could be created in any of these ways:
|
||||
|
||||
```py
|
||||
hat1 = Hat(yellow=3, blue=2, green=6)
|
||||
hat2 = Hat(red=5, orange=4)
|
||||
hat3 = Hat(red=5, orange=4, black=1, blue=0, pink=2, striped=9)
|
||||
```
|
||||
|
||||
A hat will always be created with at least one ball. The arguments passed into the hat object upon creation should be converted to a `contents` instance variable. `contents` should be a list of strings containing one item for each ball in the hat. Each item in the list should be a color name representing a single ball of that color. For example, if your hat is `{"red": 2, "blue": 1}`, `contents` should be `["red", "red", "blue"]`.
|
||||
|
||||
The `Hat` class should have a `draw` method that accepts an argument indicating the number of balls to draw from the hat. This method should remove balls at random from `contents` and return those balls as a list of strings. The balls should not go back into the hat during the draw, similar to an urn experiment without replacement. If the number of balls to draw exceeds the available quantity, return all the balls.
|
||||
|
||||
Next, create an `experiment` function in `main.py` (not inside the `Hat` class). This function should accept the following arguments:
|
||||
|
||||
- `hat`: A hat object containing balls that should be copied inside the function.
|
||||
- `expected_balls`: An object indicating the exact group of balls to attempt to draw from the hat for the experiment. For example, to determine the probability of drawing 2 blue balls and 1 red ball from the hat, set `expected_balls` to `{"blue":2, "red":1}`.
|
||||
- `num_balls_drawn`: The number of balls to draw out of the hat in each experiment.
|
||||
- `num_experiments`: The number of experiments to perform. (The more experiments performed, the more accurate the approximate probability will be.)
|
||||
|
||||
The `experiment` function should return a probability.
|
||||
|
||||
For example, if you want to determine the probability of getting at least two red balls and one green ball when you draw five balls from a hat containing six black, four red, and three green. To do this, you will perform `N` experiments, count how many times `M` you get at least two red balls and one green ball, and estimate the probability as `M/N`. Each experiment consists of starting with a hat containing the specified balls, drawing several balls, and checking if you got the balls you were attempting to draw.
|
||||
|
||||
Here is how you would call the `experiment` function based on the example above with 2000 experiments:
|
||||
|
||||
```py
|
||||
hat = Hat(black=6, red=4, green=3)
|
||||
probability = experiment(hat=hat,
|
||||
expected_balls={"red":2,"green":1},
|
||||
num_balls_drawn=5,
|
||||
num_experiments=2000)
|
||||
```
|
||||
|
||||
The output would be something like this:
|
||||
|
||||
```bash
|
||||
0.356
|
||||
```
|
||||
|
||||
Since this is based on random draws, the probability will be slightly different each time the code is run.
|
||||
|
||||
_Hint: Consider using the modules that are already imported at the top. Do not initialize random seed within the file._
|
||||
|
||||
|
||||
# --hints--
|
||||
|
||||
Creation of `hat` object should add correct contents.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile("/home/pyodide/probability_calculator.py", code);
|
||||
pyodide.FS.writeFile(
|
||||
"/home/pyodide/test_module.py",
|
||||
`
|
||||
import unittest
|
||||
import probability_calculator
|
||||
from importlib import reload
|
||||
|
||||
reload(probability_calculator)
|
||||
|
||||
probability_calculator.random.seed(95)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def test_hat_class_contents(self):
|
||||
hat = probability_calculator.Hat(red=3,blue=2)
|
||||
actual = hat.contents
|
||||
expected = ["red","red","red","blue","blue"]
|
||||
self.assertEqual(actual, expected, 'Expected creation of hat object to add correct contents.')
|
||||
`
|
||||
);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
import test_module
|
||||
from importlib import reload
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
The `draw` method in `hat` class should reduce number of items in contents.
|
||||
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile("/home/pyodide/probability_calculator.py", code);
|
||||
pyodide.FS.writeFile(
|
||||
"/home/pyodide/test_module.py",
|
||||
`
|
||||
import unittest
|
||||
import probability_calculator
|
||||
from importlib import reload
|
||||
|
||||
reload(probability_calculator)
|
||||
|
||||
probability_calculator.random.seed(95)
|
||||
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def test_hat_draw(self):
|
||||
hat = probability_calculator.Hat(red=5,blue=2)
|
||||
actual = hat.draw(2)
|
||||
expected = ['blue', 'red']
|
||||
self.assertEqual(actual, expected, 'Expected hat draw to return two random items from hat contents.')
|
||||
actual = len(hat.contents)
|
||||
expected = 5
|
||||
self.assertEqual(actual, expected, 'Expected hat draw to reduce number of items in contents.')
|
||||
`
|
||||
);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
import test_module
|
||||
from importlib import reload
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
The `draw` method should behave correctly when the number of balls to extract is bigger than the number of balls in the hat.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile("/home/pyodide/probability_calculator.py", code);
|
||||
pyodide.FS.writeFile(
|
||||
"/home/pyodide/test_module.py",
|
||||
`
|
||||
import unittest
|
||||
import probability_calculator
|
||||
from importlib import reload
|
||||
|
||||
reload(probability_calculator)
|
||||
|
||||
probability_calculator.random.seed(95)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def test_hat_draw_2(self):
|
||||
hat = probability_calculator.Hat(yellow=5,red=1,green=3,blue=9,test=1)
|
||||
actual = hat.draw(20)
|
||||
expected = ['yellow', 'yellow', 'yellow', 'yellow', 'yellow', 'red', 'green', 'green', 'green', 'blue', 'blue', 'blue', 'blue', 'blue', 'blue', 'blue', 'blue', 'blue', 'test']
|
||||
self.assertEqual(actual, expected, 'Expected hat draw to return all items from hat contents.')
|
||||
actual = len(hat.contents)
|
||||
expected = 0
|
||||
self.assertEqual(actual, expected, 'Expected hat draw to leave no items in contents.')
|
||||
`
|
||||
);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
import test_module
|
||||
from importlib import reload
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
The `experiment` method should return a different probability.
|
||||
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile("/home/pyodide/probability_calculator.py", code);
|
||||
pyodide.FS.writeFile(
|
||||
"/home/pyodide/test_module.py",
|
||||
`
|
||||
import unittest
|
||||
import probability_calculator
|
||||
from importlib import reload
|
||||
|
||||
reload(probability_calculator)
|
||||
|
||||
probability_calculator.random.seed(95)
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def test_prob_experiment(self):
|
||||
hat = probability_calculator.Hat(blue=3,red=2,green=6)
|
||||
probability = probability_calculator.experiment(hat=hat, expected_balls={"blue":2,"green":1}, num_balls_drawn=4, num_experiments=1000)
|
||||
actual = probability
|
||||
expected = 0.272
|
||||
self.assertAlmostEqual(actual, expected, delta = 0.01, msg = 'Expected experiment method to return a different probability.')
|
||||
hat = probability_calculator.Hat(yellow=5,red=1,green=3,blue=9,test=1)
|
||||
probability = probability_calculator.experiment(hat=hat, expected_balls={"yellow":2,"blue":3,"test":1}, num_balls_drawn=20, num_experiments=100)
|
||||
actual = probability
|
||||
expected = 1.0
|
||||
self.assertAlmostEqual(actual, expected, delta = 0.01, msg = 'Expected experiment method to return a different probability.')
|
||||
`
|
||||
);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
import test_module
|
||||
from importlib import reload
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
import copy
|
||||
import random
|
||||
|
||||
class Hat:
|
||||
pass
|
||||
|
||||
def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
|
||||
pass
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```py
|
||||
import copy
|
||||
import random
|
||||
|
||||
class Hat:
|
||||
def __init__(self, **hat):
|
||||
self.hat = hat
|
||||
contents = []
|
||||
for i in hat:
|
||||
for j in range(hat[i]):
|
||||
contents.append(i)
|
||||
self.contents = contents
|
||||
|
||||
|
||||
def draw(self, number):
|
||||
drawn = []
|
||||
if number >= len(self.contents):
|
||||
drawn.extend(self.contents)
|
||||
self.contents = []
|
||||
else:
|
||||
for i in range(number):
|
||||
drawn.append(
|
||||
self.contents.pop(random.randrange(len(self.contents)))
|
||||
)
|
||||
return drawn
|
||||
|
||||
def experiment(hat, expected_balls, num_balls_drawn, num_experiments):
|
||||
expected_balls_list = []
|
||||
drawn_list = []
|
||||
success = 0
|
||||
for i in expected_balls:
|
||||
for j in range(expected_balls[i]):
|
||||
expected_balls_list.append(i)
|
||||
for j in range(num_experiments):
|
||||
hat_copy = copy.deepcopy(hat)
|
||||
drawn_list.append(hat_copy.draw(num_balls_drawn))
|
||||
exp_ball_list_copy = expected_balls_list[:]
|
||||
for k in range(len(drawn_list[j])):
|
||||
try:
|
||||
ind = exp_ball_list_copy.index(drawn_list[j][k])
|
||||
exp_ball_list_copy.pop(ind)
|
||||
except:
|
||||
continue
|
||||
if len(exp_ball_list_copy) == 0:
|
||||
success += 1
|
||||
probability = success/num_experiments
|
||||
return probability
|
||||
```
|
||||
@@ -0,0 +1,582 @@
|
||||
---
|
||||
id: 5e444136903586ffb414c94d
|
||||
title: Build a Time Calculator Project
|
||||
challengeType: 23
|
||||
forumTopicId: 462360
|
||||
dashedName: build-a-time-calculator-project
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Write a function named `add_time` that takes in two required parameters and one optional parameter:
|
||||
|
||||
- a start time in the 12-hour clock format (ending in AM or PM)
|
||||
- a duration time that indicates the number of hours and minutes
|
||||
- (optional) a starting day of the week, case insensitive
|
||||
|
||||
The function should add the duration time to the start time and return the result.
|
||||
|
||||
If the result will be the next day, it should show `(next day)` after the time. If the result will be more than one day later, it should show `(n days later)` after the time, where "n" is the number of days later.
|
||||
|
||||
If the function is given the optional starting day of the week parameter, then the output should display the day of the week of the result. The day of the week in the output should appear after the time and before the number of days later.
|
||||
|
||||
Below are some examples of different cases the function should handle. Pay close attention to the spacing and punctuation of the results.
|
||||
|
||||
```py
|
||||
add_time('3:00 PM', '3:10')
|
||||
# Returns: 6:10 PM
|
||||
|
||||
add_time('11:30 AM', '2:32', 'Monday')
|
||||
# Returns: 2:02 PM, Monday
|
||||
|
||||
add_time('11:43 AM', '00:20')
|
||||
# Returns: 12:03 PM
|
||||
|
||||
add_time('10:10 PM', '3:30')
|
||||
# Returns: 1:40 AM (next day)
|
||||
|
||||
add_time('11:43 PM', '24:20', 'tueSday')
|
||||
# Returns: 12:03 AM, Thursday (2 days later)
|
||||
|
||||
add_time('6:30 PM', '205:12')
|
||||
# Returns: 7:42 AM (9 days later)
|
||||
```
|
||||
|
||||
Do not import any Python libraries. Assume that the start times are valid times. The minutes in the duration time will be a whole number less than 60, but the hour can be any whole number.
|
||||
|
||||
# --hints--
|
||||
Calling `add_time('3:30 PM', '2:12')` should return `'5:42 PM'`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/time_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py', `
|
||||
import unittest
|
||||
import time_calculator
|
||||
from importlib import reload
|
||||
|
||||
reload(time_calculator)
|
||||
|
||||
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def test_same_period(self):
|
||||
actual = time_calculator.add_time("3:30 PM", "2:12")
|
||||
expected = "5:42 PM"
|
||||
self.assertEqual(actual, expected, 'Expected calling "add_time()" with "3:30 PM", "2:12" to return "5:42 PM"')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
import test_module
|
||||
from importlib import reload
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Calling `add_time('11:55 AM', '3:12')` should return `'3:07 PM'`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/time_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py', `
|
||||
import unittest
|
||||
time_calculator
|
||||
from importlib import reload
|
||||
|
||||
reload(time_calculator)
|
||||
|
||||
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def test_different_period(self):
|
||||
actual = time_calculator.add_time("11:55 AM", "3:12")
|
||||
expected = "3:07 PM"
|
||||
self.assertEqual(actual, expected, 'Expected calling "add_time()" with "11:55 AM", "3:12" to return "3:07 PM"')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
import test_module
|
||||
from importlib import reload
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Expected time to end with `'(next day)'` when it is the next day.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/time_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py', `
|
||||
import unittest
|
||||
time_calculator
|
||||
from importlib import reload
|
||||
|
||||
reload(time_calculator)
|
||||
|
||||
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def test_next_day(self):
|
||||
actual = time_calculator.add_time("9:15 PM", "5:30")
|
||||
expected = "2:45 AM (next day)"
|
||||
self.assertEqual(actual, expected, 'Expected time to end with "(next day)" when it is the next day.')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
import test_module
|
||||
from importlib import reload
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Expected period to change from `AM` to `PM` at `12:00`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/time_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py', `
|
||||
import unittest
|
||||
time_calculator
|
||||
from importlib import reload
|
||||
|
||||
reload(time_calculator)
|
||||
|
||||
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def test_period_change_at_twelve(self):
|
||||
actual = time_calculator.add_time("11:40 AM", "0:25")
|
||||
expected = "12:05 PM"
|
||||
self.assertEqual(actual, expected, 'Expected period to change from AM to PM at 12:00')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
import test_module
|
||||
from importlib import reload
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
Calling `add_time('2:59 AM', '24:00')` should return `'2:59 AM (next day)'`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/time_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py', `
|
||||
import unittest
|
||||
time_calculator
|
||||
from importlib import reload
|
||||
|
||||
reload(time_calculator)
|
||||
|
||||
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def test_twenty_four(self):
|
||||
actual = time_calculator.add_time("2:59 AM", "24:00")
|
||||
expected = "2:59 AM (next day)"
|
||||
self.assertEqual(actual, expected, 'Expected calling "add_time()" with "2:59 AM", "24:00" to return "2:59 AM (next day)"')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
import test_module
|
||||
from importlib import reload
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Calling `add_time('11:59 PM', '24:05')` should return `'12:04 AM (2 days later)'`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/time_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py', `
|
||||
import unittest
|
||||
time_calculator
|
||||
from importlib import reload
|
||||
|
||||
reload(time_calculator)
|
||||
|
||||
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def test_two_days_later(self):
|
||||
actual = time_calculator.add_time("11:59 PM", "24:05")
|
||||
expected = "12:04 AM (2 days later)"
|
||||
self.assertEqual(actual, expected, 'Expected calling "add_time()" with "11:59 PM", "24:05" to return "12:04 AM (2 days later)"')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
import test_module
|
||||
from importlib import reload
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Calling `add_time('8:16 PM', '466:02')` should return `'6:18 AM (20 days later)'`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/time_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py', `
|
||||
import unittest
|
||||
time_calculator
|
||||
from importlib import reload
|
||||
|
||||
reload(time_calculator)
|
||||
|
||||
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def test_high_duration(self):
|
||||
actual = time_calculator.add_time("8:16 PM", "466:02")
|
||||
expected = "6:18 AM (20 days later)"
|
||||
self.assertEqual(actual, expected, 'Expected calling "add_time()" with "8:16 PM", "466:02" to return "6:18 AM (20 days later)"')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
import test_module
|
||||
from importlib import reload
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Expected adding `0:00` to return the initial time.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/time_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py', `
|
||||
import unittest
|
||||
time_calculator
|
||||
from importlib import reload
|
||||
|
||||
reload(time_calculator)
|
||||
|
||||
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def test_no_change(self):
|
||||
actual = time_calculator.add_time("5:01 AM", "0:00")
|
||||
expected = "5:01 AM"
|
||||
self.assertEqual(actual, expected, 'Expected adding 0:00 to return initial time.')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
import test_module
|
||||
from importlib import reload
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
Calling `add_time('3:30 PM', '2:12', 'Monday')`should return `'5:42 PM, Monday'`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/time_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py', `
|
||||
import unittest
|
||||
time_calculator
|
||||
from importlib import reload
|
||||
|
||||
reload(time_calculator)
|
||||
|
||||
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def test_same_period_with_day(self):
|
||||
actual = time_calculator.add_time("3:30 PM", "2:12", "Monday")
|
||||
expected = "5:42 PM, Monday"
|
||||
self.assertEqual(actual, expected, 'Expected calling "add_time()" with "3:30 PM", "2:12", "Monday" to return "5:42 PM, Monday"')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
import test_module
|
||||
from importlib import reload
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
Calling `add_time('2:59 AM', '24:00', 'saturDay')` should return `'2:59 AM, Sunday (next day)'`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/time_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py', `
|
||||
import unittest
|
||||
time_calculator
|
||||
from importlib import reload
|
||||
|
||||
reload(time_calculator)
|
||||
|
||||
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def test_twenty_four_with_day(self):
|
||||
actual = time_calculator.add_time("2:59 AM", "24:00", "saturDay")
|
||||
expected = "2:59 AM, Sunday (next day)"
|
||||
self.assertEqual(actual, expected, 'Expected calling "add_time()" with "2:59 AM", "24:00", "saturDay" to return "2:59 AM, Sunday (next day)"')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
import test_module
|
||||
from importlib import reload
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Calling `add_time('11:59 PM', '24:05', 'Wednesday')` should return `'12:04 AM, Friday (2 days later)'`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/time_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py', `
|
||||
import unittest
|
||||
time_calculator
|
||||
from importlib import reload
|
||||
|
||||
reload(time_calculator)
|
||||
|
||||
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def test_two_days_later_with_day(self):
|
||||
actual = time_calculator.add_time("11:59 PM", "24:05", "Wednesday")
|
||||
expected = "12:04 AM, Friday (2 days later)"
|
||||
self.assertEqual(actual, expected, 'Expected calling "add_time()" with "11:59 PM", "24:05", "Wednesday" to return "12:04 AM, Friday (2 days later)"')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
import test_module
|
||||
from importlib import reload
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Calling `add_time('8:16 PM', '466:02', 'tuesday')`should return `'6:18 AM, Monday (20 days later)'`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
pyodide.FS.writeFile('/home/pyodide/time_calculator.py', code);
|
||||
pyodide.FS.writeFile('/home/pyodide/test_module.py', `
|
||||
import unittest
|
||||
time_calculator
|
||||
from importlib import reload
|
||||
|
||||
reload(time_calculator)
|
||||
|
||||
|
||||
class UnitTests(unittest.TestCase):
|
||||
maxDiff = None
|
||||
def test_high_duration_with_day(self):
|
||||
actual = time_calculator.add_time("8:16 PM", "466:02", "tuesday")
|
||||
expected = "6:18 AM, Monday (20 days later)"
|
||||
self.assertEqual(actual, expected, 'Expected calling "add_time()" with "8:16 PM", "466:02", "tuesday" to return "6:18 AM, Monday (20 days later)"')
|
||||
`);
|
||||
const testCode = `
|
||||
from unittest import main
|
||||
import test_module
|
||||
from importlib import reload
|
||||
|
||||
reload(test_module)
|
||||
t = main(module='test_module', exit=False)
|
||||
t.result.wasSuccessful()
|
||||
`;
|
||||
const out = runPython(testCode);
|
||||
assert(out);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
def add_time(start, duration):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return new_time
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```py
|
||||
def add_time(start, duration, day=''):
|
||||
start_arr = start[0:-3].split(':')
|
||||
dur_arr = duration.split(':')
|
||||
tail = ''
|
||||
# converting to 24h format
|
||||
if 'AM' in start:
|
||||
if start_arr[0] == '12':
|
||||
start_arr[0] = '00'
|
||||
elif 'PM' in start:
|
||||
if start_arr[0] == '12':
|
||||
start_arr[0] = '12'
|
||||
else:
|
||||
start_arr[0] = f'{int(start_arr[0]) + 12}'
|
||||
|
||||
# adding minutes
|
||||
sum_m = int(start_arr[1]) + int(dur_arr[1])
|
||||
if sum_m > 59:
|
||||
|
||||
if (sum_m - 60 * (sum_m//60)) < 10:
|
||||
mins = f'0{(sum_m - 60 * (sum_m//60))}'
|
||||
dur_arr[0] = int(dur_arr[0]) + sum_m//60
|
||||
|
||||
else:
|
||||
mins = sum_m - 60 * (sum_m//60)
|
||||
dur_arr[0] = int(dur_arr[0]) + sum_m//60
|
||||
else:
|
||||
if sum_m < 10:
|
||||
mins = f'0{sum_m}'
|
||||
else:
|
||||
mins = sum_m
|
||||
|
||||
#adding hours
|
||||
sum_h = int(start_arr[0]) + int(dur_arr[0])
|
||||
if sum_h < 24:
|
||||
hours= sum_h
|
||||
#time_24 = f'{hours}:{mins}'
|
||||
else:
|
||||
days_after = sum_h//24
|
||||
if days_after == 1:
|
||||
hours = sum_h - 24
|
||||
tail = ' (next day)'
|
||||
else:
|
||||
hours = sum_h - 24 * days_after
|
||||
tail = f' ({days_after} days later)'
|
||||
|
||||
#converting back to AM/PM
|
||||
if hours == 0:
|
||||
hours = 12
|
||||
time = f'{hours}:{mins} AM'
|
||||
final_time = f'{time}{tail}'
|
||||
elif hours < 12:
|
||||
time = f'{hours}:{mins} AM'
|
||||
final_time = f'{time}{tail}'
|
||||
else:
|
||||
if hours > 12:
|
||||
hours = hours - 12
|
||||
time = f'{hours}:{mins} PM'
|
||||
final_time = f'{time}{tail}'
|
||||
|
||||
#days of the week
|
||||
week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
|
||||
if day:
|
||||
day = day.capitalize()
|
||||
if not tail:
|
||||
final_time = f'{time}, {day}'
|
||||
elif tail == ' (next day)':
|
||||
index = week.index(day) + 1
|
||||
if index == 7:
|
||||
index = 0
|
||||
week_day = f', {week[index]}'
|
||||
final_time = f'{time}{week_day}{tail}'
|
||||
elif tail:
|
||||
index = (week.index(day) + days_after) % 7
|
||||
week_day = f', {week[index]}'
|
||||
final_time = f'{time}{week_day}{tail}'
|
||||
|
||||
|
||||
print('\n')
|
||||
print(final_time)
|
||||
print('\n')
|
||||
return final_time
|
||||
|
||||
```
|
||||
@@ -0,0 +1,248 @@
|
||||
---
|
||||
id: 5e44412c903586ffb414c94c
|
||||
title: Build an Arithmetic Formatter Project
|
||||
challengeType: 23
|
||||
forumTopicId: 462359
|
||||
dashedName: build-an-arithmetic-formatter-project
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Students in primary school often arrange arithmetic problems vertically to make them easier to solve. For example, "235 + 52" becomes:
|
||||
|
||||
```py
|
||||
235
|
||||
+ 52
|
||||
-----
|
||||
```
|
||||
|
||||
Finish the `arithmetic_arranger` function that receives a list of strings which are arithmetic problems, and returns the problems arranged vertically and side-by-side. The function should optionally take a second argument. When the second argument is set to `True`, the answers should be displayed.
|
||||
|
||||
## Example
|
||||
|
||||
Function Call:
|
||||
|
||||
```py
|
||||
arithmetic_arranger(["32 + 698", "3801 - 2", "45 + 43", "123 + 49"])
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```py
|
||||
32 3801 45 123
|
||||
+ 698 - 2 + 43 + 49
|
||||
----- ------ ---- -----
|
||||
```
|
||||
|
||||
Function Call:
|
||||
|
||||
```py
|
||||
arithmetic_arranger(["32 + 8", "1 - 3801", "9999 + 9999", "523 - 49"], True)
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```py
|
||||
32 1 9999 523
|
||||
+ 8 - 3801 + 9999 - 49
|
||||
---- ------ ------ -----
|
||||
40 -3800 19998 474
|
||||
```
|
||||
|
||||
## Rules
|
||||
|
||||
The function will return the correct conversion if the supplied problems are properly formatted, otherwise, it will **return** a **string** that describes an error that is meaningful to the user.
|
||||
|
||||
- Situations that will return an error:
|
||||
- If there are **too many problems** supplied to the function. The limit is **five**, anything more will return: `'Error: Too many problems.'`
|
||||
- The appropriate operators the function will accept are **addition** and **subtraction**. Multiplication and division will return an error. Other operators not mentioned in this bullet point will not need to be tested. The error returned will be: `"Error: Operator must be '+' or '-'."`
|
||||
- Each number (operand) should only contain digits. Otherwise, the function will return: `'Error: Numbers must only contain digits.'`
|
||||
- Each operand (aka number on each side of the operator) has a max of four digits in width. Otherwise, the error string returned will be: `'Error: Numbers cannot be more than four digits.'`
|
||||
- If the user supplied the correct format of problems, the conversion you return will follow these rules:
|
||||
- There should be a single space between the operator and the longest of the two operands, the operator will be on the same line as the second operand, both operands will be in the same order as provided (the first will be the top one and the second will be the bottom).
|
||||
- Numbers should be right-aligned.
|
||||
- There should be four spaces between each problem.
|
||||
- There should be dashes at the bottom of each problem. The dashes should run along the entire length of each problem individually. (The example above shows what this should look like.)
|
||||
|
||||
# --hints--
|
||||
|
||||
`arithmetic_arranger(["3801 - 2", "123 + 49"])` should return `3801 123\n- 2 + 49\n------ -----`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
runPython(`
|
||||
from unittest import TestCase
|
||||
|
||||
TestCase().assertEqual(arithmetic_arranger(["3801 - 2", "123 + 49"]), ' 3801 123\\n- 2 + 49\\n------ -----')`);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`arithmetic_arranger(["1 + 2", "1 - 9380"])` should return `1 1\n+ 2 - 9380\n--- ------`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
runPython(`
|
||||
from unittest import TestCase
|
||||
|
||||
TestCase().assertEqual(arithmetic_arranger(["1 + 2", "1 - 9380"]), ' 1 1\\n+ 2 - 9380\\n--- ------')`);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`arithmetic_arranger(["3 + 855", "3801 - 2", "45 + 43", "123 + 49"])` should return `3 3801 45 123\n+ 855 - 2 + 43 + 49\n----- ------ ---- -----`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
runPython(`
|
||||
from unittest import TestCase
|
||||
|
||||
TestCase().assertEqual(arithmetic_arranger(["3 + 855", "3801 - 2", "45 + 43", "123 + 49"]), ' 3 3801 45 123\\n+ 855 - 2 + 43 + 49\\n----- ------ ---- -----')`);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`arithmetic_arranger(["11 + 4", "3801 - 2999", "1 + 2", "123 + 49", "1 - 9380"])` should return `11 3801 1 123 1\n+ 4 - 2999 + 2 + 49 - 9380\n---- ------ --- ----- ------`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
runPython(`
|
||||
from unittest import TestCase
|
||||
|
||||
TestCase().assertEqual(arithmetic_arranger(["11 + 4", "3801 - 2999", "1 + 2", "123 + 49", "1 - 9380"]), ' 11 3801 1 123 1\\n+ 4 - 2999 + 2 + 49 - 9380\\n---- ------ --- ----- ------')`);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`arithmetic_arranger(["44 + 815", "909 - 2", "45 + 43", "123 + 49", "888 + 40", "653 + 87"])` should return `'Error: Too many problems.'`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
runPython(`
|
||||
from unittest import TestCase
|
||||
|
||||
TestCase().assertEqual(arithmetic_arranger(["44 + 815", "909 - 2", "45 + 43", "123 + 49", "888 + 40", "653 + 87"]), 'Error: Too many problems.')`);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`arithmetic_arranger(["3 / 855", "3801 - 2", "45 + 43", "123 + 49"])` should return `"Error: Operator must be '+' or '-'."`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
runPython(`
|
||||
from unittest import TestCase
|
||||
|
||||
TestCase().assertEqual(arithmetic_arranger(["3 / 855", "3801 - 2", "45 + 43", "123 + 49"]), "Error: Operator must be '+' or '-'.")`);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`arithmetic_arranger(["24 + 85215", "3801 - 2", "45 + 43", "123 + 49"])` should return `'Error: Numbers cannot be more than four digits.'`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
runPython(`
|
||||
from unittest import TestCase
|
||||
|
||||
TestCase().assertEqual(arithmetic_arranger(["24 + 85215", "3801 - 2", "45 + 43", "123 + 49"]), "Error: Numbers cannot be more than four digits.")`);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`arithmetic_arranger(["98 + 3g5", "3801 - 2", "45 + 43", "123 + 49"])` should return `'Error: Numbers must only contain digits.'`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
runPython(`
|
||||
from unittest import TestCase
|
||||
|
||||
TestCase().assertEqual(arithmetic_arranger(["98 + 3g5", "3801 - 2", "45 + 43", "123 + 49"]), "Error: Numbers must only contain digits.")`);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`arithmetic_arranger(["3 + 855", "988 + 40"], True)` should return `3 988\n+ 855 + 40\n----- -----\n 858 1028`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
runPython(`
|
||||
from unittest import TestCase
|
||||
|
||||
TestCase().assertEqual(arithmetic_arranger(["3 + 855", "988 + 40"], True), " 3 988\\n+ 855 + 40\\n----- -----\\n 858 1028")`);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
`arithmetic_arranger(["32 - 698", "1 - 3801", "45 + 43", "123 + 49", "988 + 40"], True)` should return `32 1 45 123 988\n- 698 - 3801 + 43 + 49 + 40\n----- ------ ---- ----- -----\n -666 -3800 88 172 1028`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
runPython(`
|
||||
from unittest import TestCase
|
||||
|
||||
TestCase().assertEqual(arithmetic_arranger(["32 - 698", "1 - 3801", "45 + 43", "123 + 49", "988 + 40"], True), " 32 1 45 123 988\\n- 698 - 3801 + 43 + 49 + 40\\n----- ------ ---- ----- -----\\n -666 -3800 88 172 1028")`);
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
def arithmetic_arranger(problems, show_answers=False):
|
||||
|
||||
return problems
|
||||
|
||||
print(f'\n{arithmetic_arranger(["32 + 698", "3801 - 2", "45 + 43", "123 + 49"])}')
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```py
|
||||
def arithmetic_arranger(problems, result=False):
|
||||
|
||||
lin1 = ""
|
||||
lin2 = ""
|
||||
lin3 = ""
|
||||
lin4 = ""
|
||||
|
||||
if len(problems) > 5:
|
||||
return 'Error: Too many problems.'
|
||||
for problem in problems:
|
||||
[num1, sym, num2] = problem.split()
|
||||
sign = ['+', '-']
|
||||
if sym not in sign:
|
||||
return ("Error: Operator must be '+' or '-'.")
|
||||
if len(num1) > 4 or len(num2) > 4:
|
||||
return ("Error: Numbers cannot be more than four digits.")
|
||||
if not num1.isnumeric() or not num2.isnumeric():
|
||||
return ("Error: Numbers must only contain digits.")
|
||||
|
||||
lin1 += " " + num1 + " " if len(num1) >= len(
|
||||
num2) else " " * (len(num2) + 2 - len(num1)) + num1 + " "
|
||||
lin2 += sym + " " + num2 + " " if len(num2) >= len(
|
||||
num1) else sym + " " * (len(num1) - len(num2) + 1) + num2 + " "
|
||||
nmax = (len(num1) + 2) if len(num1) >= len(num2) else (len(num2) + 2)
|
||||
lin3 += "-" * nmax + " "
|
||||
op = int(num1) + int(num2) if sym == "+" else int(num1) - int(num2)
|
||||
lin4 += (" " * (nmax - len(str(op)))) + str(op) + " "
|
||||
|
||||
arranged_problems = lin1.rstrip() + "\n" + lin2.rstrip(
|
||||
) + "\n" + lin3.rstrip()
|
||||
if result:
|
||||
arranged_problems += "\n" + lin4.rstrip()
|
||||
|
||||
return arranged_problems
|
||||
```
|
||||
@@ -23,7 +23,7 @@ Add a new key-value pair to your dictionary. Use the string `species` as the key
|
||||
You should add a new key-value pair to your `copper` dictionary.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
len(copper) == 1
|
||||
`))
|
||||
})
|
||||
@@ -32,7 +32,7 @@ You should add a new key-value pair to your `copper` dictionary.
|
||||
You should have a `species` key with the value `guinea pig` inside your `copper` dictionary.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
copper == {"species": "guinea pig"}
|
||||
`))
|
||||
})
|
||||
|
||||
@@ -14,7 +14,7 @@ Now, replace the existent keys with the strings `A` and `B` — one for each nod
|
||||
Your dictionary should have an `A` key.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
"A" in my_graph
|
||||
`))
|
||||
})
|
||||
@@ -23,7 +23,7 @@ Your dictionary should have an `A` key.
|
||||
Your `A` key should have `B` as the value.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
my_graph["A"] == "B"
|
||||
`))
|
||||
})
|
||||
@@ -32,7 +32,7 @@ Your `A` key should have `B` as the value.
|
||||
Your dictionary should have an `B` key.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
"B" in my_graph
|
||||
`))
|
||||
})
|
||||
@@ -41,7 +41,7 @@ Your dictionary should have an `B` key.
|
||||
Your `B` key should have `A` as the value.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
my_graph["B"] == "A"
|
||||
`))
|
||||
})
|
||||
@@ -50,7 +50,7 @@ Your `B` key should have `A` as the value.
|
||||
Your dictionary should have two keys.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
len(my_graph) == 2
|
||||
`))
|
||||
})
|
||||
|
||||
@@ -16,7 +16,7 @@ Modify your existing dictionary to represent this arrangement. Use a list to rep
|
||||
Your dictionary should have 3 keys — `A`, `B`, and `C`.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
key_list = ["A", "B", "C"]
|
||||
len(my_graph) == 3 and all(key in my_graph for key in key_list)
|
||||
`))
|
||||
@@ -26,7 +26,7 @@ Your dictionary should have 3 keys — `A`, `B`, and `C`.
|
||||
`my_graph["A"]` should have the `B` node as the value.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
my_graph["A"] == "B"
|
||||
`))
|
||||
})
|
||||
@@ -35,7 +35,7 @@ Your dictionary should have 3 keys — `A`, `B`, and `C`.
|
||||
`my_graph["B"]` should be a list.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
type(my_graph["B"]) is list
|
||||
`))
|
||||
})
|
||||
@@ -44,7 +44,7 @@ Your dictionary should have 3 keys — `A`, `B`, and `C`.
|
||||
The value of `my_graph["B"]` should be a list containing the other two nodes.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
len(my_graph["B"]) == 2 and "A" in my_graph["B"] and "C" in my_graph["B"]
|
||||
`))
|
||||
})
|
||||
@@ -53,7 +53,7 @@ The value of `my_graph["B"]` should be a list containing the other two nodes.
|
||||
The value of `my_graph["C"]` should be the connected node.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
my_graph["C"] == "B"
|
||||
`))
|
||||
})
|
||||
|
||||
@@ -14,7 +14,7 @@ Add one last node, `D`, which is connected with `A` and `C`. Modify your diction
|
||||
Your dictionary should have 4 keys called `A`, `B`, `C`, and `D`.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
key_list = ["A", "B", "C", "D"]
|
||||
len(my_graph) == 4 and all(key in my_graph for key in key_list)
|
||||
`))
|
||||
@@ -24,7 +24,7 @@ Your dictionary should have 4 keys called `A`, `B`, `C`, and `D`.
|
||||
`my_graph["A"]` should be a list.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
type(my_graph["A"]) is list
|
||||
`))
|
||||
})
|
||||
@@ -33,7 +33,7 @@ Your dictionary should have 4 keys called `A`, `B`, `C`, and `D`.
|
||||
`my_graph["A"]` should be a list containing `B` and `D`.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
len(my_graph["A"]) == 2 and "B" in my_graph["A"] and "D" in my_graph["A"]
|
||||
`))
|
||||
})
|
||||
@@ -42,7 +42,7 @@ Your dictionary should have 4 keys called `A`, `B`, `C`, and `D`.
|
||||
`my_graph["B"]` should be a list.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
type(my_graph["B"]) is list
|
||||
`))
|
||||
})
|
||||
@@ -51,7 +51,7 @@ Your dictionary should have 4 keys called `A`, `B`, `C`, and `D`.
|
||||
`my_graph["B"]` should be a list containing `A` and `C`.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
len(my_graph["B"]) == 2 and "A" in my_graph["B"] and "C" in my_graph["B"]
|
||||
`))
|
||||
})
|
||||
@@ -60,7 +60,7 @@ Your dictionary should have 4 keys called `A`, `B`, `C`, and `D`.
|
||||
`my_graph["C"]` should be a list.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
type(my_graph["C"]) is list
|
||||
`))
|
||||
})
|
||||
@@ -69,7 +69,7 @@ Your dictionary should have 4 keys called `A`, `B`, `C`, and `D`.
|
||||
`my_graph["C"]` should be a list containing `B` and `D`.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
len(my_graph["C"]) == 2 and "B" in my_graph["C"] and "D" in my_graph["C"]
|
||||
`))
|
||||
})
|
||||
@@ -78,7 +78,7 @@ Your dictionary should have 4 keys called `A`, `B`, `C`, and `D`.
|
||||
`my_graph["D"]` should be a list.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
type(my_graph["D"]) is list
|
||||
`))
|
||||
})
|
||||
@@ -87,7 +87,7 @@ Your dictionary should have 4 keys called `A`, `B`, `C`, and `D`.
|
||||
`my_graph["D"]` should be a list containing `A` and `C`.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
len(my_graph["D"]) == 2 and "A" in my_graph["D"] and "C" in my_graph["D"]
|
||||
`))
|
||||
})
|
||||
|
||||
@@ -27,7 +27,7 @@ Modify `my_graph["A"]` into a list of tuples, considering the following distance
|
||||
Your dictionary should have 4 keys called `A`, `B`, `C`, and `D`.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
key_list = ["A", "B", "C", "D"]
|
||||
len(my_graph) == 4 and all(key in my_graph for key in key_list)
|
||||
`))
|
||||
@@ -37,7 +37,7 @@ Your dictionary should have 4 keys called `A`, `B`, `C`, and `D`.
|
||||
`my_graph["A"]` should be a list of tuples.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
type(my_graph["A"]) is list and all(type(i) is tuple for i in my_graph["A"])
|
||||
`))
|
||||
})
|
||||
@@ -46,7 +46,7 @@ Your dictionary should have 4 keys called `A`, `B`, `C`, and `D`.
|
||||
`my_graph["A"]` should be a list of tuples where the first item in the tuple is the connected node and the second item is the distance.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
tuples = [("B", 3), ("D", 1)]
|
||||
len(my_graph["A"]) == 2 and all(t in my_graph["A"] for t in tuples)
|
||||
`))
|
||||
|
||||
@@ -16,7 +16,7 @@ Declare an empty function called `shortest_path` and don't forget the `pass` key
|
||||
You should have a `shortest_path` function.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
import inspect
|
||||
inspect.isfunction(shortest_path)
|
||||
`))
|
||||
|
||||
@@ -16,7 +16,7 @@ For that your function needs two parameters: `graph`, and `start`. Add them to y
|
||||
Your function should accept `graph` and `start` as the parameters, in this order.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
import inspect
|
||||
sig = str(inspect.signature(shortest_path))
|
||||
sig == '(graph, start)'
|
||||
|
||||
@@ -22,7 +22,7 @@ Your function should take three parameters:`graph`, `start`, and `target`. The o
|
||||
The `target` parameter should have the default value of an empty string.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
import inspect
|
||||
sig = str(inspect.signature(shortest_path))
|
||||
sig == "(graph, start, target='')"
|
||||
|
||||
@@ -14,7 +14,7 @@ Now modify `my_graph["B"]` into a list of tuples. The `B-C` distance is `4`.
|
||||
`my_graph["B"]` should be a list of tuples.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
type(my_graph["B"]) is list and all(type(i) is tuple for i in my_graph["B"])
|
||||
`))
|
||||
})
|
||||
@@ -23,7 +23,7 @@ Now modify `my_graph["B"]` into a list of tuples. The `B-C` distance is `4`.
|
||||
`my_graph["B"]` should be a list of tuples where the first item in the tuple is the connected node and the second item is the distance.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
tuples = [("A", 3), ("C", 4)]
|
||||
len(my_graph["B"]) == 2 and all(t in my_graph["B"] for t in tuples)
|
||||
`))
|
||||
|
||||
@@ -14,7 +14,7 @@ In the same way, modify the remaining two lists considering that the `C-D` dista
|
||||
`my_graph["C"]` should be a list of tuples.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
type(my_graph["C"]) is list and all(type(i) is tuple for i in my_graph["C"])
|
||||
`))
|
||||
})
|
||||
@@ -23,7 +23,7 @@ In the same way, modify the remaining two lists considering that the `C-D` dista
|
||||
`my_graph["C"]` should be a list of tuples where the first item in the tuple is the connected node and the second item is the distance.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
tuples = [("B", 4), ("D", 7)]
|
||||
len(my_graph["C"]) == 2 and all(t in my_graph["C"] for t in tuples)
|
||||
`))
|
||||
@@ -33,7 +33,7 @@ In the same way, modify the remaining two lists considering that the `C-D` dista
|
||||
`my_graph["D"]` should be a list of tuples.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
type(my_graph["D"]) is list and all(type(i) is tuple for i in my_graph["D"])
|
||||
`))
|
||||
})
|
||||
@@ -42,7 +42,7 @@ In the same way, modify the remaining two lists considering that the `C-D` dista
|
||||
`my_graph["D"]` should be a list of tuples where the first item in the tuple is the connected node and the second item is the distance.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
tuples = [("A", 1), ("C", 7)]
|
||||
len(my_graph["D"]) == 2 and all(t in my_graph["D"] for t in tuples)
|
||||
`))
|
||||
|
||||
@@ -25,7 +25,7 @@ Now, you are going to test your function with another graph. Change `my_graph` i
|
||||
You should modify `my_graph` into the provided graph.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
g = {
|
||||
'A': [('B', 5), ('C', 3), ('E', 11)],
|
||||
'B': [('A', 5), ('C', 1), ('F', 2)],
|
||||
|
||||
@@ -27,7 +27,7 @@ You should have a variable called `copper`.
|
||||
Your `copper` variable should have the value of an empty dictionary. Use a pair of curly braces for that.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
copper == {}
|
||||
`))
|
||||
})
|
||||
|
||||
@@ -16,7 +16,7 @@ Add another key `age` to your dictionary and give it the integer number `2` as v
|
||||
You should add a new key-value pair to your `copper` dictionary.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
len(copper) == 2
|
||||
`))
|
||||
})
|
||||
@@ -25,7 +25,7 @@ You should add a new key-value pair to your `copper` dictionary.
|
||||
You should have an `age` key with the value `2` just after `'species': 'guinea pig'`, inside your `copper` dictionary. Don't forget the comma.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
copper == {"species": "guinea pig", "age": 2}
|
||||
`))
|
||||
})
|
||||
|
||||
@@ -25,7 +25,7 @@ After your dictionary, follow the example above to access the `species` key of `
|
||||
You should not modify your dictionary.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
copper == {"species": "guinea pig", "age": 2}
|
||||
`))
|
||||
})
|
||||
|
||||
@@ -24,7 +24,7 @@ You should rename your `copper` dictionary into `my_graph`.
|
||||
Your `my_graph` variable should be a dictionary.
|
||||
|
||||
```js
|
||||
({ test: () => assert(__pyodide.runPython(`
|
||||
({ test: () => assert(runPython(`
|
||||
type(my_graph) is dict
|
||||
`))
|
||||
})
|
||||
|
||||
@@ -16,7 +16,7 @@ Your `merge_sort` function should take a single parameter: `array`.
|
||||
```js
|
||||
({ test: () => assert(runPython(`
|
||||
import inspect
|
||||
str(inspect.signature(__locals.get('merge_sort'))) == '(array)'
|
||||
str(inspect.signature(merge_sort)) == '(array)'
|
||||
`))
|
||||
})
|
||||
```
|
||||
|
||||
@@ -19,13 +19,9 @@ You should create an `if` statement to check if `len(array) <= 1`. Don't forget
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
const transformedCode = code.replace(/\r/g, "");
|
||||
const merge_sort = __helpers.python.getDef("\n" + transformedCode, "merge_sort");
|
||||
const { function_body } = merge_sort;
|
||||
|
||||
assert.match(function_body, /if\s+len\(\s*array\s*\)\s*<=\s*1:\s*pass/);
|
||||
}
|
||||
test: () => assert(runPython(`
|
||||
_Node(_code).find_function("merge_sort").find_ifs()[0].find_conditions()[0].is_equivalent("len(array) <= 1")
|
||||
`))
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
@@ -22,13 +22,11 @@ Use the `pass` keyword in the body of the `if` statement.
|
||||
Your `if` statement should check if `__name__` has a value of `'__main__'`
|
||||
|
||||
```js
|
||||
assert.match(code, /if\s+__name__\s*==\s*("|')__main__\1\s*:/);
|
||||
```
|
||||
|
||||
You should have the `pass` keyword in the body of your `if` statement
|
||||
|
||||
```js
|
||||
assert.match(code, /if\s+__name__\s*==\s*("|')__main__\1\s*:\s*[^}]*\bpass\b/);
|
||||
({
|
||||
test: () => assert(runPython(`
|
||||
_Node(_code).find_ifs()[0].find_conditions()[0].is_equivalent("__name__ == '__main__'")
|
||||
`))
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
@@ -25,7 +25,6 @@ Your `rods` variable should be an empty dictionary.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`
|
||||
rods = __locals.get("rods")
|
||||
rods == {}
|
||||
`))
|
||||
})
|
||||
|
||||
@@ -19,8 +19,7 @@ You should use the `range()` function to assign a sequence of numbers to `rods['
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`
|
||||
a = __locals.get('rods')
|
||||
type(a['A']) is range
|
||||
type(rods['A']) is range
|
||||
`))
|
||||
})
|
||||
```
|
||||
@@ -29,8 +28,7 @@ You should use the `range()` function to assign the sequence of numbers from `3`
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`
|
||||
a = __locals.get('rods')
|
||||
a['A'] == range(3, 0, -1)
|
||||
rods['A'] == range(3, 0, -1)
|
||||
`))
|
||||
})
|
||||
```
|
||||
|
||||
@@ -17,8 +17,7 @@ You should pass your `range()` call to the `list()` function.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`
|
||||
a = __locals.get('rods')
|
||||
a['A'] == list(range(3, 0, -1))
|
||||
rods['A'] == list(range(3, 0, -1))
|
||||
`))
|
||||
})
|
||||
```
|
||||
|
||||
@@ -23,7 +23,7 @@ You should declare an empty function named `move`. Remember to use the `pass` ke
|
||||
({ test: () => {
|
||||
assert(runPython(`
|
||||
import inspect
|
||||
inspect.isfunction(__locals.get('move'))
|
||||
inspect.isfunction(move)
|
||||
`))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -23,9 +23,8 @@ The value of `number_of_moves` should be the expression to calculate the number
|
||||
|
||||
```js
|
||||
({ test: () => {
|
||||
assert(runPython(`
|
||||
a = __locals.get('NUMBER_OF_DISKS')
|
||||
__locals.get('number_of_moves') == 2**a -1
|
||||
assert(runPython(`
|
||||
number_of_moves == 2**NUMBER_OF_DISKS -1
|
||||
`))
|
||||
} })
|
||||
```
|
||||
|
||||
@@ -16,7 +16,7 @@ You should declare an empty function named `make_allowed_move`. Remember to use
|
||||
```js
|
||||
({ test: () => assert(runPython(`
|
||||
import inspect
|
||||
inspect.isfunction(__locals.get('make_allowed_move'))
|
||||
inspect.isfunction(make_allowed_move)
|
||||
`))
|
||||
})
|
||||
```
|
||||
|
||||
@@ -16,7 +16,7 @@ Your `make_allowed_move()` function should have two parameters named `rod1` and
|
||||
```js
|
||||
({ test: () => assert(runPython(`
|
||||
import inspect
|
||||
str(inspect.signature(__locals.get('make_allowed_move'))) == '(rod1, rod2)'
|
||||
str(inspect.signature(make_allowed_move)) == '(rod1, rod2)'
|
||||
`))
|
||||
})
|
||||
```
|
||||
|
||||
@@ -14,16 +14,14 @@ The `rods` dictionary will represent the three rods with their disks. Give it th
|
||||
Your `rods` dictionary should have an `'A'` key.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`'A' in __locals.get("rods")`)) })
|
||||
|
||||
({ test: () => assert(runPython(`'A' in rods`)) })
|
||||
```
|
||||
|
||||
`rods['A']` should be an empty list.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`
|
||||
a = __locals.get("rods")
|
||||
a['A'] == []
|
||||
rods['A'] == []
|
||||
`))
|
||||
})
|
||||
```
|
||||
@@ -31,16 +29,14 @@ Your `rods` dictionary should have an `'A'` key.
|
||||
Your `rods` dictionary should have a `'B'` key.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`'B' in __locals.get("rods")`)) })
|
||||
|
||||
({ test: () => assert(runPython(`'B' in rods`)) })
|
||||
```
|
||||
|
||||
`rods['B']` should be an empty list.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`
|
||||
a = __locals.get("rods")
|
||||
a['B'] == []
|
||||
rods['B'] == []
|
||||
`))
|
||||
})
|
||||
```
|
||||
@@ -48,16 +44,14 @@ Your `rods` dictionary should have a `'B'` key.
|
||||
Your `rods` dictionary should have a `'C'` key.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`'C' in __locals.get("rods")`)) })
|
||||
|
||||
({ test: () => assert(runPython(`'C' in rods`)) })
|
||||
```
|
||||
|
||||
`rods['C']` should be an empty list.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`
|
||||
a = __locals.get("rods")
|
||||
a['C'] == []
|
||||
rods['C'] == []
|
||||
`))
|
||||
})
|
||||
```
|
||||
|
||||
@@ -22,7 +22,7 @@ Your `move()` function should have `n`, `source`, `auxiliary`, and `target` as t
|
||||
```js
|
||||
({ test: () => assert(runPython(`
|
||||
import inspect
|
||||
str(inspect.signature(__locals.get('move'))) == '(n, source, auxiliary, target)'
|
||||
str(inspect.signature(move)) == '(n, source, auxiliary, target)'
|
||||
`))
|
||||
})
|
||||
```
|
||||
|
||||
@@ -17,9 +17,8 @@ You should reduce the indentation level of all the code after the `return` state
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`
|
||||
hanoi = __locals.get("move")
|
||||
a, b, c = [3, 2, 1], [], []
|
||||
hanoi(3, a, b, c)
|
||||
move(3, a, b, c)
|
||||
a == [] and b == [] and c == [3, 2, 1]
|
||||
`))
|
||||
})
|
||||
|
||||
@@ -23,9 +23,8 @@ You should add `direction` as the third parameter of your function.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`
|
||||
import inspect
|
||||
f = __locals.get("vigenere")
|
||||
sig = str(inspect.signature(f))
|
||||
import inspect
|
||||
sig = str(inspect.signature(vigenere))
|
||||
sig == '(message, key, direction)'
|
||||
`))
|
||||
})
|
||||
|
||||
@@ -24,8 +24,7 @@ You should declare a new function called `encrypt`. Remember to use the `pass` k
|
||||
```js
|
||||
({ test: () => assert(runPython(`
|
||||
import inspect
|
||||
f = __locals.get("encrypt")
|
||||
inspect.isfunction(f)
|
||||
inspect.isfunction(encrypt)
|
||||
`))
|
||||
})
|
||||
```
|
||||
@@ -35,8 +34,7 @@ Your `encrypt` function should take `message` and `key` as the parameters. The o
|
||||
```js
|
||||
({ test: () => assert(runPython(`
|
||||
import inspect
|
||||
f = __locals.get("encrypt")
|
||||
sig = inspect.signature(f)
|
||||
sig = inspect.signature(encrypt)
|
||||
str(sig) == "(message, key)"
|
||||
`))
|
||||
})
|
||||
|
||||
@@ -16,8 +16,7 @@ You should define a new function called `decrypt`.
|
||||
```js
|
||||
({ test: () => assert(runPython(`
|
||||
import inspect
|
||||
f = __locals.get("decrypt")
|
||||
inspect.isfunction(f)
|
||||
inspect.isfunction(decrypt)
|
||||
`))
|
||||
})
|
||||
```
|
||||
@@ -27,8 +26,7 @@ Your `decrypt` function should take `message` and `key` as the parameters.
|
||||
```js
|
||||
({ test: () => assert(runPython(`
|
||||
import inspect
|
||||
f = __locals.get("decrypt")
|
||||
sig = inspect.signature(f)
|
||||
sig = inspect.signature(decrypt)
|
||||
str(sig) == "(message, key)"
|
||||
`))
|
||||
})
|
||||
|
||||
@@ -23,8 +23,7 @@ The `direction` parameter of your `vigenere` function should have a default valu
|
||||
```js
|
||||
({ test: () => assert(runPython(`
|
||||
import inspect
|
||||
f = __locals.get("vigenere")
|
||||
sig = str(inspect.signature(f))
|
||||
sig = str(inspect.signature(vigenere))
|
||||
sig == '(message, key, direction=1)'
|
||||
`))
|
||||
})
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
id: 65ef181dad3d96b14a21a03e
|
||||
title: Step 1
|
||||
challengeType: 20
|
||||
dashedName: step-1
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
In this project, you will find the approximate square root of a given number using the bisection method.
|
||||
|
||||
The bisection method is a technique for finding the roots of a real-valued function. It works by narrowing down an interval where the square root lies until it converges to a value within a specified tolerance.
|
||||
|
||||
Begin by creating a function named `square_root_bisection`. Leave the parameters empty for now.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should define the function `square_root_bisection` with no parameters.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert(runPython(`
|
||||
import inspect
|
||||
inspect.isfunction(square_root_bisection)
|
||||
`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
id: 65ef190c6b51e9b5a5f7ed29
|
||||
title: Step 2
|
||||
challengeType: 20
|
||||
dashedName: step-2
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Give the `square_root_bisection` method the following parameters:
|
||||
|
||||
- `square_target`: The number for which you want to find the square root.
|
||||
- `tolerance` (optional): The acceptable difference between the square of the approximate root value and the actual target value (default is `1e-7`). The tolerance `1e-7` implies that the solution will be accurate to within `0.0000001` of the true value and is a good default choice that balances accuracy and performance.
|
||||
- `max_iterations` (optional): The maximum number of iterations to perform (default is `100`). If the method doesn't converge within this limit, you'll assume the solution is not found.
|
||||
|
||||
# --hints--
|
||||
|
||||
Your function should have these parameters: `square_target`, `tolerance = 1e-7`, and `max_iterations = 100`. The order matters.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => assert(runPython(`_Node(_code).find_function("square_root_bisection").has_args("square_target, tolerance=1e-7, max_iterations=100")`))
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
|
||||
--fcc-editable-region--
|
||||
def square_root_bisection():
|
||||
pass
|
||||
--fcc-editable-region--
|
||||
|
||||
```
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
id: 65ef19425d1b27b6c930bae6
|
||||
title: Step 3
|
||||
challengeType: 20
|
||||
dashedName: step-3
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
If the number for which you want to find the square root is negative, the code should raise an error as the square root of a negative number is not defined in real numbers.
|
||||
|
||||
Remove the `pass` statement and create an `if` statement to check if `square_target` is less than `0`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should remove the `pass` keyword.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert.isFalse(runPython(`_Node(_code).find_function("square_root_bisection").has_pass()`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should create an `if` statement to check if `square_target < 0`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert.isFalse(runPython(`_Node(_code).find_function("square_root_bisection").find_if("square_target < 0").is_empty()`))
|
||||
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
def square_root_bisection(square_target, tolerance = 1e-7, max_iterations = 100):
|
||||
pass
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
id: 65ef198fde24dfb7ff675b42
|
||||
title: Step 4
|
||||
challengeType: 20
|
||||
dashedName: step-4
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
If the `square_target` is less than `0`, raise a `ValueError` with the message `'Square root of negative number is not defined in real numbers'`. Don't forget to remove the `pass` keyword.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should remove the `pass` keyword.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
assert.isFalse(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[0].find_bodies()[0].has_pass()`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should raise a `ValueError` with the message `'Square root of negative number is not defined in real numbers'` inside the `if` body.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => {
|
||||
|
||||
assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[0].find_bodies()[0].is_equivalent("raise ValueError('Square root of negative number is not defined in real numbers')")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
def square_root_bisection(square_target, tolerance=1e-7, max_iterations=100):
|
||||
if square_target < 0:
|
||||
pass
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
id: 65ef19ec318e2fb9066381e3
|
||||
title: Step 5
|
||||
challengeType: 20
|
||||
dashedName: step-5
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
You'll create separate cases for when `square_target` is `0` or `1`.
|
||||
|
||||
Begin by creating an `if` statement to check if `square_target` is equal to `1`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should create an `if` statement to check that `square_target == 1`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_conditions()[0].is_equivalent("square_target == 1")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
def square_root_bisection(square_target, tolerance=1e-7, max_iterations=100):
|
||||
if square_target < 0:
|
||||
raise ValueError('Square root of negative number is not defined in real numbers')
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
id: 65ef1a1fcb527bba0ca82ccf
|
||||
title: Step 6
|
||||
challengeType: 20
|
||||
dashedName: step-6
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
If the `square_target` is equal to `1`, declare a variable `root` and assign it the value `1` . Also, print the message `'The square root of {square_target} is 1'`. Remember to format the message using an f-string.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should remove the `pass` keyword.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert.isFalse(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[0].has_pass()`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should assign the value `1` to the `root` variable and print the message `'The square root of {square_target} is 1'` inside the `if` body.
|
||||
|
||||
```js
|
||||
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[0].is_equivalent("root = 1\\nprint(f'The square root of {square_target} is 1')")`));
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
def square_root_bisection(square_target, tolerance=1e-7, max_iterations=100):
|
||||
if square_target < 0:
|
||||
raise ValueError('Square root of negative number is not defined in real numbers')
|
||||
if square_target == 1:
|
||||
pass
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,55 @@
|
||||
---
|
||||
id: 65ef1a50049cf9bada13266f
|
||||
title: Step 7
|
||||
challengeType: 20
|
||||
dashedName: step-7
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Create an `elif` statement to check if `square_target` is equal to `0`. If it is, assign the value `0` to the `root` variable. Also, print the message `'The square root of {square_target} is 0'`. Remember to format the message using an f-string.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have an `elif` statement to check the condition `square_target == 0`.
|
||||
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_conditions()[1].is_equivalent("square_target == 0")`));
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
You should assign the value `0` to the `root` variable and pass the argument `f'The square root of {square_target} is 0'` to a `print` call.
|
||||
|
||||
|
||||
```js
|
||||
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[1].is_equivalent("root = 0\\nprint(f'The square root of {square_target} is 0')")`));
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
--fcc-editable-region--
|
||||
def square_root_bisection(square_target, tolerance=1e-7, max_iterations=100):
|
||||
if square_target < 0:
|
||||
raise ValueError('Square root of negative number is not defined in real numbers')
|
||||
if square_target == 1:
|
||||
root = 1
|
||||
print(f'The square root of {square_target} is 1')
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
id: 65ef1a720d6e65bbb0d22463
|
||||
title: Step 8
|
||||
challengeType: 20
|
||||
dashedName: step-8
|
||||
---
|
||||
|
||||
# --description--
|
||||
Next, you are going to work on the cases where the `square_target` is a positive number apart from `1` or `0`.
|
||||
|
||||
Create an `else` clause to handle these cases.
|
||||
|
||||
# --hints--
|
||||
|
||||
Create an `else` clause and do not forget to add a `pass` keyword.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_conditions()[2] == _Node()`))
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
def square_root_bisection(square_target, tolerance=1e-7, max_iterations=100):
|
||||
if square_target < 0:
|
||||
raise ValueError('Square root of negative number is not defined in real numbers')
|
||||
if square_target == 1:
|
||||
root = 1
|
||||
print(f'The square root of {square_target} is 1')
|
||||
elif square_target == 0:
|
||||
root = 0
|
||||
print(f'The square root of {square_target} is 0')
|
||||
--fcc-editable-region--
|
||||
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,73 @@
|
||||
---
|
||||
id: 65ef1aacca094bbcc2e2a3c8
|
||||
title: Step 9
|
||||
challengeType: 20
|
||||
dashedName: step-9
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
In Python, the `max()` function returns the largest of the input values.
|
||||
|
||||
```python
|
||||
max(1, 2, 3) # Output: 3
|
||||
```
|
||||
|
||||
The variables `low` and `high` will be used to define the initial interval where the square root lies.
|
||||
|
||||
Inside the `else` clause, initialize the `low` variable to `0` and the `high` variable to be the maximum of either `1` or `square_target` as the square root of a number is always less than or equal to the number itself.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should remove the `pass` keyword.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert.isFalse(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[2].has_pass()`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should declare a variable `low` and assign it `0`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[2].find_variable("low").is_equivalent("low = 0")`)); }
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
You should declare a variable `high` and use the `max()` function to assign it the maximum value between `1` and `square_target`.
|
||||
|
||||
```js
|
||||
|
||||
({ test: () => assert(runPython(`
|
||||
node = _Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[2].find_variable("high")
|
||||
values = ["high = max(1, square_target)", "high = max(square_target, 1)"]
|
||||
any(node.is_equivalent(val) for val in values)
|
||||
`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
def square_root_bisection(square_target, tolerance=1e-7, max_iterations=100):
|
||||
if square_target < 0:
|
||||
raise ValueError('Square root of negative number is not defined in real numbers')
|
||||
if square_target == 1:
|
||||
root = 1
|
||||
print(f'The square root of {square_target} is 1')
|
||||
elif square_target == 0:
|
||||
root = 0
|
||||
print(f'The square root of {square_target} is 0')
|
||||
--fcc-editable-region--
|
||||
else:
|
||||
pass
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
id: 65ef1afca9a8f6be0d4150ba
|
||||
title: Step 10
|
||||
challengeType: 20
|
||||
dashedName: step-10
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Set the value of `root` to `None` as at this point, you don't have an approximate value yet.
|
||||
|
||||
# --hints--
|
||||
|
||||
The value of `root` should be `None`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[2].is_equivalent("low = 0\\nhigh = max(1, square_target)\\nroot = None")`));
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
def square_root_bisection(square_target, tolerance=1e-7, max_iterations=100):
|
||||
if square_target < 0:
|
||||
raise ValueError('Square root of negative number is not defined in real numbers')
|
||||
if square_target == 1:
|
||||
root = 1
|
||||
print(f'The square root of {square_target} is 1')
|
||||
elif square_target == 0:
|
||||
root = 0
|
||||
print(f'The square root of {square_target} is 0')
|
||||
--fcc-editable-region--
|
||||
else:
|
||||
low = 0
|
||||
high = max(1, square_target)
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
id: 65ef1be2b958cabf712296cd
|
||||
title: Step 11
|
||||
challengeType: 20
|
||||
dashedName: step-11
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Now you'll repeatedly narrow down the interval by finding the midpoint of the current interval and comparing the square of the midpoint with the target value.
|
||||
|
||||
For that, inside the `else` block, create a `for` loop that runs up to `max_iterations` times.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should create a `for` loop to iterate over `range(max_iterations)`. Use `_` as the loop variable.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[2].find_for_loops()[0].is_equivalent("for _ in range(max_iterations):\\n pass")`));
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
def square_root_bisection(square_target, tolerance=1e-7, max_iterations=100):
|
||||
if square_target < 0:
|
||||
raise ValueError('Square root of negative number is not defined in real numbers')
|
||||
if square_target == 1:
|
||||
root = 1
|
||||
print(f'The square root of {square_target} is 1')
|
||||
elif square_target == 0:
|
||||
root = 0
|
||||
print(f'The square root of {square_target} is 0')
|
||||
|
||||
else:
|
||||
low = 0
|
||||
high = max(1, square_target)
|
||||
root = None
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,78 @@
|
||||
---
|
||||
id: 65ef1c0a03fcabc04ded7e69
|
||||
title: Step 12
|
||||
challengeType: 20
|
||||
dashedName: step-12
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Inside the for loop, calculate the midpoint of the interval ranging from `low` to `high`. Assign this value to a variable `mid`.
|
||||
|
||||
Also, calculate the square of the midpoint (`mid`) and store it in the variable `square_mid`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should remove the `pass` keyword.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert.isFalse(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[2].find_for_loops()[0].find_bodies()[0].has_pass()`))
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
You should declare a variable `mid` and assign it `(low + high) / 2` inside the body of the `for` loop.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`
|
||||
node = _Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[2].find_for_loops()[0].find_bodies()[0].find_variable("mid")
|
||||
values = ["mid = (low + high) / 2", "mid = (high + low) / 2"]
|
||||
any(node.is_equivalent(val) for val in values)
|
||||
`))
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
You should declare a variable `square_mid` and assign it `mid**2` inside the body of the for loop.
|
||||
|
||||
```js
|
||||
({ test: () => assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[2].find_for_loops()[0].find_bodies()[0].find_variable("square_mid").is_equivalent("square_mid = mid**2")`)) })
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
def square_root_bisection(square_target, tolerance=1e-7, max_iterations=100):
|
||||
if square_target < 0:
|
||||
raise ValueError('Square root of negative number is not defined in real numbers')
|
||||
if square_target == 1:
|
||||
root = 1
|
||||
print(f'The square root of {square_target} is 1')
|
||||
elif square_target == 0:
|
||||
root = 0
|
||||
print(f'The square root of {square_target} is 0')
|
||||
|
||||
else:
|
||||
low = 0
|
||||
high = max(1, square_target)
|
||||
root = None
|
||||
|
||||
--fcc-editable-region--
|
||||
for _ in range(max_iterations):
|
||||
pass
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
id: 65ef1c34a541afc12dbb849d
|
||||
title: Step 13
|
||||
challengeType: 20
|
||||
dashedName: step-13
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
The `abs()` function returns the absolute value of a number, which is always positive, regardless of the number sign. You will use it to check that the estimated square root is close enough to the actual value.
|
||||
|
||||
Now, create an `if` statement to check if the absolute value of the difference between `square_mid` and `square_target` is within the specified `tolerance`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have an `if` statement with the condition `abs(square_mid - square_target) < tolerance:` inside the body of the `for` loop.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[2].find_for_loops()[0].find_ifs()[0].find_conditions()[0].is_equivalent("abs(square_mid - square_target) < tolerance")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
def square_root_bisection(square_target, tolerance=1e-7, max_iterations=100):
|
||||
if square_target < 0:
|
||||
raise ValueError('Square root of negative number is not defined in real numbers')
|
||||
if square_target == 1:
|
||||
root = 1
|
||||
print(f'The square root of {square_target} is 1')
|
||||
elif square_target == 0:
|
||||
root = 0
|
||||
print(f'The square root of {square_target} is 0')
|
||||
|
||||
else:
|
||||
low = 0
|
||||
high = max(1, square_target)
|
||||
root = None
|
||||
|
||||
--fcc-editable-region--
|
||||
for _ in range(max_iterations):
|
||||
mid = (low + high) / 2
|
||||
square_mid = mid**2
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
id: 65ef1cb031de30c2cde64c12
|
||||
title: Step 14
|
||||
challengeType: 20
|
||||
dashedName: step-14
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
If the difference is within the specified `tolerance`, set the value of `root` to `mid` and break out of the loop.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should remove the existing `pass` statement.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert.isFalse(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[2].find_for_loops()[0].find_ifs()[0].find_bodies()[0].has_pass()`))
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
You should assign the value of `mid` to `root` and break out of the loop.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[2].find_for_loops()[0].find_ifs()[0].find_bodies()[0].is_equivalent("root = mid\\nbreak")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
def square_root_bisection(square_target, tolerance=1e-7, max_iterations=100):
|
||||
if square_target < 0:
|
||||
raise ValueError('Square root of negative number is not defined in real numbers')
|
||||
if square_target == 1:
|
||||
root = 1
|
||||
print(f'The square root of {square_target} is 1')
|
||||
elif square_target == 0:
|
||||
root = 0
|
||||
print(f'The square root of {square_target} is 0')
|
||||
|
||||
else:
|
||||
low = 0
|
||||
high = max(1, square_target)
|
||||
root = None
|
||||
|
||||
for _ in range(max_iterations):
|
||||
mid = (low + high) / 2
|
||||
square_mid = mid**2
|
||||
|
||||
--fcc-editable-region--
|
||||
if abs(square_mid - square_target) < tolerance:
|
||||
pass
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
id: 65ef1cda150a59c3b8306944
|
||||
title: Step 15
|
||||
challengeType: 20
|
||||
dashedName: step-15
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
If the difference is not within the specified `tolerance`, create an `elif` statement to check if `square_mid` is less than `square_target`.
|
||||
|
||||
Assign the value of `mid` to `low` as the square root would now lie between `low` and `mid`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should create an `elif` statement that checks if `square_mid < square_target`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[2].find_for_loops()[0].find_ifs()[0].find_conditions()[1].is_equivalent("square_mid < square_target")`))
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
You should assign the value of `mid` to `low`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[2].find_for_loops()[0].find_ifs()[0].find_bodies()[1].is_equivalent("low = mid")`))
|
||||
}
|
||||
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
def square_root_bisection(square_target, tolerance=1e-7, max_iterations=100):
|
||||
if square_target < 0:
|
||||
raise ValueError('Square root of negative number is not defined in real numbers')
|
||||
if square_target == 1:
|
||||
root = 1
|
||||
print(f'The square root of {square_target} is 1')
|
||||
elif square_target == 0:
|
||||
root = 0
|
||||
print(f'The square root of {square_target} is 0')
|
||||
|
||||
else:
|
||||
low = 0
|
||||
high = max(1, square_target)
|
||||
root = None
|
||||
|
||||
for _ in range(max_iterations):
|
||||
mid = (low + high) / 2
|
||||
square_mid = mid**2
|
||||
|
||||
--fcc-editable-region--
|
||||
if abs(square_mid - square_target) < tolerance:
|
||||
root = mid
|
||||
break
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
id: 65ef1d104c2be9c4d8e22075
|
||||
title: Step 16
|
||||
challengeType: 20
|
||||
dashedName: step-16
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
If both the `if` and `elif` conditions are not met, the value of `mid` would be greater than `square_target`. In this case, create an `else` clause and assign the value of `mid` to `high`.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have an `else` clause.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[2].find_for_loops()[0].find_ifs()[0].find_conditions()[2]== _Node()`));
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
You should assign the value of `mid` to `high` in the `else` clause.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[2].find_for_loops()[0].find_ifs()[0].find_bodies()[2].is_equivalent("high = mid")`));
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
def square_root_bisection(square_target, tolerance=1e-7, max_iterations=100):
|
||||
if square_target < 0:
|
||||
raise ValueError('Square root of negative number is not defined in real numbers')
|
||||
if square_target == 1:
|
||||
root = 1
|
||||
print(f'The square root of {square_target} is 1')
|
||||
elif square_target == 0:
|
||||
root = 0
|
||||
print(f'The square root of {square_target} is 0')
|
||||
|
||||
else:
|
||||
low = 0
|
||||
high = max(1, square_target)
|
||||
root = None
|
||||
|
||||
for _ in range(max_iterations):
|
||||
mid = (low + high) / 2
|
||||
square_mid = mid**2
|
||||
|
||||
if abs(square_mid - square_target) < tolerance:
|
||||
root = mid
|
||||
break
|
||||
|
||||
--fcc-editable-region--
|
||||
elif square_mid < square_target:
|
||||
low = mid
|
||||
|
||||
--fcc-editable-region--
|
||||
```
|
||||
@@ -0,0 +1,76 @@
|
||||
---
|
||||
id: 65ef1d5e3d2927c5e0f4997b
|
||||
title: Step 17
|
||||
challengeType: 20
|
||||
dashedName: step-17
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Outside the for loop, create an `if` statement to check if the value of `root` is still `None`. If it is, print the message `'Failed to converge within {max_iterations} iterations.'`. Remember to format the message using an f-string.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should create an `if` statement that checks if `root is None`.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[2].find_ifs()[0].find_conditions()[0].is_equivalent("root is None")`));
|
||||
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
You should pass the argument `f'Failed to converge within {max_iterations} iterations.'` to the `print` function.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[2].find_ifs()[0].is_equivalent("if root is None:\\n print(f'Failed to converge within {max_iterations} iterations.')")`));
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
def square_root_bisection(square_target, tolerance=1e-7, max_iterations=100):
|
||||
if square_target < 0:
|
||||
raise ValueError('Square root of negative number is not defined in real numbers')
|
||||
if square_target == 1:
|
||||
root = 1
|
||||
print(f'The square root of {square_target} is 1')
|
||||
elif square_target == 0:
|
||||
root = 0
|
||||
print(f'The square root of {square_target} is 0')
|
||||
|
||||
else:
|
||||
low = 0
|
||||
high = max(1, square_target)
|
||||
root = None
|
||||
|
||||
for _ in range(max_iterations):
|
||||
mid = (low + high) / 2
|
||||
square_mid = mid**2
|
||||
|
||||
if abs(square_mid - square_target) < tolerance:
|
||||
root = mid
|
||||
break
|
||||
|
||||
elif square_mid < square_target:
|
||||
low = mid
|
||||
else:
|
||||
high = mid
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
```
|
||||
@@ -0,0 +1,77 @@
|
||||
---
|
||||
id: 65ef1d924ff2e5c7031c6ce8
|
||||
title: Step 18
|
||||
challengeType: 20
|
||||
dashedName: step-18
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Create an `else` clause to handle the case where the value of `root` is not `None`, indicating that a root hass been found. If it is not `None`, print the message `'The square root of {square_target} is approximately {root}'`. Remember to format using an f-string.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should create an `else` clause.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[2].find_ifs()[0].find_conditions()[1] == _Node()`));
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
You should print `f'The square root of {square_target} is approximately {root}'` within the `else` body.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_function("square_root_bisection").find_ifs()[1].find_bodies()[2].find_ifs()[0].find_bodies()[1].is_equivalent("print(f'The square root of {square_target} is approximately {root}')")`));
|
||||
}
|
||||
})
|
||||
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
def square_root_bisection(square_target, tolerance=1e-7, max_iterations=100):
|
||||
if square_target < 0:
|
||||
raise ValueError('Square root of negative number is not defined in real numbers')
|
||||
if square_target == 1:
|
||||
root = 1
|
||||
print(f'The square root of {square_target} is 1')
|
||||
elif square_target == 0:
|
||||
root = 0
|
||||
print(f'The square root of {square_target} is 0')
|
||||
|
||||
else:
|
||||
low = 0
|
||||
high = max(1, square_target)
|
||||
root = None
|
||||
|
||||
for _ in range(max_iterations):
|
||||
mid = (low + high) / 2
|
||||
square_mid = mid**2
|
||||
|
||||
if abs(square_mid - square_target) < tolerance:
|
||||
root = mid
|
||||
break
|
||||
|
||||
elif square_mid < square_target:
|
||||
low = mid
|
||||
else:
|
||||
high = mid
|
||||
|
||||
--fcc-editable-region--
|
||||
if root is None:
|
||||
print(f"Failed to converge within {max_iterations} iterations.")
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
```
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
id: 65ef1dd722f6e7c8294eeec4
|
||||
title: Step 19
|
||||
challengeType: 20
|
||||
dashedName: step-19
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Finally, return the value of `root` from the `square_root_bisection` function.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should return `root` at the end of the function.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
const pyClassStr = runPython(`str(_Node(_code).find_function("square_root_bisection"))`);
|
||||
assert.match(pyClassStr, /return\s*root/)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
def square_root_bisection(square_target, tolerance=1e-7, max_iterations=100):
|
||||
if square_target < 0:
|
||||
raise ValueError('Square root of negative number is not defined in real numbers')
|
||||
if square_target == 1:
|
||||
root = 1
|
||||
print(f'The square root of {square_target} is 1')
|
||||
elif square_target == 0:
|
||||
root = 0
|
||||
print(f'The square root of {square_target} is 0')
|
||||
|
||||
else:
|
||||
low = 0
|
||||
high = max(1, square_target)
|
||||
root = None
|
||||
|
||||
for _ in range(max_iterations):
|
||||
mid = (low + high) / 2
|
||||
square_mid = mid**2
|
||||
|
||||
if abs(square_mid - square_target) < tolerance:
|
||||
root = mid
|
||||
break
|
||||
|
||||
elif square_mid < square_target:
|
||||
low = mid
|
||||
else:
|
||||
high = mid
|
||||
|
||||
--fcc-editable-region--
|
||||
if root is None:
|
||||
print(f"Failed to converge within {max_iterations} iterations.")
|
||||
|
||||
else:
|
||||
print(f'The square root of {square_target} is approximately {root}')
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
```
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
id: 65ef1e10268f8ec9121446d1
|
||||
title: Step 20
|
||||
challengeType: 20
|
||||
dashedName: step-20
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Outside the function definiton, create a variable `N` and assign the value of `16` to it.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should have the variable `N = 16` outside the function definition.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () =>
|
||||
{
|
||||
assert(runPython(`_Node(_code).find_variable("N").is_equivalent("N = 16")`))
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
def square_root_bisection(square_target, tolerance=1e-7, max_iterations=100):
|
||||
if square_target < 0:
|
||||
raise ValueError('Square root of negative number is not defined in real numbers')
|
||||
if square_target == 1:
|
||||
root = 1
|
||||
print(f'The square root of {square_target} is 1')
|
||||
elif square_target == 0:
|
||||
root = 0
|
||||
print(f'The square root of {square_target} is 0')
|
||||
|
||||
else:
|
||||
low = 0
|
||||
high = max(1, square_target)
|
||||
root = None
|
||||
|
||||
for _ in range(max_iterations):
|
||||
mid = (low + high) / 2
|
||||
square_mid = mid**2
|
||||
|
||||
if abs(square_mid - square_target) < tolerance:
|
||||
root = mid
|
||||
break
|
||||
|
||||
elif square_mid < square_target:
|
||||
low = mid
|
||||
else:
|
||||
high = mid
|
||||
|
||||
if root is None:
|
||||
print(f"Failed to converge within {max_iterations} iterations.")
|
||||
|
||||
else:
|
||||
print(f'The square root of {square_target} is approximately {root}')
|
||||
|
||||
return root
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
```
|
||||
@@ -0,0 +1,115 @@
|
||||
---
|
||||
id: 65ef1eac497754cafa12a26c
|
||||
title: Step 21
|
||||
challengeType: 20
|
||||
dashedName: step-21
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
Call the `square_root_bisection` function with the `N` variable as the argument and print the result.
|
||||
|
||||
Experiment with larger values.
|
||||
|
||||
With this, you have successfully implemented the bisection method to find the square root of a number.
|
||||
|
||||
# --hints--
|
||||
|
||||
You should call the `square_root_bisection` function with the `N` variable as the argument and print the result.
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => assert(runPython(`_Node(_code).has_call("square_root_bisection(N)")`))
|
||||
})
|
||||
```
|
||||
|
||||
# --seed--
|
||||
|
||||
## --seed-contents--
|
||||
|
||||
```py
|
||||
def square_root_bisection(square_target, tolerance=1e-7, max_iterations=100):
|
||||
if square_target < 0:
|
||||
raise ValueError('Square root of negative number is not defined in real numbers')
|
||||
if square_target == 1:
|
||||
root = 1
|
||||
print(f'The square root of {square_target} is 1')
|
||||
elif square_target == 0:
|
||||
root = 0
|
||||
print(f'The square root of {square_target} is 0')
|
||||
|
||||
else:
|
||||
low = 0
|
||||
high = max(1, square_target)
|
||||
root = None
|
||||
|
||||
for _ in range(max_iterations):
|
||||
mid = (low + high) / 2
|
||||
square_mid = mid**2
|
||||
|
||||
if abs(square_mid - square_target) < tolerance:
|
||||
root = mid
|
||||
break
|
||||
|
||||
elif square_mid < square_target:
|
||||
low = mid
|
||||
else:
|
||||
high = mid
|
||||
|
||||
if root is None:
|
||||
print(f"Failed to converge within {max_iterations} iterations.")
|
||||
|
||||
else:
|
||||
print(f'The square root of {square_target} is approximately {root}')
|
||||
|
||||
return root
|
||||
|
||||
--fcc-editable-region--
|
||||
N = 16
|
||||
|
||||
--fcc-editable-region--
|
||||
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```py
|
||||
def square_root_bisection(square_target, tolerance=1e-7, max_iterations=100):
|
||||
if square_target < 0:
|
||||
raise ValueError('Square root of negative number is not defined in real numbers')
|
||||
if square_target == 1:
|
||||
root = 1
|
||||
print(f'The square root of {square_target} is 1')
|
||||
elif square_target == 0:
|
||||
root = 0
|
||||
print(f'The square root of {square_target} is 0')
|
||||
|
||||
else:
|
||||
low = 0
|
||||
high = max(1, square_target)
|
||||
root = None
|
||||
|
||||
for _ in range(max_iterations):
|
||||
mid = (low + high) / 2
|
||||
square_mid = mid**2
|
||||
|
||||
if abs(square_mid - square_target) < tolerance:
|
||||
root = mid
|
||||
break
|
||||
|
||||
elif square_mid < square_target:
|
||||
low = mid
|
||||
else:
|
||||
high = mid
|
||||
|
||||
if root is None:
|
||||
print(f"Failed to converge within {max_iterations} iterations.")
|
||||
|
||||
else:
|
||||
print(f'The square root of {square_target} is approximately {root}')
|
||||
|
||||
return root
|
||||
|
||||
N = 16
|
||||
square_root_bisection(N)
|
||||
```
|
||||
@@ -7,7 +7,7 @@ dashedName: step-8
|
||||
|
||||
# --description--
|
||||
|
||||
To see the `cat-head` element, give it a linear gradient background with `#5e5e5e` at `85%` and `#45454f` at `100%`.
|
||||
To see the `.cat-head` element, give it a linear gradient background with `#5e5e5e` at `85%` and `#45454f` at `100%`.
|
||||
|
||||
You might not notice the difference between these two colors, but they are there.
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ Inside your `.cat-ears` element, create two `div` elements with the classes `cat
|
||||
|
||||
# --hints--
|
||||
|
||||
You should not change the existing `div` element with the class `car-ears`.
|
||||
You should not change the existing `div` element with the class `cat-ears`.
|
||||
|
||||
```js
|
||||
assert(document.querySelectorAll('div.cat-ears').length === 1);
|
||||
|
||||
@@ -11,7 +11,7 @@ The last position property value is `sticky`. `sticky` positioning is a hybrid o
|
||||
|
||||
Change the value of the `position` property of `.cat-head` to `sticky`, set `top` to `0`, then remove `left` and its value.
|
||||
|
||||
**Note**: To see how `sticky` works, you have to place a couple of texts before and after your `.cat-head` `div` element. If you scroll up after that, you'll see that the `.cat-head` gets stuck to the top and remains there.
|
||||
**Note**: To see how `sticky` works, you have to place a couple of texts before and after your `.cat-head` `div` element. If you scroll down after that, you'll see that the `.cat-head` gets stuck to the top and remains there.
|
||||
|
||||
# --hints--
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ while (continueLoop) {
|
||||
--fcc-editable-region--
|
||||
|
||||
--fcc-editable-region--
|
||||
if (done === count) {
|
||||
if (done === count) {
|
||||
continueLoop = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ let done = 0;
|
||||
while (continueLoop) {
|
||||
done++;
|
||||
rows.push(padRow(done, count));
|
||||
if (done === count) {
|
||||
if (done === count) {
|
||||
continueLoop = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ let done = 0;
|
||||
while (done !== count) {
|
||||
done++;
|
||||
rows.push(padRow(done, count));
|
||||
if (done === count) {
|
||||
if (done === count) {
|
||||
continueLoop = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,15 +23,7 @@ Test value of `__name__`
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => assert(__pyodide.runPython(`__name__ == '__main__'`))
|
||||
})
|
||||
```
|
||||
|
||||
Test __locals and __pyodide
|
||||
|
||||
```js
|
||||
({
|
||||
test: () => assert(__pyodide.runPython(`__locals.get('add')(4,5) == 9`))
|
||||
test: () => assert(runPython(`__name__ == '__main__'`))
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
id: 658111239f39a01c8f095c44
|
||||
videoId: nLDychdBwUg
|
||||
title: "Dialogue 1: What Motivates the Team?"
|
||||
challengeType: 21
|
||||
dashedName: dialogue-1-what-motivates-the-team
|
||||
@@ -13,3 +12,275 @@ Watch the video below to understand the context of the upcoming lessons.
|
||||
# --assignment--
|
||||
|
||||
Watch the video
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Brian",
|
||||
"position": { "x": -25, "y": 0, "z": 1 }
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"position": { "x": 125, "y": 0, "z": 1 }
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1
|
||||
},
|
||||
"alwaysShowDialogue": true
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Brian",
|
||||
"position": { "x": 25, "y": 0, "z": 1 },
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"position": { "x": 70, "y": 0, "z": 1 },
|
||||
"startTime": 0.5
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 1,
|
||||
"finishTime": 4.5,
|
||||
"dialogue": {
|
||||
"text": "Hey Maria, I have a question… Do you know what motivates the team?",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 4.9,
|
||||
"finishTime": 7.4,
|
||||
"dialogue": {
|
||||
"text": "How about you? What makes you feel motivated?",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 8.7,
|
||||
"finishTime": 12.3,
|
||||
"dialogue": {
|
||||
"text": "Hi Brian! Well, one thing that really motivates me is learning new things.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 12.7,
|
||||
"finishTime": 16,
|
||||
"dialogue": {
|
||||
"text": "I love exploring many new technologies and improving my skills.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 16.5,
|
||||
"finishTime": 18.2,
|
||||
"dialogue": {
|
||||
"text": "It keeps me excited about our projects.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 19.7,
|
||||
"finishTime": 20.9,
|
||||
"dialogue": {
|
||||
"text": "That's great to hear, Maria.",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 21.3,
|
||||
"finishTime": 24.7,
|
||||
"dialogue": {
|
||||
"text": "Learning and growing professionally motivates me a lot.",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 25,
|
||||
"finishTime": 27.2,
|
||||
"dialogue": {
|
||||
"text": "But you know what demotivates me sometimes?",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 27.7,
|
||||
"finishTime": 32.6,
|
||||
"dialogue": {
|
||||
"text": "Dealing with many tight deadlines and feeling like I'm rushing to complete tasks.",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 33.1,
|
||||
"finishTime": 37.3,
|
||||
"dialogue": {
|
||||
"text": "I can understand that, Brian. Racing against the clock can be demotivating.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 37.7,
|
||||
"finishTime": 39.7,
|
||||
"dialogue": {
|
||||
"text": "Well, collaborating with our creative team",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 39.7,
|
||||
"finishTime": 42.5,
|
||||
"dialogue": {
|
||||
"text": "and brainstorming many ideas really inspires me.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 42.8,
|
||||
"finishTime": 44.6,
|
||||
"dialogue": {
|
||||
"text": "It's where we generate our best concepts.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 45.5,
|
||||
"finishTime": 49,
|
||||
"dialogue": {
|
||||
"text": "I agree, Maria. Collaboration and creativity are great.",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 49.3,
|
||||
"finishTime": 53.6,
|
||||
"dialogue": {
|
||||
"text": "The problem is encountering many technical issues that slow our progress down.",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 54,
|
||||
"finishTime": 55.5,
|
||||
"dialogue": {
|
||||
"text": "It is really frustrating.",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 56.5,
|
||||
"finishTime": 58.4,
|
||||
"dialogue": {
|
||||
"text": "Yeah, technical glitches are complicated",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 58.4,
|
||||
"finishTime": 61,
|
||||
"dialogue": {
|
||||
"text": "and there's not much we can do other than try to solve them.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 62,
|
||||
"finishTime": 63.3,
|
||||
"dialogue": {
|
||||
"text": "But do you know what else is great?",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 63.7,
|
||||
"finishTime": 66.7,
|
||||
"dialogue": {
|
||||
"text": "Seeing the team's enthusiasm after solving these issues.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 67.1,
|
||||
"finishTime": 69.8,
|
||||
"dialogue": {
|
||||
"text": "When you see the team inspired, it can boost your motivation.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 71.3,
|
||||
"finishTime": 75.4,
|
||||
"dialogue": {
|
||||
"text": "Yeah. Wow. You know what? This was really a motivating talk.",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 75.7,
|
||||
"finishTime": 77.1,
|
||||
"dialogue": {
|
||||
"text": "Thanks for sharing your thoughts.",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 77.7,
|
||||
"finishTime": 79.8,
|
||||
"dialogue": {
|
||||
"text": "Anytime. It's good to have these discussions.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 80,
|
||||
"finishTime": 81.6,
|
||||
"dialogue": {
|
||||
"text": "It reminds us of what keeps us going.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"position": { "x": 125, "y": 0, "z": 1 },
|
||||
"startTime": 82.1
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"position": { "x": -25, "y": 0, "z": 1 },
|
||||
"startTime": 82.6
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 22
|
||||
dashedName: task-6
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Maria: Hi Brian! Well, one thing that really motivates me is learning new things.
|
||||
-->
|
||||
<!-- (Audio) Maria: Hi, Brian! Well, one thing that really motivates me is learning new things. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -18,7 +15,7 @@ A gerund is the `-ing` form of a verb used as a noun. It can be the subject of a
|
||||
|
||||
## --sentence--
|
||||
|
||||
`Well, one thing that really motivates me is _ new things.`
|
||||
`Hi, Brian. Well, one thing that really motivates me is _ new things.`
|
||||
|
||||
## --blanks--
|
||||
|
||||
@@ -27,3 +24,47 @@ A gerund is the `-ing` form of a verb used as a noun. It can be the subject of a
|
||||
### --feedback--
|
||||
|
||||
This word is a gerund, the `-ing` form of the verb used as a noun, indicating the action or process of gaining knowledge.
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"position": {"x":50,"y":0,"z":1.5},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 7.48,
|
||||
"finishTimestamp": 11.10
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 1,
|
||||
"finishTime": 4.62,
|
||||
"dialogue": {
|
||||
"text": "Hi, Brian. Well, one thing that really motivates me is learning new things.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 0,
|
||||
"startTime": 5.12
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 22
|
||||
dashedName: task-5
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Maria: Hi Brian! Well, one thing that really motivates me is learning new things.
|
||||
-->
|
||||
<!-- (Audio) Maria: Hi, Brian! Well, one thing that really motivates me is learning new things. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -20,7 +17,7 @@ When you add an `s` at the end of a word, like `things`, it means you are talkin
|
||||
|
||||
## --sentence--
|
||||
|
||||
`Hi Brian! _, one _ that really motivates me _ learning new _.`
|
||||
`Hi, Brian! _, one _ that really motivates me _ learning new _.`
|
||||
|
||||
## --blanks--
|
||||
|
||||
@@ -53,3 +50,47 @@ This is the verb `to be` conjugated in the third person singular.
|
||||
### --feedback--
|
||||
|
||||
Maria uses this word to talk about more than one item or idea she likes to learn. It is the plural form of `thing`.
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"position": {"x":50,"y":0,"z":1.5},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 7.48,
|
||||
"finishTimestamp": 11.10
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 1,
|
||||
"finishTime": 4.62,
|
||||
"dialogue": {
|
||||
"text": "Hi, Brian. Well, one thing that really motivates me is learning new things.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 0,
|
||||
"startTime": 5.12
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 19
|
||||
dashedName: task-7
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Maria: Hi Brian! Well, one thing that really motivates me is learning new things.
|
||||
-->
|
||||
<!-- (Audio) Maria: Hi Brian! Well, one thing that really motivates me is learning new things. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -51,3 +48,47 @@ learning new things
|
||||
## --video-solution--
|
||||
|
||||
4
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"position": {"x":50,"y":0,"z":1.5},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 7.48,
|
||||
"finishTimestamp": 11.10
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 1,
|
||||
"finishTime": 4.62,
|
||||
"dialogue": {
|
||||
"text": "Hi, Brian. Well, one thing that really motivates me is learning new things.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 0,
|
||||
"startTime": 5.12
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 22
|
||||
dashedName: task-8
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Maria: I love exploring many new technologies and improving my skills.
|
||||
-->
|
||||
<!-- (Audio) Maria: I love exploring many new technologies and improving my skills. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -37,3 +34,47 @@ This word is a gerund describing the activity Maria enjoys related to discoverin
|
||||
### --feedback--
|
||||
|
||||
Another gerund that follows `and`, indicating another activity Maria enjoys, which is about getting better at something. It also ends in `-ing` and serves as a noun.
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"position": {"x":50,"y":0,"z":1.5},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 11.76,
|
||||
"finishTimestamp": 15.04
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 1,
|
||||
"finishTime": 4.28,
|
||||
"dialogue": {
|
||||
"text": "I love exploring many new technologies and improving my skills.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 0,
|
||||
"startTime": 4.78
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 19
|
||||
dashedName: task-10
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Maria: I love exploring many new technologies and improving my skills. It keeps me excited about our projects.
|
||||
-->
|
||||
<!-- (Audio) Maria: I love exploring many new technologies and improving my skills. It keeps me excited about our projects. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -26,7 +23,7 @@ In `I love exploring many new technologies`, how is `exploring` used?
|
||||
|
||||
## --answers--
|
||||
|
||||
As a present continuous
|
||||
As a verb in the present continuous structure
|
||||
|
||||
### --feedback--
|
||||
|
||||
@@ -34,7 +31,7 @@ Present continuous are for actions happening now. This is not showing an action
|
||||
|
||||
---
|
||||
|
||||
As a simple present verb
|
||||
As a verb in the simple present structure
|
||||
|
||||
### --feedback--
|
||||
|
||||
@@ -42,11 +39,11 @@ Simple present verbs don't end in `-ing`.
|
||||
|
||||
---
|
||||
|
||||
As a gerund
|
||||
As a verb in the gerund form
|
||||
|
||||
---
|
||||
|
||||
As a past participle
|
||||
As a verb in the past participle form
|
||||
|
||||
### --feedback--
|
||||
|
||||
@@ -55,3 +52,47 @@ Past participles are for perfect tenses or as adjectives. This is not used like
|
||||
## --video-solution--
|
||||
|
||||
3
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"position": {"x":50,"y":0,"z":1.5},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 11.76,
|
||||
"finishTimestamp": 17.26
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 1,
|
||||
"finishTime": 6.50,
|
||||
"dialogue": {
|
||||
"text": "I love exploring many new technologies and improving my skills. It keeps me excited about our projects.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 0,
|
||||
"startTime": 7.00
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 22
|
||||
dashedName: task-18
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Maria: I can understand that, Brian. Racing against the clock can be demotivating.
|
||||
-->
|
||||
<!-- (Audio) Maria: I can understand that, Brian. Racing against the clock can be demotivating. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -31,3 +28,47 @@ Adding a prefix to a word can change its meaning.
|
||||
### --feedback--
|
||||
|
||||
Maria uses an adjective ending in `-ing` to describe a feeling that is the opposite of `motivating`.
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"position": {"x":50,"y":0,"z":1.5},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 32.22,
|
||||
"finishTimestamp": 36.08
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 1,
|
||||
"finishTime": 4.86,
|
||||
"dialogue": {
|
||||
"text": "I can understand that, Brian. Racing against the clock can be demotivating.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 0,
|
||||
"startTime": 5.36
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 22
|
||||
dashedName: task-11
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Brian: That's great to hear, Maria.
|
||||
-->
|
||||
<!-- (Audio) Brian: That's great to hear, Maria. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -27,3 +24,47 @@ Listen to the audio and complete the sentence.
|
||||
### --feedback--
|
||||
|
||||
This word is used when someone listens to what another person says.
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Brian",
|
||||
"position": {"x":50,"y":15,"z":1.2},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 18.68,
|
||||
"finishTimestamp": 19.86
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Brian",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 1,
|
||||
"finishTime": 2.18,
|
||||
"dialogue": {
|
||||
"text": "That's great to hear, Maria.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"opacity": 0,
|
||||
"startTime": 2.68
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 22
|
||||
dashedName: task-12
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Maria: Learning and growing professionally motivates me a lot.
|
||||
-->
|
||||
<!-- (Audio) Maria: Learning and growing professionally motivates me a lot. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -49,3 +46,47 @@ This word means to develop or become bigger or more advanced. It ends with `-ing
|
||||
### --feedback--
|
||||
|
||||
This word is related to work or a career. It describes doing something in a way that shows good skills and behavior at a job. it ends with `-ly`
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Brian",
|
||||
"position": {"x":50,"y":15,"z":1.2},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 20.28,
|
||||
"finishTimestamp": 23.66
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Brian",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 1,
|
||||
"finishTime": 4.38,
|
||||
"dialogue": {
|
||||
"text": "Learning and growing professionally motivates me a lot.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"opacity": 0,
|
||||
"startTime": 4.88
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 19
|
||||
dashedName: task-13
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Brian: That's great to hear, Maria. Learning and growing professionally motivates me a lot.
|
||||
-->
|
||||
<!-- (Audio) Brian: That's great to hear, Maria. Learning and growing professionally motivates me a lot. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -51,3 +48,47 @@ Reflect on how skill improvement fits into overall personal and professional dev
|
||||
## --video-solution--
|
||||
|
||||
1
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Brian",
|
||||
"position": {"x":50,"y":15,"z":1.2},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 18.68,
|
||||
"finishTimestamp": 23.66
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Brian",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 1,
|
||||
"finishTime": 5.98,
|
||||
"dialogue": {
|
||||
"text": "That's great to hear, Maria. Learning and growing professionally motivates me a lot.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"opacity": 0,
|
||||
"startTime": 6.48
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 19
|
||||
dashedName: task-14
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Brian: That's great to hear, Maria. Learning and growing professionally motivates me a lot. But you know what demotivates me sometimes?
|
||||
-->
|
||||
<!-- (Audio) Brian: That's great to hear, Maria. Learning and growing professionally motivates me a lot. But you know what demotivates me sometimes? -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -53,3 +50,65 @@ He's adding to the conversation, not changing the topic.
|
||||
## --video-solution--
|
||||
|
||||
2
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Brian",
|
||||
"position": {"x":50,"y":15,"z":1.2},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 18.68,
|
||||
"finishTimestamp": 26.26
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Brian",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 1,
|
||||
"finishTime": 2.18,
|
||||
"dialogue": {
|
||||
"text": "That's great to hear, Maria.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 2.60,
|
||||
"finishTime": 5.64,
|
||||
"dialogue": {
|
||||
"text": "Learning and growing professionally motivates me a lot,",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 6.02,
|
||||
"finishTime": 8.58,
|
||||
"dialogue": {
|
||||
"text": "but you know what demotivates me sometimes?",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"opacity": 0,
|
||||
"startTime": 9.08
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -28,4 +28,48 @@ Listen to the audio and complete the sentence.
|
||||
|
||||
### --feedback--
|
||||
|
||||
This word means feeling very happy and eager.
|
||||
This word means feeling very happy and eager.
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"position": {"x":50,"y":0,"z":1.5},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 15.32,
|
||||
"finishTimestamp": 17.26
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 1,
|
||||
"finishTime": 2.94,
|
||||
"dialogue": {
|
||||
"text": "It keeps me excited about our projects.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 0,
|
||||
"startTime": 3.44
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 19
|
||||
dashedName: task-16
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Brian:Dealing with many tight deadlines and feeling like I'm rushing to complete tasks.
|
||||
-->
|
||||
<!-- (Audio) Brian:Dealing with many tight deadlines and feeling like I'm rushing to complete tasks. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -55,3 +52,47 @@ This phrase means having plenty of time, which is different from what Brian mean
|
||||
## --video-solution--
|
||||
|
||||
3
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Brian",
|
||||
"position": {"x":50,"y":15,"z":1.2},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 26.66,
|
||||
"finishTimestamp": 31.58
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Brian",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 1,
|
||||
"finishTime": 5.92,
|
||||
"dialogue": {
|
||||
"text": "Dealing with many tight deadlines and feeling like I'm rushing to complete tasks.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"opacity": 0,
|
||||
"startTime": 6.42
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 22
|
||||
dashedName: task-17
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Brian: Dealing with many tight deadlines and feeling like I'm rushing to complete tasks.
|
||||
-->
|
||||
<!-- (Audio) Brian: Dealing with many tight deadlines and feeling like I'm rushing to complete tasks. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -47,3 +44,47 @@ This word is a preposition used to compare or illustrate a similarity to somethi
|
||||
### --feedback--
|
||||
|
||||
It means you are doing something quickly because you do not have much time. It ends with `-ing`.
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Brian",
|
||||
"position": {"x":50,"y":15,"z":1.2},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 26.66,
|
||||
"finishTimestamp": 31.58
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Brian",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 1,
|
||||
"finishTime": 5.92,
|
||||
"dialogue": {
|
||||
"text": "Dealing with many tight deadlines and feeling like I'm rushing to complete tasks.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"opacity": 0,
|
||||
"startTime": 6.42
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,6 +5,8 @@ challengeType: 19
|
||||
dashedName: task-20
|
||||
---
|
||||
|
||||
<!-- (Audio) Maria: Well, collaborating with our creative team and brainstorming many ideas really inspires me. -->
|
||||
|
||||
# --description--
|
||||
|
||||
The word `brainstorming` refers to a group discussion to produce ideas and solve problems.
|
||||
@@ -46,3 +48,47 @@ It means adhering to specific instructions, which is not the same as the word.
|
||||
## --video-solution--
|
||||
|
||||
2
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"position": {"x":50,"y":0,"z":1.5},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 36.50,
|
||||
"finishTimestamp": 41.38
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 1,
|
||||
"finishTime": 5.88,
|
||||
"dialogue": {
|
||||
"text": "Well, collaborating with our creative team and brainstorming many ideas really inspires me.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 0,
|
||||
"startTime": 6.38
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 22
|
||||
dashedName: task-28
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Brian: The problem is encountering many technical issues that make our progress slow down.
|
||||
-->
|
||||
<!-- (Audio) Brian: The problem is encountering many technical issues that slow our progress down. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -18,7 +15,7 @@ The phrase `slow down` means to decrease in speed or reduce the rate of progress
|
||||
|
||||
## --sentence--
|
||||
|
||||
`The problem is encountering many technical issues that make our progress _ _.`
|
||||
`The problem is encountering many technical issues that _ our progress _.`
|
||||
|
||||
## --blanks--
|
||||
|
||||
@@ -35,3 +32,47 @@ This word is used to describe a decrease in speed or pace.
|
||||
### --feedback--
|
||||
|
||||
This adverb complements the phrase to indicate a reduction or decrease in intensity, speed, or amount.
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Brian",
|
||||
"position": {"x":50,"y":15,"z":1.2},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 48.30,
|
||||
"finishTimestamp": 52.62
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Brian",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"startTime": 1,
|
||||
"finishTime": 5.32,
|
||||
"dialogue": {
|
||||
"text": "The problem is encountering many technical issues that slow our progress down.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Brian",
|
||||
"opacity": 0,
|
||||
"startTime": 5.82
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,6 +5,8 @@ challengeType: 19
|
||||
dashedName: task-32
|
||||
---
|
||||
|
||||
<!-- (Audio) Maria: Yeah, technical glitches are complicated and there’s not much we can do other than try to solve them. -->
|
||||
|
||||
# --description--
|
||||
|
||||
The phrase `other than` indicates the presence of an alternative or different option.
|
||||
@@ -46,3 +48,47 @@ It means the singular or exclusive option, which is not the same as the phrase.
|
||||
## --video-solution--
|
||||
|
||||
3
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"position": {"x":50,"y":0,"z":1.5},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 55.34,
|
||||
"finishTimestamp": 60.16
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 1,
|
||||
"finishTime": 5.82,
|
||||
"dialogue": {
|
||||
"text": "Yeah, technical glitches are complicated and there's not much we can do other than try to solve them.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 0,
|
||||
"startTime": 6.32
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 22
|
||||
dashedName: task-35
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Maria: When you see the team inspired, it can boost your motivation.
|
||||
-->
|
||||
<!-- (Audio) Maria: When you see the team inspired, it can boost your motivation. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -43,3 +40,47 @@ This possessive adjective is used to refer to something that belongs to the pers
|
||||
### --feedback--
|
||||
|
||||
This noun refers to the reason or reasons one has for acting or behaving in a particular way.
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"position": {"x":50,"y":0,"z":1.5},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 66.12,
|
||||
"finishTimestamp": 68.80
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 1,
|
||||
"finishTime": 3.68,
|
||||
"dialogue": {
|
||||
"text": "When you see the team inspired, it can boost your motivation.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 0,
|
||||
"startTime": 4.18
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 22
|
||||
dashedName: task-38
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Anytime. It's good to have these discussions. It reminds us of what keeps us going.
|
||||
-->
|
||||
<!-- (Audio) Maria: Anytime. It's good to have these discussions. It reminds us of what keeps us going. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -29,3 +26,47 @@ In the dialogue, Maria talks about the importance of discussions to help them re
|
||||
### --feedback--
|
||||
|
||||
This verb is used to make someone think of something they might have forgotten. It brings something back into someone's mind.
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"position": {"x":50,"y":0,"z":1.5},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 76.52,
|
||||
"finishTimestamp": 80.60
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 1,
|
||||
"finishTime": 5.08,
|
||||
"dialogue": {
|
||||
"text": "Anytime. It's good to have these discussions. It reminds us of what keeps us going.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 0,
|
||||
"startTime": 5.58
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 22
|
||||
dashedName: task-39
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
It reminds us of what keeps us going.
|
||||
-->
|
||||
<!-- (Audio) Maria: It reminds us of what keeps us going. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -43,3 +40,47 @@ This pronoun refers to the speaker and at least one other person, indicating a c
|
||||
### --feedback--
|
||||
|
||||
This word is used in the context of continuing forward or persevering in a particular action or state.
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "cafe.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"position": {"x":50,"y":0,"z":1.5},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-1.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 79.06,
|
||||
"finishTimestamp": 80.60
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"startTime": 1,
|
||||
"finishTime": 2.54,
|
||||
"dialogue": {
|
||||
"text": "It reminds us of what keeps us going.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Maria",
|
||||
"opacity": 0,
|
||||
"startTime": 3.04
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
id: 658160772584ba319849f910
|
||||
videoId: nLDychdBwUg
|
||||
title: "Dialogue 2: Asking How Someone Feels"
|
||||
challengeType: 21
|
||||
dashedName: dialogue-2-asking-how-someone-feels
|
||||
@@ -13,3 +12,239 @@ Watch the video below to understand the context of the upcoming lessons.
|
||||
# --assignment--
|
||||
|
||||
Watch the video
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "company2-roof.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Alice",
|
||||
"position": { "x": -25, "y": 0, "z": 1 }
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"position": { "x": 125, "y": 0, "z": 1 }
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-2.mp3",
|
||||
"startTime": 1
|
||||
},
|
||||
"alwaysShowDialogue": true
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Alice",
|
||||
"position": { "x": 25, "y": 0, "z": 1 },
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"position": { "x": 70, "y": 0, "z": 1 },
|
||||
"startTime": 0.5
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"startTime": 2,
|
||||
"finishTime": 5.6,
|
||||
"dialogue": {
|
||||
"text": "Hi Tom, you look a bit down these days. Is everything okay?",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"startTime": 6.3,
|
||||
"finishTime": 9.5,
|
||||
"dialogue": {
|
||||
"text": "Hey Alice, yeah, I feel a bit demotivated.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"startTime": 9.8,
|
||||
"finishTime": 13.6,
|
||||
"dialogue": {
|
||||
"text": "One thing that really gets to me is working long hours without any breaks.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"startTime": 13.8,
|
||||
"finishTime": 16.7,
|
||||
"dialogue": {
|
||||
"text": "It's exhausting, and it feels like I'm constantly running",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"startTime": 16.7,
|
||||
"finishTime": 18.1,
|
||||
"dialogue": {
|
||||
"text": "without knowing where I'm going.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"startTime": 18.9,
|
||||
"finishTime": 22.7,
|
||||
"dialogue": {
|
||||
"text": "I totally get that, Tom. Working overtime all the time can be draining.",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"startTime": 23.4,
|
||||
"finishTime": 25.7,
|
||||
"dialogue": {
|
||||
"text": "Personally, I hate dealing with office politics.",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"startTime": 26.2,
|
||||
"finishTime": 28.8,
|
||||
"dialogue": {
|
||||
"text": "It's frustrating when people are constantly trying to beat each other",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"startTime": 28.8,
|
||||
"finishTime": 30.6,
|
||||
"dialogue": {
|
||||
"text": "instead of working together as a team.",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"startTime": 31.3,
|
||||
"finishTime": 34.7,
|
||||
"dialogue": {
|
||||
"text": "You're right, Alice. Dealing with office politics is never fun.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"startTime": 35,
|
||||
"finishTime": 38.4,
|
||||
"dialogue": {
|
||||
"text": "Another thing that gets to me is having too many meetings.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"startTime": 38.9,
|
||||
"finishTime": 41.7,
|
||||
"dialogue": {
|
||||
"text": "Sometimes, it feels like we're meeting for no reason,",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"startTime": 41.7,
|
||||
"finishTime": 44.3,
|
||||
"dialogue": {
|
||||
"text": "and it's hard to find time to actually work on projects.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"startTime": 45,
|
||||
"finishTime": 48.4,
|
||||
"dialogue": {
|
||||
"text": "I hear you, Tom. Sitting in meetings for hours can be discouraging.",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"startTime": 49,
|
||||
"finishTime": 52.6,
|
||||
"dialogue": {
|
||||
"text": "For me, what really annoys me is having to do a bunch of repetitive tasks",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"startTime": 52.6,
|
||||
"finishTime": 56.6,
|
||||
"dialogue": {
|
||||
"text": "without any variation. It feels like I'm wasting my skills and creativity.",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"startTime": 57.06,
|
||||
"finishTime": 59,
|
||||
"dialogue": {
|
||||
"text": "That does sound frustrating, Alice.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"startTime": 59.6,
|
||||
"finishTime": 62.8,
|
||||
"dialogue": {
|
||||
"text": "Repeating the same tasks over and over can be demotivating.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"startTime": 63.2,
|
||||
"finishTime": 66.4,
|
||||
"dialogue": {
|
||||
"text": "Thanks for listening, by the way. It feels good to talk about these things.",
|
||||
"align": "right"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"startTime": 66.8,
|
||||
"finishTime": 69.4,
|
||||
"dialogue": {
|
||||
"text": "Of course, Tom. We all have our moments of demotivation,",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"startTime": 69.4,
|
||||
"finishTime": 71.3,
|
||||
"dialogue": {
|
||||
"text": "and it's good to share and support each other.",
|
||||
"align": "left"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"position": { "x": 125, "y": 0, "z": 1 },
|
||||
"startTime": 71.8
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"position": { "x": -25, "y": 0, "z": 1 },
|
||||
"startTime": 72.3
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 22
|
||||
dashedName: task-40
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Alice: Hi Tom, you look a bit down these days. Is everything okay?
|
||||
-->
|
||||
<!-- (Audio) Alice: Hi, Tom. You look a bit down these days. Is everything okay? -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -22,7 +19,7 @@ In this conversation, Alice notices something about Tom's mood and asks if he's
|
||||
|
||||
## --sentence--
|
||||
|
||||
`Hi Tom, you look a bit _ _ days. Is everything okay?`
|
||||
`Hi, Tom. You look a bit _ _ days. Is everything okay?`
|
||||
|
||||
## --blanks--
|
||||
|
||||
@@ -39,3 +36,47 @@ This word is used to describe feeling sad or unhappy. It's like when you're not
|
||||
### --feedback--
|
||||
|
||||
This word is used with `days` to talk about the current time or the recent period.
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "company2-roof.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Alice",
|
||||
"position": {"x":50,"y":0,"z":1.4},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-2.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 0.98,
|
||||
"finishTimestamp": 4.58
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Alice",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"startTime": 1,
|
||||
"finishTime": 4.60,
|
||||
"dialogue": {
|
||||
"text": "Hi, Tom. You look a bit down these days. Is everything okay?",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"opacity": 0,
|
||||
"startTime": 5.10
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 22
|
||||
dashedName: task-41
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Tom: Hey Alice, yeah, I feel a bit demotivated.
|
||||
-->
|
||||
<!-- (Audio) Tom: Hey, Alice. Yeah, I feel a bit demotivated. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -20,7 +17,7 @@ When you see `-ed` at the end of a word like `demotivate`, it's talking about ho
|
||||
|
||||
## --sentence--
|
||||
|
||||
`Hey Alice, yeah, I feel a bit _.`
|
||||
`Hey, Alice. Yeah, I feel a bit _.`
|
||||
|
||||
## --blanks--
|
||||
|
||||
@@ -29,3 +26,47 @@ When you see `-ed` at the end of a word like `demotivate`, it's talking about ho
|
||||
### --feedback--
|
||||
|
||||
This word is used to describe how Tom feels. It ends with `ed`.
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "company2-roof.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Tom",
|
||||
"position": {"x":50,"y":15,"z":1.2},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-2.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 5.30,
|
||||
"finishTimestamp": 8.48
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Tom",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"startTime": 1,
|
||||
"finishTime": 4.18,
|
||||
"dialogue": {
|
||||
"text": "Hey, Alice. Yeah, I feel a bit demotivated.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"opacity": 0,
|
||||
"startTime": 4.68
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 22
|
||||
dashedName: task-42
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
"One thing that really gets to me is working long hours without any breaks."
|
||||
-->
|
||||
<!-- (Audio) Tom: One thing that really gets to me is working long hours without any breaks. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -46,8 +43,52 @@ This word means `lacking` or `not having` something.
|
||||
|
||||
---
|
||||
|
||||
`break`
|
||||
`breaks`
|
||||
|
||||
### --feedback--
|
||||
|
||||
This word refers to a short period of rest or pause from work or activity.
|
||||
This word refers to a short period of rest or pause from work or activity. Use the plural form.
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "company2-roof.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Tom",
|
||||
"position": {"x":50,"y":15,"z":1.2},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-2.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 8.84,
|
||||
"finishTimestamp": 12.60
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Tom",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"startTime": 1,
|
||||
"finishTime": 4.76,
|
||||
"dialogue": {
|
||||
"text": "One thing that really gets to me is working long hours without any breaks.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"opacity": 0,
|
||||
"startTime": 5.26
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 22
|
||||
dashedName: task-43
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
"It's exhausting, and it feels like I'm constantly running without knowing where I'm going."
|
||||
-->
|
||||
<!-- (Audio) Tom: It's exhausting, and it feels like I'm constantly running without knowing where I'm going. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -45,3 +42,47 @@ This word means something is happening all the time or very often.
|
||||
### --feedback--
|
||||
|
||||
This word is used to indicate the absence of something.
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "company2-roof.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Tom",
|
||||
"position": {"x":50,"y":15,"z":1.2},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-2.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 12.82,
|
||||
"finishTimestamp": 17.12
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Tom",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"startTime": 1,
|
||||
"finishTime": 5.30,
|
||||
"dialogue": {
|
||||
"text": "It's exhausting and it feels like I'm constantly running without knowing where I'm going.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"opacity": 0,
|
||||
"startTime": 5.80
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 19
|
||||
dashedName: task-44
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Tom: Hey Alice, yeah, I feel a bit demotivated. One thing that really gets to me is working long hours without any breaks. It's exhausting, and it feels like I'm constantly running without knowing where I'm going.
|
||||
-->
|
||||
<!-- (Audio) Tom: Hey Alice, yeah, I feel a bit demotivated. One thing that really gets to me is working long hours without any breaks. It's exhausting, and it feels like I'm constantly running without knowing where I'm going. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -18,7 +15,7 @@ Tom talks about what's making him feel demotivated. Let's figure out what is bot
|
||||
|
||||
## --text--
|
||||
|
||||
What is making Tom feel demotivated and why?
|
||||
What is making Tom feel demotivated?
|
||||
|
||||
## --answers--
|
||||
|
||||
@@ -51,3 +48,65 @@ Reflect on Tom's words about his work routine and how it makes him feel.
|
||||
## --video-solution--
|
||||
|
||||
2
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "company2-roof.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Tom",
|
||||
"position": {"x":50,"y":15,"z":1.2},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-2.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 5.30,
|
||||
"finishTimestamp": 17.12
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Tom",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"startTime": 1,
|
||||
"finishTime": 4.18,
|
||||
"dialogue": {
|
||||
"text": "Hey, Alice. Yeah, I feel a bit demotivated.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"startTime": 4.54,
|
||||
"finishTime": 8.3,
|
||||
"dialogue": {
|
||||
"text": "One thing that really gets to me is working long hours without any breaks.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"startTime": 8.52,
|
||||
"finishTime": 12.82,
|
||||
"dialogue": {
|
||||
"text": "It's exhausting and it feels like I'm constantly running without knowing where I'm going.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Tom",
|
||||
"opacity": 0,
|
||||
"startTime": 13.32
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 19
|
||||
dashedName: task-45
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Alice: I totally get that, Tom.
|
||||
-->
|
||||
<!-- (Audio) Alice: I totally get that, Tom. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -51,3 +48,47 @@ She understands how Tom feels
|
||||
## --video-solution--
|
||||
|
||||
4
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "company2-roof.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Alice",
|
||||
"position": {"x":50,"y":0,"z":1.4},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-2.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 17.70,
|
||||
"finishTimestamp": 18.98
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Alice",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"startTime": 1,
|
||||
"finishTime": 2.28,
|
||||
"dialogue": {
|
||||
"text": "I totally get that, Tom.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"opacity": 0,
|
||||
"startTime": 2.78
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 22
|
||||
dashedName: task-46
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
Alice: I totally get that, Tom. Working overtime all the time can be draining.
|
||||
-->
|
||||
<!-- (Audio) Alice: I totally get that, Tom. Working overtime all the time can be draining. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -37,3 +34,47 @@ This word means working more hours than what is normally required, often beyond
|
||||
### --feedback--
|
||||
|
||||
This word describes something that makes you feel very tired, like it's taking all your energy away.
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "company2-roof.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Alice",
|
||||
"position": {"x":50,"y":0,"z":1.4},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-2.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 17.70,
|
||||
"finishTimestamp": 21.72
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Alice",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"startTime": 1,
|
||||
"finishTime": 5.02,
|
||||
"dialogue": {
|
||||
"text": "I totally get that, Tom. Working overtime all the time can be draining.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"opacity": 0,
|
||||
"startTime": 5.52
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 22
|
||||
dashedName: task-47
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
"Personally, I hate dealing with office politics."
|
||||
-->
|
||||
<!-- (Audio) Alice: Personally, I hate dealing with office politics. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -35,3 +32,47 @@ This word means managing or handling, especially when the situation is challengi
|
||||
### --feedback--
|
||||
|
||||
This word, in the context of the office, refers to the social and power dynamics among coworkers and within the workplace environment.
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "company2-roof.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Alice",
|
||||
"position": {"x":50,"y":0,"z":1.4},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-2.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 22.26,
|
||||
"finishTimestamp": 24.78
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Alice",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"startTime": 1,
|
||||
"finishTime": 3.52,
|
||||
"dialogue": {
|
||||
"text": "Personally, I hate dealing with office politics.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"opacity": 0,
|
||||
"startTime": 4.02
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,10 +5,7 @@ challengeType: 22
|
||||
dashedName: task-48
|
||||
---
|
||||
|
||||
<!--
|
||||
AUDIO REFERENCE:
|
||||
"It's frustrating when people are constantly trying to beat each other instead of working together as a team."
|
||||
-->
|
||||
<!-- (Audio) Alice: It's frustrating when people are constantly trying to beat each other instead of working together as a team. -->
|
||||
|
||||
# --description--
|
||||
|
||||
@@ -45,3 +42,47 @@ This word means making an effort to do something, often something challenging.
|
||||
### --feedback--
|
||||
|
||||
This word is about doing tasks, especially with others to achieve a common goal or finish a project.
|
||||
|
||||
# --scene--
|
||||
|
||||
```json
|
||||
{
|
||||
"setup": {
|
||||
"background": "company2-roof.png",
|
||||
"characters": [
|
||||
{
|
||||
"character": "Alice",
|
||||
"position": {"x":50,"y":0,"z":1.4},
|
||||
"opacity": 0
|
||||
}
|
||||
],
|
||||
"audio": {
|
||||
"filename": "4.1-2.mp3",
|
||||
"startTime": 1,
|
||||
"startTimestamp": 25.02,
|
||||
"finishTimestamp": 29.38
|
||||
}
|
||||
},
|
||||
"commands": [
|
||||
{
|
||||
"character": "Alice",
|
||||
"opacity": 1,
|
||||
"startTime": 0
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"startTime": 1,
|
||||
"finishTime": 5.36,
|
||||
"dialogue": {
|
||||
"text": "It's frustrating when people are constantly trying to beat each other instead of working together as a team.",
|
||||
"align": "center"
|
||||
}
|
||||
},
|
||||
{
|
||||
"character": "Alice",
|
||||
"opacity": 0,
|
||||
"startTime": 5.86
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user