From 8f8247dfefd9e2ecedc0225e3b6ea1611b5c6ef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20B=20Nagy?= <20251272+BNAndras@users.noreply.github.com> Date: Thu, 3 Jul 2025 21:01:16 -0700 Subject: [PATCH] Add `flower-field` to replace `minesweeper` --- config.json | 17 ++- config.yaml | 14 +- .../flower-field/.docs/instructions.md | 26 ++++ .../flower-field/.docs/introduction.md | 7 + .../practice/flower-field/.meta/Makefile | 28 ++++ .../practice/flower-field/.meta/config.json | 23 ++++ .../flower-field/.meta/flower-field-test.ys | 91 +++++++++++++ .../flower-field/.meta/flower-field.ys | 19 +++ .../practice/flower-field/.meta/tests.toml | 46 +++++++ .../.yamlscript/exercism-ys-installer | 127 ++++++++++++++++++ exercises/practice/flower-field/GNUmakefile | 49 +++++++ exercises/practice/flower-field/Makefile | 8 ++ .../flower-field/flower-field-test.ys | 91 +++++++++++++ .../practice/flower-field/flower-field.ys | 4 + 14 files changed, 543 insertions(+), 7 deletions(-) create mode 100644 exercises/practice/flower-field/.docs/instructions.md create mode 100644 exercises/practice/flower-field/.docs/introduction.md create mode 100644 exercises/practice/flower-field/.meta/Makefile create mode 100644 exercises/practice/flower-field/.meta/config.json create mode 100644 exercises/practice/flower-field/.meta/flower-field-test.ys create mode 100644 exercises/practice/flower-field/.meta/flower-field.ys create mode 100644 exercises/practice/flower-field/.meta/tests.toml create mode 100644 exercises/practice/flower-field/.yamlscript/exercism-ys-installer create mode 100644 exercises/practice/flower-field/GNUmakefile create mode 100644 exercises/practice/flower-field/Makefile create mode 100644 exercises/practice/flower-field/flower-field-test.ys create mode 100644 exercises/practice/flower-field/flower-field.ys diff --git a/config.json b/config.json index 4481bf8..bfe932b 100644 --- a/config.json +++ b/config.json @@ -8,15 +8,15 @@ "representer": false, "analyzer": false }, - "test_runner": { - "average_run_time": 1 - }, "blurb": "YAMLScript is a dynamic, general purpose programming language. It has a clean YAML syntax and embeds nicely into existing YAML files, making the desired parts of them dynamic. When a YAMLScript program is run, the source code transpiles to Clojure code, and is evaluted by a native binary runtime interpreter called `ys` (not by the JVM).", "version": 3, "online_editor": { "indent_style": "space", "indent_size": 2 }, + "test_runner": { + "average_run_time": 1 + }, "files": { "solution": [ "%{kebab_slug}.ys" @@ -508,13 +508,22 @@ "prerequisites": [], "difficulty": 8 }, + { + "slug": "flower-field", + "name": "Flower Field", + "uuid": "911b5139-299b-4c92-8dea-cf1bfa75ba2f", + "practices": [], + "prerequisites": [], + "difficulty": 8 + }, { "slug": "minesweeper", "name": "Minesweeper", "uuid": "4e7dd5dd-a6b6-4d8c-be9c-7a5995a86de9", "practices": [], "prerequisites": [], - "difficulty": 8 + "difficulty": 8, + "status": "deprecated" } ] }, diff --git a/config.yaml b/config.yaml index 50e29ec..dd47d88 100644 --- a/config.yaml +++ b/config.yaml @@ -12,9 +12,6 @@ status: representer: false analyzer: false -test_runner: - average_run_time: 1 - blurb: YAMLScript is a dynamic, general purpose programming language. It has a clean YAML syntax and embeds nicely into existing YAML files, making @@ -29,6 +26,9 @@ online_editor: indent_style: space indent_size: 2 +test_runner: + average_run_time: 1 + files: solution: - '%{kebab_slug}.ys' @@ -456,12 +456,20 @@ exercises: prerequisites: [] difficulty: 8 + - slug: flower-field + name: Flower Field + uuid: 911b5139-299b-4c92-8dea-cf1bfa75ba2f + practices: [] + prerequisites: [] + difficulty: 8 + - slug: minesweeper name: Minesweeper uuid: 4e7dd5dd-a6b6-4d8c-be9c-7a5995a86de9 practices: [] prerequisites: [] difficulty: 8 + status: deprecated tags: - execution_mode/compiled diff --git a/exercises/practice/flower-field/.docs/instructions.md b/exercises/practice/flower-field/.docs/instructions.md new file mode 100644 index 0000000..bbdae0c --- /dev/null +++ b/exercises/practice/flower-field/.docs/instructions.md @@ -0,0 +1,26 @@ +# Instructions + +Your task is to add flower counts to empty squares in a completed Flower Field garden. +The garden itself is a rectangle board composed of squares that are either empty (`' '`) or a flower (`'*'`). + +For each empty square, count the number of flowers adjacent to it (horizontally, vertically, diagonally). +If the empty square has no adjacent flowers, leave it empty. +Otherwise replace it with the count of adjacent flowers. + +For example, you may receive a 5 x 4 board like this (empty spaces are represented here with the '·' character for display on screen): + +```text +·*·*· +··*·· +··*·· +····· +``` + +Which your code should transform into this: + +```text +1*3*1 +13*31 +·2*2· +·111· +``` diff --git a/exercises/practice/flower-field/.docs/introduction.md b/exercises/practice/flower-field/.docs/introduction.md new file mode 100644 index 0000000..af9b615 --- /dev/null +++ b/exercises/practice/flower-field/.docs/introduction.md @@ -0,0 +1,7 @@ +# Introduction + +[Flower Field][history] is a compassionate reimagining of the popular game Minesweeper. +The object of the game is to find all the flowers in the garden using numeric hints that indicate how many flowers are directly adjacent (horizontally, vertically, diagonally) to a square. +"Flower Field" shipped in regional versions of Microsoft Windows in Italy, Germany, South Korea, Japan and Taiwan. + +[history]: https://web.archive.org/web/20020409051321fw_/http://rcm.usr.dsi.unimi.it/rcmweb/fnm/ diff --git a/exercises/practice/flower-field/.meta/Makefile b/exercises/practice/flower-field/.meta/Makefile new file mode 100644 index 0000000..5113d0b --- /dev/null +++ b/exercises/practice/flower-field/.meta/Makefile @@ -0,0 +1,28 @@ +SHELL := bash + +BASE := $(shell pwd) + +export YS_VERSION := 0.1.96 + +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/flower-field/.meta/config.json b/exercises/practice/flower-field/.meta/config.json new file mode 100644 index 0000000..dbc39c6 --- /dev/null +++ b/exercises/practice/flower-field/.meta/config.json @@ -0,0 +1,23 @@ +{ + "authors": [ + "ingydotnet" + ], + "contributors": [ + "BNAndras" + ], + "files": { + "solution": [ + "flower-field.ys" + ], + "test": [ + "flower-field-test.ys", + "GNUmakefile", + "Makefile", + ".yamlscript/exercism-ys-installer" + ], + "example": [ + ".meta/flower-field.ys" + ] + }, + "blurb": "Mark all the flowers in a garden." +} diff --git a/exercises/practice/flower-field/.meta/flower-field-test.ys b/exercises/practice/flower-field/.meta/flower-field-test.ys new file mode 100644 index 0000000..dd253dc --- /dev/null +++ b/exercises/practice/flower-field/.meta/flower-field-test.ys @@ -0,0 +1,91 @@ +#!/usr/bin/env ys-0 + +use ys::taptest: :all +load: 'flower-field.ys' + +test:: +- name: No rows + code: annotate([]) + want: [] + +- name: No columns + code: annotate([""]) + want: + - '' + +- name: No flowers + code: annotate([" " " " " "]) + want: + - ' ' + - ' ' + - ' ' + +- name: garden full of flowers + code: annotate(["***" "***" "***"]) + want: + - '***' + - '***' + - '***' + +- name: flower surrounded by spaces + code: annotate([" " " * " " "]) + want: + - '111' + - 1*1 + - '111' + +- name: Space surrounded by flowers + code: annotate(["***" "* *" "***"]) + want: + - '***' + - '*8*' + - '***' + +- name: Horizontal line + code: annotate([" * * "]) + want: + - 1*2*1 + +- name: Horizontal line, flowers at edges + code: annotate(["* *"]) + want: + - '*1 1*' + +- name: Vertical line + code: annotate([" " "*" " " "*" " "]) + want: + - '1' + - '*' + - '2' + - '*' + - '1' + +- name: Vertical line, flowers at edges + code: annotate(["*" " " " " " " "*"]) + want: + - '*' + - '1' + - ' ' + - '1' + - '*' + +- name: Cross + code: annotate([" * " " * " "*****" " * " " * "]) + want: + - ' 2*2 ' + - 25*52 + - '*****' + - 25*52 + - ' 2*2 ' + +- name: Large garden + code: annotate([" * * " " * " " * " " * *" " * * " " "]) + want: + - 1*22*1 + - 12*322 + - ' 123*2' + - 112*4* + - 1*22*2 + - '111111' + +done: 12 diff --git a/exercises/practice/flower-field/.meta/flower-field.ys b/exercises/practice/flower-field/.meta/flower-field.ys new file mode 100644 index 0000000..154057e --- /dev/null +++ b/exercises/practice/flower-field/.meta/flower-field.ys @@ -0,0 +1,19 @@ +!YS-v0 + +defn annotate(garden): + map-indexed _ garden: + fn(r row): !:join + map-indexed _ row: + fn(c col): + list =: + ? for x [-1 0 1], + y [-1 0 1] + :when garden + .get(r + x) + .get(c + y) + .eq(\\*) + : 1 + cond: + list.#.!: \\space + col == \\*: col + else: \\0 + list.# diff --git a/exercises/practice/flower-field/.meta/tests.toml b/exercises/practice/flower-field/.meta/tests.toml new file mode 100644 index 0000000..c2b24fd --- /dev/null +++ b/exercises/practice/flower-field/.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. + +[237ff487-467a-47e1-9b01-8a891844f86c] +description = "no rows" + +[4b4134ec-e20f-439c-a295-664c38950ba1] +description = "no columns" + +[d774d054-bbad-4867-88ae-069cbd1c4f92] +description = "no flowers" + +[225176a0-725e-43cd-aa13-9dced501f16e] +description = "garden full of flowers" + +[3f345495-f1a5-4132-8411-74bd7ca08c49] +description = "flower surrounded by spaces" + +[6cb04070-4199-4ef7-a6fa-92f68c660fca] +description = "space surrounded by flowers" + +[272d2306-9f62-44fe-8ab5-6b0f43a26338] +description = "horizontal line" + +[c6f0a4b2-58d0-4bf6-ad8d-ccf4144f1f8e] +description = "horizontal line, flowers at edges" + +[a54e84b7-3b25-44a8-b8cf-1753c8bb4cf5] +description = "vertical line" + +[b40f42f5-dec5-4abc-b167-3f08195189c1] +description = "vertical line, flowers at edges" + +[58674965-7b42-4818-b930-0215062d543c] +description = "cross" + +[dd9d4ca8-9e68-4f78-a677-a2a70fd7a7b8] +description = "large garden" diff --git a/exercises/practice/flower-field/.yamlscript/exercism-ys-installer b/exercises/practice/flower-field/.yamlscript/exercism-ys-installer new file mode 100644 index 0000000..ae3fa01 --- /dev/null +++ b/exercises/practice/flower-field/.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/flower-field/GNUmakefile b/exercises/practice/flower-field/GNUmakefile new file mode 100644 index 0000000..5446a82 --- /dev/null +++ b/exercises/practice/flower-field/GNUmakefile @@ -0,0 +1,49 @@ +SHELL := bash + +BASE := $(shell pwd) + +export YS_VERSION := 0.1.96 + +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/flower-field/Makefile b/exercises/practice/flower-field/Makefile new file mode 100644 index 0000000..06b6f00 --- /dev/null +++ b/exercises/practice/flower-field/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/flower-field/flower-field-test.ys b/exercises/practice/flower-field/flower-field-test.ys new file mode 100644 index 0000000..dd253dc --- /dev/null +++ b/exercises/practice/flower-field/flower-field-test.ys @@ -0,0 +1,91 @@ +#!/usr/bin/env ys-0 + +use ys::taptest: :all +load: 'flower-field.ys' + +test:: +- name: No rows + code: annotate([]) + want: [] + +- name: No columns + code: annotate([""]) + want: + - '' + +- name: No flowers + code: annotate([" " " " " "]) + want: + - ' ' + - ' ' + - ' ' + +- name: garden full of flowers + code: annotate(["***" "***" "***"]) + want: + - '***' + - '***' + - '***' + +- name: flower surrounded by spaces + code: annotate([" " " * " " "]) + want: + - '111' + - 1*1 + - '111' + +- name: Space surrounded by flowers + code: annotate(["***" "* *" "***"]) + want: + - '***' + - '*8*' + - '***' + +- name: Horizontal line + code: annotate([" * * "]) + want: + - 1*2*1 + +- name: Horizontal line, flowers at edges + code: annotate(["* *"]) + want: + - '*1 1*' + +- name: Vertical line + code: annotate([" " "*" " " "*" " "]) + want: + - '1' + - '*' + - '2' + - '*' + - '1' + +- name: Vertical line, flowers at edges + code: annotate(["*" " " " " " " "*"]) + want: + - '*' + - '1' + - ' ' + - '1' + - '*' + +- name: Cross + code: annotate([" * " " * " "*****" " * " " * "]) + want: + - ' 2*2 ' + - 25*52 + - '*****' + - 25*52 + - ' 2*2 ' + +- name: Large garden + code: annotate([" * * " " * " " * " " * *" " * * " " "]) + want: + - 1*22*1 + - 12*322 + - ' 123*2' + - 112*4* + - 1*22*2 + - '111111' + +done: 12 diff --git a/exercises/practice/flower-field/flower-field.ys b/exercises/practice/flower-field/flower-field.ys new file mode 100644 index 0000000..93db865 --- /dev/null +++ b/exercises/practice/flower-field/flower-field.ys @@ -0,0 +1,4 @@ +!YS-v0 + +defn annotate(garden): + # Implement the 'annotate' function.