fork download
  1. object Main {
  2. import scala.util.{Left => Failed, Right => Ok}
  3.  
  4. sealed trait UriException { self =>
  5. def explain: String
  6.  
  7. def |+|(that: UriException): UriException = new UriException {
  8. def explain = self.explain + " | " + that.explain
  9. }
  10.  
  11. override def toString = explain
  12. }
  13.  
  14. case class NotFound(code: String) extends UriException {
  15. def explain = s"can not translate '$code'"
  16. }
  17.  
  18. case class Flaw(c: Char) extends UriException {
  19. def explain = s"'$c' can't be appeared in URI"
  20. }
  21.  
  22. type Result = Either[UriException, String]
  23.  
  24. implicit class ResultPlus(self: Result) {
  25. def |+|(that: Result): Result = (self, that) match {
  26. case (Ok(s1), Ok(s2)) => Ok(s1 + s2)
  27. case (Failed(ex1), Failed(ex2)) => Failed(ex1 |+| ex2)
  28. case (f@Failed(_), _) => f
  29. case (_, f@Failed(_)) => f
  30. }
  31. }
  32.  
  33. val code2sc = Map(
  34. "20" -> " ",
  35. "21" -> "!",
  36. "24" -> "$",
  37. "25" -> "%",
  38. "28" -> "(",
  39. "29" -> ")",
  40. "2a" -> "*"
  41. )
  42. val scChar = code2sc.values map (_.head)
  43.  
  44. def toSecialCharacter(c1: Char, c2: Char): Result = {
  45. val code = (c1.toString + c2.toString).toLowerCase
  46.  
  47. (code2sc get code) match {
  48. case Some(specialChar) => Ok(specialChar)
  49. case None => Failed(NotFound("%" + code))
  50. }
  51. }
  52.  
  53. def decode(uri: String): Result = {
  54. @annotation.tailrec
  55. def loop(chars: List[Char], res: Result = Ok("")): Result = chars match {
  56. case '%' :: a :: b :: rest => loop(rest, res |+| toSecialCharacter(a, b))
  57. case c :: rest =>
  58. if (scChar exists (_ == c)) loop(rest, res |+| Failed(Flaw(c)))
  59. else loop(rest, res |+| Ok(c.toString))
  60. case Nil => res
  61. }
  62.  
  63. loop(uri.toList)
  64. }
  65.  
  66. def prettyFormat(res: Result): String = res match {
  67. case Failed(reason) => s"Failed ($reason)"
  68. case Ok(decoded) => decoded
  69. }
  70.  
  71. val prettyPrint = decode _ andThen prettyFormat _ andThen println _
  72.  
  73. def main(args: Array[String]) {
  74. import scala.util.{Try, Success, Failure}
  75. import java.util.Scanner
  76. import java.io.{File, FileInputStream => FIS}
  77.  
  78. @annotation.tailrec
  79. def loop(sc: Scanner, remain: Int): Unit = (sc.hasNextLine, remain) match {
  80. case (_, 0) => ()
  81. case (false, _) => ()
  82. case (true, _) => prettyPrint(sc.nextLine.trim take 80); loop(sc, remain - 1)
  83. }
  84.  
  85. List("""Happy%20Joy%20Joy%21""", """http://a...content-available-to-author-only...t.com/%2a""") foreach prettyPrint
  86. }
  87. }
Success #stdin #stdout 0.41s 382208KB
stdin
Standard input is empty
stdout
Happy Joy Joy!
http://a...content-available-to-author-only...t.com/*