From 95f6f86b50efc41fd64c5115c3971e89a7665bce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingy=20d=C3=B6t=20Net?= Date: Fri, 25 Oct 2024 09:29:18 -0700 Subject: [PATCH] Implement exercise 'prime-factors' --- config.json | 8 ++ config.yaml | 7 + .../prime-factors/.docs/instructions.md | 36 +++++ .../practice/prime-factors/.meta/Makefile | 28 ++++ .../practice/prime-factors/.meta/config.json | 22 +++ .../prime-factors/.meta/prime-factors-test.ys | 96 +++++++++++++ .../prime-factors/.meta/prime-factors.ys | 8 ++ .../practice/prime-factors/.meta/tests.toml | 46 +++++++ .../.yamlscript/exercism-ys-installer | 127 ++++++++++++++++++ exercises/practice/prime-factors/GNUmakefile | 49 +++++++ exercises/practice/prime-factors/Makefile | 8 ++ .../prime-factors/prime-factors-test.ys | 84 ++++++++++++ .../practice/prime-factors/prime-factors.ys | 4 + 13 files changed, 523 insertions(+) create mode 100644 exercises/practice/prime-factors/.docs/instructions.md create mode 100644 exercises/practice/prime-factors/.meta/Makefile create mode 100644 exercises/practice/prime-factors/.meta/config.json create mode 100644 exercises/practice/prime-factors/.meta/prime-factors-test.ys create mode 100644 exercises/practice/prime-factors/.meta/prime-factors.ys create mode 100644 exercises/practice/prime-factors/.meta/tests.toml create mode 100644 exercises/practice/prime-factors/.yamlscript/exercism-ys-installer create mode 100644 exercises/practice/prime-factors/GNUmakefile create mode 100644 exercises/practice/prime-factors/Makefile create mode 100644 exercises/practice/prime-factors/prime-factors-test.ys create mode 100644 exercises/practice/prime-factors/prime-factors.ys diff --git a/config.json b/config.json index 07fd0d5..4481bf8 100644 --- a/config.json +++ b/config.json @@ -68,6 +68,14 @@ "prerequisites": [], "difficulty": 1 }, + { + "slug": "prime-factors", + "name": "Prime Factors", + "uuid": "9cc8f9a8-66c4-44e2-ad9d-c9ca4efa9dfc", + "practices": [], + "prerequisites": [], + "difficulty": 1 + }, { "slug": "resistor-color", "name": "Resistor Color", diff --git a/config.yaml b/config.yaml index fb135d0..50e29ec 100644 --- a/config.yaml +++ b/config.yaml @@ -71,6 +71,13 @@ exercises: prerequisites: [] difficulty: 1 + - slug: prime-factors + name: Prime Factors + uuid: 9cc8f9a8-66c4-44e2-ad9d-c9ca4efa9dfc + practices: [] + prerequisites: [] + difficulty: 1 + - slug: resistor-color name: Resistor Color uuid: edb17966-2a6c-47c8-ac65-d66b00deb97b diff --git a/exercises/practice/prime-factors/.docs/instructions.md b/exercises/practice/prime-factors/.docs/instructions.md new file mode 100644 index 0000000..252cc8e --- /dev/null +++ b/exercises/practice/prime-factors/.docs/instructions.md @@ -0,0 +1,36 @@ +# Instructions + +Compute the prime factors of a given natural number. + +A prime number is only evenly divisible by itself and 1. + +Note that 1 is not a prime number. + +## Example + +What are the prime factors of 60? + +- Our first divisor is 2. + 2 goes into 60, leaving 30. +- 2 goes into 30, leaving 15. + - 2 doesn't go cleanly into 15. + So let's move on to our next divisor, 3. +- 3 goes cleanly into 15, leaving 5. + - 3 does not go cleanly into 5. + The next possible factor is 4. + - 4 does not go cleanly into 5. + The next possible factor is 5. +- 5 does go cleanly into 5. +- We're left only with 1, so now, we're done. + +Our successful divisors in that computation represent the list of prime factors of 60: 2, 2, 3, and 5. + +You can check this yourself: + +```text +2 * 2 * 3 * 5 += 4 * 15 += 60 +``` + +Success! diff --git a/exercises/practice/prime-factors/.meta/Makefile b/exercises/practice/prime-factors/.meta/Makefile new file mode 100644 index 0000000..9314ec0 --- /dev/null +++ b/exercises/practice/prime-factors/.meta/Makefile @@ -0,0 +1,28 @@ +SHELL := bash + +BASE := $(shell pwd) + +export YS_VERSION := 0.1.80 + +YS_LOCAL_PREFIX := ../../../../.local/v$(YS_VERSION) + +YS_LOCAL_BIN := $(YS_LOCAL_PREFIX)/bin + +YS_BIN := $(YS_LOCAL_BIN)/ys-$(YS_VERSION) + +TEST_FILE ?= $(wildcard *-test.ys) + + +export PATH := $(YS_LOCAL_BIN):$(PATH) + +export YSPATH := $(BASE) + + +default: + +test: $(YS_BIN) + prove -v $(TEST_FILE) + +$(YS_BIN): + curl -s https://yamlscript.org/install | \ + BIN=1 VERSION=$(YS_VERSION) PREFIX=$(YS_LOCAL_PREFIX) bash >/dev/null diff --git a/exercises/practice/prime-factors/.meta/config.json b/exercises/practice/prime-factors/.meta/config.json new file mode 100644 index 0000000..cbac889 --- /dev/null +++ b/exercises/practice/prime-factors/.meta/config.json @@ -0,0 +1,22 @@ +{ + "authors": [ + "ingydotnet" + ], + "files": { + "solution": [ + "prime-factors.ys" + ], + "test": [ + "prime-factors-test.ys", + "GNUmakefile", + "Makefile", + ".yamlscript/exercism-ys-installer" + ], + "example": [ + ".meta/prime-factors.ys" + ] + }, + "blurb": "Compute the prime factors of a given natural number.", + "source": "The Prime Factors Kata by Uncle Bob", + "source_url": "https://web.archive.org/web/20221026171801/http://butunclebob.com/ArticleS.UncleBob.ThePrimeFactorsKata" +} diff --git a/exercises/practice/prime-factors/.meta/prime-factors-test.ys b/exercises/practice/prime-factors/.meta/prime-factors-test.ys new file mode 100644 index 0000000..5ee92fe --- /dev/null +++ b/exercises/practice/prime-factors/.meta/prime-factors-test.ys @@ -0,0 +1,96 @@ +#!/usr/bin/env ys-0 + +require ys::taptest: :all + +use: prime-factors + +test:: +- name: No factors + code: factors(1) + want: [] + uuid: 924fc966-a8f5-4288-82f2-6b9224819ccd + +- name: Prime number + code: factors(2) + want: + - 2 + uuid: 17e30670-b105-4305-af53-ddde182cb6ad + +- name: Another prime number + code: factors(3) + want: + - 3 + uuid: 238d57c8-4c12-42ef-af34-ae4929f94789 + +- name: Square of a prime + code: factors(9) + want: + - 3 + - 3 + uuid: f59b8350-a180-495a-8fb1-1712fbee1158 + +- name: Product of first prime + code: factors(4) + want: + - 2 + - 2 + uuid: 756949d3-3158-4e3d-91f2-c4f9f043ee70 + +- name: Cube of a prime + code: factors(8) + want: + - 2 + - 2 + - 2 + uuid: bc8c113f-9580-4516-8669-c5fc29512ceb + +- name: Product of second prime + code: factors(27) + want: + - 3 + - 3 + - 3 + uuid: 7d6a3300-a4cb-4065-bd33-0ced1de6cb44 + +- name: Product of third prime + code: factors(625) + want: + - 5 + - 5 + - 5 + - 5 + uuid: 073ac0b2-c915-4362-929d-fc45f7b9a9e4 + +- name: Product of first and second prime + code: factors(6) + want: + - 2 + - 3 + uuid: 6e0e4912-7fb6-47f3-a9ad-dbcd79340c75 + +- name: Product of primes and non-primes + code: factors(12) + want: + - 2 + - 2 + - 3 + uuid: 00485cd3-a3fe-4fbe-a64a-a4308fc1f870 + +- name: Product of primes + code: factors(901255) + want: + - 5 + - 17 + - 23 + - 461 + uuid: 02251d54-3ca1-4a9b-85e1-b38f4b0ccb91 + +- name: Factors include a large prime + code: factors(93819012551) + want: + - 11 + - 9539 + - 894119 + uuid: 070cf8dc-e202-4285-aa37-8d775c9cd473 + +done: 12 diff --git a/exercises/practice/prime-factors/.meta/prime-factors.ys b/exercises/practice/prime-factors/.meta/prime-factors.ys new file mode 100644 index 0000000..91fb5cc --- /dev/null +++ b/exercises/practice/prime-factors/.meta/prime-factors.ys @@ -0,0 +1,8 @@ +!yamlscript/v0 + +defn factors(value): + or _ []: + when value >= 2: + divisor =: range(2 (value / 2).++) + .filter(\((value % _) == 0)):first || value + into [divisor]: factors(quot(value divisor)) diff --git a/exercises/practice/prime-factors/.meta/tests.toml b/exercises/practice/prime-factors/.meta/tests.toml new file mode 100644 index 0000000..6f9cc8c --- /dev/null +++ b/exercises/practice/prime-factors/.meta/tests.toml @@ -0,0 +1,46 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[924fc966-a8f5-4288-82f2-6b9224819ccd] +description = "no factors" + +[17e30670-b105-4305-af53-ddde182cb6ad] +description = "prime number" + +[238d57c8-4c12-42ef-af34-ae4929f94789] +description = "another prime number" + +[f59b8350-a180-495a-8fb1-1712fbee1158] +description = "square of a prime" + +[756949d3-3158-4e3d-91f2-c4f9f043ee70] +description = "product of first prime" + +[bc8c113f-9580-4516-8669-c5fc29512ceb] +description = "cube of a prime" + +[7d6a3300-a4cb-4065-bd33-0ced1de6cb44] +description = "product of second prime" + +[073ac0b2-c915-4362-929d-fc45f7b9a9e4] +description = "product of third prime" + +[6e0e4912-7fb6-47f3-a9ad-dbcd79340c75] +description = "product of first and second prime" + +[00485cd3-a3fe-4fbe-a64a-a4308fc1f870] +description = "product of primes and non-primes" + +[02251d54-3ca1-4a9b-85e1-b38f4b0ccb91] +description = "product of primes" + +[070cf8dc-e202-4285-aa37-8d775c9cd473] +description = "factors include a large prime" diff --git a/exercises/practice/prime-factors/.yamlscript/exercism-ys-installer b/exercises/practice/prime-factors/.yamlscript/exercism-ys-installer new file mode 100644 index 0000000..ae3fa01 --- /dev/null +++ b/exercises/practice/prime-factors/.yamlscript/exercism-ys-installer @@ -0,0 +1,127 @@ +#!/env/bin/env bash + +set -euo pipefail + +intro-prompt() ( + cat <<... +-------------------------------------------------------------------------------- + +This YAMLScript Exercism exercise requires the YAMLScript version $version +interpreter command file to be installed here: + + $prefix/bin/ys + +You can install it by pressing Enter now, or by running this command: + + $make install-ys + +This should only take a few seconds and you only need to do this once. +Other exercises will use the same file. + +See https://yamlscript.org/doc/install/ for more YAMLScript installation info. + +-------------------------------------------------------------------------------- + +Would you like to install the 'ys' file now? + +... + + printf "Press Enter to install. Ctl-C to Quit."; read -r +) + +main() { + setup "$@" + + install-from-local + + $auto && intro-prompt + + installed || install-from-release || true + installed || install-from-build || true + installed || + die "Installing '$installed' failed. Giving up." \ + "Consider filing an issue at: $gh_issue_url" + + echo + echo 'Success!' + echo "$installed is now installed." + echo +} + +installed() { + [[ -f $installed ]] +} + +install-from-local() { + local path + path=$(command -v "$ysfq") || true + if [[ -f $path ]]; then + mkdir -p "$bin" + cp "$path" "$bin"/ + ln -fs "$ysfq" "$bin/ys-0" + ln -fs "$ysfq" "$bin/ys" + (installed && $auto) && exit + true + fi +} + +install-from-release() ( + set -x + curl -s https://yamlscript.org/install | + BIN=1 VERSION="$version" PREFIX="$prefix" bash +) + +install-from-build() ( + cat <<... + +The binary release installation failed. +We can attempt to build and install $ysfq now. +This can take from 1 to 5 minutes to complete. + +... + + printf "Press Enter to install. Ctl-C to Quit."; read -r + + [[ -d /tmp && -w /tmp ]] || + die "Can't write to /tmp" \ + 'Giving up.' + + set -x + + rm -fr "$yamlscript_clone" + + git clone --branch="$version" "$yamlscript_repo" "$yamlscript_clone" + + "$make" -C "$yamlscript_clone/ys" install PREFIX="$prefix" +) + +setup() { + version=$1 + prefix=$2 + make=$3 + auto=false + [[ ${4-} ]] && auto=true + + [[ $version =~ ^0\.1\.[0-9]+$ ]] || + die "Invalid YS_VERSION '$version'" + + bin=$prefix/bin + ysfq=ys-$version + installed=$bin/$ysfq + + if installed; then + echo "'$installed' is already installed." + exit + fi + + yamlscript_repo=https://github.com/yaml/yamlscript + yamlscript_clone=/tmp/yamlscript-exercism + gh_issue_url=https://github.com/exercism/yamlscript/issues +} + +die() { + printf '%s\n' "$@" >&2 + exit 1 +} + +main "$@" diff --git a/exercises/practice/prime-factors/GNUmakefile b/exercises/practice/prime-factors/GNUmakefile new file mode 100644 index 0000000..78a395a --- /dev/null +++ b/exercises/practice/prime-factors/GNUmakefile @@ -0,0 +1,49 @@ +SHELL := bash + +BASE := $(shell pwd) + +export YS_VERSION := 0.1.80 + +YS_LOCAL_PREFIX := ../../../.local/v$(YS_VERSION) +ifeq (,$(shell [[ -d "$(YS_LOCAL_PREFIX)" ]] && echo ok)) +YS_LOCAL_PREFIX := $(shell cd .. && pwd -P)/.local/v$(YS_VERSION) +endif + +YS_LOCAL_BIN := $(YS_LOCAL_PREFIX)/bin +YS_BIN := $(YS_LOCAL_BIN)/ys-$(YS_VERSION) + +YS_INSTALLER := .yamlscript/exercism-ys-installer +YS_INSTALLER_CMD := \ + bash $(YS_INSTALLER) $(YS_VERSION) $(YS_LOCAL_PREFIX) $(MAKE) + +TEST_FILE ?= $(wildcard *-test.ys) + +export PATH := $(YS_LOCAL_BIN):$(PATH) +export YSPATH := $(BASE) + + +#------------------------------------------------------------------------------- +default: + @echo " No default make rule. Try 'make test'." + +test: $(YS_BIN) + prove -v $(TEST_FILE) + +install-ys: + @$(YS_INSTALLER_CMD) + +uninstall-ys: + rm -fr $(YS_LOCAL_PREFIX) + + +#------------------------------------------------------------------------------- +ifdef EXERCISM_YAMLSCRIPT_GHA +$(YS_BIN): + +else ifeq (/mnt/,$(dir $(BASE))) +$(YS_BIN): + +else +$(YS_BIN): + @$(YS_INSTALLER_CMD) auto +endif diff --git a/exercises/practice/prime-factors/Makefile b/exercises/practice/prime-factors/Makefile new file mode 100644 index 0000000..06b6f00 --- /dev/null +++ b/exercises/practice/prime-factors/Makefile @@ -0,0 +1,8 @@ +# This Makefile is a decoy to attempt to detect when a non-GNU make is being +# used and alert the user. + +test: + @echo "You appear to be using a non-GNU version of the 'make' program." + @echo "The YAMLScript Exercism track requires you to use GNU make." + @echo "Please try 'make $@' again using GNU make." + @exit 1 diff --git a/exercises/practice/prime-factors/prime-factors-test.ys b/exercises/practice/prime-factors/prime-factors-test.ys new file mode 100644 index 0000000..1856663 --- /dev/null +++ b/exercises/practice/prime-factors/prime-factors-test.ys @@ -0,0 +1,84 @@ +#!/usr/bin/env ys-0 + +require ys::taptest: :all + +use: prime-factors + +test:: +- name: No factors + code: factors(1) + want: [] + +- name: Prime number + code: factors(2) + want: + - 2 + +- name: Another prime number + code: factors(3) + want: + - 3 + +- name: Square of a prime + code: factors(9) + want: + - 3 + - 3 + +- name: Product of first prime + code: factors(4) + want: + - 2 + - 2 + +- name: Cube of a prime + code: factors(8) + want: + - 2 + - 2 + - 2 + +- name: Product of second prime + code: factors(27) + want: + - 3 + - 3 + - 3 + +- name: Product of third prime + code: factors(625) + want: + - 5 + - 5 + - 5 + - 5 + +- name: Product of first and second prime + code: factors(6) + want: + - 2 + - 3 + +- name: Product of primes and non-primes + code: factors(12) + want: + - 2 + - 2 + - 3 + +- name: Product of primes + code: factors(901255) + want: + - 5 + - 17 + - 23 + - 461 + +- name: Factors include a large prime + code: factors(93819012551) + want: + - 11 + - 9539 + - 894119 + +done: 12 diff --git a/exercises/practice/prime-factors/prime-factors.ys b/exercises/practice/prime-factors/prime-factors.ys new file mode 100644 index 0000000..6599f0c --- /dev/null +++ b/exercises/practice/prime-factors/prime-factors.ys @@ -0,0 +1,4 @@ +!yamlscript/v0 + +defn factors(value): + # Implement the 'factors' function.