From 780dc17b36c2412bdd5f9341b1a86e740d221d45 Mon Sep 17 00:00:00 2001 From: Danylo Negrienko Date: Sat, 29 Jun 2024 03:38:25 -0400 Subject: [PATCH] space_age --- elixir/space-age/.exercism/config.json | 36 ++++++++++++ elixir/space-age/.exercism/metadata.json | 1 + elixir/space-age/.formatter.exs | 4 ++ elixir/space-age/.gitignore | 24 ++++++++ elixir/space-age/HELP.md | 75 ++++++++++++++++++++++++ elixir/space-age/README.md | 58 ++++++++++++++++++ elixir/space-age/lib/space_age.ex | 35 +++++++++++ elixir/space-age/mix.exs | 28 +++++++++ elixir/space-age/test/space_age_test.exs | 70 ++++++++++++++++++++++ elixir/space-age/test/test_helper.exs | 2 + 10 files changed, 333 insertions(+) create mode 100644 elixir/space-age/.exercism/config.json create mode 100644 elixir/space-age/.exercism/metadata.json create mode 100644 elixir/space-age/.formatter.exs create mode 100644 elixir/space-age/.gitignore create mode 100644 elixir/space-age/HELP.md create mode 100644 elixir/space-age/README.md create mode 100644 elixir/space-age/lib/space_age.ex create mode 100644 elixir/space-age/mix.exs create mode 100644 elixir/space-age/test/space_age_test.exs create mode 100644 elixir/space-age/test/test_helper.exs diff --git a/elixir/space-age/.exercism/config.json b/elixir/space-age/.exercism/config.json new file mode 100644 index 0000000..4cc5495 --- /dev/null +++ b/elixir/space-age/.exercism/config.json @@ -0,0 +1,36 @@ +{ + "authors": [ + "rubysolo" + ], + "contributors": [ + "angelikatyborska", + "Cohen-Carlisle", + "dalexj", + "devonestes", + "henrik", + "jinyeow", + "koriroys", + "kytrinyx", + "lpil", + "neenjaw", + "parkerl", + "pminten", + "sotojuan", + "Teapane", + "waiting-for-dev" + ], + "files": { + "solution": [ + "lib/space_age.ex" + ], + "test": [ + "test/space_age_test.exs" + ], + "example": [ + ".meta/example.ex" + ] + }, + "blurb": "Given an age in seconds, calculate how old someone is in terms of a given planet's solar years.", + "source": "Partially inspired by Chapter 1 in Chris Pine's online Learn to Program tutorial.", + "source_url": "https://pine.fm/LearnToProgram/?Chapter=01" +} diff --git a/elixir/space-age/.exercism/metadata.json b/elixir/space-age/.exercism/metadata.json new file mode 100644 index 0000000..f4e1895 --- /dev/null +++ b/elixir/space-age/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"elixir","exercise":"space-age","id":"a5e01ddaed4e4e6187c5fa10c72075ab","url":"https://exercism.org/tracks/elixir/exercises/space-age","handle":"negrienko","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/elixir/space-age/.formatter.exs b/elixir/space-age/.formatter.exs new file mode 100644 index 0000000..d2cda26 --- /dev/null +++ b/elixir/space-age/.formatter.exs @@ -0,0 +1,4 @@ +# Used by "mix format" +[ + inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"] +] diff --git a/elixir/space-age/.gitignore b/elixir/space-age/.gitignore new file mode 100644 index 0000000..10e34a4 --- /dev/null +++ b/elixir/space-age/.gitignore @@ -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"). +space_age-*.tar + diff --git a/elixir/space-age/HELP.md b/elixir/space-age/HELP.md new file mode 100644 index 0000000..868c2be --- /dev/null +++ b/elixir/space-age/HELP.md @@ -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/.exs:LINENUM` - runs only a single test, the test from `.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/space_age.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) +- The [Elixir track's programming category on the forum](https://forum.exercism.org/c/programming/elixir) +- [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. + +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. \ No newline at end of file diff --git a/elixir/space-age/README.md b/elixir/space-age/README.md new file mode 100644 index 0000000..b7d5c6b --- /dev/null +++ b/elixir/space-age/README.md @@ -0,0 +1,58 @@ +# Space Age + +Welcome to Space Age on Exercism's Elixir Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Instructions + +Given an age in seconds, calculate how old someone would be on: + +- Mercury: orbital period 0.2408467 Earth years +- Venus: orbital period 0.61519726 Earth years +- Earth: orbital period 1.0 Earth years, 365.25 Earth days, or 31557600 seconds +- Mars: orbital period 1.8808158 Earth years +- Jupiter: orbital period 11.862615 Earth years +- Saturn: orbital period 29.447498 Earth years +- Uranus: orbital period 84.016846 Earth years +- Neptune: orbital period 164.79132 Earth years + +So if you were told someone were 1,000,000,000 seconds old, you should +be able to say that they're 31.69 Earth-years old. + +If you're wondering why Pluto didn't make the cut, go watch [this YouTube video][pluto-video]. + +Note: The actual length of one complete orbit of the Earth around the sun is closer to 365.256 days (1 sidereal year). +The Gregorian calendar has, on average, 365.2425 days. +While not entirely accurate, 365.25 is the value used in this exercise. +See [Year on Wikipedia][year] for more ways to measure a year. + +[pluto-video]: https://www.youtube.com/watch?v=Z_2gbGXzFbs +[year]: https://en.wikipedia.org/wiki/Year#Summary + +## Source + +### Created by + +- @rubysolo + +### Contributed to by + +- @angelikatyborska +- @Cohen-Carlisle +- @dalexj +- @devonestes +- @henrik +- @jinyeow +- @koriroys +- @kytrinyx +- @lpil +- @neenjaw +- @parkerl +- @pminten +- @sotojuan +- @Teapane +- @waiting-for-dev + +### Based on + +Partially inspired by Chapter 1 in Chris Pine's online Learn to Program tutorial. - https://pine.fm/LearnToProgram/?Chapter=01 \ No newline at end of file diff --git a/elixir/space-age/lib/space_age.ex b/elixir/space-age/lib/space_age.ex new file mode 100644 index 0000000..ce79dc4 --- /dev/null +++ b/elixir/space-age/lib/space_age.ex @@ -0,0 +1,35 @@ +defmodule SpaceAge do + @type planet :: + :mercury + | :venus + | :earth + | :mars + | :jupiter + | :saturn + | :uranus + | :neptune + + @planets ~w(mercury venus earth mars jupiter saturn uranus neptune)a + + defguardp is_planet(planet) when planet in @planets + + defp factor(:mercury), do: 0.2408467 + defp factor(:venus), do: 0.61519726 + defp factor(:earth), do: 1.0 + defp factor(:mars), do: 1.8808158 + defp factor(:jupiter), do: 11.862615 + defp factor(:saturn), do: 29.447498 + defp factor(:uranus), do: 84.016846 + defp factor(:neptune), do: 164.79132 + + @doc """ + Return the number of years a person that has lived for 'seconds' seconds is + aged on 'planet', or an error if 'planet' is not a planet. + """ + @spec age_on(planet, pos_integer) :: {:ok, float} | {:error, String.t()} + def age_on(planet, seconds) when is_planet(planet), + do: {:ok, seconds / (factor(planet) * 31_557_600)} + + def age_on(_planet, _seconds), + do: {:error, "not a planet"} +end diff --git a/elixir/space-age/mix.exs b/elixir/space-age/mix.exs new file mode 100644 index 0000000..384551f --- /dev/null +++ b/elixir/space-age/mix.exs @@ -0,0 +1,28 @@ +defmodule SpaceAge.MixProject do + use Mix.Project + + def project do + [ + app: :space_age, + version: "0.1.0", + # elixir: "~> 1.8", + 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 diff --git a/elixir/space-age/test/space_age_test.exs b/elixir/space-age/test/space_age_test.exs new file mode 100644 index 0000000..8017b28 --- /dev/null +++ b/elixir/space-age/test/space_age_test.exs @@ -0,0 +1,70 @@ +defmodule SpaceAgeTest do + use ExUnit.Case + + test "age on Earth" do + input = 1_000_000_000 + {:ok, age} = SpaceAge.age_on(:earth, input) + assert_in_delta 31.69, age, 0.005 + end + + test "age on Mercury" do + input = 2_134_835_688 + {:ok, age} = SpaceAge.age_on(:earth, input) + assert_in_delta 67.65, age, 0.005 + {:ok, age} = SpaceAge.age_on(:mercury, input) + assert_in_delta 280.88, age, 0.005 + end + + test "age on Venus" do + input = 189_839_836 + {:ok, age} = SpaceAge.age_on(:earth, input) + assert_in_delta 6.02, age, 0.005 + {:ok, age} = SpaceAge.age_on(:venus, input) + assert_in_delta 9.78, age, 0.005 + end + + test "age on Mars" do + input = 2_129_871_239 + {:ok, age} = SpaceAge.age_on(:earth, input) + assert_in_delta 67.49, age, 0.005 + {:ok, age} = SpaceAge.age_on(:mars, input) + assert_in_delta 35.88, age, 0.005 + end + + test "age on Jupiter" do + input = 901_876_382 + {:ok, age} = SpaceAge.age_on(:earth, input) + assert_in_delta 28.58, age, 0.005 + {:ok, age} = SpaceAge.age_on(:jupiter, input) + assert_in_delta 2.41, age, 0.005 + end + + test "age on Saturn" do + input = 2_000_000_000 + {:ok, age} = SpaceAge.age_on(:earth, input) + assert_in_delta 63.38, age, 0.005 + {:ok, age} = SpaceAge.age_on(:saturn, input) + assert_in_delta 2.15, age, 0.005 + end + + test "age on Uranus" do + input = 1_210_123_456 + {:ok, age} = SpaceAge.age_on(:earth, input) + assert_in_delta 38.35, age, 0.005 + {:ok, age} = SpaceAge.age_on(:uranus, input) + assert_in_delta 0.46, age, 0.005 + end + + test "age on Neptune" do + input = 1_821_023_456 + {:ok, age} = SpaceAge.age_on(:earth, input) + assert_in_delta 57.70, age, 0.005 + {:ok, age} = SpaceAge.age_on(:neptune, input) + assert_in_delta 0.35, age, 0.005 + end + + test "invalid planet causes error" do + input = 680_804_807 + assert SpaceAge.age_on(:sun, input) == {:error, "not a planet"} + end +end diff --git a/elixir/space-age/test/test_helper.exs b/elixir/space-age/test/test_helper.exs new file mode 100644 index 0000000..35fc5bf --- /dev/null +++ b/elixir/space-age/test/test_helper.exs @@ -0,0 +1,2 @@ +ExUnit.start() +ExUnit.configure(exclude: :pending, trace: true)