diff --git a/config.json b/config.json index 7b1f79c7..239198f3 100644 --- a/config.json +++ b/config.json @@ -445,7 +445,16 @@ "prerequisites": [], "difficulty": 1, "topics": [] - } + }, + { + "slug": "series", + "name": "Series", + "uuid": "84d718e2-8924-47da-a3a5-69e8e65d8345", + "practices": [], + "prerequisites": [], + "difficulty": 1, + "topics": [] + } ] }, "concepts": [], diff --git a/exercises/practice/series/.docs/instructions.md b/exercises/practice/series/.docs/instructions.md new file mode 100644 index 00000000..e32cc38c --- /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 00000000..9c3229d6 --- /dev/null +++ b/exercises/practice/series/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "habere-et-dispertire" + ], + "files": { + "solution": [ + "Series.rakumod" + ], + "test": [ + "series.rakutest" + ], + "example": [ + ".meta/solutions/Series.rakumod" + ] + }, + "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/solutions/Series.rakumod b/exercises/practice/series/.meta/solutions/Series.rakumod new file mode 100644 index 00000000..d62a5bea --- /dev/null +++ b/exercises/practice/series/.meta/solutions/Series.rakumod @@ -0,0 +1,3 @@ +sub series ( Str $string, Int $length where 1..$string.chars ) is export { + gather take .join for $string.comb.rotor: $length => -$length.pred +} diff --git a/exercises/practice/series/.meta/template-data.yaml b/exercises/practice/series/.meta/template-data.yaml new file mode 100644 index 00000000..83975596 --- /dev/null +++ b/exercises/practice/series/.meta/template-data.yaml @@ -0,0 +1,29 @@ +properties: + slices: + test: |- + if %case:exists { + sprintf(q:to/END/, %case.raku, %case.raku, %case.raku); + dies-ok( + { series(%s, %s) }, + %s, + ); + END + } + else { + sprintf(q:to/END/, (%case, %case, %case.<>.List, %case).map(*.raku)); + cmp-ok( + series(%s, %s), + &infix:<~~>, + %s, + %s, + ); + END + } +example: |- + sub series ( Str $string, Int $length where 1..$string.chars ) is export { + gather take .join for $string.comb.rotor: $length => -$length.pred + } + +stub: |- + sub series ($string, $length) is export { + } diff --git a/exercises/practice/series/.meta/tests.toml b/exercises/practice/series/.meta/tests.toml new file mode 100644 index 00000000..9696f51f --- /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.rakumod b/exercises/practice/series/Series.rakumod new file mode 100644 index 00000000..5568eefb --- /dev/null +++ b/exercises/practice/series/Series.rakumod @@ -0,0 +1,2 @@ +sub series ($string, $length) is export { +} diff --git a/exercises/practice/series/series.rakutest b/exercises/practice/series/series.rakutest new file mode 100644 index 00000000..0a600276 --- /dev/null +++ b/exercises/practice/series/series.rakutest @@ -0,0 +1,73 @@ +#!/usr/bin/env raku +use Test; +use lib $?FILE.IO.dirname; +use Series; + +cmp-ok( # begin: 7ae7a46a-d992-4c2a-9c15-a112d125ebad + series("1", 1), + &infix:<~~>, + ("1",), + "slices of one from one", +); # end: 7ae7a46a-d992-4c2a-9c15-a112d125ebad + +cmp-ok( # begin: 3143b71d-f6a5-4221-aeae-619f906244d2 + series("12", 1), + &infix:<~~>, + ("1", "2"), + "slices of one from two", +); # end: 3143b71d-f6a5-4221-aeae-619f906244d2 + +cmp-ok( # begin: dbb68ff5-76c5-4ccd-895a-93dbec6d5805 + series("35", 2), + &infix:<~~>, + ("35",), + "slices of two", +); # end: dbb68ff5-76c5-4ccd-895a-93dbec6d5805 + +cmp-ok( # begin: 19bbea47-c987-4e11-a7d1-e103442adf86 + series("9142", 2), + &infix:<~~>, + ("91", "14", "42"), + "slices of two overlap", +); # end: 19bbea47-c987-4e11-a7d1-e103442adf86 + +cmp-ok( # begin: 8e17148d-ba0a-4007-a07f-d7f87015d84c + series("777777", 3), + &infix:<~~>, + ("777", "777", "777", "777"), + "slices can include duplicates", +); # end: 8e17148d-ba0a-4007-a07f-d7f87015d84c + +cmp-ok( # begin: bd5b085e-f612-4f81-97a8-6314258278b0 + series("918493904243", 5), + &infix:<~~>, + ("91849", "18493", "84939", "49390", "93904", "39042", "90424", "04243"), + "slices of a long series", +); # end: bd5b085e-f612-4f81-97a8-6314258278b0 + +dies-ok( # begin: 6d235d85-46cf-4fae-9955-14b6efef27cd + { series("12345", 6) }, + "slice length is too large", +); # end: 6d235d85-46cf-4fae-9955-14b6efef27cd + +dies-ok( # begin: d7957455-346d-4e47-8e4b-87ed1564c6d7 + { series("12345", 42) }, + "slice length is way too large", +); # end: d7957455-346d-4e47-8e4b-87ed1564c6d7 + +dies-ok( # begin: d34004ad-8765-4c09-8ba1-ada8ce776806 + { series("12345", 0) }, + "slice length cannot be zero", +); # end: d34004ad-8765-4c09-8ba1-ada8ce776806 + +dies-ok( # begin: 10ab822d-8410-470a-a85d-23fbeb549e54 + { series("123", -1) }, + "slice length cannot be negative", +); # end: 10ab822d-8410-470a-a85d-23fbeb549e54 + +dies-ok( # begin: c7ed0812-0e4b-4bf3-99c4-28cbbfc246a2 + { series("", 1) }, + "empty series is invalid", +); # end: c7ed0812-0e4b-4bf3-99c4-28cbbfc246a2 + +done-testing;