When building Nikeza, I needed a content provider to have adequate space for topics. In addition, I needed the space available (which was two lines) to look reasonably balanced. Hence, I wanted the two lines worth of topics to be close in length.

**I was able to implement this requirement:**

**I wrote the algorithm originally in F#:**

let rec organize group1 group2 remainingWords : string list * string list=
let next words =
match words |> List.tryLast with
| Some w -> w
| None -> ""
let sorted = remainingWords |> List.sortBy(fun (w:string) -> w.Length)
let longest = sorted |> next
if longest.Length = 0
then (group1, group2)
else let updatedWords = sorted |> List.filter(fun w -> w <> longest)
let nextLongest = updatedWords |> next
if nextLongest.Length = 0
then (group1, longest::group2)
else let remaining = updatedWords |> List.filter(fun w -> w <> nextLongest)
if remaining |> List.isEmpty
then (longest::group1, nextLongest::group2)
else remaining |> organize (longest::group1) (nextLongest::group2)

**I used the following test:**

let result = organize [] [] ["Some big word"; "Some other big word"; "Word"; "F#"; "C#"; "Elm"; "Software Development"; "Web Development"]

**The result was the following:**

val result : string list * string list =
(["C#"; "Word"; "Web Development"; "Software Development"],
["F#"; "Elm"; "Some big word"; "Some other big word"])

**I then ported the F# implementation to Elm:**

organize : List Topic -> List Topic -> List Topic -> ( List Topic, List Topic )
organize group1 group2 remainingTopics =
let
next topics =
topics |> List.reverse |> List.head
sorted =
remainingTopics |> List.sortBy (\t -> String.length t.name)
in
case sorted |> next of
Nothing ->
( group1, group2 )
Just longest ->
let
updatedTopics =
sorted |> List.filter (\t -> t /= longest)
in
case updatedTopics |> next of
Nothing ->
( group1, longest :: group2 )
Just nextLongest ->
let
remaining =
updatedTopics |> List.filter (\t -> t /= nextLongest)
in
if remaining |> List.isEmpty then
( longest :: group1, nextLongest :: group2 )
else
remaining |> organize (longest :: group1) (nextLongest :: group2)

### Like this:

Like Loading...