Guest User

Untitled

a guest
Nov 18th, 2018
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.67 KB | None | 0 0
  1. import scala.collection.mutable.Stack
  2. import scala.collection.mutable.ListBuffer
  3. import scala.io.Source
  4. import java.io._
  5.  
  6. case class Input(
  7. letter: Char,
  8. left: Char,
  9. right: List[Char]
  10. )
  11. case class Data(
  12. input: List[Input],
  13. alphabet: List[Char],
  14. word: List[Char]
  15. )
  16. case class Graph(
  17. nodes: Map[Char, List[Int]],
  18. relation: List[(Char, Char)]
  19. )
  20.  
  21. object Main {
  22. val lowerCase: List[Char] = "zxcvbnmasdfghjklqwertyuiop".toList
  23.  
  24.  
  25. def main(args: Array[String]): Unit = {
  26. val Data(list, alphabet, word) = parse("test.txt")
  27.  
  28. val dr = Relations.dependency(list)
  29. println("Dependency Relation:\t" + dr)
  30. val idr = Relations.complementary(dr,alphabet)
  31. println("Independency Relation:\t" + idr)
  32. val fclasses = Foata.calculate(dr,word,alphabet)
  33. println("Foata classes:\t\t\t" + fclasses)
  34.  
  35. GraphOperations.dumpToFile(GraphOperations.createGraph(dr,word))
  36. }
  37.  
  38. def parse(fileName: String): Data = {
  39. var exp: List[Char] = List()
  40. var alphabet: List[Char] = List()
  41. val file = Source.fromFile(fileName).getLines
  42. val buffer: ListBuffer[Input] = new ListBuffer()
  43.  
  44. file.foreach(line => {
  45. if(line.startsWith("(")){
  46. val letter = line.charAt(1)
  47. val left = line.charAt(4)
  48. val right = line.substring(7).filter(lowerCase.contains).toList
  49. buffer += Input(letter,left,right)
  50. }
  51. if(line.startsWith("w"))
  52. exp = line.substring(4).toList
  53. if(line.startsWith("A"))
  54. alphabet = lowerCase.filter(c => line.contains(c))
  55. })
  56. Data(buffer.toList, alphabet, exp)
  57. }
  58. }
  59.  
  60. object Relations{
  61. import cats.instances.list._
  62. import cats.syntax.all._
  63.  
  64. def dependency(inList: List[Input]): List[(Char, Char)] ={
  65. val relation = for{
  66. input <- inList
  67. right <- input.right
  68. x <- inList.filter{ case Input(_,left,_) => left == right}
  69. } yield (input.letter, x.letter)
  70. makeSymmetric(relation)
  71. }
  72.  
  73. def complementary[T](relation: List[(T, T)], alphabet: List[T]): List[(T, T)] =
  74. (alphabet |@| alphabet).tupled.filterNot(relation.contains)
  75.  
  76. def makeSymmetric[T](relation: List[(T, T)]): List[(T, T)] = {
  77. val buffer: ListBuffer[(T, T)] = new ListBuffer()
  78. relation.foreach{
  79. case (l: T, r: T) =>
  80. buffer += l -> r
  81. if(!relation.contains(r -> l))
  82. buffer += r -> l
  83. }
  84. buffer.toList
  85. }
  86.  
  87. def removeSymmetric[T](relation: List[(T,T)]): List[(T,T)] = {
  88. val buffer: ListBuffer[(T,T)] = new ListBuffer()
  89. relation.foreach{case (left,right) =>
  90. if(!buffer.contains(right -> left))
  91. buffer += left -> right
  92. }
  93. buffer.toList
  94. }
  95.  
  96.  
  97. def removeReflexive[T](relation: List[(T,T)]): List[(T,T)] =
  98. relation.filterNot{case (l,r) => l ==r }
  99. }
  100.  
  101. object Foata{
  102.  
  103. def calculate(dr: List[(Char, Char)], word: List[Char], alphabet: List[Char]): List[List[Char]] ={
  104. val r = Relations.removeReflexive(dr)
  105. val stacks = alphabet.map(letter => letter -> new Stack[Char]()).toMap
  106.  
  107. word.reverse.foreach( x => {
  108. stacks(x).push(x)
  109. r.filter{ case (l, _) => l == x }
  110. .map(_._2)
  111. .foreach(stacks(_).push('*'))
  112. })
  113.  
  114. val fb: ListBuffer[List[Char]] = new ListBuffer()
  115. var max = stacks.map(s => s._2.length).max
  116.  
  117. while (max > 0){
  118. val buffer: ListBuffer[Char] = new ListBuffer()
  119. stacks.foreach(s =>
  120. if(s._2.length == max)
  121. buffer += s._2.pop()
  122. )
  123. max -= 1
  124. val done = buffer.filterNot(_ == '*').sorted.toList
  125. if(done.nonEmpty)
  126. fb += done
  127. }
  128. fb.toList
  129. }
  130. }
  131.  
  132. object GraphOperations{
  133. import cats.instances.list._
  134. import cats.syntax.all._
  135.  
  136. def createGraph(dr: List[(Char, Char)], word: List[Char]): Graph = {
  137. var nodes: Map[Char, List[Int]] = Map()
  138.  
  139. word.zipWithIndex.foreach{ case (c, i) =>
  140. nodes = if(nodes.contains(c)) nodes + (c -> (i :: nodes(c))) else nodes + (c -> List(i))
  141. }
  142.  
  143. val r = dr.filter{ case (left, right) =>
  144. val different = left != right && word.contains(left) && word.contains(right)
  145. val reflective = left == right && word.count(_ == left) >= 2
  146. different || reflective
  147. }
  148.  
  149. Graph(nodes,Relations.removeSymmetric(r))
  150. }
  151.  
  152. def dumpToFile(graph: Graph): Unit ={
  153. val pw = new PrintWriter(new File("graph.dot"))
  154.  
  155. pw.write("digraph g{\n")
  156.  
  157. graph.relation.foreach{case (left, right) =>
  158. val r0 = (graph.nodes(left) |@| graph.nodes(right)).tupled
  159. val r1 = Relations.removeReflexive(r0)
  160. val r2 = Relations.removeSymmetric(r1)
  161. r2.foreach{
  162. case (i,j) => pw.write("\t"+i.toString +" -> " + j.toString + "\n")
  163. }
  164. }
  165.  
  166. graph.nodes.foreach{case(c, nums) =>
  167. nums.foreach(i =>
  168. pw.write("\t"+ i.toString +"[label="+c+"]\n")
  169. )
  170. }
  171.  
  172. pw.write("}\n")
  173. pw.close()
  174. }
  175. }
Add Comment
Please, Sign In to add comment