Last active
May 5, 2016 12:58
-
-
Save GlulkAlex/183ec116621c146c344ae3785be89291 to your computer and use it in GitHub Desktop.
Functional Programming: Recursion, Divide and Conquer, String Parsing, Scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object Solution { | |
def main(args: Array[String]) { | |
/* Enter your code here. | |
Read input from STDIN. | |
Print output to STDOUT. | |
Your class should be named Solution | |
*/ | |
///>>> it seems that something faster than O(N) needed | |
///> QuickSortMerge may be ? O(N * log(N)) ??? | |
/* | |
aaabaaaaccaaaaba => a3ba4c2a4ba | |
-> top-down | |
"aaabaaaa" + "ccaaaaba" | |
"aaab" + "aaaa" + "ccaa" + "aaba" | |
"aa" + "ab" + "aa" + "aa" + "cc" + "aa" + "aa" + "ba" | |
-> ground-up | |
"a2", "ab", "a2", "a2", "c2", "a2", "a2", "ba" | |
"a2" + "ab", "a2" + "a2", "c2" + "a2", "a2" + "ba" | |
"a3b", "a4", "c2a2", "a2ba" | |
"a3b" + "a4", "c2a2" + "a2ba" | |
"a3ba4", "c2a4ba" | |
"a3ba4" + "c2a4ba" | |
"a3ba4c2a4ba" == "a3ba4c2a4ba" <- Done | |
... | |
so, for each chunk .head & .last -> needed | |
case class Chunk( | |
head: Char | |
, head_Count: Int = 1 | |
, body: String = "" | |
, last: Option[Char] = None | |
, last_Count: Int = 0) | |
"a2" -> Chunk(head = 'a', head_Count = 2) == Chunk(a,2,,None,0) | |
"a3b" -> Chunk(head = 'a', 3, "", Some('b'), 1) == Chunk(a,3,,Some(b),1) | |
"a3ba4" -> Chunk(head = 'a', 3, "b", Some('a'), 4) == Chunk(a,3,b,Some(a),4) | |
... | |
Merge step: | |
Cases: | |
"a2" + "ab" => "a3b" | |
Chunk(a,2,,None,0) + Chunk(a,1,,Some(b),1) => Chunk(a,3,,Some(b),1) -> | |
if ( | |
c_1.last_Count == 0 || | |
//c_1.body == "" || // <- 1st is .last then .body | |
c_1.last.isEmpty ) && | |
c_2.last.nonEmpty && | |
c_2.body == "" && | |
c_1.head == c_2.head | |
merged.head_Count = c_1.head_Count + c_2.head_Count | |
merged.body = c_2.body | |
merged.last = c_2.last | |
merged.last_Count = c_2.last_Count | |
"a2" + "a2" => "a4" | |
Chunk(a,2,,None,0) + Chunk(a,2,,None,0) => Chunk(a,4,,None,0) -> | |
if ( | |
c_1.last_Count == 0 || | |
c_1.body == "" || | |
c_1.last.isEmpty ) && | |
c_1.head == c_2.head | |
merged.head_Count = c_1.head_Count + c_2.head_Count | |
merged.body = c_2.body | |
merged.last = c_2.last | |
merged.last_Count = c_2.last_Count | |
"c2" + "a2" => "c2a2" | |
Chunk(c,2,,None,0) + Chunk(a,2,,None,0) => Chunk(c,2,,Some(a),2) -> | |
if ( | |
c_1.last_Count == 0 || | |
c_1.body == "" || | |
c_1.last.isEmpty ) && | |
c_1.head != c_2.head | |
merged.head_Count = c_1.head_Count | |
merged.body = c_2.body | |
merged.last = c_2.last | |
merged.last_Count = c_2.last_Count | |
"c2a2" + "a2ba" => "c2a4ba" | |
Chunk(a,2,,None,0) + Chunk(b,1,,None,0) => Chunk(a,3,,Some(b),1) -> | |
if (c_1.last_Count == 0 (|| c_1.body == "") || c_1.last.isEmpty ) && c_1.head == c_2.head | |
merged.head_Count = c_1.head_Count + c_2.head_Count | |
merged.body = c_2.body | |
merged.last = c_2.last | |
merged.last_Count = c_2.last_Count | |
"a3ba4" + "c2a4ba" => "a3ba4c2a4ba" | |
Chunk(a,3,b,Some(a),4) + Chunk(c,2,a4b,Some(a),1) => Chunk(a,3,ba4{c2a4b,Some(a),1}) -> | |
if (c_1.last_Count > 0 || c_1.body != "" || c_1.last.nonEmpty ) && c_1.last != c_2.head | |
merged.head_Count = c_1.head_Count | |
merged.body = c_1.body + c_1.last + (c_1.last_Count > 1 | "") + c_2.body | |
merged.last = c_2.last | |
merged.last_Count = c_2.last_Count | |
*/ | |
import scala.annotation.tailrec | |
import scala.io.StdIn | |
import scala.util.{Try, Success, Failure} | |
val is_Debug_Mode: Boolean = ( | |
//true | |
false | |
) | |
/*val test_Cases_Total: Int = ( | |
scala.io.StdIn | |
//.readInt() | |
.readLine() | |
)*/ | |
/**/ | |
//val msg: String = scala.io.StdIn.readLine() | |
//scala.collection.immutable.Stream[Char] = Stream(1, ?) | |
//val msg: Stream[Char] = scala.io.StdIn.readLine().toStream | |
val msg: Try[Stream[Char]] = Try( | |
StdIn.readLine( | |
//"Message to deflate:\n" | |
).toStream | |
) | |
/*msg match { | |
case Success(v) => Success(v) | |
case Failure(e) => e.getMessage | |
}*/ | |
if (is_Debug_Mode) { | |
//println(s"""test_Cases_Total:${test_Cases_Total}""") | |
println(s"""msg:${msg}""") | |
} | |
/* | |
Contract: | |
(.head != .last if .head.nonEmpty && .body == "" | .isEmpty) && | |
body.head != .head && | |
body.last != .last | |
if .last exist / .nonEmpty => .head exist / .nonEmpty | |
if .body exist / .nonEmpty => | |
(.head exist / .nonEmpty && .last exist / .nonEmpty) || | |
(.head .isEmpty && .last .isEmpty) | |
*/ | |
case class Chunk( | |
//head: Char | |
head: Option[Char] = None | |
, head_Count: Int = 0//1 | |
, body: String = "" | |
, last: Option[Char] = None | |
, last_Count: Int = 0 | |
) { | |
//Auxiliary Constructor | |
/*def this( | |
//error: ambiguous reference to overloaded definition | |
head: Option[Char] = None | |
, head_Count: Int = 0//1 | |
, body: String = "" | |
, last: Option[Char] = None | |
, last_Count: Int = 0 | |
) { | |
///> Contract validation | |
this(head, head_Count, body, last, last_Count) | |
}*/ | |
def empty_Count(count: Int): String = if (count > 0) { | |
count.toString | |
} else { | |
"" | |
} | |
def mkString: String = "" + head.getOrElse("") + | |
more_Then_2_Str(head_Count) + | |
body + | |
last.getOrElse("") + | |
more_Then_2_Str(last_Count) | |
override def toString: String = "" + head.getOrElse("") + empty_Count(head_Count) + "." + | |
body + "." + | |
last.getOrElse("") + empty_Count(last_Count) | |
///> Contract validation | |
// assert | |
if (body != "") { | |
///> this part fails for Test Case #9 - 12 | |
if (is_Debug_Mode) { | |
assert( | |
(head.nonEmpty && last.nonEmpty) || (head.isEmpty && last.isEmpty) | |
, s"""Contract violation -> .head: ${head} or .last: ${last} isEmpty""" + | |
s""" when .body: ${body} is nonEmpty""" | |
) | |
} | |
} else { | |
/*if (head.nonEmpty && body == "" && head == last) { | |
if (is_Debug_Mode) { | |
println(s"""Contract violation -> .head: ${head} == .last: ${last}""") | |
} | |
}*/ | |
if ( | |
//is_Debug_Mode | |
true | |
) { | |
assert( | |
head.nonEmpty && head != last | |
, s"""Contract violation -> .head: ${head} == .last: ${last}""" + | |
s""" when .body: ${body} isEmpty""" | |
) | |
} | |
} | |
} | |
def more_Then_2_Str(counter: Int): String = if (counter > 1) {counter.toString} else {""} | |
/* | |
cases: | |
".." + ".." => ".." | |
".a3b." + ".c5." => ".." <- unexpected case | |
... | |
"a2.." + ".." => "a2.." | |
".." + "a2.." => "a2.." | |
... | |
"a2.." + "a3.." => "a5.." | |
"a2.." + "b3.." => "a2..b3" | |
... | |
"a2.." + "a1..b1" => "a3..b1" | |
"a2.." + "c1..b1" => "a2.c.b1" | |
... | |
p13.. + p4.s3i4.z3 => p17.s3i4.z3 | |
r13.. + p4.s3i4.z3 => r13.p4s3i4.z3 | |
... | |
p4.s3i4.z3 + z1.. => p4.s3i4.z4 | |
p4.s3i4.z3 + y1.. => p4.s3i4z3.y1 | |
... | |
"a2..b1" + "b3.." => "a2.b4" | |
"a2..b1" + "c1.." => "a2.b.c1" | |
... | |
"a2..b3" + "a1..b1" => "a2.b3a.b1" | |
"a2..b3" + "b1..c1" => "a2.b4.c1" | |
... | |
"a2.c.b3" + "b1..c1" => "a2.cb4.c1" | |
"a2.c.a3" + "b1..c1" => "a2.ca3b.c1" | |
... | |
"a2..b3" + "b1.a4.c1" => "a2.b4a4.c1" | |
"a2..b3" + "c1.a4.b1" => "a2.b3ca4.b1" | |
... | |
"a2.c.b3" + "b1.a5.c1" => "a2.cb4a5.c1" | |
"a2.c.b3" + "a1.b5.c1" => "a2.cb3ab5.c1" | |
*/ | |
def merge( | |
/*left_Part: String | |
,right_Part: String | |
): Left[String, Chunk] = {*/ | |
/*left: Right[String, Chunk] | |
,right: Right[String, Chunk] | |
): Right[String, Chunk] = {*/ | |
//left: Either[String, Chunk] | |
//,right: Either[String, Chunk] | |
left_Part: Chunk | |
,right_Part: Chunk | |
//): Either[String,Chunk] = { | |
): Chunk = { | |
//val Right(left_Part)/*: Chunk*/ = left | |
//val Right(right_Part)/*: Chunk*/ = right | |
(left_Part, right_Part) match { | |
///> ".." + ".." => ".." | |
case (Chunk(None, 0, "", None, 0), Chunk(None, 0, "", None, 0)) => { | |
if (is_Debug_Mode) {println(s""".. + .. => ..: ${left_Part} + ${right_Part}""")} | |
left_Part // right_Part | |
} | |
case (Chunk(None, 0, l_B, None, 0), Chunk(None, 0, r_B, None, 0)) => { | |
///> ".a3b." + ".c5." => ".." <- unexpected case | |
if (is_Debug_Mode) {println(s""".a3b. + .a3b. => ?.?.?: ${left_Part} + ${right_Part}""")} | |
assert(left_Part.head.nonEmpty && right_Part.head.nonEmpty, "unexpected merge case") | |
Chunk(None, 0, "", None, 0) | |
} | |
//case BodyWarper(b) if b != "b1" => b | |
case (Chunk(Some(l_H), l_H_C, "", None, 0), Chunk(None, 0, "", None, 0)) => { | |
///> "a2.." + ".." => "a2.." | |
if (is_Debug_Mode) {println(s"""a2.. + .. => a2..: ${left_Part} + ${right_Part}""")} | |
left_Part | |
} | |
case (Chunk(None, 0, "", None, 0), Chunk(Some(r_H), r_H_C, "", None, 0)) => { | |
///> ".." + "a2.." => "a2.." | |
if (is_Debug_Mode) {println(s""".. + a2.. => a2..: ${left_Part} + ${right_Part}""")} | |
right_Part | |
} | |
case (Chunk(Some(l_H), l_H_C, "", None, 0), Chunk(Some(r_H), r_H_C, "", None, 0)) => { | |
///> "a2.." + "a3.." => "a5.." | |
///> "a2.." + "b3.." => "a2..b3" | |
val result = if (l_H == r_H) { | |
if (is_Debug_Mode) {print(s"""a2.. + a3.. => a5..: ${left_Part} + ${right_Part}""")} | |
Chunk( | |
head = left_Part.head | |
,head_Count = left_Part.head_Count + right_Part.head_Count | |
,body = ""//right_Part.body | |
,last = None//right_Part.last | |
,last_Count = 0//right_Part.last_Count | |
) | |
} else { | |
if (is_Debug_Mode) {print(s"""a2.. + b3.. => a2..b3: ${left_Part} + ${right_Part}""")} | |
Chunk( | |
head = left_Part.head | |
,head_Count = left_Part.head_Count | |
,body = "" | |
,last = right_Part.head | |
,last_Count = right_Part.head_Count | |
) | |
} | |
if (is_Debug_Mode) {print(s""" = ${result}\n""")} | |
result | |
} | |
case (Chunk(Some(l_H), l_H_C, "", None, 0), Chunk(Some(r_H), r_H_C, "", Some(r_L), r_L_C)) => { | |
///> "a2.." + "a1..b1" => "a3..b1" | |
///> "a2.." + "c1..b1" => "a2.c.b1" | |
if (l_H == r_H) { | |
if (is_Debug_Mode) {println(s"""a2.. + a1..b1 => a3..b1: ${left_Part} + ${right_Part}""")} | |
Chunk( | |
head = left_Part.head | |
,head_Count = l_H_C + r_H_C | |
,body = ""//right_Part.body | |
,last = right_Part.last | |
,last_Count = r_L_C | |
) | |
} else { | |
if (is_Debug_Mode) {println(s"""a2.. + c1..b1 => a2.c.b1: ${left_Part} + ${right_Part}""")} | |
Chunk( | |
head = left_Part.head | |
,head_Count = l_H_C | |
// total count > 1 | |
,body = r_H + | |
more_Then_2_Str(r_H_C) | |
,last = right_Part.last | |
,last_Count = r_L_C | |
) | |
} | |
} | |
case (Chunk(Some(l_H), l_H_C, "", Some(l_L), l_L_C), Chunk(Some(r_H), r_H_C, "", None, 0)) => { | |
///> "a2..b1" + "b3.." => "a2.b4" | |
///> "a2..b1" + "c1.." => "a2.b.c1" | |
if (l_L == r_H) { | |
if (is_Debug_Mode) {println(s"""a2..b1 + b3.. => a2.b4: ${left_Part} + ${right_Part}""")} | |
Chunk( | |
head = left_Part.head | |
,head_Count = l_H_C | |
,body = ""//right_Part.body | |
,last = right_Part.head | |
,last_Count = l_L_C + r_H_C | |
) | |
} else { | |
if (is_Debug_Mode) {println(s"""a2..b1 + c1.. => a2.b.c1: ${left_Part} + ${right_Part}""")} | |
Chunk( | |
head = left_Part.head | |
,head_Count = l_H_C | |
// total count > 1 | |
,body = l_L + | |
more_Then_2_Str(l_L_C) | |
,last = right_Part.head | |
,last_Count = r_H_C | |
) | |
} | |
} | |
case ( | |
Chunk(Some(l_H), l_H_C, "", None, 0), | |
Chunk(Some(r_H), r_H_C, r_B, Some(r_L), r_L_C)) | |
if r_B != "" => { | |
///>p13.. + p4.s3i4.z3 => p17.s3i4.z3 | |
///>r13.. + p4.s3i4.z3 => r13.p4s3i4.z3 | |
if (l_H == r_H) { | |
if (is_Debug_Mode) {println(s"""p13.. + p4.s3i4.z3 => p17.s3i4.z3: ${left_Part} + ${right_Part}""")} | |
Chunk( | |
head = left_Part.head | |
,head_Count = l_H_C + r_H_C | |
,body = r_B | |
,last = right_Part.last | |
,last_Count = r_L_C | |
) | |
} else { | |
if (is_Debug_Mode) {println(s"""r13.. + p4.s3i4.z3 => r13.p4s3i4.z3: ${left_Part} + ${right_Part}""")} | |
Chunk( | |
head = left_Part.head | |
,head_Count = l_H_C | |
// total count > 1 | |
,body = r_H + more_Then_2_Str(r_H_C) + r_B | |
,last = right_Part.last | |
,last_Count = r_L_C | |
) | |
} | |
} | |
case ( | |
Chunk(Some(l_H), l_H_C, l_B, Some(l_L), l_L_C), | |
Chunk(Some(r_H), r_H_C, "", None, 0)) if l_B != "" => { | |
///> p4.s3i4.z3 + z1.. => p4.s3i4.z4 | |
///> p4.s3i4.z3 + y1.. => p4.s3i4z3.y1 | |
if (l_L == r_H) { | |
if (is_Debug_Mode) {println(s"""p4.s3i4.z3 + z1.. => p4.s3i4.z4: ${left_Part} + ${right_Part}""")} | |
Chunk( | |
head = left_Part.head | |
,head_Count = l_H_C | |
,body = l_B | |
,last = left_Part.last | |
,last_Count = l_L_C + r_H_C | |
) | |
} else { | |
if (is_Debug_Mode) {println(s"""p4.s3i4.z3 + y1.. => p4.s3i4z3.y1: ${left_Part} + ${right_Part}""")} | |
Chunk( | |
head = left_Part.head | |
,head_Count = l_H_C | |
// total count > 1 | |
,body = l_B + l_L + more_Then_2_Str(l_L_C) | |
,last = right_Part.head | |
,last_Count = r_H_C | |
) | |
} | |
} | |
case ( | |
Chunk(Some(l_H), l_H_C, "", Some(l_L), l_L_C), | |
Chunk(Some(r_H), r_H_C, "", Some(r_L), r_L_C)) => { | |
///> "a2..b3" + "a1..b1" => "a2.b3a.b1" | |
///> "a2..b3" + "b1..c1" => "a2.b4.c1" | |
if (l_L == r_H) { | |
if (is_Debug_Mode) {println(s"""a2..b3 + a1..b1 => a2.b3a.b1: ${left_Part} + ${right_Part}""")} | |
Chunk( | |
head = left_Part.head | |
,head_Count = l_H_C | |
// total count > 1 | |
,body = l_L + more_Then_2_Str(l_L_C + r_H_C) | |
,last = right_Part.last | |
,last_Count = r_L_C | |
) | |
} else { | |
if (is_Debug_Mode) {println(s"""a2..b3 + b1..c1 => a2.b4.c1: ${left_Part} + ${right_Part}""")} | |
Chunk( | |
head = left_Part.head | |
,head_Count = l_H_C | |
// total count > 1 | |
,body = l_L + more_Then_2_Str(l_L_C) + r_H + more_Then_2_Str(r_H_C) | |
,last = right_Part.last | |
,last_Count = r_L_C | |
) | |
} | |
} | |
case ( | |
Chunk(Some(l_H), l_H_C, l_B, Some(l_L), l_L_C), | |
Chunk(Some(r_H), r_H_C, "", Some(r_L), r_L_C)) if l_B != "" => { | |
///> "a2.c.b3" + "b1..c1" => "a2.cb4.c1" | |
///> "a2.c.a3" + "b1..c1" => "a2.ca3b.c1" | |
if (l_L == r_H) { | |
if (is_Debug_Mode) {println(s"""a2.c.b3 + b1..c1 => a2.cb4.c1: ${left_Part} + ${right_Part}""")} | |
Chunk( | |
head = left_Part.head | |
,head_Count = l_H_C | |
// total count > 1 | |
,body = l_B + l_L + more_Then_2_Str(l_L_C + r_H_C) | |
,last = right_Part.last | |
,last_Count = r_L_C | |
) | |
} else { | |
if (is_Debug_Mode) {println(s"""a2.c.a3 + b1..c1 => a2.ca3b.c1: ${left_Part} + ${right_Part}""")} | |
Chunk( | |
head = left_Part.head | |
,head_Count = l_H_C | |
// total count > 1 | |
,body = l_B + l_L + more_Then_2_Str(l_L_C) + r_H + more_Then_2_Str(r_H_C) | |
,last = right_Part.last | |
,last_Count = r_L_C | |
) | |
} | |
} | |
case ( | |
Chunk(Some(l_H), l_H_C, "", Some(l_L), l_L_C), | |
Chunk(Some(r_H), r_H_C, r_B, Some(r_L), r_L_C)) if r_B != "" => { | |
///> "a2..b3" + "b1.a4.c1" => "a2.b4a4.c1" | |
///> "a2..b3" + "c1.a4.b1" => "a2.b3ca4.b1" | |
if (l_L == r_H) { | |
if (is_Debug_Mode) {println(s"""a2..b3 + b1.a4.c1 => a2.b4a4.c1: ${left_Part} + ${right_Part}""")} | |
Chunk( | |
head = left_Part.head | |
,head_Count = l_H_C | |
// total count > 1 | |
,body = l_L + more_Then_2_Str(l_L_C + r_H_C) + r_B | |
,last = right_Part.last | |
,last_Count = r_L_C | |
) | |
} else { | |
if (is_Debug_Mode) {println(s"""a2..b3 + c1.a4.b1 => a2.b3ca4.b1: ${left_Part} + ${right_Part}""")} | |
Chunk( | |
head = left_Part.head | |
,head_Count = l_H_C | |
// total count > 1 | |
,body = l_L + more_Then_2_Str(l_L_C) + r_H + more_Then_2_Str(r_H_C) + r_B | |
,last = right_Part.last | |
,last_Count = r_L_C | |
) | |
} | |
} case _ => { | |
///> "a2.c.b3" + "b1.a5.c1" => "a2.cb4a5.c1" | |
///> "a2.c.b3" + "a1.b5.c1" => "a2.cb3ab5.c1" | |
/*if ( | |
left_Part.head.nonEmpty && | |
left_Part.body != "" && | |
left_Part.last.nonEmpty && | |
right_Part.head.nonEmpty && | |
right_Part.body != "" && | |
right_Part.last.isEmpty | |
)*/ | |
if (left_Part.last == right_Part.head) { | |
if (is_Debug_Mode) {println(s"""a2.c.b3 + b1.a5.c1 => a2.cb4a5.c1: ${left_Part} + ${right_Part}""")} | |
Chunk( | |
head = left_Part.head | |
,head_Count = left_Part.head_Count | |
// total count > 1 | |
,body = left_Part.body + | |
left_Part.last.getOrElse("") + | |
more_Then_2_Str(left_Part.last_Count + right_Part.head_Count) + | |
right_Part.body | |
,last = right_Part.last | |
,last_Count = right_Part.last_Count | |
) | |
} else { | |
if (is_Debug_Mode) {println(s"""a2.c.b3 + a1.a5.c1 => a2.cb3ab5.c1: ${left_Part} + ${right_Part}""")} | |
Chunk( | |
head = left_Part.head | |
,head_Count = left_Part.head_Count | |
// total count > 1 | |
,body = left_Part.body + | |
left_Part.last.getOrElse("") + | |
more_Then_2_Str(left_Part.last_Count) + | |
right_Part.head.getOrElse("") + | |
more_Then_2_Str(right_Part.head_Count) + | |
right_Part.body | |
,last = right_Part.last | |
,last_Count = right_Part.last_Count | |
) | |
} | |
} | |
} | |
} | |
//An infix type T1 op T2 ? | |
// tuple ? | |
def divide( | |
//source_Str: String | |
source_Str: Chunk | |
//): Either[String, Chunk] = { | |
///> so, actual result must be contained in the Chunk.body | |
///> + may be one last merge to use nonempty Chunk.head & Chunk.last ??? | |
): Chunk = { | |
/* | |
val Right(r) = divide("!") | |
r: Chunk = Chunk(a,3,b,Some(a),4) | |
*/ | |
//val source_Str_Length: Int = source_Str.length | |
val source_Str_Length: Int = source_Str.body.length | |
//if (is_Debug_Mode) {println(s"""dividing ...""")} | |
if (is_Debug_Mode) {println(s"""dividing source_Str_Length: ${source_Str_Length} ...""")} | |
/* | |
source_Str_Length: 3 | |
source_Str_Length: 1 | |
source_Str_Length: 0 ... | |
java.lang.StackOverflowError | |
*/ | |
if ( | |
source_Str_Length > 2 && | |
source_Str.head.isEmpty | |
//source_Str.head.nonEmpty | |
) { | |
///>>> Merge step | |
///> actual / final result | |
//5 / 2 -> res22: Int = 2 | |
//5 / 2.0 -> res23: Double = 2.5 | |
//"0123456789".take(5) | |
//"0123456789".drop(5) | |
if (is_Debug_Mode) { | |
println(s"""merging ... """ + | |
s"""${Chunk(body = source_Str.body.take(source_Str_Length / 2))}""" + | |
s""" with ${Chunk(body = source_Str.body.drop(source_Str_Length / 2))}""")} | |
merge( | |
divide( | |
//source_Str.take(source_Str_Length / 2) | |
Chunk(body = source_Str.body.take(source_Str_Length / 2)) | |
) /*match { | |
///> '"" + ' for inferred type cast | |
case Right(Chunk(h, h_C, b, Some(l), l_C)) => Left("" + h + h_C + b + l + l_C) | |
case Right(Chunk(h, h_C, b, None, _)) => Left("" + h + h_C + b) | |
case Left(str) => Left(str) | |
}*/ | |
,divide( | |
//source_Str.drop(source_Str_Length / 2) | |
Chunk(body = source_Str.body.drop(source_Str_Length / 2)) | |
) /*match { | |
///> '"" + ' for inferred type cast | |
case Right(Chunk(h, h_C, b, Some(l), l_C)) => Left("" + h + h_C + b + l + l_C) | |
case Right(Chunk(h, h_C, b, None, _)) => Left("" + h + h_C + b) | |
case Left(str) => Left(str) | |
}*/ | |
) | |
} else if (source_Str_Length == 2) { | |
///>>> base case | |
//val List(head, last) = source_Str.toList | |
//scala> val (a, b) = (c_1.body.head, c_1.body.tail.head) | |
//a: Char = O | |
//b: Char = K | |
val (head, last) = (source_Str.body.head, source_Str.body.tail.head) | |
if (is_Debug_Mode) {println(s"""head: ${head}, last: ${last}""")} | |
//Right(Chunk('a',3,"b",Some('a'),4)) | |
/* | |
var List(a, b) = "AB".toList | |
a: Char = A | |
b: Char = B | |
scala> "ab".endsWith("a") | |
res27: Boolean = false | |
scala> "ab".endsWith("b") | |
res28: Boolean = true | |
"aaabbc".dropWhile(_ == 'a') | |
res30: String = bbc | |
*/ | |
if ( | |
head == last | |
//source_Str.head == source_Str.tail.head | |
//source_Str.head == source_Str.last | |
//source_Str.endsWith(source_Str.head) | |
//source_Str(0) == source_Str(1) | |
) { | |
if (is_Debug_Mode) {println(s"""Chunk(head, 2): ${Chunk(Some(head), 2)}""")} | |
//Right(Chunk(head, 2)) | |
Chunk(Some(head), 2) | |
} else { //if (head != last) | |
if (is_Debug_Mode) {println( | |
s"""Chunk(head, 1, "", Some(last), 1): ${Chunk(Some(head), 1, "", Some(last), 1)}""")} | |
//Right(Chunk(head, 1, "", Some(last), 1)) | |
Chunk(Some(head), 1, "", Some(last), 1) | |
} | |
} else if (source_Str_Length == 1) { | |
///>>> base case | |
///> source_Str.body.length == 1 | |
//Right(Chunk(source_Str.head)) | |
//if (source_Str.head.nonEmpty) { | |
//if (is_Debug_Mode) {println(s"""Chunk(source_Str.head): ${Chunk(source_Str.head)}""")} | |
//Chunk(source_Str.head) | |
//} else { | |
if (is_Debug_Mode) {println(s"""Chunk(source_Str.head): ${Chunk(Some(source_Str.body.head), 1)}""")} | |
//Chunk(Some(source_Str.body.head), 1) | |
Chunk(Some(source_Str.body.head), 1, "", None, 0) | |
//} | |
} else {//if (source_Str_Length <= 0) { | |
///>>> base case ??? <- nonEmpty Char | |
///>>> non merge case -> instant result return | |
///> so, actual result must be contained in the Chunk.body | |
//if (is_Debug_Mode) {println(s"""Left(source_Str) == ''""")} | |
if (is_Debug_Mode) { | |
println(s"""source_Str_Length: ${source_Str_Length} => ${Chunk(body = source_Str.body)}""")} | |
//Left(source_Str) | |
//Chunk(body = source_Str.body) | |
//Chunk() | |
Chunk(None, 0, "", None, 0) | |
} | |
} | |
// O(N) | |
@tailrec | |
//scala.annotation.tailrec | |
def parse_Str( | |
source_Str: String | |
//,last_Char_Counter: Int = 0 | |
,char_Sequense_Length: Int = 0 | |
///> accum.last | |
,last_Char: Option[Char] = None//Char//String = "" | |
,accum: String = "" | |
///> local log switch | |
,is_Debug_Mode: Boolean = false | |
): String = { | |
/* | |
cases: | |
.head.nonEmpty //&& .tail.nonEmpty//.tail.head.nonEmpty | |
//.head == .tail.head | |
accum.isEmpty | |
char_Sequense_Length += 1 | |
//accum += .head | |
accum.nonEmpty | |
accum.last == .head// == .tail.head | |
char_Sequense_Length += 1 | |
accum.last != .head | |
char_Sequense_Length == 0 | |
accum += .head | |
char_Sequense_Length > 0 | |
accum += accum.last + char_Sequense_Length | |
char_Sequense_Length = 0 | |
//.head.nonEmpty && .tail.isEmpty//.tail.head.isEmpty | |
.head.isEmpty // => && .tail.head.isEmpty | |
.head == .tail.head | |
char_Sequense_Length == 0 | |
accum += accum.last | |
char_Sequense_Length > 0 | |
accum += accum.last + char_Sequense_Length | |
//char_Sequense_Length = 0 | |
=> accum | |
*/ | |
if (source_Str.isEmpty) { | |
if (is_Debug_Mode) {println(s"""source_Str.isEmpty""")} | |
if (is_Debug_Mode) {println(s"""accum: ${accum}, char_Sequense_Length: ${char_Sequense_Length}""")} | |
if (char_Sequense_Length <= 1) { | |
if (is_Debug_Mode) {println(s"""char_Sequense_Length == 0""")} | |
// result | |
accum + last_Char.getOrElse("") | |
} else {//if (char_Sequense_Length > 1) | |
if (is_Debug_Mode) {println(s"""char_Sequense_Length > 0""")} | |
// result | |
accum + last_Char.getOrElse("") + char_Sequense_Length | |
} | |
} else {//if (source_Str.nonEmpty) | |
if (is_Debug_Mode) {println(s"""source_Str.nonEmpty""")} | |
if (is_Debug_Mode) {println(s"""accum: ${accum}, char_Sequense_Length: ${char_Sequense_Length}""")} | |
/*var next_Last_Char_Counter = 0 | |
var next_Last_Char = "" | |
var next_Accum = ""*/ | |
/*if (accum.isEmpty) { | |
if (is_Debug_Mode) {println(s"""accum.isEmpty""")} | |
// recursion | |
parse_Str(source_Str.tail, char_Sequense_Length + 1, Some(source_Str.head), accum) | |
} else { //if (accum.nonEmpty) | |
if (is_Debug_Mode) {println(s"""accum.nonEmpty""")}*/ | |
if (last_Char == Some(source_Str.head)) { | |
if (is_Debug_Mode) {println(s"""last_Char:${last_Char} == Some(source_Str.head:${source_Str.head})""")} | |
// recursion | |
//if (last_Char.nonEmpty) | |
//parse_Str(source_Str.tail, char_Sequense_Length + 1, last_Char, accum) | |
parse_Str(source_Str.tail, char_Sequense_Length + 1, Some(source_Str.head), accum) | |
} else {//(last_Char != source_Str.head) | |
if (is_Debug_Mode) {println(s"""last_Char:${last_Char} != Some(source_Str.head:${source_Str.head})""")} | |
if (char_Sequense_Length <= 1) { | |
if (is_Debug_Mode) {println(s"""char_Sequense_Length <= 1""")} | |
// recursion | |
parse_Str(source_Str.tail, 1, Some(source_Str.head), accum + last_Char.getOrElse("")) | |
} else {//if (char_Sequense_Length > 0) | |
if (is_Debug_Mode) {println(s"""char_Sequense_Length > 1""")} | |
// recursion | |
parse_Str( | |
source_Str.tail | |
, 1 | |
, Some(source_Str.head) | |
, accum + last_Char.getOrElse("") + char_Sequense_Length) | |
} | |
} | |
//} | |
} | |
} | |
// O(N) | |
def parse_Str_2( | |
//source_Str: String | |
//msg: String | |
msg: Stream[Char] | |
): String = { | |
//import scala.util.{Try, Success, Failure} | |
var result: String = "" | |
var char_Sequense_Length: Int = 0 | |
var last_Char: Option[Char] = None | |
//var char: Char = '\n' | |
/**/ | |
for { | |
char <- msg | |
//char <- scala.io.StdIn.readLine() | |
} {/**/ | |
//while(condition) { | |
/*do { | |
//statement(s) | |
try { | |
char = scala.io.StdIn.readChar() | |
println(s"""char: ${char}""") | |
} catch { | |
case ex: java.io.EOFException => { | |
println(s"""java.io.EOFException: ${result}""") | |
char = '\n' | |
} | |
case ex: java.lang.StringIndexOutOfBoundsException => { | |
println(s"""java.lang.StringIndexOutOfBoundsException: ${result}""") | |
char = '\n' | |
} | |
} */ | |
//} while( condition ) | |
if (last_Char == Some(char)) { | |
if (is_Debug_Mode) {println(s"""last_Char:${last_Char} == Some(char:${char})""")} | |
char_Sequense_Length += 1 | |
//last_Char = Some(char) | |
} else {//(last_Char != source_Str.head) | |
if (is_Debug_Mode) {println(s"""last_Char:${last_Char} != Some(char:${char})""")} | |
result += last_Char.getOrElse("") | |
if (char_Sequense_Length <= 1) { | |
if (is_Debug_Mode) {println(s"""char_Sequense_Length <= 1""")} | |
//char_Sequense_Length = 1 | |
//last_Char = Some(char) | |
//result += last_Char.getOrElse("") | |
} else {//if (char_Sequense_Length > 0) | |
if (is_Debug_Mode) {println(s"""char_Sequense_Length > 1""")} | |
//char_Sequense_Length = 1 | |
//last_Char = Some(char) | |
//result += last_Char.getOrElse("") + char_Sequense_Length | |
result += char_Sequense_Length | |
} | |
char_Sequense_Length = 1 | |
last_Char = Some(char) | |
} | |
} //while( char != '\n' ) | |
result += last_Char.getOrElse("") | |
if (char_Sequense_Length <= 1) { | |
if (is_Debug_Mode) {println(s"""char_Sequense_Length == 0""")} | |
// result | |
//result += last_Char.getOrElse("") | |
} else {//if (char_Sequense_Length > 1) | |
if (is_Debug_Mode) {println(s"""char_Sequense_Length > 0""")} | |
// result | |
//result += last_Char.getOrElse("") + char_Sequense_Length | |
result += char_Sequense_Length.toString() | |
} | |
result | |
} | |
///>>>*** unit test ***<<</// | |
import scala.util.Random | |
//trait Generator[+T] { | |
//val rand = new java.util.Random | |
//def generate = rand.nextInt() | |
//def interval(lo: Int, hi: Int) : Generator[Int] = for { X <- integers } yield lo + x % (hi - lo) | |
val rand = new Random() | |
//rand: scala.util.Random = scala.util.Random@dfd3711 | |
//scala> rand.nextInt(2) | |
//res12: Int = 0 | 1 <- boolean generator | |
//scala> (97 + rand.nextInt(122-97+1)).toChar | |
//res27: Char = a | |
def a_z_Random: Char = { | |
val a_Byte: Byte = 'a'.toByte | |
val z_Byte: Byte = 'z'.toByte | |
(a_Byte + rand.nextInt(z_Byte - a_Byte + 1)).toChar | |
} | |
/// 1≤length(msg)≤10^5 | |
case class String_Compression(input_Str: String = "aaa", expected_Result: String = "a3") | |
@tailrec | |
def make_Test_String( | |
length_Limit: Int = 100//rand.nextInt(length_Limit) | |
,result_Accum: String = ""//String_Compression = String_Compression("", "") | |
): String = { | |
//): String_Compression = { | |
if (length_Limit <= 0) { | |
///> base case | |
result_Accum | |
} else { | |
///> recursion | |
val current_Char: Char = a_z_Random | |
val char_Repetition: Int = rand.nextInt(length_Limit) | |
//scala> (1 to 5 + 1).map(_ => 'a') | |
//res28: scala.collection.immutable.IndexedSeq[Char] = Vector(a, a, a, a, a, a) | |
//scala> (1 to 5 + 1).map(_ => 'a').mkString | |
//res29: String = aaaaaa | |
//scala> (1 to 5 + 1).map(_ => "a").fold[String]("")(_ + _) | |
//res56: String = aaaaaa | |
val str_Chunk: String = (1 to char_Repetition + 1).map(_ => current_Char).mkString | |
make_Test_String( | |
length_Limit - 1 - char_Repetition | |
,result_Accum + str_Chunk | |
) | |
} | |
} | |
val result_Chunk: Chunk = divide(Chunk(body = msg.getOrElse(Stream('!')).mkString)) | |
//val result_String: String = result_Chunk.mkString | |
val result: String = /*"" + result_Chunk.head.getOrElse("") + | |
more_Then_2_Str(result_Chunk.head_Count) + | |
result_Chunk.body + | |
result_Chunk.last.getOrElse("") + | |
more_Then_2_Str(result_Chunk.last_Count)*/ | |
result_Chunk.mkString | |
/* | |
cases: | |
"a2.." + ".." => "a2.." | |
".." + "a2.." => "a2.." | |
... | |
"a2.." + "a3.." => "a5.." | |
"a2.." + "b3.." => "a2..b3" | |
... | |
"a2.." + "a1..b1" => "a3..b1" | |
"a2.." + "c1..b1" => "a2.c.b1" | |
... | |
"a2..b1" + "b3.." => "a2.b4" | |
"a2..b1" + "c1.." => "a2.b.c1" | |
... | |
"a2..b3" + "a1..b1" => "a2.b3a.b1" | |
"a2..b3" + "b1..c1" => "a2.b4.c1" | |
... | |
"a2.c.b3" + "b1..c1" => "a2.cb4.c1" | |
"a2.c.a3" + "b1..c1" => "a2.ca3b.c1" | |
... | |
"a2..b3" + "b1.a4.c1" => "a2.b4a4.c1" | |
"a2..b3" + "c1.a4.b1" => "a2.b3ca4.b1" | |
... | |
"a2.c.b3" + "b1.a5.c1" => "a2.cb4a5.c1" | |
"a2.c.b3" + "a1.b5.c1" => "a2.cb3ab5.c1" | |
*/ | |
//val (t_C_1, t_C_2) = (Chunk(Some('a'), 2), Chunk(None, 0, "", None, 0)) | |
//val expected = Chunk(Some('a'), 2) //> OK | |
//val (t_C_1, t_C_2) = (Chunk(None, 0, "", None, 0), Chunk(Some('a'), 2)) | |
//val expected = Chunk(Some('a'), 2) //> OK | |
//val (t_C_1, t_C_2) = (Chunk(Some('b'), 1), Chunk(Some('b'), 2)) | |
//val expected = Chunk(Some('b'), 3) //> OK | |
//val (t_C_1, t_C_2) = (Chunk(Some('a'), 2, "", None, 0), Chunk(Some('a'), 1, "", Some('b'), 1)) | |
//val expected = Chunk(Some('a'), 3, "", Some('b'), 1) //> OK | |
//val (t_C_1, t_C_2) = (Chunk(Some('a'), 2, "", None, 0), Chunk(Some('c'), 1, "", Some('b'), 1)) | |
//val expected = Chunk(Some('a'), 2, "c", Some('b'), 1) //> OK | |
//val (t_C_1, t_C_2) = (Chunk(Some('a'), 2, "", Some('b'), 1), Chunk(Some('b'), 3, "", None, 0)) | |
//val expected = Chunk(Some('a'), 2, "", Some('b'), 4) //> OK | |
//val (t_C_1, t_C_2) = (Chunk(Some('a'), 2, "", Some('b'), 1), Chunk(Some('c'), 3, "", None, 0)) | |
//val expected = Chunk(Some('a'), 2, "b", Some('c'), 3) //> OK | |
//val (t_C_1, t_C_2) = (Chunk(Some('a'), 2, "", Some('b'), 3), Chunk(Some('a'), 1, "", Some('b'), 1)) | |
//val expected = Chunk(Some('a'), 2, "b3a", Some('b'), 1) //> OK | |
//val (t_C_1, t_C_2) = (Chunk(Some('a'), 2, "", Some('b'), 3), Chunk(Some('b'), 1, "", Some('c'), 1)) | |
//val expected = Chunk(Some('a'), 2, "b4", Some('c'), 1) //> OK | |
//val (t_C_1, t_C_2) = (Chunk(Some('a'), 2, "c", Some('b'), 3), Chunk(Some('b'), 1, "", Some('c'), 1)) | |
//val expected = Chunk(Some('a'), 2, "cb4", Some('c'), 1) //> OK | |
//val (t_C_1, t_C_2) = (Chunk(Some('a'), 2, "c", Some('a'), 3), Chunk(Some('b'), 1, "", Some('c'), 1)) | |
//val expected = Chunk(Some('a'), 2, "ca3b", Some('c'), 1) //> OK | |
//val (t_C_1, t_C_2) = (Chunk(Some('a'), 2, "", Some('b'), 3), Chunk(Some('b'), 1, "a4", Some('c'), 1)) | |
//val expected = Chunk(Some('a'), 2, "b4a4", Some('c'), 1) //> OK | |
//val (t_C_1, t_C_2) = (Chunk(Some('a'), 2, "", Some('b'), 3), Chunk(Some('c'), 1, "a4", Some('c'), 1)) | |
//val expected = Chunk(Some('a'), 2, "b3ca4", Some('c'), 1) //> OK | |
//val (t_C_1, t_C_2) = (Chunk(Some('a'), 2, "c", Some('b'), 3), Chunk(Some('b'), 1, "a5", Some('c'), 1)) | |
//val expected = Chunk(Some('a'), 2, "cb4a5", Some('c'), 1) //> OK | |
//val (t_C_1, t_C_2) = (Chunk(Some('a'), 2, "c", Some('b'), 3), Chunk(Some('a'), 1, "b5", Some('c'), 1)) | |
//val expected = Chunk(Some('a'), 2, "cb3ab5", Some('c'), 1) //> OK | |
///> p13.. + p4.s3i4.z3 <- (was | were) missing case shape / pattern | |
//val (t_C_1, t_C_2) = (Chunk(Some('p'), 13, "", None, 0), Chunk(Some('p'), 4, "s3i4", Some('z'), 3)) | |
//val expected = Chunk(Some('p'), 17, "s3i4", Some('z'), 3) //> OK | |
///> t1.x2.u1 + u5.. => t1.x2.u6 <- (was | were) missing case shape / pattern | |
val (t_C_1, t_C_2) = (Chunk(Some('t'), 1, "x2", Some('u'), 1), Chunk(Some('u'), 5, "", None, 0)) | |
val expected = Chunk(Some('t'), 1, "x2", Some('u'), 6) | |
val m_T_1 = merge(t_C_1, t_C_2) | |
if (is_Debug_Mode) {println(s"""merge(${t_C_1}, ${t_C_2}): ${m_T_1}""")} | |
if (is_Debug_Mode) {assert(m_T_1 == expected, s"""expected: ${expected}""")} | |
if (is_Debug_Mode) { | |
(0 to 9).foreach(v => { | |
val t_S: String = make_Test_String(rand.nextInt(100) + 1) | |
val exp_R: String = parse_Str(t_S) | |
val act_R: String = divide(Chunk(body = t_S)).mkString | |
println(s"""test_String_${v}: ${t_S}""") | |
assert(act_R == exp_R, s"""actual: ${act_R} != ${exp_R} expected""") | |
println(s"""compressed: ${act_R}""") | |
} | |
) | |
} | |
//println(parse_Str(msg.mkString)) | |
//println(parse_Str_2(msg.getOrElse(Stream('!')))) | |
///> it pass Test Case #9 & 15 -> not time is up alert | |
//println(divide(msg.getOrElse(Stream('!')).mkString)) | |
if (is_Debug_Mode) {println(s"""result_Chunk: ${result_Chunk}""")} | |
if (is_Debug_Mode) {println(s"""result_Chunk: ${result_Chunk.mkString}""")} | |
println(result) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment