Avatar of paulfioravanti

paulfioravanti's solution

to Series in the Elm Track

Published at Jul 26 2019 · 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 first time you start an exercise, you'll need to ensure you have the appropriate dependencies installed. Thankfully, Elm makes that easy for you and will install dependencies when you try to run tests or build the code.

Execute the tests with:

$ elm-test

Automatically run tests again when you save changes:

$ elm-test --watch

As you work your way through the test suite, 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 =
    let
        length =
            String.length input
    in
    if size == 0 then
        Err "slice length cannot be zero"

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

    else if length == 0 then
        Err "series cannot be empty"

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

    else
        input
            |> toIntList
            |> chunkEvery size
            |> Ok



-- PRIVATE


toIntList : String -> List Int
toIntList input =
    let
        toInt string =
            string
                |> String.toInt
                |> Maybe.withDefault 0
    in
    input
        |> String.split ""
        |> List.map toInt


chunkEvery : Int -> List Int -> List (List Int)
chunkEvery size inputList =
    if size == List.length inputList then
        [ inputList ]

    else
        let
            chunk =
                List.take size inputList

            step =
                1

            tail =
                List.drop step inputList
        in
        chunk :: chunkEvery size tail

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?