Julio Biason
3 years ago
10 changed files with 363 additions and 0 deletions
@ -0,0 +1,21 @@ |
|||||||
|
{ |
||||||
|
"blurb": "Learn about booleans by implementing the rules of the Pac-Man game.", |
||||||
|
"authors": [ |
||||||
|
"neenjaw" |
||||||
|
], |
||||||
|
"contributors": [ |
||||||
|
"Cohen-Carlisle" |
||||||
|
], |
||||||
|
"files": { |
||||||
|
"solution": [ |
||||||
|
"lib/rules.ex" |
||||||
|
], |
||||||
|
"test": [ |
||||||
|
"test/rules_test.exs" |
||||||
|
], |
||||||
|
"exemplar": [ |
||||||
|
".meta/exemplar.ex" |
||||||
|
] |
||||||
|
}, |
||||||
|
"language_versions": ">=1.10" |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
{"track":"elixir","exercise":"pacman-rules","id":"0e1b851e229a4567b01888d36d142a83","url":"https://exercism.org/tracks/elixir/exercises/pacman-rules","handle":"JBiason","is_requester":true,"auto_approve":false} |
@ -0,0 +1,24 @@ |
|||||||
|
# The directory Mix will write compiled artifacts to. |
||||||
|
/_build/ |
||||||
|
|
||||||
|
# If you run "mix test --cover", coverage assets end up here. |
||||||
|
/cover/ |
||||||
|
|
||||||
|
# The directory Mix downloads your dependencies sources to. |
||||||
|
/deps/ |
||||||
|
|
||||||
|
# Where third-party dependencies like ExDoc output generated docs. |
||||||
|
/doc/ |
||||||
|
|
||||||
|
# Ignore .fetch files in case you like to edit your project deps locally. |
||||||
|
/.fetch |
||||||
|
|
||||||
|
# If the VM crashes, it generates a dump, let's ignore it too. |
||||||
|
erl_crash.dump |
||||||
|
|
||||||
|
# Also ignore archive artifacts (built via "mix archive.build"). |
||||||
|
*.ez |
||||||
|
|
||||||
|
# Ignore package tarball (built via "mix hex.build"). |
||||||
|
booleans-*.tar |
||||||
|
|
@ -0,0 +1,75 @@ |
|||||||
|
# Help |
||||||
|
|
||||||
|
## Running the tests |
||||||
|
|
||||||
|
From the terminal, change to the base directory of the exercise then execute the tests with: |
||||||
|
|
||||||
|
```bash |
||||||
|
$ mix test |
||||||
|
``` |
||||||
|
|
||||||
|
This will execute the test file found in the `test` subfolder -- a file ending in `_test.exs` |
||||||
|
|
||||||
|
Documentation: |
||||||
|
|
||||||
|
* [`mix test` - Elixir's test execution tool](https://hexdocs.pm/mix/Mix.Tasks.Test.html) |
||||||
|
* [`ExUnit` - Elixir's unit test library](https://hexdocs.pm/ex_unit/ExUnit.html) |
||||||
|
|
||||||
|
## Pending tests |
||||||
|
|
||||||
|
In test suites of practice exercises, all but the first test have been tagged to be skipped. |
||||||
|
|
||||||
|
Once you get a test passing, you can unskip the next one by commenting out the relevant `@tag :pending` with a `#` symbol. |
||||||
|
|
||||||
|
For example: |
||||||
|
|
||||||
|
```elixir |
||||||
|
# @tag :pending |
||||||
|
test "shouting" do |
||||||
|
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!" |
||||||
|
end |
||||||
|
``` |
||||||
|
|
||||||
|
If you wish to run all tests at once, you can include all skipped test by using the `--include` flag on the `mix test` command: |
||||||
|
|
||||||
|
```bash |
||||||
|
$ mix test --include pending |
||||||
|
``` |
||||||
|
|
||||||
|
Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the file `test/test_helper.exs`. |
||||||
|
|
||||||
|
```elixir |
||||||
|
# ExUnit.configure(exclude: :pending, trace: true) |
||||||
|
``` |
||||||
|
|
||||||
|
## Useful `mix test` options |
||||||
|
|
||||||
|
* `test/<FILE>.exs:LINENUM` - runs only a single test, the test from `<FILE>.exs` whose definition is on line `LINENUM` |
||||||
|
* `--failed` - runs only tests that failed the last time they ran |
||||||
|
* `--max-failures` - the suite stops evaluating tests when this number of test failures |
||||||
|
is reached |
||||||
|
* `--seed 0` - disables randomization so the tests in a single file will always be ran |
||||||
|
in the same order they were defined in |
||||||
|
|
||||||
|
## Submitting your solution |
||||||
|
|
||||||
|
You can submit your solution using the `exercism submit lib/rules.ex` 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 [Elixir track's documentation](https://exercism.org/docs/tracks/elixir) |
||||||
|
- [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. |
||||||
|
|
||||||
|
If you're stuck on something, it may help to look at some of the [available resources](https://exercism.org/docs/tracks/elixir/resources) out there where answers might be found. |
||||||
|
If you can't find what you're looking for in the documentation, feel free to ask help in the Exercism's BEAM [gitter channel](https://gitter.im/exercism/xerlang). |
@ -0,0 +1,33 @@ |
|||||||
|
# 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 |
||||||
|
|
||||||
|
- You need to define a [named function][named-function] with 2 arguments. The first argument is a [boolean][boolean] value, whether pac-man has a power pellet active. The second argument is a [boolean][boolean] value, whether pac-man is touching a ghost. |
||||||
|
- The function must return a [boolean][boolean] value. |
||||||
|
- You can use the [boolean][boolean] operator [`and/2`][boolean-function] to combine the arguments for a result. |
||||||
|
|
||||||
|
## 2. Define if pac-man scores |
||||||
|
|
||||||
|
- You need to define a [named function][named-function] with 2 arguments. The first argument is a [boolean][boolean] value, whether pac-man is touching a power pellet. The second argument is a [boolean][boolean] value, whether pac-man is touching a dot. |
||||||
|
- The function must return a [boolean][boolean] value. |
||||||
|
- You can use the [boolean][boolean] operator [`or/2`][boolean-function] to combine the arguments for a result. |
||||||
|
|
||||||
|
## 3. Define if pac-man loses |
||||||
|
|
||||||
|
- You need to define a [named function][named-function] with 2 arguments. The first argument is a [boolean][boolean] value, whether pac-man has a power pellet active. The second argument is a [boolean][boolean] value, whether pac-man is touching a ghost. |
||||||
|
- The function must return a [boolean][boolean] value. |
||||||
|
- You can use the [boolean][boolean] operators [`and/2`][boolean-function] and [`not/1`][boolean-function] to combine the arguments for a result. |
||||||
|
|
||||||
|
## 4. Define if pac-man wins |
||||||
|
|
||||||
|
- You need to define a [named function][named-function] with 3 arguments. The second argument is a [boolean][boolean] value, whether pac-man has eaten all of the dots. The first argument is a [boolean][boolean] value, whether pac-man has a power pellet active. The second argument is a [boolean][boolean] value, whether pac-man is touching a ghost. |
||||||
|
- The function must return a [boolean][boolean] value. |
||||||
|
- You can use the [boolean][boolean] operators [`and/2`][boolean-function] and [`not/1`][boolean-function] to combine the arguments and results of invoked functions. |
||||||
|
|
||||||
|
[named-function]: https://elixir-lang.org/getting-started/modules-and-functions.html#named-functions |
||||||
|
[boolean]: https://elixir-lang.org/getting-started/basic-types.html#booleans |
||||||
|
[boolean-function]: https://elixir-lang.org/getting-started/basic-operators.html |
@ -0,0 +1,91 @@ |
|||||||
|
# Pacman Rules |
||||||
|
|
||||||
|
Welcome to Pacman Rules on Exercism's Elixir 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 |
||||||
|
|
||||||
|
Elixir represents true and false values with the boolean type. There are only two values: _true_ and _false_. These values can be bound to a variable: |
||||||
|
|
||||||
|
```elixir |
||||||
|
true_variable = true |
||||||
|
false_variable = false |
||||||
|
``` |
||||||
|
|
||||||
|
We can evaluate strict boolean expressions using the `and/2`, `or/2`, and `not/1` operator functions. |
||||||
|
|
||||||
|
```elixir |
||||||
|
true_variable = true and true |
||||||
|
false_variable = true and false |
||||||
|
|
||||||
|
true_variable = false or true |
||||||
|
false_variable = false or false |
||||||
|
|
||||||
|
true_variable = not false |
||||||
|
false_variable = not true |
||||||
|
``` |
||||||
|
|
||||||
|
When writing a function that returns a boolean value, it is idiomatic to end the function name with a `?`. |
||||||
|
|
||||||
|
```elixir |
||||||
|
def either_true?(a, b) do |
||||||
|
a or b |
||||||
|
end |
||||||
|
``` |
||||||
|
|
||||||
|
## Instructions |
||||||
|
|
||||||
|
In this exercise, you need to translate some rules from the classic game Pac-Man into Elixir 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 `Rules.eat_ghost?/2` 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. |
||||||
|
|
||||||
|
```elixir |
||||||
|
Rules.eat_ghost?(false, true) |
||||||
|
# => false |
||||||
|
``` |
||||||
|
|
||||||
|
## 2. Define if Pac-Man scores |
||||||
|
|
||||||
|
Define the `Rules.score?/2` 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. |
||||||
|
|
||||||
|
```elixir |
||||||
|
Rules.score?(true, true) |
||||||
|
# => true |
||||||
|
``` |
||||||
|
|
||||||
|
## 3. Define if Pac-Man loses |
||||||
|
|
||||||
|
Define the `Rules.lose?/2` 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. |
||||||
|
|
||||||
|
```elixir |
||||||
|
Rules.lose?(false, true) |
||||||
|
# => true |
||||||
|
``` |
||||||
|
|
||||||
|
## 4. Define if Pac-Man wins |
||||||
|
|
||||||
|
Define the `Rules.win?/3` 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. |
||||||
|
|
||||||
|
```elixir |
||||||
|
Rules.win?(false, true, false) |
||||||
|
# => false |
||||||
|
``` |
||||||
|
|
||||||
|
## Source |
||||||
|
|
||||||
|
### Created by |
||||||
|
|
||||||
|
- @neenjaw |
||||||
|
|
||||||
|
### Contributed to by |
||||||
|
|
||||||
|
- @Cohen-Carlisle |
@ -0,0 +1,17 @@ |
|||||||
|
defmodule Rules do |
||||||
|
def eat_ghost?(power_pellet_active, touching_ghost) do |
||||||
|
power_pellet_active && touching_ghost |
||||||
|
end |
||||||
|
|
||||||
|
def score?(touching_power_pellet, touching_dot) do |
||||||
|
touching_power_pellet || touching_dot |
||||||
|
end |
||||||
|
|
||||||
|
def lose?(power_pellet_active, touching_ghost) do |
||||||
|
! power_pellet_active && touching_ghost |
||||||
|
end |
||||||
|
|
||||||
|
def win?(has_eaten_all_dots, power_pellet_active, touching_ghost) do |
||||||
|
has_eaten_all_dots && ! lose?(power_pellet_active, touching_ghost) |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,28 @@ |
|||||||
|
defmodule Rules.MixProject do |
||||||
|
use Mix.Project |
||||||
|
|
||||||
|
def project do |
||||||
|
[ |
||||||
|
app: :pacman_rules, |
||||||
|
version: "0.1.0", |
||||||
|
# elixir: "~> 1.10", |
||||||
|
start_permanent: Mix.env() == :prod, |
||||||
|
deps: deps() |
||||||
|
] |
||||||
|
end |
||||||
|
|
||||||
|
# Run "mix help compile.app" to learn about applications. |
||||||
|
def application do |
||||||
|
[ |
||||||
|
extra_applications: [:logger] |
||||||
|
] |
||||||
|
end |
||||||
|
|
||||||
|
# Run "mix help deps" to learn about dependencies. |
||||||
|
defp deps do |
||||||
|
[ |
||||||
|
# {:dep_from_hexpm, "~> 0.3.0"}, |
||||||
|
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} |
||||||
|
] |
||||||
|
end |
||||||
|
end |
@ -0,0 +1,71 @@ |
|||||||
|
defmodule RulesTest do |
||||||
|
use ExUnit.Case |
||||||
|
|
||||||
|
describe "eat_ghost?/2" do |
||||||
|
@tag task_id: 1 |
||||||
|
test "ghost gets eaten" do |
||||||
|
assert Rules.eat_ghost?(true, true) |
||||||
|
end |
||||||
|
|
||||||
|
@tag task_id: 1 |
||||||
|
test "ghost does not get eaten because no power pellet active" do |
||||||
|
refute Rules.eat_ghost?(false, true) |
||||||
|
end |
||||||
|
|
||||||
|
@tag task_id: 1 |
||||||
|
test "ghost does not get eaten because not touching ghost" do |
||||||
|
refute Rules.eat_ghost?(true, false) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
describe "score?/2" do |
||||||
|
@tag task_id: 2 |
||||||
|
test "score when eating dot" do |
||||||
|
assert Rules.score?(false, true) |
||||||
|
end |
||||||
|
|
||||||
|
@tag task_id: 2 |
||||||
|
test "score when eating power pellet" do |
||||||
|
assert Rules.score?(true, false) |
||||||
|
end |
||||||
|
|
||||||
|
@tag task_id: 2 |
||||||
|
test "no score when nothing eaten" do |
||||||
|
refute Rules.score?(false, false) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
describe "lose?/2" do |
||||||
|
@tag task_id: 3 |
||||||
|
test "lose if touching a ghost without a power pellet active" do |
||||||
|
assert Rules.lose?(false, true) |
||||||
|
end |
||||||
|
|
||||||
|
@tag task_id: 3 |
||||||
|
test "don't lose if touching a ghost with a power pellet active" do |
||||||
|
refute Rules.lose?(true, true) |
||||||
|
end |
||||||
|
|
||||||
|
@tag task_id: 3 |
||||||
|
test "don't lose if not touching a ghost" do |
||||||
|
refute Rules.lose?(true, false) |
||||||
|
end |
||||||
|
end |
||||||
|
|
||||||
|
describe "win?/3" do |
||||||
|
@tag task_id: 4 |
||||||
|
test "win if all dots eaten" do |
||||||
|
assert Rules.win?(true, false, false) |
||||||
|
end |
||||||
|
|
||||||
|
@tag task_id: 4 |
||||||
|
test "don't win if all dots eaten, but touching a ghost" do |
||||||
|
refute Rules.win?(true, false, true) |
||||||
|
end |
||||||
|
|
||||||
|
@tag task_id: 4 |
||||||
|
test "win if all dots eaten and touching a ghost with a power pellet active" do |
||||||
|
assert Rules.win?(true, true, true) |
||||||
|
end |
||||||
|
end |
||||||
|
end |
Loading…
Reference in new issue