From a1bc604816133b66b848256f5b13e84a796ac1bc Mon Sep 17 00:00:00 2001 From: Rogerio Chaves Date: Sun, 24 Sep 2017 20:57:04 -0300 Subject: [PATCH 1/2] make transpose call stack size safe --- src/List/Extra.elm | 13 +++++++++---- tests/Tests.elm | 5 +++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/List/Extra.elm b/src/List/Extra.elm index 3f661ef..580d2db 100644 --- a/src/List/Extra.elm +++ b/src/List/Extra.elm @@ -813,13 +813,18 @@ If some rows are shorter than the following rows, their elements are skipped: -} transpose : List (List a) -> List (List a) -transpose ll = +transpose = + transposeHelp [] + + +transposeHelp : List (List a) -> List (List a) -> List (List a) +transposeHelp acc ll = case ll of [] -> - [] + acc [] :: xss -> - transpose xss + transposeHelp acc xss (x :: xs) :: xss -> let @@ -829,7 +834,7 @@ transpose ll = tails = filterMap tail xss in - (x :: heads) :: transpose (xs :: tails) + transposeHelp (acc ++ [ x :: heads ]) (xs :: tails) {-| Return the list of all subsequences of a list. diff --git a/tests/Tests.elm b/tests/Tests.elm index ad05930..e0d1c47 100644 --- a/tests/Tests.elm +++ b/tests/Tests.elm @@ -123,6 +123,11 @@ all = Expect.equal (transpose [ [ 10, 11 ], [ 20 ], [], [ 30, 31, 32 ] ]) [ [ 10, 20, 30 ], [ 11, 31 ], [ 32 ] ] + , test "transposes large lists" <| + \() -> + Expect.equal + (transpose [ List.repeat 10000 1 ]) + (List.repeat 10000 [ 1 ]) ] , describe "subsequences" <| [ test "computes subsequences" <| From 017e8243a6f544f9ade6b4914f02b5c16795968a Mon Sep 17 00:00:00 2001 From: Rogerio Chaves Date: Wed, 29 Nov 2017 00:35:35 -0200 Subject: [PATCH 2/2] use @pzp1997's faster implementation of transpose --- src/List/Extra.elm | 26 ++++++++------------------ tests/Tests.elm | 6 +++--- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/src/List/Extra.elm b/src/List/Extra.elm index 580d2db..68816b4 100644 --- a/src/List/Extra.elm +++ b/src/List/Extra.elm @@ -813,28 +813,18 @@ If some rows are shorter than the following rows, their elements are skipped: -} transpose : List (List a) -> List (List a) -transpose = - transposeHelp [] +transpose listOfLists = + List.foldr (List.map2 (::)) (List.repeat (rowsLength listOfLists) []) listOfLists -transposeHelp : List (List a) -> List (List a) -> List (List a) -transposeHelp acc ll = - case ll of +rowsLength : List (List a) -> Int +rowsLength listOfLists = + case listOfLists of [] -> - acc - - [] :: xss -> - transposeHelp acc xss + 0 - (x :: xs) :: xss -> - let - heads = - filterMap head xss - - tails = - filterMap tail xss - in - transposeHelp (acc ++ [ x :: heads ]) (xs :: tails) + x :: _ -> + List.length x {-| Return the list of all subsequences of a list. diff --git a/tests/Tests.elm b/tests/Tests.elm index e0d1c47..0936034 100644 --- a/tests/Tests.elm +++ b/tests/Tests.elm @@ -118,11 +118,11 @@ all = Expect.equal (transpose [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]) [ [ 1, 4 ], [ 2, 5 ], [ 3, 6 ] ] - , test "short rows are skipped" <| + , test "truncate the matrix to the shortest row size" <| \() -> Expect.equal - (transpose [ [ 10, 11 ], [ 20 ], [], [ 30, 31, 32 ] ]) - [ [ 10, 20, 30 ], [ 11, 31 ], [ 32 ] ] + (transpose [ [ 10, 11 ], [ 20 ], [ 30, 31, 32 ] ]) + [ [ 10, 20, 30 ] ] , test "transposes large lists" <| \() -> Expect.equal