Browse Source

Meltdown Mitigation

master
Julio Biason 3 years ago
parent
commit
930eae8149
  1. 11
      python/meltdown-mitigation/.exercism/config.json
  2. 1
      python/meltdown-mitigation/.exercism/metadata.json
  3. 63
      python/meltdown-mitigation/HELP.md
  4. 47
      python/meltdown-mitigation/HINTS.md
  5. 173
      python/meltdown-mitigation/README.md
  6. 95
      python/meltdown-mitigation/conditionals.py
  7. 73
      python/meltdown-mitigation/conditionals_test.py

11
python/meltdown-mitigation/.exercism/config.json

@ -0,0 +1,11 @@
{
"blurb": "Learn about conditionals and avoid a meltdown by developing a simple control system for a Nuclear Reactor.",
"icon": "circular-buffer",
"authors": ["sachsom95", "BethanyG"],
"contributors": ["kbuc"],
"files": {
"solution": ["conditionals.py"],
"test": ["conditionals_test.py"],
"exemplar": [".meta/exemplar.py"]
}
}

1
python/meltdown-mitigation/.exercism/metadata.json

@ -0,0 +1 @@
{"track":"python","exercise":"meltdown-mitigation","id":"28cf35db9e26476f84878c7ab42700a3","url":"https://exercism.org/tracks/python/exercises/meltdown-mitigation","handle":"JBiason","is_requester":true,"auto_approve":false}

63
python/meltdown-mitigation/HELP.md

@ -0,0 +1,63 @@
# Help
## Running the tests
You can run the included tests by typing `pytest <exercisename>_test.py` on the command line from within the exercise's directory.
You can also tell Python to run the pytest module on the command line from either within the exercise directory or with a path to the exercise directory.
`python -m pytest <exercisename>_test.py` from within the exercise directory.
`python -m pytest /fully/qualified/path/to/<exercisename>/` OR `python -m pytest realtive/path/to/<exercisename>` from a non-exercise directory.
Many IDE's and code editors also have built-in support for using PyTest to run tests.
- [Visual Studio Code](https://code.visualstudio.com/docs/python/testing)
- [PyCharm Professional & Community Editions](https://www.jetbrains.com/help/pycharm/pytest.html#create-pytest-test)
- [Atom](https://atom.io/packages/atom-python-test)
- [Spyder](https://www.spyder-ide.org/blog/introducing-unittest-plugin/)
- [Sublime](https://github.com/kaste/PyTest)
- [vim-test](https://github.com/vim-test/vim-test)
See the [Python tests page](https://github.com/exercism/python/blob/main/docs/TESTS.md) for more information.
### Common `pytest` options
- `-v` : enable verbose output.
- `-x` : stop running tests on first failure.
- `--ff` : run failures from previous test before running other test cases.
For other options, see `python -m pytest -h`. PyTest documentation can be found [here](https://docs.pytest.org/en/latest/getting-started.html).
## Submitting your solution
You can submit your solution using the `exercism submit conditionals.py` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Python track's documentation](https://exercism.org/docs/tracks/python)
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
Below are some resources for getting help if you run into trouble:
- [The PSF](https://www.python.org) hosts Python downloads, documentation, and community resources.
- [Python Community on Discord](https://pythondiscord.com/) is a very helpful and active community.
- [#python on Libera.chat](https://www.python.org/community/irc/) this is where the cored developers for the language hang out and get work done.
- [Exercism on Gitter](https://gitter.im/exercism/home) join the Python room for Python-related questions or problems.
- [/r/learnpython/](https://www.reddit.com/r/learnpython/) is a subreddit designed for Python learners.
- [Python Community Forums](https://discuss.python.org/)
- [Pythontutor](http://pythontutor.com/) for stepping through small code snippets visually.
Additionally, [StackOverflow](http://stackoverflow.com/questions/tagged/python) is a good spot to search for your problem/question to see if it has been answered already.
If not - you can always [ask](https://stackoverflow.com/help/how-to-ask) or [answer](https://stackoverflow.com/help/how-to-answer) someone else's question.

47
python/meltdown-mitigation/HINTS.md

@ -0,0 +1,47 @@
# Hints
## General
- The Python Docs on [Control Flow Tools][control flow tools] and the Real Python tutorial on [conditionals][real python conditionals] are great places to start.
- The Python Docs on [Boolean Operations][boolean operations] can be a great refresher on `bools`, as can the Real Python tutorial on [booleans][python booleans].
- The Python Docs on [Comparisons][comparisons] and [comparisons examples][python comparisons examples] can be a great refresher for comparisons.
## 1. Check for criticality
- Comparison operators and boolean operations can be combined and used with conditionals.
- Conditional expressions must evaluate to `True` or `False`.
- `else` can be used for a code block that will execute when all conditional tests return `False`.
```python
>>> item = 'blue'
>>> item_2 = 'green'
>>> if len(item) >=3 and len(item_2) < 5:
print('Both pass the test!')
elif len(item) >=3 or len(item_2) < 5:
print('One passes the test!')
else:
print('None pass the test!')
...
One passes the test!
```
## 2. Determine the Power output range
- Comparison operators can be combined and used with conditionals.
- Any number of `elif` statements can be used as "branches".
- Each "branch" can have a separate `return`
## 3. Fail Safe Mechanism
- Comparison operators can be combined and used with conditionals.
- Any number of `elif` statements can be used as "branches".
- Each "branch" can have a separate `return`
[python comparisons examples]: https://www.tutorialspoint.com/python/comparison_operators_example.htm
[boolean operations]: https://docs.python.org/3/library/stdtypes.html#boolean-operations-and-or-not
[comparisons]: https://docs.python.org/3/library/stdtypes.html#comparisons
[python booleans]: https://realpython.com/python-boolean/
[real python conditionals]: https://realpython.com/python-conditional-statements/
[control flow tools]: https://docs.python.org/3/tutorial/controlflow.html

173
python/meltdown-mitigation/README.md

@ -0,0 +1,173 @@
# Meltdown Mitigation
Welcome to Meltdown Mitigation on Exercism's Python Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
## Introduction
In Python, [`if`][if statement], `elif` (_a contraction of 'else and if'_) and `else` statements are used to [control the flow][control flow tools] of execution and make decisions in a program.
Unlike many other programming languages, Python versions 3.9 and below do not offer a formal case-switch statement, instead using multiple `elif` statements to serve a similar purpose.
Python 3.10 introduces a variant case-switch statement called `pattern matching`, which will be covered separately in another concept.
Conditional statements use expressions that must resolve to `True` or `False` -- either by returning a `bool` directly, or by evaluating ["truthy" or "falsy"][truth value testing].
```python
x = 10
y = 5
# The comparison '>' returns the bool 'True',
# so the statement is printed.
if x > y:
print("x is greater than y")
...
>>> x is greater than y
```
When paired with `if`, an optional `else` code block will execute when the original `if` condition evaluates to `False`:
```python
x = 5
y = 10
# The comparison '>' here returns the bool 'False',
# so the 'else' block is executed instead of the 'if' block.
if x > y:
print("x is greater than y")
else:
print("y is greater than x")
...
>>> y is greater than x
```
`elif` allows for multiple evaluations/branches.
```python
x = 5
y = 10
z = 20
# The 'elif' statement allows for the checking of more conditions.
if x > y:
print("x is greater than y and z")
elif y > z:
print("y is greater than x and z")
else:
print("z is great than x and y")
...
>>> z is great than x and y
```
[Boolean operations][boolean operations] and [comparisons][comparisons] can be combined with conditionals for more complex testing:
```python
>>> def classic_fizzbuzz(number):
if number % 3 == 0 and number % 5 == 0:
return 'FizzBuzz!'
elif number % 5 == 0:
return 'Buzz!'
elif number % 3 == 0:
return 'Fizz!'
else:
return str(number)
>>> classic_fizzbuzz(15)
'FizzBuzz!'
>>> classic_fizzbuzz(13)
'13'
```
[if statement]: https://docs.python.org/3/reference/compound_stmts.html#the-if-statement
[control flow tools]: https://docs.python.org/3/tutorial/controlflow.html#more-control-flow-tools
[truth value testing]: https://docs.python.org/3/library/stdtypes.html#truth-value-testing
[boolean operations]: https://docs.python.org/3/library/stdtypes.html#boolean-operations-and-or-not
[comparisons]: https://docs.python.org/3/library/stdtypes.html#comparisons
## Instructions
In this exercise, we'll develop a simple control system for a nuclear reactor.
For a reactor to produce the power it must be in a state of _criticality_.
If the reactor is in a state less than criticality, it can become damaged.
If the reactor state goes beyond criticality, it can overload and result in a meltdown.
We want to mitigate the chances of meltdown and correctly manage reactor state.
The following three tasks are all related to writing code for maintaining ideal reactor state.
## 1. Check for criticality
The first thing a control system has to do is check if the reactor is balanced in criticality.
A reactor is said to be critical if it satisfies the following conditions:
- The temperature is less than 800.
- The number of neutrons emitted per second is greater than 500.
- The product of temperature and neutrons emitted per second is less than 500000.
Implement the function `is_criticality_balanced()` that takes `temperature` and `neutrons_emitted` as parameters, and returns `True` if the criticality conditions are met, `False` if not.
```python
>>> is_criticality_balanced(750, 600)
True
```
## 2. Determine the Power output range
Once the reactor has started producing power its efficiency needs to be determined.
Efficiency can be grouped into 4 bands:
1. `green` -> efficiency of 80% or more,
2. `orange` -> efficiency of less than 80% but at least 60%,
3. `red` -> efficiency below 60%, but still 30% or more,
4. `black` -> less than 30% efficient.
The percentage value can be calculated as `(generated_power/theoretical_max_power)*100`
where `generated_power` = `voltage` * `current`.
Note that the percentage value is usually not an integer number, so make sure to consider the
proper use of the `<` and `<=` comparisons.
Implement the function `reactor_efficiency(<voltage>, <current>, <theoretical_max_power>)`, with three parameters: `voltage`,
`current`, and `theoretical_max_power`.
This function should return the efficiency band of the reactor : 'green', 'orange', 'red', or 'black'.
```python
>>> reactor_efficiency(200,50,15000)
'orange'
```
## 3. Fail Safe Mechanism
Your final task involves creating a fail-safe mechanism to avoid overload and meltdown.
This mechanism will determine if the reactor is below, at, or above the ideal criticality threshold.
Criticality can then be increased, decreased, or stopped by inserting (or removing) control rods into the reactor.
Implement the function called `fail_safe()`, which takes 3 parameters: `temperature`,
`neutrons_produced_per_second`, and `threshold`, and outputs a status code for the reactor.
- If `temperature * neutrons_produced_per_second` < 90% of `threshold`, output a status code of 'LOW'
indicating that control rods must be removed to produce power.
- If `temperature * neutrons_produced_per_second` are within plus or minus 10% of the `threshold`
the reactor is in _criticality_ and the status code of 'NORMAL' should be output, indicating that the
reactor is in optimum condition and control rods are in an ideal position.
- If `temperature * neutrons_produced_per_second` is not in the above-stated ranges, the reactor is
going into meltdown and a status code of 'DANGER' must be passed to immediately shut down the reactor.
```python
>>> fail_safe(temperature=1000, neutrons_produced_per_second=30, threshold=5000)
'DANGER'
```
## Source
### Created by
- @sachsom95
- @BethanyG
### Contributed to by
- @kbuc

95
python/meltdown-mitigation/conditionals.py

@ -0,0 +1,95 @@
""" Meltdown Mitigation exercise """
from typing import Union
from typing import Literal
EFFICIENCY_GREEN = 'green'
EFFICIENCY_ORANGE = 'orange'
EFFICIENCY_RED = 'red'
EFFICIENCY_BLACK = 'black'
EFFICIENCY = Literal[EFFICIENCY_GREEN, EFFICIENCY_ORANGE, EFFICIENCY_RED,
EFFICIENCY_BLACK]
FAIL_SAFE_LOW = 'LOW'
FAIL_SAFE_NORMAL = 'NORMAL'
FAIL_SAFE_DANGER = 'DANGER'
FAIL_SAFE = Literal[FAIL_SAFE_LOW, FAIL_SAFE_NORMAL, FAIL_SAFE_DANGER]
def is_criticality_balanced(temperature: Union[int, float],
neutrons_emitted: Union[int, float]) -> bool:
"""Verify criticality is balanced.
:param temperature: temperature value (integer or float)
:param neutrons_emitted: number of neutrons emitted per second (integer or float)
:return: boolean True if conditions met, False if not
A reactor is said to be critical if it satisfies the following conditions:
- The temperature is less than 800.
- The number of neutrons emitted per second is greater than 500.
- The product of temperature and neutrons emitted per second is less than 500000.
"""
return (temperature < 800
and neutrons_emitted > 500
and ((neutrons_emitted * temperature) < 500000))
def reactor_efficiency(voltage: Union[int, float],
current: Union[int, float],
theoretical_max_power: Union[int, float]) -> EFFICIENCY:
"""Assess reactor efficiency zone.
:param voltage: voltage value (integer or float)
:param current: current value (integer or float)
:param theoretical_max_power: power that corresponds to a 100% efficiency (integer or float)
:return: str one of 'green', 'orange', 'red', or 'black'
Efficiency can be grouped into 4 bands:
1. green -> efficiency of 80% or more,
2. orange -> efficiency of less than 80% but at least 60%,
3. red -> efficiency below 60%, but still 30% or more,
4. black -> less than 30% efficient.
The percentage value is calculated as
(generated power/ theoretical max power)*100
where generated power = voltage * current
"""
generated_power = voltage * current
efficiency = (generated_power / theoretical_max_power) * 100
efficiency_color = EFFICIENCY_BLACK
if efficiency >= 80:
efficiency_color = EFFICIENCY_GREEN
elif efficiency >= 60:
efficiency_color = EFFICIENCY_ORANGE
elif efficiency >= 30:
efficiency_color = EFFICIENCY_RED
return efficiency_color
def fail_safe(temperature: Union[int, float],
neutrons_produced_per_second: Union[int, float],
threshold: Union[int, float]):
"""Assess and return status code for the reactor.
:param temperature: value of the temperature (integer or float)
:param neutrons_produced_per_second: neutron flux (integer or float)
:param threshold: threshold (integer or float)
:return: str one of: 'LOW', 'NORMAL', 'DANGER'
- `temperature * neutrons per second` < 90% of `threshold` == 'LOW'
- `temperature * neutrons per second` +/- 10% of `threshold` == 'NORMAL'
- `temperature * neutrons per second` is not in the above-stated ranges == 'DANGER'
"""
heated_neutrons = temperature * neutrons_produced_per_second
efficiency = (heated_neutrons / threshold) * 100
state = FAIL_SAFE_DANGER
if efficiency < 90:
state = FAIL_SAFE_LOW
elif efficiency >= 90 and efficiency <= 110:
state = FAIL_SAFE_NORMAL
return state

73
python/meltdown-mitigation/conditionals_test.py

@ -0,0 +1,73 @@
import unittest
import pytest
from conditionals import (is_criticality_balanced,
reactor_efficiency,
fail_safe)
class MeltdownMitigationTest(unittest.TestCase):
"""Test cases for Meltdown mitigation exercise.
"""
@pytest.mark.task(taskno=1)
def test_is_criticality_balanced(self):
"""Testing border cases around typical points.
T, n == (800, 500), (625, 800), (500, 1000), etc.
"""
test_data = ((750, 650, True), (799, 501, True), (500, 600, True),
(1000, 800, False), (800, 500, False), (800, 500.01, False),
(799.99, 500, False), (500.01, 999.99, False), (625, 800, False),
(625.99, 800, False), (625.01, 799.99, False), (799.99, 500.01, True),
(624.99, 799.99, True), (500, 1000, False), (500.01, 1000, False),
(499.99, 1000, True))
for variant, data in enumerate(test_data, start=1):
temperature, neutrons_emitted, expected = data
with self.subTest(f"variation #{variant}", temperature=temperature, neutrons_emitted=neutrons_emitted, expected=expected):
got = is_criticality_balanced(temperature, neutrons_emitted)
msg=f"Expected {expected} but returned {got} with T={temperature} and neutrinos={neutrons_emitted}"
self.assertEqual(got, expected, msg)
@pytest.mark.task(taskno=2)
def test_reactor_efficiency(self):
voltage = 10
theoretical_max_power = 10000
# The numbers are chosen so that current == 10 x percentage
test_data = ((1000, 'green'), (999, 'green'), (800, 'green'),
(799, 'orange'), (700, 'orange'), (600, 'orange'),
(599, 'red'), (560, 'red'), (400, 'red'), (300, 'red'),
(299, 'black'), (200, 'black'), (0, 'black'))
for variant, data in enumerate(test_data, start=1):
current, expected = data
with self.subTest(f"variation #{variant}", voltage=voltage, current=current,
theoretical_max_power=theoretical_max_power, expected=expected):
got = reactor_efficiency(voltage, current, theoretical_max_power)
msg=f"Expected {expected} but returned {got} with voltage={voltage}, current={current}, " \
f"max_pow={theoretical_max_power}"
self.assertEqual(got, expected, msg)
@pytest.mark.task(taskno=3)
def test_fail_safe(self):
temperature = 10
threshold = 10000
test_data = ((399, 'LOW'), (300, 'LOW'), (1, 'LOW'),
(0, 'LOW'), (901, 'NORMAL'), (1000, 'NORMAL'),
(1099, 'NORMAL'), (899, 'LOW'), (700, 'LOW'),
(400, 'LOW'), (1101, 'DANGER'), (1200, 'DANGER'))
for variant, data in enumerate(test_data, start=1):
neutrons_produced_per_second, expected = data
with self.subTest(f"variation #{variant}", temperature=temperature,
neutrons_produced_per_second=neutrons_produced_per_second,
threshold=threshold, expected=expected):
got = fail_safe(temperature, neutrons_produced_per_second, threshold)
msg = f"Expected {expected} but returned {got} with T={temperature}, " \
f"neutrons={neutrons_produced_per_second}, threshold={threshold}"
self.assertEqual(got, expected, msg)
Loading…
Cancel
Save