Traverse tree in a functional way - algorithm

I've implemented a basic mutable tree in Scala and I want to traverse it in a functional way in order to search for an element, but I don't know how to implement it. I want also the algorithm to be tail recursive if possible.
The tree is a structure with a value and a list of leafs that are also trees.
Any help would be appreciated.
This is the code that I have (focus on getOpt method):
package main
import scala.collection.mutable.ListBuffer
sealed trait Tree[Node] {
val node: Node
val parent: Option[Tree[Node]]
val children: ListBuffer[Tree[Node]]
def add(n: Node): Tree[Node]
def size: Int
def getOpt(p: (Node) => Boolean): Option[Tree[Node]]
override def toString = {
s"""[$node${if (children.isEmpty) "" else s", Children: $children"}]"""
}
}
case class ConcreteTree(override val node: Int) extends Tree[Int] {
override val children = ListBuffer[Tree[Int]]()
override val parent: Option[Tree[Int]] = None
override def add(n: Int): ConcreteTree = {
val newNode = new ConcreteTree(n) {override val parent: Option[Tree[Int]] = Some(this)}
children += newNode
newNode
}
override def size: Int = {
def _size(t: Tree[Int]): Int = {
1 + t.children.foldLeft(0)((sum, tree) => sum + _size(tree))
}
_size(this)
}
// This method is not correct
override def getOpt(p: (Int) => Boolean): Option[Tree[Int]] = {
def _getOpt(tree: Tree[Int], p: (Int) => Boolean): Option[Tree[Int]] = {
tree.children.map {
t =>
if(p(t.node)) Some(t) else t.children.map(_getOpt(_, p))
}
}
}
}
object Main {
def main(args: Array[String]) {
val tree1 = ConcreteTree(1)
val tree2 = tree1.add(2)
val tree3 = tree1.add(3)
println(tree1.getOpt(_ == 2))
}
}
#doertsch answer is the best approach that I have at the moment.

I would actually go for something more flexible and implement a generic function to produce a lazy stream of your flattened tree, then a lot of your later work will become much easier. Something like this:
def traverse[Node](tree: Tree[Node]): Stream[Tree[Node]] =
tree #:: (tree.children map traverse).fold(Stream.Empty)(_ ++ _)
Then your getOpt reduces to this:
override def getOpt(p: (Int) => Boolean): Option[Tree[Int]] =
traverse(tree) find {x => p(x.node)}
Simplifying even further, if you're just interested in the data without the Tree structure, you can just get a stream of nodes, giving you:
def nodes[Node](tree: Tree[Node]): Stream[Node] = traverse(tree) map (_.node)
def getNode(p: (Int) => Boolean): Option[Int] = nodes(tree) find p
This opens other possibilities for very concise and readable code like nodes(tree) filter (_ > 3), nodes(tree).sum, nodes(tree) contains 12, and similar expressions.

Using the methods exists and find (which every List provides), you can achieve the "finish when a result is found" behaviour. (Although it might be argued that internally, these are not implemented in a totally functional way: https://github.com/scala/scala/blob/5adc400f5ece336f3f5ff19691204975d41e652e/src/library/scala/collection/LinearSeqOptimized.scala#L88)
Your code might look as follows:
case class Tree(nodeValue: Long, children: List[Tree]) {
def containsValue(search: Long): Boolean =
search == nodeValue || children.exists(_.containsValue(search))
def findSubTreeWithNodeValue(search: Long): Option[Tree] =
if (search == nodeValue)
Some(this)
else
children.find(_.containsValue(search)).
flatMap(_.findSubTreeWithNodeValue(search))
}
On the last two lines, the find application will return the correct subtree of the current node, in case one exists, and the flatMap part will extract the correct subtree from it recursively, or leave the None result unchanged if the value was not found.
This one, however, has the unlovely characteristic of doing parts of the traversal twice, once for determining whether a result exists, and once for extracting it from the tree that contains it. There might be a way to fix this in a more efficient way, but I can't figure it out at the moment ...

I think, you are looking for something like this:
#tailrec
def findInTree[T](value: T, stack: List[Node[T]]): Option[Node[T]] = stack match {
case Nil => None
case Node(value) :: _ => stack.headOption
case head :: tail => findInTree(value, head.children ++ tail)
}
This does not traverse parts of the tree twice, and is also tail-recursive.
I changed your class definitions a little bit for clarity, but it's the same idea.
You call it something like this: findInTree(valueToFind, List(root))

When turning a collection into a view, all transformers like map are implemented lazily. This means elements are only processed as required. This should solve your problem:
override def getOpt(p: (Int) => Boolean): Option[Tree[Int]] = {
if (p(node)) Some(this)
else children.view.map(_.getOpt(p)).find(_.isDefined).getOrElse(None)
}
So we are mapping (lazily) over the children, turning them into Options of the searched node. Subsequently we find the first such Option being not None. The final getOrElse(None) is required to "flatten" the nested Options since find returns an Option itself.
I didn't actually run the code, so please excuse minor mistakes. However, the general approach should have become clear.

Related

Getting the Shorest Path question right in Kotlin

So I got a question that was delivered as a 2D List
val SPE = listOf(
listOf('w', 'x'),
listOf('x', 'y'),
listOf('z', 'y'),
listOf('z', 'v'),
listOf('w', 'v')
)
It asks to find the shortest path between w and z. So obviously, BFS would be the best course of action here to find that path the fastest. Here's my code for it
fun shortestPath(edges: List<List<Char>>, root: Char, destination: Char): Int {
val graph = buildGraph3(edges)
val visited = hashSetOf(root)
val queue = mutableListOf(mutableListOf(root, 0))
while (queue.size > 0){
val node = queue[0].removeFirst()
val distance = queue[0].removeAt(1)
if (node == destination) return distance as Int
graph[node]!!.forEach{
if (!visited.contains(it)){
visited.add(it)
queue.add(mutableListOf(it, distance + 1))
}
}
}
queue.sortedByDescending { it.size }
return queue[0][1]
}
fun buildGraph3(edges: List<List<Char>>): HashMap<Char, MutableList<Char>> {
val graph = HashMap<Char, MutableList<Char>>()
for (i in edges.indices){
for (n in 0 until edges[i].size){
var a = edges[i][0]
var b = edges[i][1]
if (!graph.containsKey(a)) { graph[a] = mutableListOf() }
if (!graph.containsKey(b)) { graph[b] = mutableListOf() }
graph[a]?.add(b)
graph[b]?.add(b)
}
}
return graph
}
I am stuck on the return part. I wanted to use a list to keep track of the incrementation of the char, but it wont let me return the number. I could have done this wrong, so any help is appreciated. Thanks.
If I paste your code into an editor I get this warning on your return queue[0][1] statement:
Type mismatch: inferred type is {Comparable<*> & java.io.Serializable} but Int was expected
The problem here is queue contains lists that hold Chars and Int distances, mixed together. You haven't specified the type that list holds, so Kotlin has to infer it from the types of the things you've put in the list. The most general type that covers both is Any?, but the compiler tries to be as specific as it can, inferring the most specific type that covers both Char and Int.
In this case, that's Comparable<*> & java.io.Serializable. So when you pull an item out with queue[0][1], the value you get is a Comparable<*> & java.io.Serializable, not an Int, which is what your function is supposed to be returning.
You can "fix" this by casting - since you know how your list is meant to be organised, two elements with a Char then an Int, you can provide that information to the compiler, since it has no idea what you're doing beyond what it can infer:
val node = queue[0].removeFirst() as Char
val distance = queue[0].removeAt(1) as Int
...
return queue[0][1] as Int
But ideally you'd be using the type system to create some structure around your data, so the compiler knows exactly what everything is. The most simple, generic one of these is a Pair (or a Triple if you need 3 elements):
val queue = mutableListOf(Pair<Char, Int>(root, 0))
// or if you don't want to explicitly specify the type
val queue = mutableListOf(root to 0)
Now the type system knows that the items in your queue are Pairs where the first element is a Char, and the second is an Int. No need to cast anything, and it will be able to help you as you try to work with that data, and tell you if you're doing the wrong thing.
It might be better to make actual classes that reflect your data, e.g.
data class Step(node: Char, distance: Int)
because a Pair is pretty general, but it's up to you. You can pull the data out of it like this:
val node = queue[0].first
val distance = queue[0].second
// or use destructuring to assign the components to multiple variables at once
val (node, distance) = queue[0]
If you make those changes, you'll have to rework some of your algorithm - but you'll have to do that anyway, it's broken in a few ways. I'll just give you some pointers:
your return queue[0][1] line can only be reached when queue is empty
queue[0].removeAt(1) is happening on a list that now has 1 element (i.e. at index 0)
don't you need to remove items from your queue instead?
when building your graph, you call add(b) twice
try printing your graph, the queue at each stage in the loop etc to see what's happening! Make sure it's doing what you expect. Comment out any code that doesn't work so you can make sure the stuff that runs before that is working.
Good luck with it! Hopefully once you get your types sorted out things will start to fall into place more easily

I did not get the Desired Outcome for this Question in Kotlin?

So I was creating an adjacency list from an Undirected Graph
val presentedGraph = listOf(
listOf('i', 'j'),
listOf('k', 'i'),
listOf('m', 'k'),
listOf('k', 'l'),
listOf('o', 'n')
)
The outcome that I was looking for was this
hashMapOf(
'i' to listOf('j', 'k'),
'j' to listOf('i'),
'k' to listOf('i', 'm', 'l'),
'm' to listOf('k'),
'l' to listOf('k'),
'o' to listOf('n'),
'n' to listOf('o')
)
But got this instead
{i=[i], j=[j], k=[k], l=[l], m=[m], n=[n], o=[o]}
Here's the code for it
fun undirectedPath (edges: List<List<Char>>, root: Char, destination: Char){
val graph = buildGraph(edges)
println(graph)
}
fun buildGraph(edges: List<List<Char>>): HashMap<Char, List<Char>>{
val graph = hashMapOf<Char, List<Char>>()
for (i in edges.indices){
for (j in edges[i].indices){
val a = edges[i][j]
val b = edges[i][j]
if (!graph.containsKey(a)) { graph[a] = listOf() }
if (!graph.containsKey(b)) { graph[b] = listOf() }
graph[a] = listOf(b)
graph[b] = listOf(a)
}
}
return graph
}
Any help will be appreciated, Thank You.
Several things wrong here:
The fact that you're setting both a and b to the same expression ought to be a clue that one of them is wrong! In fact a should be set to edges[i][0].
Because j runs from 0, it effectively assumes an extra edge from each node to itself. To avoid that, j should skip the first item and start from 1.
Each time you assign graph[a] and graph[b], you discard any previous items. That's why the result has only one target for each edge. To fix that, you need to add() the target to the existing list…
…which means that each target list must be a MutableList.
Those changes should be enough to get the result you want.
However, there are still several code smells present. For one thing, the input is a list of lists — but each of the inner lists has exactly two items. It would be neater to use a more precise structure, such as a Pair.
And it's always worth being aware of the standard library, which includes a wide range of manipulations and algorithms. In this case, you could replace the whole function with a one-liner:
fun buildGraph(edges: List<Pair<Char, Char>>)
= (edges + edges.map{ it.second to it.first })
.groupBy({ it.first }, { it.second })
As well as being a good deal shorter, that also makes it a good deal clearer what it's doing: combining the list of edges with the reverse list, and returning a map from each node to the list of nodes it connects to/from.
You can try this.
val hashMap = HashMap<Char, ArrayList<Char>>()
presentedGraph.forEach { list ->
list.forEach { char ->
if (!hashMap.containsKey(char)) {
hashMap[char] = arrayListOf()
}
hashMap[char]?.addAll(list.filter { char != it }.toList().distinct())
}
}
println(hashMap)
Output:
{i=[j, k], j=[i], k=[i, m, l], l=[k], m=[k], n=[o], o=[n]}

Finding 'tidy numbers' in Scala

A tidy number is a number whose digits are in non-decreasing order, e.g. 1234. Here is a way of finding tidy numbers written in Ruby:
def tidy_number(n)
n.to_s.chars.sort.join.to_i == n
end
p tidy_number(12345678) # true
p tidy_number(12345878) # false
I tried to write the same thing in Scala and arrived at the following:
object MyClass {
def tidy_number(n:Int) = n.toString.toList.sorted.mkString.toInt == n;
def main(args: Array[String]) {
println(tidy_number(12345678)) // true
println(tidy_number(12345878)) // false
}
}
The only way I could do it in Scala was by converting an integer to a string to a list and then sorting the list and going back again. My question: is there a better way? 'Better' in the sense there are fewer conversions. I'm mainly looking for a concise piece of Scala but I'd be grateful if someone pointed out a more concise way of doing it in Ruby as well.
You can use sorted on strings in Scala, so
def tidy_number(n: Int) = {
val s = n.toString
s == s.sorted
}
Doing it in two parts also avoids an extra toInt conversion.
I've never used ruby, but this post suggests you're doing it the best way
You can check each adjacent pair of digits to make sure that the first value is <= the second:
def tidy_number(n:Int) =
n.toString.sliding(2,1).forall(p => p(0) <= p(1))
Update following from helpful comments
As noted in the comments, this fails for single-digit numbers. Taking this and another comment together gives this:
def tidy_number(n:Int) =
(" "+n).sliding(2,1).forall(p => p(0) <= p(1))
Being even more pedantic it would be better to convert back to Int before comparing so that you don't rely on the sort order of the characters representing digits being the same as the sort order for the digits themselves.
def tidy_number(n:Int) =
(" "+n).sliding(2,1).forall(p => p(0).toInt <= p(1).toInt)
The only way I could do it in Scala was by converting an integer to a string to a list and then sorting the list and going back again. My question: is there a better way?
String conversion and sorting is not required.
def tidy_number(n :Int) :Boolean =
Iterator.iterate(n)(_/10)
.takeWhile(_>0)
.map(_%10)
.sliding(2)
.forall{case Seq(a,b) => a >= b
case _ => true} //is a single digit "tidy"?
Better? Hard to say. One minor advantage is that the math operations (/ and %) stop after the first false. So for the Int value 1234567890 there are only 3 ops (2 modulo and 1 division) before the result is returned. (Digits are compared in reverse order.)
But seeing as an Int is, at most, only 10 digits long, I'd go with Joel Berkeley's answer just for its brevity.
def tidyNum(n:Int) = {
var t =n; var b = true;
while(b && t!=0){b=t%10>=(t/10)%10;t=t/10};b
}
In Scala REPL:
scala> tidyNum(12345678)
res20: Boolean = true
scala> tidyNum(12343678)
res21: Boolean = false
scala> tidyNum(12)
res22: Boolean = true
scala> tidyNum(1)
res23: Boolean = true
scala> tidyNum(121)
res24: Boolean = false
This can work for any size with just the modification of type such as Long or BigInt in function signature like tidyNum(n:Long) or tidyNum(n:BigInt) as below:
def tidyNum(n:BigInt) = {
var t =n; var b = true;
while(b && t!=0){b=t%10>=(t/10)%10;t=t/10};b
}
scala> tidyNum(BigInt("123456789"))
res26: Boolean = true
scala> tidyNum(BigInt("1234555555555555555555555567890"))
res29: Boolean = false
scala> tidyNum(BigInt("123455555555555555555555556789"))
res30: Boolean = true
And the BigInt can be used for types Int, Long as well.

How can a "while remaining" algorithm be converted to functional style?

In my imperative-style Scala code, I have an algorithm:
def myProcessor(val items: List) {
var numProcessed = 0
while(numProcessed < items.size) {
val processedSoFar = items.size - numProcessed
numProcessed += processNextBlockOfItems(items, processedSoFar)
}
}
I would like to keep the "block processing" functionality, and not just do a "takeWhile" on the items list. How can I rewrite this in functional style?
You need to change it to a recursive style wherein you "pass" in the "state" of each loop
#tailrec
def myProcessor(items: List[A], count: Int = 0): Int = items match{
case Nil => count
case x :: xs =>
processNextBlockOfItems(items, count)
myProcessor(xs, count + 1)
}
assuming that "processedSoFar" is not an index. If you can work with the current "head" of the list:
#tailrec
def myProcessor(items: List[A], count: Int = 0): Int = items match{
case Nil => count
case x :: xs =>
process(x)
myProcessor(xs, count + 1)
}
where process would only process the current "head" of the List.
So, this depends on what you consider to be more functional, but here's a version without the 'var'
def myProcessorFunctional(items: List[Int]) {
def myProcessorHelper(items: List[Int], numProcessed: Int) {
if (numProcessed < items.size) {
val processedSoFar = items.size - numProcessed
myProcessorHelper(items,
numProcessed + processNextBlockOfItems(items, processedSoFar))
}
}
myProcessorHelper(items, 0)
}
(making it a list of Ints just for simplicity, it would be easy to make it work with a generic List)
I have to say it's one of those cases where I don't mind the mutable variable - it's clear, no reference to it escapes the method.
But as I said in a comment above, processNextBlockOfItems is inherently non-functional anyway, since it's called for its side effects. A more functional way would be for it to return the state of its processing so far, and this state would be updated (and returned) on a subsequent call. Right now, if you in the middle of processing two different items lists, you'd have the issue of maintaining two different partially-processed states within processNextBlockOfItems...
Later:
Still ignoring the state issue, one convenient change would be if processNextBlockOfItems always processed the first block of the items list passed to it, returned the remaining items it had not processed (this is convenient and efficient if using List, so much so I'm wondering why you're using indicies).
This would yield something like:
def myProcessorMoreFunctional(items: List[Int]) {
if (!items.isEmpty) {
myProcessorMoreFunctional(processNextBlockOfItems(items))
}
}

Scalaz Validation, validate inner value

I have a Validation object
val v = Validation[String, Option[Int]]
I need to make a second validation, to check if actual Integer value is equals to 100 for example. If I do
val vv = v.map(_.map(intValue => if (intValue == 100)
intValue.success[String]
else
"Bad value found".fail[Integer]))
I get:
Validation[String, Option[Validation[String, Int]]]
How is it possible to get vv also as Validation[String, Option[Int]] in most concise way
=========
Found possible solution from my own:
val validation: Validation[String, Option[Int]] = Some(100).success[String]
val validatedTwice: Validation[String, Option[Int]] = validation.fold(
_ => validation, // if Failure then return it
_.map(validateValue _) getOrElse validation // validate Successful result
)
def validateValue(value: Int): Validation[String, Option[Int]] = {
if (value == 100)
Some(value).success[String]
else
"Bad value".fail[Option[Int]]
}
Looks not concise and elegant although it works
==============
Second solution from my own, but also looks over-compicated:
val validatedTwice2: Validation[String, Option[Int]] = validation.flatMap(
_.map(validateValue _).map(_.map(Some(_))) getOrElse validation)
def validateValue(value: Int): Validation[String, Int] = {
if (value == 100)
value.success[String]
else
"Bad value".fail[Int]
}
Your solution is over-complicated. The following will suffice!
v flatMap (_.filter(_ == 100).toSuccess("Bad value found"))
The toSuccess comes from OptionW and converts an Option[A] into a Validation[X, A] taking the value provided for the failure case in the event that the option is empty. The flatMap works like this:
Validation[X, A]
=> (A => Validation[X, B])
=> (via flatMap) Validation[X, B]
That is, flatMap maps and then flattens (join in scalaz-parlance):
Validation[X, A]
=> (A => Validation[X, B]]
=> (via map) Validation[X, Validation[X, B]]
=> (via join) Validation[X, B]
First, let's set up some type aliases because typing this out repeatedly will get old pretty fast. We'll tidy up your validation logic a little too while we're here.
type V[X] = Validation[String, X]
type O[X] = Option[X]
def checkInt(i: Int): V[Int] = Validation.fromEither(i != 100 either "Bad value found" or i)
val v: V[O[Int]] = _
this is where we're starting out - b1 is equivalent to your vv situation
val b1: V[O[V[Int]]] = v.map(_.map(checkInt))
so let's sequence the option to flip over the V[O[V[Int]]] into a V[V[O[Int]]]
val b2: V[V[O[Int]]] = v.map(_.map(checkInt)).map(_.sequence[V, Int])
or if you're feeling lambda-y it could have been
sequence[({type l[x] = Validation[String, x]})#l, Int]
next we flatten out that nested validation - we're going to pull in the Validation monad because we actually do want the fastfail behaviour here, although it's generally not the right thing to do.
implicit val monad = Validation.validationMonad[String]
val b3: V[O[Int]] = v.map(_.map(checkInt)).map(_.sequence[V, Int]).join
So now we've got a Validation[String, Option[Int]], so we're there, but this is still pretty messy. Lets use some equational reasoning to tidy it up
By the second functor law we know that:
X.map(_.f).map(_.g) = X.map(_.f.g) =>
val i1: V[O[Int]] = v.map(_.map(checkInt).sequence[V, Int]).join
and by the definition of a monad:
X.map(f).join = X.flatMap(f) =>
val i2: V[O[Int]] = v.flatMap(_.map(checkInt).sequence[V, Int])
and then we apply the free theorem of traversal:
(I struggled with that bloody paper so much, but it looks like some of it sunk in!):
X.map(f).sequence = X.traverse(f andThen identity) = X.traverse(f) =>
val i3: V[O[Int]] = v.flatMap(_.traverse[V, Int](checkInt))
so now we're looking at something a bit more civilised. I imagine there's some trickery to be played with the flatMap and traverse, but I've run out of inspiration.
Use flatMap, like so:
v.flatMap(_.parseInt.fail.map(_.getMessage).validation)

Resources