C++: completed Pacman Rules and Freelancer Rates

This commit is contained in:
Andrew Scott 2024-07-12 16:48:10 -04:00
parent 1b76fd05a3
commit 4ca5823d45
Signed by: a
GPG key ID: 7CD5A5977E4931C1
22 changed files with 36666 additions and 0 deletions

View file

@ -0,0 +1,21 @@
{
"authors": [
"vaeng"
],
"files": {
"solution": [
"freelancer_rates.cpp"
],
"test": [
"freelancer_rates_test.cpp"
],
"exemplar": [
".meta/exemplar.cpp"
]
},
"forked_from": [
"elixir/freelancer-rates"
],
"icon": "freelancer-rates",
"blurb": "Learn about integers and floating point numbers by helping a freelancer communicate with a project manager about billing."
}

View file

@ -0,0 +1 @@
{"track":"cpp","exercise":"freelancer-rates","id":"f6c4621e106f4d0c8aea55136a76694e","url":"https://exercism.org/tracks/cpp/exercises/freelancer-rates","handle":"Chomp1295","is_requester":true,"auto_approve":false}

View file

@ -0,0 +1,66 @@
# Basic CMake project
cmake_minimum_required(VERSION 3.5.1)
# Get the exercise name from the current directory
get_filename_component(exercise ${CMAKE_CURRENT_SOURCE_DIR} NAME)
# Name the project after the exercise
project(${exercise} CXX)
# Get a source filename from the exercise name by replacing -'s with _'s
string(REPLACE "-" "_" file ${exercise})
# Implementation could be only a header
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}.cpp)
set(exercise_cpp ${file}.cpp)
else()
set(exercise_cpp "")
endif()
# Use the common Catch library?
if(EXERCISM_COMMON_CATCH)
# For Exercism track development only
add_executable(${exercise} ${file}_test.cpp $<TARGET_OBJECTS:catchlib>)
elseif(EXERCISM_TEST_SUITE)
# The Exercism test suite is being run, the Docker image already
# includes a pre-built version of Catch.
find_package(Catch2 REQUIRED)
add_executable(${exercise} ${file}_test.cpp)
target_link_libraries(${exercise} PRIVATE Catch2::Catch2WithMain)
# When Catch is installed system wide we need to include a different
# header, we need this define to use the correct one.
target_compile_definitions(${exercise} PRIVATE EXERCISM_TEST_SUITE)
else()
# Build executable from sources and headers
add_executable(${exercise} ${file}_test.cpp test/tests-main.cpp)
endif()
set_target_properties(${exercise} PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED OFF
CXX_EXTENSIONS OFF
)
set(CMAKE_BUILD_TYPE Debug)
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(GNU|Clang)")
set_target_properties(${exercise} PROPERTIES
# added "-Wno-unused-parameter" to remove compiler warnings
# should make it easier for students to run their first real code
COMPILE_FLAGS "-Wall -Wextra -Wpedantic -Werror -Wno-unused-parameter"
)
endif()
# Configure to run all the tests?
if(${EXERCISM_RUN_ALL_TESTS})
target_compile_definitions(${exercise} PRIVATE EXERCISM_RUN_ALL_TESTS)
endif()
# Tell MSVC not to warn us about unchecked iterators in debug builds
if(${MSVC})
set_target_properties(${exercise} PROPERTIES
COMPILE_DEFINITIONS_DEBUG _SCL_SECURE_NO_WARNINGS)
endif()
# Run the tests on every build
add_custom_target(test_${exercise} ALL DEPENDS ${exercise} COMMAND ${exercise})

View file

@ -0,0 +1,61 @@
# Help
## Running the tests
Running the tests involves running `cmake -G` and then using the build command appropriate for your platform.
Detailed instructions on how to do this can be found on the [Running the Tests][cpp-tests-instructions] page for C++ on exercism.org.
## Passing the Tests
When you start a new exercise locally, the files are configured so that only the first test is performed.
Get that first test compiling, linking and passing by following the [three rules of test-driven development][three-laws-of-tdd].
Create just enough structure by declaring namespaces, functions, classes, etc., to satisfy any compiler errors and get the test to fail.
Then write just enough code to get the test to pass.
Once you've done that, uncomment the next test by moving the line `if defined(EXERCISM_RUN_ALL_TESTS)` past the next test.
See the example below from the Bob exercise (file `bob_test.cpp`, line 15):
```diff
-#if defined(EXERCISM_RUN_ALL_TESTS)
TEST_CASE("shouting")
{
REQUIRE("Whoa, chill out!" == bob::hey("WATCH OUT!"));
}
+#if defined(EXERCISM_RUN_ALL_TESTS)
```
Moving this line past the next test may result in compile errors as new constructs may be invoked that you haven't yet declared or defined.
Again, fix the compile errors minimally to get a failing test, then change the code minimally to pass the test, refactor your implementation for readability and expressiveness and then go on to the next test.
Try to use standard C++17 facilities in preference to writing your own low-level algorithms or facilities by hand.
[cpp-tests-instructions]: https://exercism.org/docs/tracks/cpp/tests
[three-laws-of-tdd]: http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
## Submitting your solution
You can submit your solution using the `exercism submit freelancer_rates.cpp` 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 [C++ track's documentation](https://exercism.org/docs/tracks/cpp)
- The [C++ track's programming category on the forum](https://forum.exercism.org/c/programming/cpp)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [`c++-faq` tag on StackOverflow](https://stackoverflow.com/tags/c%2b%2b-faq/info)
- [C++ FAQ from isocpp.com](https://isocpp.org/faq)
- [CppReference](http://en.cppreference.com/) is a wiki reference to the C++ language and standard library
- [C traps and pitfalls](http://www.slideshare.net/LegalizeAdulthood/c-traps-and-pitfalls-for-c-programmers) is useful if you are new to C++, but have programmed in C

View file

@ -0,0 +1,24 @@
# Hints
## General
- Browse the [`cmath` reference][cmath-reference] to learn about common mathematical operations and transformations that work with `doubles`.
## 1. Calculate the daily rate given an hourly rate
- Basic arithmetic operations where one argument is an `int`, and the other is a `double`, will return a `double`.
## 2. Calculate a discounted price
- Basic arithmetic operations where one argument is an `int`, and the other is a `double`, will return a `double`.
## 3. Calculate the monthly rate, given an hourly rate and a discount
- There is a [function in the `cmath` header][cmath-ceil] for rounding up.
## 4. Calculate the number of workdays given a budget, hourly rate, and discount
- Casting a `double` to an `int` will truncate the number at the decimal point.
[cmath-reference]: https://en.cppreference.com/w/cpp/header/cmath
[cmath-ceil]: https://en.cppreference.com/w/cpp/numeric/math/ceil

View file

@ -0,0 +1,161 @@
# Freelancer Rates
Welcome to Freelancer Rates on Exercism's C++ 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
The built-in number types in C++ can be divided into integers and floating points.
Integers are whole numbers like `0`, `691`, or `-2`.
Floating point numbers are numbers with a decimal point like `6.02214076`, `0.1`, or `-1.616`.
## Integers
The following example shows the declaration and initialization of four different variables
```cpp
int m_morales{9241}; // base 10: 0-9
int a_apaec{0x24CD}; // base 16: 0-9 and A-F
int m_gargan{0b10010000011001}; // base 2: 0-1
int b_reilly{022031}; // base 8: 0-7
// Leading with a 0 not the letter o.
```
When you assign a value to an `int` variable, you can do so directly with a literal.
A literal is a hard-coded number like `9241`.
There are different integer literals for several bases of the representation.
Decimal integer literals are the most common and use the digits `0` to `9`.
By adding a special prefix, like `0x`, it is possible to use other bases.
The example above shows the number `9421` in its four representations and prefixes.
All variables are initialized to the same value.
For more details on the different representation systems, take a look at [a small tutorial][cpp_numerical_bases].
You can use an apostrophe to separate digits for easier readability.
`9'241` is the same as `0b0100'100'0001'1001` or `92'4'1`.
## Floating-Point Numbers
The floating-point literals come in two flavors.
In addition to the intuitive `0.0024` it is possible to use its scientific notation `2.4e-3`.
The most common floating-point type is `double`.
## Arithmetic
C++ supports `+`, `-`, `*`, `/`, `(` and `)` and `%` to form expressions.
The result from the operation between two integers is also an integer.
`5 / 2` will return `2`.
When one of the involved types is a floating-point type, the result will also be of a floating-point.
`5.0 / 2` and `5 / 2.0` will return `2.5`.
`%` is the remainder operator and will return the remainder of an integer division: `5%3` is `2`.
## Assignment operator
The assignment operator assigns a variable with a literal.
Always takes place from right to left, and never the other way around.
```cpp
int length = 5;
int width = 2;
length = width;
```
Here integer value `5` is assigned to the variable `length`.
Then integer value `2` is assigned to variable `width`.
Finally value of `width` is copied to the variable `length` and the earlier value `5` will be lost.
Consider also that we are only assigning the value of `width` to `length` at the moment of the assignment operation.
Therefore, if the value of `width` changes at a later moment, it will not affect the value taken by `length`.
Assignment operator can be combined with the other operators(arithmetic & bitwise) known as `compound assignment` operators `+=`, `-=`, `*=`, `/=`, `%=`.
These operators modifies the current value of a variable by performing an operation on it.
```cpp
// we start with 0 people
int people{};
// we need 0 eggs
int eggs{};
// two people joined:
people += 2;
// people is now 2
// let's add 3 eggs per person
eggs += 3 * people;
// eggs is now 6
```
Variables `people` & `eggs` are initialized to `0`.
Then, we add integer value `2` over the existing value `0` of the variable `people` and assign it back to `people`.
`people` becomes `2` now.
Later, we add `3` eggs for each person, which turns out to be `6` eggs in total.
Now add this `6` to existing value `0` of the variable `eggs` and assign it back to `eggs`.
`eggs` will be `6` now.
The equivalent expression would be `people = people + 2` and `eggs = eggs + (3 * people)`.
[cpp_numerical_bases]: https://cplusplus.com/doc/hex/
## Instructions
In this exercise, you'll be writing code to help a freelancer communicate with a project manager.
Your task is to provide a few utilities to quickly calculate daily and monthly rates, optionally with a given discount.
We first establish a few rules between the freelancer and the project manager:
- The daily rate is 8 times the hourly rate.
- A month has 22 billable days.
Sometimes, the freelancer is offering to apply a discount on their daily rate (for example for their most loyal customers or not-for-profit customers).
Discounts are modeled as fractional numbers representing percentages, for example, `25.0` (25%).
## 1. Calculate the daily rate given an hourly rate
Implement a function called `daily_rate` to calculate the daily rate given an hourly rate as a parameter.
The contract defines that a day has 8 billable hours.
```cpp
daily_rate(60)
// => 480.0
```
The returned daily rate should be of type `double`.
## 2. Calculate a discounted price
Implement a function `apply_discount` to calculates the price after a discount.
It should accept two parameters: the original price and the discount rate in percent.
```cpp
apply_discount(150, 10)
// => 135.0
```
The returned value should always be of type `double`, not rounded in any way.
## 3. Calculate the monthly rate, given an hourly rate and a discount
Implement a `monthly_rate` function to calculate the discounted monthly rate.
It should have two parameters, an hourly rate and the discount in percent.
```cpp
monthly_rate(77, 10.5)
// => 12130
```
The returned monthly rate should be rounded up (take the ceiling) to the nearest integer.
## 4. Calculate the number of complete workdays given a budget, hourly rate, and discount
Implement a function `days_in_budget` that takes a budget, an hourly rate, and a discount, and calculates how many complete days of work that covers.
```cpp
days_in_budget(20'000, 80, 11.0)
// => 35
```
The returned number of days should be rounded down (take the floor) to the next integer.
## Source
### Created by
- @vaeng

Binary file not shown.

View file

@ -0,0 +1,22 @@
#include <cmath>
// daily_rate calculates the daily rate given an hourly rate
double daily_rate(double hourly_rate) { return hourly_rate * 8; }
// apply_discount calculates the price after a discount
double apply_discount(double before_discount, double discount) {
return before_discount * ((100 - discount) / 100);
}
// monthly_rate calculates the monthly rate, given an hourly rate and a discount
// The returned monthly rate is rounded up to the nearest integer.
int monthly_rate(double hourly_rate, double discount) {
return ceil(apply_discount(daily_rate(hourly_rate) * 22, discount));
}
// days_in_budget calculates the number of workdays given a budget, hourly rate,
// and discount The returned number of days is rounded down (take the floor) to
// the next integer.
int days_in_budget(int budget, double hourly_rate, double discount) {
return floor(budget / apply_discount(daily_rate(hourly_rate), discount));
}

View file

@ -0,0 +1,68 @@
#include "freelancer_rates.cpp"
#ifdef EXERCISM_TEST_SUITE
#include <catch2/catch.hpp>
#else
#include "test/catch.hpp"
#endif
using namespace std;
TEST_CASE("it's the hourly_rate times 8", "[task_1]") {
REQUIRE(daily_rate(50) == 400.0);
}
TEST_CASE("it always returns a float", "[task_1]") {
REQUIRE(daily_rate(60) == 480.0);
}
TEST_CASE("it does not round", "[task_1]") {
REQUIRE(daily_rate(55.1) == 440.8);
}
TEST_CASE("a discount of 10 percent leaves 90 percent of the original price",
"[task_2]") {
REQUIRE(apply_discount(140.0, 10) == 126.0);
}
TEST_CASE("it doesn't round", "[task_2]") {
// If unsure about the syntax of this test see:
// https://github.com/catchorg/Catch2/blob/devel/docs/comparing-floating-point-numbers.md#withinrel
REQUIRE_THAT(apply_discount(111.11, 13.5),
Catch::Matchers::WithinRel(96.11015, 0.000001));
}
TEST_CASE("it's the daily_rate times 22", "[task_3]") {
REQUIRE(monthly_rate(62, 0.0) == 10'912);
}
TEST_CASE("the result is rounded up", "[task_3]") {
// 11_052.8
REQUIRE(monthly_rate(62.8, 0.0) == 11'053);
// 11_475.2
REQUIRE(monthly_rate(65.2, 0.0) == 11'476);
}
TEST_CASE("gives a discount", "[task_3]") {
// 11'792 - 12% * 11_792 = 10'376.96
REQUIRE(monthly_rate(67, 12.0) == 10'377);
}
TEST_CASE("it's the budget divided by the daily rate", "[task_4]") {
REQUIRE(days_in_budget(1'600, 50, 0.0) == 4);
}
TEST_CASE("it rounds down to next decimal place", "[task_4]") {
// 9.97727
REQUIRE(days_in_budget(4'390, 55, 0.0) == 9);
// 10.18182
REQUIRE(days_in_budget(4'480, 55, 0.0) == 10);
}
TEST_CASE("it applies the discount", "[task_4]") {
// Without discount: 0.8
// With discount: 1.07
REQUIRE(days_in_budget(480, 70, 20) == 1);
}
#if defined(EXERCISM_RUN_ALL_TESTS)
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,2 @@
#define CATCH_CONFIG_MAIN
#include "catch.hpp"

View file

@ -0,0 +1,20 @@
{
"authors": [
"vaeng"
],
"files": {
"solution": [
"pacman_rules.cpp"
],
"test": [
"pacman_rules_test.cpp"
],
"exemplar": [
".meta/exemplar.cpp"
]
},
"forked_from": [
"elixir/pacman-rules"
],
"blurb": "Learn about booleans by implementing the rules of the Pac-Man game."
}

View file

@ -0,0 +1 @@
{"track":"cpp","exercise":"pacman-rules","id":"10de72cd2ba04a1e98b8e7e51cc18fa8","url":"https://exercism.org/tracks/cpp/exercises/pacman-rules","handle":"Chomp1295","is_requester":true,"auto_approve":false}

View file

@ -0,0 +1,66 @@
# Basic CMake project
cmake_minimum_required(VERSION 3.5.1)
# Get the exercise name from the current directory
get_filename_component(exercise ${CMAKE_CURRENT_SOURCE_DIR} NAME)
# Name the project after the exercise
project(${exercise} CXX)
# Get a source filename from the exercise name by replacing -'s with _'s
string(REPLACE "-" "_" file ${exercise})
# Implementation could be only a header
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}.cpp)
set(exercise_cpp ${file}.cpp)
else()
set(exercise_cpp "")
endif()
# Use the common Catch library?
if(EXERCISM_COMMON_CATCH)
# For Exercism track development only
add_executable(${exercise} ${file}_test.cpp $<TARGET_OBJECTS:catchlib>)
elseif(EXERCISM_TEST_SUITE)
# The Exercism test suite is being run, the Docker image already
# includes a pre-built version of Catch.
find_package(Catch2 REQUIRED)
add_executable(${exercise} ${file}_test.cpp)
target_link_libraries(${exercise} PRIVATE Catch2::Catch2WithMain)
# When Catch is installed system wide we need to include a different
# header, we need this define to use the correct one.
target_compile_definitions(${exercise} PRIVATE EXERCISM_TEST_SUITE)
else()
# Build executable from sources and headers
add_executable(${exercise} ${file}_test.cpp test/tests-main.cpp)
endif()
set_target_properties(${exercise} PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED OFF
CXX_EXTENSIONS OFF
)
set(CMAKE_BUILD_TYPE Debug)
if("${CMAKE_CXX_COMPILER_ID}" MATCHES "(GNU|Clang)")
set_target_properties(${exercise} PROPERTIES
# added "-Wno-unused-parameter" to remove compiler warnings
# should make it easier for students to run their first real code
COMPILE_FLAGS "-Wall -Wextra -Wpedantic -Werror -Wno-unused-parameter"
)
endif()
# Configure to run all the tests?
if(${EXERCISM_RUN_ALL_TESTS})
target_compile_definitions(${exercise} PRIVATE EXERCISM_RUN_ALL_TESTS)
endif()
# Tell MSVC not to warn us about unchecked iterators in debug builds
if(${MSVC})
set_target_properties(${exercise} PROPERTIES
COMPILE_DEFINITIONS_DEBUG _SCL_SECURE_NO_WARNINGS)
endif()
# Run the tests on every build
add_custom_target(test_${exercise} ALL DEPENDS ${exercise} COMMAND ${exercise})

61
cpp/pacman-rules/HELP.md Normal file
View file

@ -0,0 +1,61 @@
# Help
## Running the tests
Running the tests involves running `cmake -G` and then using the build command appropriate for your platform.
Detailed instructions on how to do this can be found on the [Running the Tests][cpp-tests-instructions] page for C++ on exercism.org.
## Passing the Tests
When you start a new exercise locally, the files are configured so that only the first test is performed.
Get that first test compiling, linking and passing by following the [three rules of test-driven development][three-laws-of-tdd].
Create just enough structure by declaring namespaces, functions, classes, etc., to satisfy any compiler errors and get the test to fail.
Then write just enough code to get the test to pass.
Once you've done that, uncomment the next test by moving the line `if defined(EXERCISM_RUN_ALL_TESTS)` past the next test.
See the example below from the Bob exercise (file `bob_test.cpp`, line 15):
```diff
-#if defined(EXERCISM_RUN_ALL_TESTS)
TEST_CASE("shouting")
{
REQUIRE("Whoa, chill out!" == bob::hey("WATCH OUT!"));
}
+#if defined(EXERCISM_RUN_ALL_TESTS)
```
Moving this line past the next test may result in compile errors as new constructs may be invoked that you haven't yet declared or defined.
Again, fix the compile errors minimally to get a failing test, then change the code minimally to pass the test, refactor your implementation for readability and expressiveness and then go on to the next test.
Try to use standard C++17 facilities in preference to writing your own low-level algorithms or facilities by hand.
[cpp-tests-instructions]: https://exercism.org/docs/tracks/cpp/tests
[three-laws-of-tdd]: http://butunclebob.com/ArticleS.UncleBob.TheThreeRulesOfTdd
## Submitting your solution
You can submit your solution using the `exercism submit pacman_rules.cpp` 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 [C++ track's documentation](https://exercism.org/docs/tracks/cpp)
- The [C++ track's programming category on the forum](https://forum.exercism.org/c/programming/cpp)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [`c++-faq` tag on StackOverflow](https://stackoverflow.com/tags/c%2b%2b-faq/info)
- [C++ FAQ from isocpp.com](https://isocpp.org/faq)
- [CppReference](http://en.cppreference.com/) is a wiki reference to the C++ language and standard library
- [C traps and pitfalls](http://www.slideshare.net/LegalizeAdulthood/c-traps-and-pitfalls-for-c-programmers) is useful if you are new to C++, but have programmed in C

27
cpp/pacman-rules/HINTS.md Normal file
View file

@ -0,0 +1,27 @@
# Hints
## General
- Don't worry about how the arguments are derived, just focus on combining the arguments to return the intended result.
## 1. Define if pac-man can eat a ghost
- The function must return a boolean value.
- You can use the logical operator and ([`&&`][logical operators]) to combine the arguments for a result.
## 2. Define if pac-man scores
- The function must return a boolean value.
- You can use the logical operator or ([`||`][logical operators]) to combine the arguments for a result.
## 3. Define if pac-man loses
- The function must return a boolean value.
- You can use the boolean operators [`&&`][logical operators] and [`!`][logical operators] to combine the arguments for a result.
## 4. Define if pac-man wins
- The function must return a boolean value.
- You can use the boolean operators [`&&`][logical operators] and [`!`][logical operators] to combine the arguments and results of one of the previously implemented functions.
[logical operators]: https://en.cppreference.com/w/cpp/language/operator_logical

View file

@ -0,0 +1,95 @@
# Pacman Rules
Welcome to Pacman Rules on Exercism's C++ 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
Booleans in C++ are represented by the `bool` type.
A `bool` is either `true` or `false`.
## Logical Operators
C++ supports three boolean operators: `!` (NOT), `&&` (AND), and `||` (OR).
You can also use the alternative versions `not`, `and`, and `or`.
```cpp
true || false // => true
true && false // => false
!true // => false
not false // => true
```
## Precedence
The three boolean operators each have different _operator precedence_.
As a consequence, they are evaluated in this order: `!` first, `&&` second, and finally `||`.
If you want to force a different ordering, you can enclose a boolean expression in parentheses (ie. `()`), as the parentheses have even higher operator precedence.
```cpp
!true && false // => false
!(true and false) // => true
```
~~~~exercism/advanced
## Conversion
If you use `true` or `false` in a place where a number is expected, they will be converted to `1` and `0` respectively.
If you use a number in a Boolean operation, everything except `0` is treated as `true` - even negative values.
```cpp
!true && 0.0 // => false
true + true + false // => 2
```
~~~~
## Instructions
In this exercise, you need to translate some rules from the classic game Pac-Man into C++ functions.
You have four rules to translate, all related to the game states.
> Don't worry about how the arguments are derived, just focus on combining the arguments to return the intended result.
## 1. Define if Pac-Man eats a ghost
Define the `can_eat_ghost` function that takes two arguments (_if Pac-Man has a power pellet active_ and _if Pac-Man is touching a ghost_) and returns a boolean value if Pac-Man is able to eat the ghost. The function should return true only if Pac-Man has a power pellet active and is touching a ghost.
```cpp
can_eat_ghost(false, true);
// => false
```
## 2. Define if Pac-Man scores
Define the `scored` function that takes two arguments (_if Pac-Man is touching a power pellet_ and _if Pac-Man is touching a dot_) and returns a boolean value if Pac-Man scored. The function should return true if Pac-Man is touching a power pellet or a dot.
```cpp
scored(true, true);
// => true
```
## 3. Define if Pac-Man loses
Define the `lost` function that takes two arguments (_if Pac-Man has a power pellet active_ and _if Pac-Man is touching a ghost_) and returns a boolean value if Pac-Man loses. The function should return true if Pac-Man is touching a ghost and does not have a power pellet active.
```cpp
lost(false, true);
// => true
```
## 4. Define if Pac-Man wins
Define the `won` function that takes three arguments (_if Pac-Man has eaten all of the dots_, _if Pac-Man has a power pellet active_, and _if Pac-Man is touching a ghost_) and returns a boolean value if Pac-Man wins. The function should return true if Pac-Man has eaten all of the dots and has not lost based on the arguments defined in part 3.
```cpp
won(false, true, false);
// => false
```
## Source
### Created by
- @vaeng

BIN
cpp/pacman-rules/pacman-rules Executable file

Binary file not shown.

View file

@ -0,0 +1,28 @@
// eat_ghost returns a boolean value if Pac-Man is able to eat the ghost.
// The function should return true only if Pac-Man has a power pellet active
// and is touching a ghost.
bool can_eat_ghost(bool power_pellet_active, bool touching_ghost) {
return power_pellet_active && touching_ghost;
}
// score returns a boolean value if Pac-Man scored.
// The function should return true if Pac-Man is touching a power pellet or a
// dot.
bool scored(bool touching_power_pellet, bool touching_dot) {
return touching_power_pellet || touching_dot;
}
// lost returns a boolean value if Pac-Man loses.
// The function should return true if Pac-Man is touching a ghost and
// does not have a power pellet active.
bool lost(bool power_pellet_active, bool touching_ghost) {
return !power_pellet_active && touching_ghost;
}
// won returns a boolean value if Pac-Man wins.
// The function should return true if Pac-Man
// has eaten all of the dots and has not lost
bool won(bool has_eaten_all_dots, bool power_pellet_active,
bool touching_ghost) {
return has_eaten_all_dots && !lost(power_pellet_active, touching_ghost);
}

View file

@ -0,0 +1,66 @@
#include "pacman_rules.cpp"
#ifdef EXERCISM_TEST_SUITE
#include <catch2/catch.hpp>
#else
#include "test/catch.hpp"
#endif
TEST_CASE("ghost gets eaten", "[task_1]") {
REQUIRE(can_eat_ghost(true, true));
}
TEST_CASE("ghost does not get eaten because no power pellet active",
"[task_1]") {
REQUIRE_FALSE(can_eat_ghost(false, true));
}
TEST_CASE("ghost does not get eaten because not touching ghost", "[task_1]") {
REQUIRE_FALSE(can_eat_ghost(true, false));
}
TEST_CASE("ghost does not get eaten because no power pellet is active, even if "
"not touching ghost",
"[task_1]") {
REQUIRE_FALSE(can_eat_ghost(false, false));
}
TEST_CASE("score when eating dot", "[task_2]") { REQUIRE(scored(false, true)); }
TEST_CASE("score when eating power pellet", "[task_2]") {
REQUIRE(scored(true, false));
}
TEST_CASE("no score when nothing eaten", "[task_2]") {
REQUIRE_FALSE(scored(false, false));
}
TEST_CASE("lose if touching a ghost without a power pellet active",
"[task_3]") {
REQUIRE(lost(false, true));
}
TEST_CASE("don't lose if touching a ghost with a power pellet active",
"[task_3]") {
REQUIRE_FALSE(lost(true, true));
}
TEST_CASE("don't lose if not touching a ghost", "[task_3]") {
REQUIRE_FALSE(lost(true, false));
}
TEST_CASE("win if all dots eaten", "[task_4]") {
REQUIRE(won(true, false, false));
}
TEST_CASE("don't win if all dots eaten, but touching a ghost", "[task_4]") {
REQUIRE_FALSE(won(true, false, true));
}
TEST_CASE(
"win if all dots eaten and touching a ghost with a power pellet active",
"[task_4]") {
REQUIRE(won(true, true, true));
}
#if defined(EXERCISM_RUN_ALL_TESTS)
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,2 @@
#define CATCH_CONFIG_MAIN
#include "catch.hpp"