Skip to content

Instantly share code, notes, and snippets.

@sumew
Last active November 26, 2020 07:15
Show Gist options
  • Save sumew/2f8948d7459e3130bb1cf886f148668c to your computer and use it in GitHub Desktop.
Save sumew/2f8948d7459e3130bb1cf886f148668c to your computer and use it in GitHub Desktop.
A generic representation of a sliding window problem
def lengthOfLongestSubstring(in: String): Int = {
//A type alias to simplify the syntax
type CounterContainer[T] = Map[T, Int]
//The elements are Chars and our container, a map with the Char as key and the frequence as value holds the elements within the current window
val longest = new SlidingWindow[Char, CounterContainer[Char]] {
override val input: Seq[Char] = in
//The initial state consists of windows of 0 width at the beginning of the sequence and an empty container
override def initialize() = State(Window(0, 0), Window(0, 0), Map.empty[Char, Int])
//We terminate when the current window's right edge reaches the last element of the input
override def terminate(s: State[CounterContainer[Char]]): Boolean = input.length == s.current.r
//When expanding, we increment frequency of element at the right edge of our current window to our container and expand the window
override def expand(s: State[CounterContainer[Char]]): State[CounterContainer[Char]] =
s.copy(
contained = s.contained.updatedWith(input(s.lastIndex()))(opt => Some(opt.fold(1)(count => count + 1))),
current = s.current ||-> 1
)
//When shrinking we decrement the element at the left edge of our current window and move that edge to the right
override def shrink(s: State[CounterContainer[Char]]): State[CounterContainer[Char]] =
s.copy(
contained = s.contained
.get(input(s.firstIndex()))
.fold(s.contained)(count => s.contained.updated(input(s.firstIndex()), count - 1)),
current = s.current |->| 1
)
override def better(b: Window, c: Window) = if (c.size < b.size) b else c //the problem asks for the longest
override def shouldExpand(s: State[CounterContainer[Char]]) = !s.contained.values.exists(_ > 1)// expand only when there are no repeated characters
override def satisfied(s: State[CounterContainer[Char]]): Boolean = shouldExpand(s) //The condition (without repeated characters) holds
}
val s: State[CounterContainer[Char]] = longest.run()
s.best.size
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment