From e0d41ab4506cfb444eddc8d599beb6117fcfe269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ingy=20d=C3=B6t=20Net?= Date: Fri, 13 Sep 2024 22:12:03 -0700 Subject: [PATCH] Implement exercise 'diamond' --- config.json | 8 ++ config.yaml | 7 + .../practice/diamond/.docs/instructions.md | 52 +++++++ .../diamond/.meta/.yamlscript/exercise.mk | 1 + exercises/practice/diamond/.meta/Makefile | 28 ++++ exercises/practice/diamond/.meta/config.json | 23 ++++ .../practice/diamond/.meta/diamond-test.ys | 100 ++++++++++++++ exercises/practice/diamond/.meta/diamond.ys | 7 + exercises/practice/diamond/.meta/tests.toml | 25 ++++ .../practice/diamond/.yamlscript/exercise.mk | 1 + .../diamond/.yamlscript/exercism-ys-installer | 127 ++++++++++++++++++ exercises/practice/diamond/GNUmakefile | 49 +++++++ exercises/practice/diamond/Makefile | 8 ++ exercises/practice/diamond/diamond-test.ys | 95 +++++++++++++ exercises/practice/diamond/diamond.ys | 4 + 15 files changed, 535 insertions(+) create mode 100644 exercises/practice/diamond/.docs/instructions.md create mode 100644 exercises/practice/diamond/.meta/.yamlscript/exercise.mk create mode 100644 exercises/practice/diamond/.meta/Makefile create mode 100644 exercises/practice/diamond/.meta/config.json create mode 100644 exercises/practice/diamond/.meta/diamond-test.ys create mode 100644 exercises/practice/diamond/.meta/diamond.ys create mode 100644 exercises/practice/diamond/.meta/tests.toml create mode 100644 exercises/practice/diamond/.yamlscript/exercise.mk create mode 100644 exercises/practice/diamond/.yamlscript/exercism-ys-installer create mode 100644 exercises/practice/diamond/GNUmakefile create mode 100644 exercises/practice/diamond/Makefile create mode 100644 exercises/practice/diamond/diamond-test.ys create mode 100644 exercises/practice/diamond/diamond.ys diff --git a/config.json b/config.json index 0aea4fa..4489ec1 100644 --- a/config.json +++ b/config.json @@ -340,6 +340,14 @@ "prerequisites": [], "difficulty": 5 }, + { + "slug": "diamond", + "name": "Diamond", + "uuid": "b907e51b-3272-4fb7-b43c-09bcf2005fbd", + "practices": [], + "prerequisites": [], + "difficulty": 5 + }, { "slug": "matching-brackets", "name": "Matching Brackets", diff --git a/config.yaml b/config.yaml index 493580f..462a6a9 100644 --- a/config.yaml +++ b/config.yaml @@ -310,6 +310,13 @@ exercises: prerequisites: [] difficulty: 5 + - slug: diamond + name: Diamond + uuid: b907e51b-3272-4fb7-b43c-09bcf2005fbd + practices: [] + prerequisites: [] + difficulty: 5 + - slug: matching-brackets name: Matching Brackets uuid: a6c79db6-925c-45c3-8a59-aa9d96a4740b diff --git a/exercises/practice/diamond/.docs/instructions.md b/exercises/practice/diamond/.docs/instructions.md new file mode 100644 index 0000000..3034802 --- /dev/null +++ b/exercises/practice/diamond/.docs/instructions.md @@ -0,0 +1,52 @@ +# Instructions + +The diamond kata takes as its input a letter, and outputs it in a diamond shape. +Given a letter, it prints a diamond starting with 'A', with the supplied letter at the widest point. + +## Requirements + +- The first row contains one 'A'. +- The last row contains one 'A'. +- All rows, except the first and last, have exactly two identical letters. +- All rows have as many trailing spaces as leading spaces. (This might be 0). +- The diamond is horizontally symmetric. +- The diamond is vertically symmetric. +- The diamond has a square shape (width equals height). +- The letters form a diamond shape. +- The top half has the letters in ascending order. +- The bottom half has the letters in descending order. +- The four corners (containing the spaces) are triangles. + +## Examples + +In the following examples, spaces are indicated by `·` characters. + +Diamond for letter 'A': + +```text +A +``` + +Diamond for letter 'C': + +```text +··A·· +·B·B· +C···C +·B·B· +··A·· +``` + +Diamond for letter 'E': + +```text +····A···· +···B·B··· +··C···C·· +·D·····D· +E·······E +·D·····D· +··C···C·· +···B·B··· +····A···· +``` diff --git a/exercises/practice/diamond/.meta/.yamlscript/exercise.mk b/exercises/practice/diamond/.meta/.yamlscript/exercise.mk new file mode 100644 index 0000000..c80936e --- /dev/null +++ b/exercises/practice/diamond/.meta/.yamlscript/exercise.mk @@ -0,0 +1 @@ +YS_VERSION := 0.1.76 diff --git a/exercises/practice/diamond/.meta/Makefile b/exercises/practice/diamond/.meta/Makefile new file mode 100644 index 0000000..ba39335 --- /dev/null +++ b/exercises/practice/diamond/.meta/Makefile @@ -0,0 +1,28 @@ +SHELL := bash + +BASE := $(shell pwd) + +export YS_VERSION := 0.1.76 + +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/diamond/.meta/config.json b/exercises/practice/diamond/.meta/config.json new file mode 100644 index 0000000..1c10a56 --- /dev/null +++ b/exercises/practice/diamond/.meta/config.json @@ -0,0 +1,23 @@ +{ + "authors": [ + "ingydotnet" + ], + "files": { + "solution": [ + "diamond.ys" + ], + "test": [ + "diamond-test.ys", + "GNUmakefile", + "Makefile", + ".yamlscript/exercise.mk", + ".yamlscript/exercism-ys-installer" + ], + "example": [ + ".meta/diamond.ys" + ] + }, + "blurb": "Given a letter, print a diamond starting with 'A' with the supplied letter at the widest point.", + "source": "Seb Rose", + "source_url": "https://web.archive.org/web/20220807163751/http://claysnow.co.uk/recycling-tests-in-tdd/" +} diff --git a/exercises/practice/diamond/.meta/diamond-test.ys b/exercises/practice/diamond/.meta/diamond-test.ys new file mode 100644 index 0000000..d599018 --- /dev/null +++ b/exercises/practice/diamond/.meta/diamond-test.ys @@ -0,0 +1,100 @@ +#!/usr/bin/env ys-0 + +require ys::taptest: :all + +use: diamond + +test:: +- name: Degenerate case with a single 'a' row + code: rows("A") + want: |2 + A + uuid: 202fb4cc-6a38-4883-9193-a29d5cb92076 + +- name: Degenerate case with no row containing 3 distinct groups of spaces + code: rows("B") + want: |2 + A + B B + A + uuid: bd6a6d78-9302-42e9-8f60-ac1461e9abae + +- name: Smallest non-degenerate case with odd diamond side length + code: rows("C") + want: |2 + A + B B + C C + B B + A + uuid: af8efb49 14ed-447f-8944-4cc59ce3fd76 + +- name: Smallest non-degenerate case with even diamond side length + code: rows("D") + want: |2 + A + B B + C C + D D + C C + B B + A + uuid: e0c19a95 9888-4d05-86a0-fa81b9e70d1d + +- name: Largest possible diamond + code: rows("Z") + want: |2 + A + B B + C C + D D + E E + F F + G G + H H + I I + J J + K K + L L + M M + N N + O O + P P + Q Q + R R + S S + T T + U U + V V + W W + X X + Y Y + Z Z + Y Y + X X + W W + V V + U U + T T + S S + R R + Q Q + P P + O O + N N + M M + L L + K K + J J + I I + H H + G G + F F + E E + D D + C C + B B + A + uuid: 82ea9aa9 4c0e-442a-b07e-40204e925944 + +done: 5 diff --git a/exercises/practice/diamond/.meta/diamond.ys b/exercises/practice/diamond/.meta/diamond.ys new file mode 100644 index 0000000..7a8ad8f --- /dev/null +++ b/exercises/practice/diamond/.meta/diamond.ys @@ -0,0 +1,7 @@ +!yamlscript/v0 + +defn rows(letter): + loop C letter.0, I (' ' * (((-64 + C) * 2) - 3)), O '', dmnd '': + line =: if(I.? "$O$C$I$C$O\n" "$O$C$O\n") + dmnd =: if(dmnd.? "$line$dmnd$line" line) + if I.?: recur(C.--, I.drop(2).join(), "$O ", dmnd), dmnd diff --git a/exercises/practice/diamond/.meta/tests.toml b/exercises/practice/diamond/.meta/tests.toml new file mode 100644 index 0000000..4e7802e --- /dev/null +++ b/exercises/practice/diamond/.meta/tests.toml @@ -0,0 +1,25 @@ +# 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. + +[202fb4cc-6a38-4883-9193-a29d5cb92076] +description = "Degenerate case with a single 'A' row" + +[bd6a6d78-9302-42e9-8f60-ac1461e9abae] +description = "Degenerate case with no row containing 3 distinct groups of spaces" + +[af8efb49-14ed-447f-8944-4cc59ce3fd76] +description = "Smallest non-degenerate case with odd diamond side length" + +[e0c19a95-9888-4d05-86a0-fa81b9e70d1d] +description = "Smallest non-degenerate case with even diamond side length" + +[82ea9aa9-4c0e-442a-b07e-40204e925944] +description = "Largest possible diamond" diff --git a/exercises/practice/diamond/.yamlscript/exercise.mk b/exercises/practice/diamond/.yamlscript/exercise.mk new file mode 100644 index 0000000..2506034 --- /dev/null +++ b/exercises/practice/diamond/.yamlscript/exercise.mk @@ -0,0 +1 @@ +YS_VERSION := 0.1.75 diff --git a/exercises/practice/diamond/.yamlscript/exercism-ys-installer b/exercises/practice/diamond/.yamlscript/exercism-ys-installer new file mode 100644 index 0000000..ae3fa01 --- /dev/null +++ b/exercises/practice/diamond/.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/diamond/GNUmakefile b/exercises/practice/diamond/GNUmakefile new file mode 100644 index 0000000..c050127 --- /dev/null +++ b/exercises/practice/diamond/GNUmakefile @@ -0,0 +1,49 @@ +SHELL := bash + +BASE := $(shell pwd) + +include .yamlscript/exercise.mk + +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/diamond/Makefile b/exercises/practice/diamond/Makefile new file mode 100644 index 0000000..06b6f00 --- /dev/null +++ b/exercises/practice/diamond/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/diamond/diamond-test.ys b/exercises/practice/diamond/diamond-test.ys new file mode 100644 index 0000000..7f03d98 --- /dev/null +++ b/exercises/practice/diamond/diamond-test.ys @@ -0,0 +1,95 @@ +#!/usr/bin/env ys-0 + +require ys::taptest: :all + +use: diamond + +test:: +- name: Degenerate case with a single 'a' row + code: rows("A") + want: |2 + A + +- name: Degenerate case with no row containing 3 distinct groups of spaces + code: rows("B") + want: |2 + A + B B + A + +- name: Smallest non-degenerate case with odd diamond side length + code: rows("C") + want: |2 + A + B B + C C + B B + A + + name: Smallest non-degenerate case with even diamond side length + code: rows("D") + want: |2 + A + B B + C C + D D + C C + B B + A + + name: Largest possible diamond + code: rows("Z") + want: |2 + A + B B + C C + D D + E E + F F + G G + H H + I I + J J + K K + L L + M M + N N + O O + P P + Q Q + R R + S S + T T + U U + V V + W W + X X + Y Y + Z Z + Y Y + X X + W W + V V + U U + T T + S S + R R + Q Q + P P + O O + N N + M M + L L + K K + J J + I I + H H + G G + F F + E E + D D + C C + B B + A + +done: 5 diff --git a/exercises/practice/diamond/diamond.ys b/exercises/practice/diamond/diamond.ys new file mode 100644 index 0000000..66395b1 --- /dev/null +++ b/exercises/practice/diamond/diamond.ys @@ -0,0 +1,4 @@ +!yamlscript/v0 + +defn rows(letter): + # Implement the 'rows' function.