diff --git a/bin/add-practice-exercise b/bin/add-practice-exercise index 87436ec..ab658db 100755 --- a/bin/add-practice-exercise +++ b/bin/add-practice-exercise @@ -71,6 +71,8 @@ fi exercise_dir="exercises/practice/${slug}" files=$(jq -r --arg dir "${exercise_dir}" '.files | to_entries | map({key: .key, value: (.value | map("'"'"'" + $dir + "/" + . + "'"'"'") | join(" and "))}) | from_entries' "${exercise_dir}/.meta/config.json") +touch "generators/exercises/${slug//-/_}.py" + cat << NEXT_STEPS Your next steps are: diff --git a/config.json b/config.json index 610f340..0326552 100644 --- a/config.json +++ b/config.json @@ -377,6 +377,14 @@ "prerequisites": [], "difficulty": 4 }, + { + "slug": "series", + "name": "Series", + "uuid": "4f4ae55e-e180-47d9-90bf-be104a3f7b31", + "practices": [], + "prerequisites": [], + "difficulty": 4 + }, { "slug": "sieve", "name": "Sieve", diff --git a/exercises/practice/series/.docs/instructions.md b/exercises/practice/series/.docs/instructions.md new file mode 100644 index 0000000..fd97a67 --- /dev/null +++ b/exercises/practice/series/.docs/instructions.md @@ -0,0 +1,19 @@ +# Instructions + +Given a string of digits, output all the contiguous substrings of length `n` in that string in the order that they appear. + +For example, the string "49142" has the following 3-digit series: + +- "491" +- "914" +- "142" + +And the following 4-digit series: + +- "4914" +- "9142" + +And if you ask for a 6-digit series from a 5-digit string, you deserve whatever you get. + +Note that these series are only required to occupy _adjacent positions_ in the input; +the digits need not be _numerically consecutive_. diff --git a/exercises/practice/series/.meta/config.json b/exercises/practice/series/.meta/config.json new file mode 100644 index 0000000..cd518a7 --- /dev/null +++ b/exercises/practice/series/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "keiravillekode" + ], + "files": { + "solution": [ + "series.fut" + ], + "test": [ + "test.fut" + ], + "example": [ + ".meta/example.fut" + ] + }, + "blurb": "Given a string of digits, output all the contiguous substrings of length `n` in that string.", + "source": "A subset of the Problem 8 at Project Euler", + "source_url": "https://projecteuler.net/problem=8" +} diff --git a/exercises/practice/series/.meta/example.fut b/exercises/practice/series/.meta/example.fut new file mode 100644 index 0000000..27453d1 --- /dev/null +++ b/exercises/practice/series/.meta/example.fut @@ -0,0 +1,6 @@ +def slices (series: []u8) (sliceLength: i64): [][]u8 = + let seriesLength = length series + let n = seriesLength + 1 - sliceLength + let slice = \i -> series[i:i + sliceLength] :> [sliceLength]u8 + in + assert (1 <= n && n <= seriesLength) (tabulate n slice) diff --git a/exercises/practice/series/.meta/tests.toml b/exercises/practice/series/.meta/tests.toml new file mode 100644 index 0000000..9696f51 --- /dev/null +++ b/exercises/practice/series/.meta/tests.toml @@ -0,0 +1,43 @@ +# 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. + +[7ae7a46a-d992-4c2a-9c15-a112d125ebad] +description = "slices of one from one" + +[3143b71d-f6a5-4221-aeae-619f906244d2] +description = "slices of one from two" + +[dbb68ff5-76c5-4ccd-895a-93dbec6d5805] +description = "slices of two" + +[19bbea47-c987-4e11-a7d1-e103442adf86] +description = "slices of two overlap" + +[8e17148d-ba0a-4007-a07f-d7f87015d84c] +description = "slices can include duplicates" + +[bd5b085e-f612-4f81-97a8-6314258278b0] +description = "slices of a long series" + +[6d235d85-46cf-4fae-9955-14b6efef27cd] +description = "slice length is too large" + +[d7957455-346d-4e47-8e4b-87ed1564c6d7] +description = "slice length is way too large" + +[d34004ad-8765-4c09-8ba1-ada8ce776806] +description = "slice length cannot be zero" + +[10ab822d-8410-470a-a85d-23fbeb549e54] +description = "slice length cannot be negative" + +[c7ed0812-0e4b-4bf3-99c4-28cbbfc246a2] +description = "empty series is invalid" diff --git a/exercises/practice/series/series.fut b/exercises/practice/series/series.fut new file mode 100644 index 0000000..ad8219b --- /dev/null +++ b/exercises/practice/series/series.fut @@ -0,0 +1 @@ +def slices (series: []u8) (sliceLength: i64): [][]u8 = ??? diff --git a/exercises/practice/series/test.fut b/exercises/practice/series/test.fut new file mode 100644 index 0000000..c204d72 --- /dev/null +++ b/exercises/practice/series/test.fut @@ -0,0 +1,59 @@ +import "series" + +-- slices of one from one +-- == +-- input { "1" 1 } +-- output { ["1"] } + +-- slices of one from two +-- == +-- input { "12" 1 } +-- output { ["1", "2"] } + +-- slices of two +-- == +-- input { "35" 2 } +-- output { ["35"] } + +-- slices of two overlap +-- == +-- input { "9142" 2 } +-- output { ["91", "14", "42"] } + +-- slices can include duplicates +-- == +-- input { "777777" 3 } +-- output { ["777", "777", "777", "777"] } + +-- slices of a long series +-- == +-- input { "918493904243" 5 } +-- output { ["91849", "18493", "84939", "49390", "93904", "39042", "90424", "04243"] } + +-- slice length is too large +-- == +-- input { "12345" 6 } +-- error: Error* + +-- slice length is way too large +-- == +-- input { "12345" 42 } +-- error: Error* + +-- slice length cannot be zero +-- == +-- input { "12345" 0 } +-- error: Error* + +-- slice length cannot be negative +-- == +-- input { "123" -1 } +-- error: Error* + +-- empty series is invalid +-- == +-- input { "" 1 } +-- error: Error* + +let main (series: []u8) (sliceLength: i32): [][]u8 = + slices series (i64.i32 sliceLength) diff --git a/generators/exercises/series.py b/generators/exercises/series.py new file mode 100644 index 0000000..2e1d88b --- /dev/null +++ b/generators/exercises/series.py @@ -0,0 +1,17 @@ +def gen_test_case(prop, description, inp, expected, f): + series = inp["series"] + sliceLength = inp["sliceLength"] + + f.write(f"-- {description}\n") + f.write("-- ==\n") + f.write(f'-- input {{ "{series}" {sliceLength} }}\n') + if isinstance(expected, dict): + f.write("-- error: Error*\n\n") + else: + expected = str(expected).replace("'", '"') + f.write(f"-- output {{ {expected} }}\n\n") + + +def gen_main(f): + f.write("let main (series: []u8) (sliceLength: i32): [][]u8 =\n") + f.write(" slices series (i64.i32 sliceLength)\n")