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