Imagine you have two string sequences:
val s1 = Seq("c", "a", "b", "z", "a", "b")
val s2 = Seq("a", "b")
You need to come up with an algorithm that generates a binary membership mask of s2
in s1
, e.g.:
algorithm(s1, s2) => 011000
Here are some other examples:
val s1 = Seq("a", "b", "z", "c", "a")
val s2 = Seq("a", "b", "z")
11100
val s1 = Seq("z", "b", "a", "a", "b")
val s2 = Seq("a", "b")
00011
val s1 = Seq("z", "b", "a", "a", "b")
val s2 = Seq("a")
00100
val s1 = Seq("z", "b", "a", "a", "b")
val s2 = Seq("a", "a")
00110
Notice that we only count first sequence match and discard the rest sequence matches.
Basically, in case of s2 = Seq("z", "b", "a", "a", "b")
and s1 = Seq("a", "b")
we are trying to solve the following task:
"z" "b" "a" "a" "b"
| | | | |
" " " " " " "a" "b"
| | | | |
0 0 0 1 1
Why? Imagine you have a sequence of auto-generated strings like "This is Google Inc ." but you only need to extract "Google" from it cutting everything else. It is easy when you know what you are searching for but once it is "This is ? Inc ." you have no way but to rely on binary masks that you collected from a big corpus. In order to generate such masks, you first need the algorithm described above.
I have come up with a simple while loop. This looks pretty ugly, so there should be another more Scala-like solution. How would you solve it?
def binmask(a: Seq[String], b: Seq[String]): String = {
val x = a.sliding(b.length, 1)
var continue = true
var mask = ""
while (continue && x.hasNext) {
val g = x.next()
if (g == b) {
mask += "1"*b.length + "0"*x.length
continue = false
} else mask += "0"
}
if (continue) mask += "0"
mask
}
s2
never occurs ins1
? For example,binmask(Seq("a", "b", "a", "a", "b"), Seq("b", "b"))
is"0000"
, which is shorter thanbinmask(Seq("a", "b", "a", "a", "b"), Seq("a", "a"))
, which is"00110"
. Is that intentional? \$\endgroup\$s2
that exist ins1
beforehand. But this is a valid point. I added anotherif
condition. \$\endgroup\$