Skip to content

Commit

Permalink
Add series exercise (#85)
Browse files Browse the repository at this point in the history
  • Loading branch information
ageron authored Sep 13, 2024
1 parent a0acf63 commit 69203c3
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 0 deletions.
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,14 @@
"prerequisites": [],
"difficulty": 2
},
{
"slug": "series",
"name": "Series",
"uuid": "fac9c337-2216-414d-a7be-50205d161f3f",
"practices": [],
"prerequisites": [],
"difficulty": 2
},
{
"slug": "sublist",
"name": "Sublist",
Expand Down
19 changes: 19 additions & 0 deletions exercises/practice/series/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -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_.
18 changes: 18 additions & 0 deletions exercises/practice/series/.meta/Example.roc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module [slices]

slices : Str, U64 -> List Str
slices = \string, sliceLength ->
chars = string |> Str.toUtf8
len = chars |> List.len
if len == 0 || sliceLength == 0 || sliceLength > len then
[]
else
maybeList =
List.range { start: At 0, end: At (len - sliceLength) }
|> List.mapTry \startIndex ->
chars
|> List.sublist { start: startIndex, len: sliceLength }
|> Str.fromUtf8
when maybeList is
Ok list -> list
Err (BadUtf8 _ _) -> crash "Only ASCII strings are supported"
19 changes: 19 additions & 0 deletions exercises/practice/series/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"authors": [
"ageron"
],
"files": {
"solution": [
"Series.roc"
],
"test": [
"series-test.roc"
],
"example": [
".meta/Example.roc"
]
},
"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"
}
18 changes: 18 additions & 0 deletions exercises/practice/series/.meta/template.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{%- import "generator_macros.j2" as macros with context -%}
{{ macros.canonical_ref() }}
{{ macros.header() }}

import {{ exercise | to_pascal }} exposing [{{ cases[0]["property"] | to_camel }}]

{% for case in cases -%}
# {{ case["description"] }}
{%- if case["expected"]["error"] %} – just return an empty list{%- endif %}
expect
result = {{ case["input"]["series"] | to_roc }} |> {{ case["property"] | to_camel }} {{ case["input"]["sliceLength"] | to_roc }}
{%- if case["expected"]["error"] %}
result == []
{%- else %}
result == {{ case["expected"] | to_roc }}
{%- endif %}

{% endfor %}
44 changes: 44 additions & 0 deletions exercises/practice/series/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# 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"
include = false

[c7ed0812-0e4b-4bf3-99c4-28cbbfc246a2]
description = "empty series is invalid"
5 changes: 5 additions & 0 deletions exercises/practice/series/Series.roc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module [slices]

slices : Str, U64 -> List Str
slices = \string, sliceLength ->
crash "Please implement the 'slices' function"
62 changes: 62 additions & 0 deletions exercises/practice/series/series-test.roc
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# These tests are auto-generated with test data from:
# https://github.com/exercism/problem-specifications/tree/main/exercises/series/canonical-data.json
# File last updated on 2024-09-13
app [main] {
pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br",
}

main =
Task.ok {}

import Series exposing [slices]

# slices of one from one
expect
result = "1" |> slices 1
result == ["1"]

# slices of one from two
expect
result = "12" |> slices 1
result == ["1", "2"]

# slices of two
expect
result = "35" |> slices 2
result == ["35"]

# slices of two overlap
expect
result = "9142" |> slices 2
result == ["91", "14", "42"]

# slices can include duplicates
expect
result = "777777" |> slices 3
result == ["777", "777", "777", "777"]

# slices of a long series
expect
result = "918493904243" |> slices 5
result == ["91849", "18493", "84939", "49390", "93904", "39042", "90424", "04243"]

# slice length is too large – just return an empty list
expect
result = "12345" |> slices 6
result == []

# slice length is way too large – just return an empty list
expect
result = "12345" |> slices 42
result == []

# slice length cannot be zero – just return an empty list
expect
result = "12345" |> slices 0
result == []

# empty series is invalid – just return an empty list
expect
result = "" |> slices 1
result == []

0 comments on commit 69203c3

Please sign in to comment.