謎言語ウキャス

  • タグ:
  • タグはありません
/**
  * 謎言語ウキャス
  *  こんにちわ →  ᓦᐓᔦᐓᓾᐓᓴᐓᔢᐓ
  *  吾輩は猫である。名前はまだ無い。 → ᗟᐡᓢᐹᔂᐓᑙᐮᓺᐓᓕᐓᔞᐓ。ᖮᐡ᙭ᐠᔂᐓᔑᐓᓳᐓᓎᐭᓗᐓ。
  *  謎言語ウキャスは、@yuroyoroがScalaでテキトーに10分くらいで実装しました。
  *    →  ᗅᐷᒷᐷᕕᐷᔹᐓᕀᐓᕶᐓᕌᐓᔂᐓ、@yuroyoroᓟᐓScalaᓺᐓᕙᐓᕀᐓᕛᐓᖏᐓᓾᐓ10ᘦᐠᓢᐓᔜᐓᓗᐓᓺᐓᗃᐤᗻᐶᓪᐓᔑᐓᓪᐓᓲᐓ。
  *
  */
object UCAS extends App{
  import java.text.Normalizer
  import java.lang.Character.UnicodeBlock

  def toUcasChar(c:Char) = {
    def g(n:Int):Char = (n + 5120).toChar
    def worker(xs:Seq[Char], n:Int):Seq[Char] = if( n < 639 ) xs :+ g(n) else worker( xs :+ g(n % 639), n / 639)

    if( isHKC(c) ) worker(Seq.empty[Char], c.toInt) else Seq(c)
  }

  def fromUcasChar(a:Char, b:Char) = {
    (( (b.toInt - 5120) * 639 ) + a.toInt - 5120 ).toChar
  }

  def isHKC(c:Char) = UnicodeBlock.of(c) match {
    case UnicodeBlock.HIRAGANA | UnicodeBlock.KATAKANA  | UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS => true
    case _ => false
  }

  def isUcas(c:Char) = UnicodeBlock.of(c) == UnicodeBlock.UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS


  def encode(s:String) = {
    Normalizer.normalize(s, Normalizer.Form.NFKC).map{ toUcasChar }.flatten.mkString
  }

  def decode(s:String) = {
    def worker( xs:List[Char], res:List[Char]):List[Char] = xs match {
      case a::b::t if isUcas(a) && isUcas(b) => worker( t, res :+ fromUcasChar(a, b))
      case h::t => worker(t, res :+ h)
      case _ => res
    }

    worker( s.toList, List.empty[Char] ).mkString
  }

  def rand(n:Int = 140) = {
    scala.io.Codec.toUTF8 ((1 to n).map{_ => (util.Random.nextInt(639) + 5120).toChar})
  }

  def readFromStdIn = scala.io.Source.fromInputStream(java.lang.System.in).mkString

  args.headOption.foreach{ cmd => cmd match {
    case "rand" =>
      val n = args.tail.headOption.map{ _.toInt}.getOrElse(140)
      rand(n).foreach{b => java.lang.System.out.write(b)}
    case "decode" =>
      if(args.tail.isEmpty) println(decode(readFromStdIn))
      else args.tail.foreach{ s => println(decode(s)) }
    case "encode" =>
      if(args.tail.isEmpty) println(encode(readFromStdIn))
      else args.tail.foreach{ s => println(encode(s)) }
    case _ =>
      println("""usage: scala UCAS (rand|decode|encode) <strings...>""")
    }
  }

}