String contains non-overlapping letter pairs I was trying my hand at learning Elixir via ancient adventofcode puzzles and was trying to write a function to satisfy this requirement:


  It contains a pair of any two letters that appears at least twice in
  the string without overlapping, like xyxy (xy) or aabcdefgaa (aa), but
  not like aaa (aa, but it overlaps).


Here is what I came up with, but it feels like it might be unwieldy. Is there a way to make it more elegant?

  def has_non_overlapping_pair(string) do
    0..String.length(string)-2 
      |&gt; Enum.map(fn n -&gt;
          String.slice(string, n, 2)
      end)
      |&gt; Enum.reduce(["_"], fn pair, acc -&gt;
          if pair == hd(acc) do ["_"|acc] 
          else [pair|acc] end
      end)
      |&gt; count_occurrences
      |&gt; Map.delete("_")
      |&gt; Map.values
      |&gt; Enum.any?(fn val -&gt; val &gt; 1 end)
  end
You could use a map to store the pairs with their first occurrence while iterating over the pairs. Break if the current pair was already found at a position less than the current position minus 1.

def has_non_overlapping_pair(string) do
  0..String.length(string) - 2
  |&gt; Enum.reduce_while(%{}, fn n, m -&gt;
    pair = String.slice(string, n, 2)
    pos  = Map.get(m, pair, n)
    cond do
      pos == n     -&gt; {:cont, Map.put(m, pair, n)}
      pos == n - 1 -&gt; {:cont, m}
      true         -&gt; {:halt, true}
    end
  end) == true
end