From 3619e2ad13e223db388698ad3f386e686e89e9e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jegors=20=C4=8Cemisovs?= Date: Sun, 14 Apr 2024 13:19:14 +0300 Subject: [PATCH 1/4] Add the "Proverb" exercise. This exercise includes adding tests, example, instructions, and metadata for a new exercise called "Proverb". The main purpose of this exercise is to refine the learner's knowledge about manipulating and filtering strings in a list. The program takes an arbitrary list of inputs and generates a series of statements often found in a proverb. The final output will depend on these inputs and the order they've been placed in. --- config.json | 8 + .../practice/proverb/.docs/instructions.md | 19 + exercises/practice/proverb/.meta/config.json | 17 + exercises/practice/proverb/.meta/example.awk | 7 + exercises/practice/proverb/.meta/tests.toml | 28 + exercises/practice/proverb/bats-extra.bash | 637 ++++++++++++++++++ exercises/practice/proverb/proverb.awk | 4 + exercises/practice/proverb/test-proverb.bats | 67 ++ 8 files changed, 787 insertions(+) create mode 100644 exercises/practice/proverb/.docs/instructions.md create mode 100644 exercises/practice/proverb/.meta/config.json create mode 100644 exercises/practice/proverb/.meta/example.awk create mode 100644 exercises/practice/proverb/.meta/tests.toml create mode 100644 exercises/practice/proverb/bats-extra.bash create mode 100644 exercises/practice/proverb/proverb.awk create mode 100644 exercises/practice/proverb/test-proverb.bats diff --git a/config.json b/config.json index dd71e71..517d78c 100644 --- a/config.json +++ b/config.json @@ -609,6 +609,14 @@ "practices": [], "prerequisites": [], "difficulty": 8 + }, + { + "slug": "proverb", + "name": "Proverb", + "uuid": "3467ee94-4209-425b-b39d-9703b4eec9e4", + "practices": [], + "prerequisites": [], + "difficulty": 1 } ], "foregone": [ diff --git a/exercises/practice/proverb/.docs/instructions.md b/exercises/practice/proverb/.docs/instructions.md new file mode 100644 index 0000000..f6fb859 --- /dev/null +++ b/exercises/practice/proverb/.docs/instructions.md @@ -0,0 +1,19 @@ +# Instructions + +For want of a horseshoe nail, a kingdom was lost, or so the saying goes. + +Given a list of inputs, generate the relevant proverb. +For example, given the list `["nail", "shoe", "horse", "rider", "message", "battle", "kingdom"]`, you will output the full text of this proverbial rhyme: + +```text +For want of a nail the shoe was lost. +For want of a shoe the horse was lost. +For want of a horse the rider was lost. +For want of a rider the message was lost. +For want of a message the battle was lost. +For want of a battle the kingdom was lost. +And all for the want of a nail. +``` + +Note that the list of inputs may vary; your solution should be able to handle lists of arbitrary length and content. +No line of the output text should be a static, unchanging string; all should vary according to the input given. diff --git a/exercises/practice/proverb/.meta/config.json b/exercises/practice/proverb/.meta/config.json new file mode 100644 index 0000000..1324bf2 --- /dev/null +++ b/exercises/practice/proverb/.meta/config.json @@ -0,0 +1,17 @@ +{ + "authors": [], + "files": { + "solution": [ + "proverb.awk" + ], + "test": [ + "test-proverb.bats" + ], + "example": [ + ".meta/example.awk" + ] + }, + "blurb": "For want of a horseshoe nail, a kingdom was lost, or so the saying goes. Output the full text of this proverbial rhyme.", + "source": "Wikipedia", + "source_url": "https://en.wikipedia.org/wiki/For_Want_of_a_Nail" +} diff --git a/exercises/practice/proverb/.meta/example.awk b/exercises/practice/proverb/.meta/example.awk new file mode 100644 index 0000000..e4ebf83 --- /dev/null +++ b/exercises/practice/proverb/.meta/example.awk @@ -0,0 +1,7 @@ +{ + for (i = 1; i < NF; i++) + print "For want of a " $i " the " $(i + 1) " was lost." +} +NF > 0 { + print "And all for the want of a " $1 "." +} diff --git a/exercises/practice/proverb/.meta/tests.toml b/exercises/practice/proverb/.meta/tests.toml new file mode 100644 index 0000000..dc92a0c --- /dev/null +++ b/exercises/practice/proverb/.meta/tests.toml @@ -0,0 +1,28 @@ +# 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. + +[e974b73e-7851-484f-8d6d-92e07fe742fc] +description = "zero pieces" + +[2fcd5f5e-8b82-4e74-b51d-df28a5e0faa4] +description = "one piece" + +[d9d0a8a1-d933-46e2-aa94-eecf679f4b0e] +description = "two pieces" + +[c95ef757-5e94-4f0d-a6cb-d2083f5e5a83] +description = "three pieces" + +[433fb91c-35a2-4d41-aeab-4de1e82b2126] +description = "full proverb" + +[c1eefa5a-e8d9-41c7-91d4-99fab6d6b9f7] +description = "four pieces modernized" diff --git a/exercises/practice/proverb/bats-extra.bash b/exercises/practice/proverb/bats-extra.bash new file mode 100644 index 0000000..54d4807 --- /dev/null +++ b/exercises/practice/proverb/bats-extra.bash @@ -0,0 +1,637 @@ +# This is the source code for bats-support and bats-assert, concatenated +# * https://github.com/bats-core/bats-support +# * https://github.com/bats-core/bats-assert +# +# Comments have been removed to save space. See the git repos for full source code. + +############################################################ +# +# bats-support - Supporting library for Bats test helpers +# +# Written in 2016 by Zoltan Tombol +# +# To the extent possible under law, the author(s) have dedicated all +# copyright and related and neighboring rights to this software to the +# public domain worldwide. This software is distributed without any +# warranty. +# +# You should have received a copy of the CC0 Public Domain Dedication +# along with this software. If not, see +# . +# + +fail() { + (( $# == 0 )) && batslib_err || batslib_err "$@" + return 1 +} + +batslib_is_caller() { + local -i is_mode_direct=1 + + # Handle options. + while (( $# > 0 )); do + case "$1" in + -i|--indirect) is_mode_direct=0; shift ;; + --) shift; break ;; + *) break ;; + esac + done + + # Arguments. + local -r func="$1" + + # Check call stack. + if (( is_mode_direct )); then + [[ $func == "${FUNCNAME[2]}" ]] && return 0 + else + local -i depth + for (( depth=2; depth<${#FUNCNAME[@]}; ++depth )); do + [[ $func == "${FUNCNAME[$depth]}" ]] && return 0 + done + fi + + return 1 +} + +batslib_err() { + { if (( $# > 0 )); then + echo "$@" + else + cat - + fi + } >&2 +} + +batslib_count_lines() { + local -i n_lines=0 + local line + while IFS='' read -r line || [[ -n $line ]]; do + (( ++n_lines )) + done < <(printf '%s' "$1") + echo "$n_lines" +} + +batslib_is_single_line() { + for string in "$@"; do + (( $(batslib_count_lines "$string") > 1 )) && return 1 + done + return 0 +} + +batslib_get_max_single_line_key_width() { + local -i max_len=-1 + while (( $# != 0 )); do + local -i key_len="${#1}" + batslib_is_single_line "$2" && (( key_len > max_len )) && max_len="$key_len" + shift 2 + done + echo "$max_len" +} + +batslib_print_kv_single() { + local -ir col_width="$1"; shift + while (( $# != 0 )); do + printf '%-*s : %s\n' "$col_width" "$1" "$2" + shift 2 + done +} + +batslib_print_kv_multi() { + while (( $# != 0 )); do + printf '%s (%d lines):\n' "$1" "$( batslib_count_lines "$2" )" + printf '%s\n' "$2" + shift 2 + done +} + +batslib_print_kv_single_or_multi() { + local -ir width="$1"; shift + local -a pairs=( "$@" ) + + local -a values=() + local -i i + for (( i=1; i < ${#pairs[@]}; i+=2 )); do + values+=( "${pairs[$i]}" ) + done + + if batslib_is_single_line "${values[@]}"; then + batslib_print_kv_single "$width" "${pairs[@]}" + else + local -i i + for (( i=1; i < ${#pairs[@]}; i+=2 )); do + pairs[$i]="$( batslib_prefix < <(printf '%s' "${pairs[$i]}") )" + done + batslib_print_kv_multi "${pairs[@]}" + fi +} + +batslib_prefix() { + local -r prefix="${1:- }" + local line + while IFS='' read -r line || [[ -n $line ]]; do + printf '%s%s\n' "$prefix" "$line" + done +} + +batslib_mark() { + local -r symbol="$1"; shift + # Sort line numbers. + set -- $( sort -nu <<< "$( printf '%d\n' "$@" )" ) + + local line + local -i idx=0 + while IFS='' read -r line || [[ -n $line ]]; do + if (( ${1:--1} == idx )); then + printf '%s\n' "${symbol}${line:${#symbol}}" + shift + else + printf '%s\n' "$line" + fi + (( ++idx )) + done +} + +batslib_decorate() { + echo + echo "-- $1 --" + cat - + echo '--' + echo +} + +############################################################ + +assert() { + if ! "$@"; then + batslib_print_kv_single 10 'expression' "$*" \ + | batslib_decorate 'assertion failed' \ + | fail + fi +} + +assert_equal() { + if [[ $1 != "$2" ]]; then + batslib_print_kv_single_or_multi 8 \ + 'expected' "$2" \ + 'actual' "$1" \ + | batslib_decorate 'values do not equal' \ + | fail + fi +} + +assert_failure() { + : "${output?}" + : "${status?}" + + (( $# > 0 )) && local -r expected="$1" + if (( status == 0 )); then + batslib_print_kv_single_or_multi 6 'output' "$output" \ + | batslib_decorate 'command succeeded, but it was expected to fail' \ + | fail + elif (( $# > 0 )) && (( status != expected )); then + { local -ir width=8 + batslib_print_kv_single "$width" \ + 'expected' "$expected" \ + 'actual' "$status" + batslib_print_kv_single_or_multi "$width" \ + 'output' "$output" + } \ + | batslib_decorate 'command failed as expected, but status differs' \ + | fail + fi +} + +assert_line() { + local -i is_match_line=0 + local -i is_mode_partial=0 + local -i is_mode_regexp=0 + : "${lines?}" + + # Handle options. + while (( $# > 0 )); do + case "$1" in + -n|--index) + if (( $# < 2 )) || ! [[ $2 =~ ^([0-9]|[1-9][0-9]+)$ ]]; then + echo "\`--index' requires an integer argument: \`$2'" \ + | batslib_decorate 'ERROR: assert_line' \ + | fail + return $? + fi + is_match_line=1 + local -ri idx="$2" + shift 2 + ;; + -p|--partial) is_mode_partial=1; shift ;; + -e|--regexp) is_mode_regexp=1; shift ;; + --) shift; break ;; + *) break ;; + esac + done + + if (( is_mode_partial )) && (( is_mode_regexp )); then + echo "\`--partial' and \`--regexp' are mutually exclusive" \ + | batslib_decorate 'ERROR: assert_line' \ + | fail + return $? + fi + + # Arguments. + local -r expected="$1" + + if (( is_mode_regexp == 1 )) && [[ '' =~ $expected ]] || (( $? == 2 )); then + echo "Invalid extended regular expression: \`$expected'" \ + | batslib_decorate 'ERROR: assert_line' \ + | fail + return $? + fi + + # Matching. + if (( is_match_line )); then + # Specific line. + if (( is_mode_regexp )); then + if ! [[ ${lines[$idx]} =~ $expected ]]; then + batslib_print_kv_single 6 \ + 'index' "$idx" \ + 'regexp' "$expected" \ + 'line' "${lines[$idx]}" \ + | batslib_decorate 'regular expression does not match line' \ + | fail + fi + elif (( is_mode_partial )); then + if [[ ${lines[$idx]} != *"$expected"* ]]; then + batslib_print_kv_single 9 \ + 'index' "$idx" \ + 'substring' "$expected" \ + 'line' "${lines[$idx]}" \ + | batslib_decorate 'line does not contain substring' \ + | fail + fi + else + if [[ ${lines[$idx]} != "$expected" ]]; then + batslib_print_kv_single 8 \ + 'index' "$idx" \ + 'expected' "$expected" \ + 'actual' "${lines[$idx]}" \ + | batslib_decorate 'line differs' \ + | fail + fi + fi + else + # Contained in output. + if (( is_mode_regexp )); then + local -i idx + for (( idx = 0; idx < ${#lines[@]}; ++idx )); do + [[ ${lines[$idx]} =~ $expected ]] && return 0 + done + { local -ar single=( 'regexp' "$expected" ) + local -ar may_be_multi=( 'output' "$output" ) + local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )" + batslib_print_kv_single "$width" "${single[@]}" + batslib_print_kv_single_or_multi "$width" "${may_be_multi[@]}" + } \ + | batslib_decorate 'no output line matches regular expression' \ + | fail + elif (( is_mode_partial )); then + local -i idx + for (( idx = 0; idx < ${#lines[@]}; ++idx )); do + [[ ${lines[$idx]} == *"$expected"* ]] && return 0 + done + { local -ar single=( 'substring' "$expected" ) + local -ar may_be_multi=( 'output' "$output" ) + local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )" + batslib_print_kv_single "$width" "${single[@]}" + batslib_print_kv_single_or_multi "$width" "${may_be_multi[@]}" + } \ + | batslib_decorate 'no output line contains substring' \ + | fail + else + local -i idx + for (( idx = 0; idx < ${#lines[@]}; ++idx )); do + [[ ${lines[$idx]} == "$expected" ]] && return 0 + done + { local -ar single=( 'line' "$expected" ) + local -ar may_be_multi=( 'output' "$output" ) + local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )" + batslib_print_kv_single "$width" "${single[@]}" + batslib_print_kv_single_or_multi "$width" "${may_be_multi[@]}" + } \ + | batslib_decorate 'output does not contain line' \ + | fail + fi + fi +} + +assert_output() { + local -i is_mode_partial=0 + local -i is_mode_regexp=0 + local -i is_mode_nonempty=0 + local -i use_stdin=0 + : "${output?}" + + # Handle options. + if (( $# == 0 )); then + is_mode_nonempty=1 + fi + + while (( $# > 0 )); do + case "$1" in + -p|--partial) is_mode_partial=1; shift ;; + -e|--regexp) is_mode_regexp=1; shift ;; + -|--stdin) use_stdin=1; shift ;; + --) shift; break ;; + *) break ;; + esac + done + + if (( is_mode_partial )) && (( is_mode_regexp )); then + echo "\`--partial' and \`--regexp' are mutually exclusive" \ + | batslib_decorate 'ERROR: assert_output' \ + | fail + return $? + fi + + # Arguments. + local expected + if (( use_stdin )); then + expected="$(cat -)" + else + expected="${1-}" + fi + + # Matching. + if (( is_mode_nonempty )); then + if [ -z "$output" ]; then + echo 'expected non-empty output, but output was empty' \ + | batslib_decorate 'no output' \ + | fail + fi + elif (( is_mode_regexp )); then + if [[ '' =~ $expected ]] || (( $? == 2 )); then + echo "Invalid extended regular expression: \`$expected'" \ + | batslib_decorate 'ERROR: assert_output' \ + | fail + elif ! [[ $output =~ $expected ]]; then + batslib_print_kv_single_or_multi 6 \ + 'regexp' "$expected" \ + 'output' "$output" \ + | batslib_decorate 'regular expression does not match output' \ + | fail + fi + elif (( is_mode_partial )); then + if [[ $output != *"$expected"* ]]; then + batslib_print_kv_single_or_multi 9 \ + 'substring' "$expected" \ + 'output' "$output" \ + | batslib_decorate 'output does not contain substring' \ + | fail + fi + else + if [[ $output != "$expected" ]]; then + batslib_print_kv_single_or_multi 8 \ + 'expected' "$expected" \ + 'actual' "$output" \ + | batslib_decorate 'output differs' \ + | fail + fi + fi +} + +assert_success() { + : "${output?}" + : "${status?}" + + if (( status != 0 )); then + { local -ir width=6 + batslib_print_kv_single "$width" 'status' "$status" + batslib_print_kv_single_or_multi "$width" 'output' "$output" + } \ + | batslib_decorate 'command failed' \ + | fail + fi +} + +refute() { + if "$@"; then + batslib_print_kv_single 10 'expression' "$*" \ + | batslib_decorate 'assertion succeeded, but it was expected to fail' \ + | fail + fi +} + +refute_line() { + local -i is_match_line=0 + local -i is_mode_partial=0 + local -i is_mode_regexp=0 + : "${lines?}" + + # Handle options. + while (( $# > 0 )); do + case "$1" in + -n|--index) + if (( $# < 2 )) || ! [[ $2 =~ ^([0-9]|[1-9][0-9]+)$ ]]; then + echo "\`--index' requires an integer argument: \`$2'" \ + | batslib_decorate 'ERROR: refute_line' \ + | fail + return $? + fi + is_match_line=1 + local -ri idx="$2" + shift 2 + ;; + -p|--partial) is_mode_partial=1; shift ;; + -e|--regexp) is_mode_regexp=1; shift ;; + --) shift; break ;; + *) break ;; + esac + done + + if (( is_mode_partial )) && (( is_mode_regexp )); then + echo "\`--partial' and \`--regexp' are mutually exclusive" \ + | batslib_decorate 'ERROR: refute_line' \ + | fail + return $? + fi + + # Arguments. + local -r unexpected="$1" + + if (( is_mode_regexp == 1 )) && [[ '' =~ $unexpected ]] || (( $? == 2 )); then + echo "Invalid extended regular expression: \`$unexpected'" \ + | batslib_decorate 'ERROR: refute_line' \ + | fail + return $? + fi + + # Matching. + if (( is_match_line )); then + # Specific line. + if (( is_mode_regexp )); then + if [[ ${lines[$idx]} =~ $unexpected ]]; then + batslib_print_kv_single 6 \ + 'index' "$idx" \ + 'regexp' "$unexpected" \ + 'line' "${lines[$idx]}" \ + | batslib_decorate 'regular expression should not match line' \ + | fail + fi + elif (( is_mode_partial )); then + if [[ ${lines[$idx]} == *"$unexpected"* ]]; then + batslib_print_kv_single 9 \ + 'index' "$idx" \ + 'substring' "$unexpected" \ + 'line' "${lines[$idx]}" \ + | batslib_decorate 'line should not contain substring' \ + | fail + fi + else + if [[ ${lines[$idx]} == "$unexpected" ]]; then + batslib_print_kv_single 5 \ + 'index' "$idx" \ + 'line' "${lines[$idx]}" \ + | batslib_decorate 'line should differ' \ + | fail + fi + fi + else + # Line contained in output. + if (( is_mode_regexp )); then + local -i idx + for (( idx = 0; idx < ${#lines[@]}; ++idx )); do + if [[ ${lines[$idx]} =~ $unexpected ]]; then + { local -ar single=( 'regexp' "$unexpected" 'index' "$idx" ) + local -a may_be_multi=( 'output' "$output" ) + local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )" + batslib_print_kv_single "$width" "${single[@]}" + if batslib_is_single_line "${may_be_multi[1]}"; then + batslib_print_kv_single "$width" "${may_be_multi[@]}" + else + may_be_multi[1]="$( printf '%s' "${may_be_multi[1]}" | batslib_prefix | batslib_mark '>' "$idx" )" + batslib_print_kv_multi "${may_be_multi[@]}" + fi + } \ + | batslib_decorate 'no line should match the regular expression' \ + | fail + return $? + fi + done + elif (( is_mode_partial )); then + local -i idx + for (( idx = 0; idx < ${#lines[@]}; ++idx )); do + if [[ ${lines[$idx]} == *"$unexpected"* ]]; then + { local -ar single=( 'substring' "$unexpected" 'index' "$idx" ) + local -a may_be_multi=( 'output' "$output" ) + local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )" + batslib_print_kv_single "$width" "${single[@]}" + if batslib_is_single_line "${may_be_multi[1]}"; then + batslib_print_kv_single "$width" "${may_be_multi[@]}" + else + may_be_multi[1]="$( printf '%s' "${may_be_multi[1]}" | batslib_prefix | batslib_mark '>' "$idx" )" + batslib_print_kv_multi "${may_be_multi[@]}" + fi + } \ + | batslib_decorate 'no line should contain substring' \ + | fail + return $? + fi + done + else + local -i idx + for (( idx = 0; idx < ${#lines[@]}; ++idx )); do + if [[ ${lines[$idx]} == "$unexpected" ]]; then + { local -ar single=( 'line' "$unexpected" 'index' "$idx" ) + local -a may_be_multi=( 'output' "$output" ) + local -ir width="$( batslib_get_max_single_line_key_width "${single[@]}" "${may_be_multi[@]}" )" + batslib_print_kv_single "$width" "${single[@]}" + if batslib_is_single_line "${may_be_multi[1]}"; then + batslib_print_kv_single "$width" "${may_be_multi[@]}" + else + may_be_multi[1]="$( printf '%s' "${may_be_multi[1]}" | batslib_prefix | batslib_mark '>' "$idx" )" + batslib_print_kv_multi "${may_be_multi[@]}" + fi + } \ + | batslib_decorate 'line should not be in output' \ + | fail + return $? + fi + done + fi + fi +} + +refute_output() { + local -i is_mode_partial=0 + local -i is_mode_regexp=0 + local -i is_mode_empty=0 + local -i use_stdin=0 + : "${output?}" + + # Handle options. + if (( $# == 0 )); then + is_mode_empty=1 + fi + + while (( $# > 0 )); do + case "$1" in + -p|--partial) is_mode_partial=1; shift ;; + -e|--regexp) is_mode_regexp=1; shift ;; + -|--stdin) use_stdin=1; shift ;; + --) shift; break ;; + *) break ;; + esac + done + + if (( is_mode_partial )) && (( is_mode_regexp )); then + echo "\`--partial' and \`--regexp' are mutually exclusive" \ + | batslib_decorate 'ERROR: refute_output' \ + | fail + return $? + fi + + # Arguments. + local unexpected + if (( use_stdin )); then + unexpected="$(cat -)" + else + unexpected="${1-}" + fi + + if (( is_mode_regexp == 1 )) && [[ '' =~ $unexpected ]] || (( $? == 2 )); then + echo "Invalid extended regular expression: \`$unexpected'" \ + | batslib_decorate 'ERROR: refute_output' \ + | fail + return $? + fi + + # Matching. + if (( is_mode_empty )); then + if [ -n "$output" ]; then + batslib_print_kv_single_or_multi 6 \ + 'output' "$output" \ + | batslib_decorate 'output non-empty, but expected no output' \ + | fail + fi + elif (( is_mode_regexp )); then + if [[ $output =~ $unexpected ]]; then + batslib_print_kv_single_or_multi 6 \ + 'regexp' "$unexpected" \ + 'output' "$output" \ + | batslib_decorate 'regular expression should not match output' \ + | fail + fi + elif (( is_mode_partial )); then + if [[ $output == *"$unexpected"* ]]; then + batslib_print_kv_single_or_multi 9 \ + 'substring' "$unexpected" \ + 'output' "$output" \ + | batslib_decorate 'output should not contain substring' \ + | fail + fi + else + if [[ $output == "$unexpected" ]]; then + batslib_print_kv_single_or_multi 6 \ + 'output' "$output" \ + | batslib_decorate 'output equals, but it was expected to differ' \ + | fail + fi + fi +} diff --git a/exercises/practice/proverb/proverb.awk b/exercises/practice/proverb/proverb.awk new file mode 100644 index 0000000..bca5f43 --- /dev/null +++ b/exercises/practice/proverb/proverb.awk @@ -0,0 +1,4 @@ +BEGIN { + print "Implement this solution" > "/dev/stderr" + exit 1 +} diff --git a/exercises/practice/proverb/test-proverb.bats b/exercises/practice/proverb/test-proverb.bats new file mode 100644 index 0000000..2c18c27 --- /dev/null +++ b/exercises/practice/proverb/test-proverb.bats @@ -0,0 +1,67 @@ +#!/usr/bin/env bats +load bats-extra + +@test "zero pieces" { + #[[ $BATS_RUN_SKIPPED == "true" ]] || skip + run gawk -f proverb.awk <<< "" + + assert_success + assert_equal "${#lines[@]}" 0 +} + +@test "one piece" { + [[ $BATS_RUN_SKIPPED == "true" ]] || skip + run gawk -f proverb.awk <<< "nail" + + assert_success + assert_line --index 0 -- "And all for the want of a nail." + assert_equal "${#lines[@]}" 1 +} + +@test "two pieces" { + [[ $BATS_RUN_SKIPPED == "true" ]] || skip + run gawk -f proverb.awk <<< "nail shoe" + + assert_success + assert_line --index 0 -- "For want of a nail the shoe was lost." + assert_line --index 1 -- "And all for the want of a nail." + assert_equal "${#lines[@]}" 2 +} + +@test "three pieces" { + [[ $BATS_RUN_SKIPPED == "true" ]] || skip + run gawk -f proverb.awk <<< "nail shoe horse" + + assert_success + assert_line --index 0 -- "For want of a nail the shoe was lost." + assert_line --index 1 -- "For want of a shoe the horse was lost." + assert_line --index 2 -- "And all for the want of a nail." + assert_equal "${#lines[@]}" 3 +} + +@test "full proverb" { + [[ $BATS_RUN_SKIPPED == "true" ]] || skip + run gawk -f proverb.awk <<< "nail shoe horse rider message battle kingdom" + + assert_success + assert_line --index 0 -- "For want of a nail the shoe was lost." + assert_line --index 1 -- "For want of a shoe the horse was lost." + assert_line --index 2 -- "For want of a horse the rider was lost." + assert_line --index 3 -- "For want of a rider the message was lost." + assert_line --index 4 -- "For want of a message the battle was lost." + assert_line --index 5 -- "For want of a battle the kingdom was lost." + assert_line --index 6 -- "And all for the want of a nail." + assert_equal "${#lines[@]}" 7 +} + +@test "four pieces modernized" { + [[ $BATS_RUN_SKIPPED == "true" ]] || skip + run gawk -f proverb.awk <<< "pin gun soldier battle" + + assert_success + assert_line --index 0 -- "For want of a pin the gun was lost." + assert_line --index 1 -- "For want of a gun the soldier was lost." + assert_line --index 2 -- "For want of a soldier the battle was lost." + assert_line --index 3 -- "And all for the want of a pin." + assert_equal "${#lines[@]}" 4 +} From 3fab589a93af40c0595b6dced287a2cb7dc3ffea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jegors=20=C4=8Cemisovs?= Date: Sun, 14 Apr 2024 13:21:59 +0300 Subject: [PATCH 2/4] Reorder exercises in config.json The 'Proverb' exercise has been reordered within the configuration file config.json. This change puts exercises in order according to their difficulty level. The difficulty level was also adjusted from 1 to 2 for 'Proverb'. --- config.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/config.json b/config.json index 517d78c..43f4b70 100644 --- a/config.json +++ b/config.json @@ -202,6 +202,14 @@ "prerequisites": [], "difficulty": 2 }, + { + "slug": "proverb", + "name": "Proverb", + "uuid": "3467ee94-4209-425b-b39d-9703b4eec9e4", + "practices": [], + "prerequisites": [], + "difficulty": 2 + }, { "slug": "rotational-cipher", "name": "Rotational Cipher", @@ -609,14 +617,6 @@ "practices": [], "prerequisites": [], "difficulty": 8 - }, - { - "slug": "proverb", - "name": "Proverb", - "uuid": "3467ee94-4209-425b-b39d-9703b4eec9e4", - "practices": [], - "prerequisites": [], - "difficulty": 1 } ], "foregone": [ From 93f484a68d5971dcbe2a88e781753034cf1c2713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jegors=20=C4=8Cemisovs?= Date: Sun, 14 Apr 2024 13:23:09 +0300 Subject: [PATCH 3/4] Update author information in config.json files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The author data has been updated in the config.json files for both the 'automated-readability-index' and 'proverb' practice exercises. "Jegors Čemisovs" has been replaced with "rabestro" for the readability index, and "rabestro" has been added to the proverb exercise. --- .../practice/automated-readability-index/.meta/config.json | 2 +- exercises/practice/proverb/.meta/config.json | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/exercises/practice/automated-readability-index/.meta/config.json b/exercises/practice/automated-readability-index/.meta/config.json index a516b47..034039d 100644 --- a/exercises/practice/automated-readability-index/.meta/config.json +++ b/exercises/practice/automated-readability-index/.meta/config.json @@ -1,6 +1,6 @@ { "authors": [ - "Jegors Čemisovs" + "rabestro" ], "files": { "solution": [ diff --git a/exercises/practice/proverb/.meta/config.json b/exercises/practice/proverb/.meta/config.json index 1324bf2..abc599d 100644 --- a/exercises/practice/proverb/.meta/config.json +++ b/exercises/practice/proverb/.meta/config.json @@ -1,5 +1,7 @@ { - "authors": [], + "authors": [ + "rabestro" + ], "files": { "solution": [ "proverb.awk" From 4ef304151359ea37e758bebc24ad1387b22da07b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jegors=20=C4=8Cemisovs?= Date: Sun, 14 Apr 2024 13:49:00 +0300 Subject: [PATCH 4/4] Refactor the proverb exercise's example.awk file The conditional statement has been simplified in the example.awk file for the 'proverb' exercise. --- exercises/practice/proverb/.meta/example.awk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/proverb/.meta/example.awk b/exercises/practice/proverb/.meta/example.awk index e4ebf83..eedad40 100644 --- a/exercises/practice/proverb/.meta/example.awk +++ b/exercises/practice/proverb/.meta/example.awk @@ -2,6 +2,6 @@ for (i = 1; i < NF; i++) print "For want of a " $i " the " $(i + 1) " was lost." } -NF > 0 { +NF { print "And all for the want of a " $1 "." }