🎉 Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io 🎉
Avatar of epequeno

epequeno's solution

to Series in the Elm Track

Published at Apr 24 2021 · 0 comments
Instructions
Test suite
Solution

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.

Elm Installation

Refer to the Installing Elm page for information about installing elm.

Writing the Code

The code you have to write is located inside the src/ directory of the exercise. Elm automatically installs packages dependencies the first time you run the tests so we can start by running the tests from the exercise directory with:

$ elm-test

To automatically run tests again when you save changes:

$ elm-test --watch

As you work your way through the tests suite in the file tests/Tests.elm, be sure to remove the skip <| calls from each test until you get them all passing!

Source

A subset of the Problem 8 at Project Euler http://projecteuler.net/problem=8

Submitting Incomplete Solutions

It is possible to submit an incomplete solution so you can see how others have completed the exercise.

Tests.elm

module Tests exposing (tests)

import Expect
import Series exposing (slices)
import Test exposing (..)


tests : Test
tests =
    describe "Series"
        [ test "slices of one from one" <|
            \() ->
                Expect.equal (Ok [ [ 1 ] ])
                    (slices 1 "1")
        , skip <|
            test "slices of one from two" <|
                \() ->
                    Expect.equal (Ok [ [ 1 ], [ 2 ] ])
                        (slices 1 "12")
        , skip <|
            test "slices of two" <|
                \() ->
                    Expect.equal (Ok [ [ 3, 5 ] ])
                        (slices 2 "35")
        , skip <|
            test "slices of two overlap" <|
                \() ->
                    Expect.equal (Ok [ [ 9, 1 ], [ 1, 4 ], [ 4, 2 ] ])
                        (slices 2 "9142")
        , skip <|
            test "slices can include duplicates" <|
                \() ->
                    Expect.equal (Ok [ [ 7, 7, 7 ], [ 7, 7, 7 ], [ 7, 7, 7 ], [ 7, 7, 7 ] ])
                        (slices 3 "777777")
        , skip <|
            test "slices of a long series" <|
                \() ->
                    Expect.equal (Ok [ [ 9, 1, 8, 4, 9 ], [ 1, 8, 4, 9, 3 ], [ 8, 4, 9, 3, 9 ], [ 4, 9, 3, 9, 0 ], [ 9, 3, 9, 0, 4 ], [ 3, 9, 0, 4, 2 ], [ 9, 0, 4, 2, 4 ], [ 0, 4, 2, 4, 3 ] ])
                        (slices 5 "918493904243")
        , skip <|
            test "slice length is too large" <|
                \() ->
                    Expect.equal (Err "slice length cannot be greater than series length")
                        (slices 6 "12345")
        , skip <|
            test "slice length cannot be zero" <|
                \() ->
                    Expect.equal (Err "slice length cannot be zero")
                        (slices 0 "12345")
        , skip <|
            test "slice length cannot be negative" <|
                \() ->
                    Expect.equal (Err "slice length cannot be negative")
                        (slices -1 "123")
        , skip <|
            test "empty series is invalid" <|
                \() ->
                    Expect.equal (Err "series cannot be empty")
                        (slices 1 "")
        ]
module Series exposing (slices)


slices : Int -> String -> Result String (List (List Int))
slices size input =
    if input == "" then
        Err "series cannot be empty"

    else if size == 0 then
        Err "slice length cannot be zero"

    else if size < 0 then
        Err "slice length cannot be negative"

    else if size > String.length input then
        Err "slice length cannot be greater than series length"

    else
        Ok (getSlices size input)


getSlices : Int -> String -> List (List Int)
getSlices size input =
    List.range 0 (String.length input)
        |> List.map (\i -> String.slice i (i + size) input |> convertChunk)
        |> List.filter (\l -> not (List.isEmpty l))
        |> List.filter (\l -> List.length l >= size)


convertChunk : String -> List Int
convertChunk input =
    input
        |> String.toList
        |> List.map String.fromChar
        |> List.map String.toInt
        |> List.map (Maybe.withDefault 0)

Community comments

Find this solution interesting? Ask the author a question to learn more.

What can you learn from this solution?

A huge amount can be learned from reading other people’s code. This is why we wanted to give exercism users the option of making their solutions public.

Here are some questions to help you reflect on this solution and learn the most from it.

  • What compromises have been made?
  • Are there new concepts here that you could read more about to improve your understanding?