Problem:
失われし数

時は3xxx年、高度に発達した文明は停滞期を迎えていた。歴史家たちはこの状況を打開しようと過去の叡智を学ぶことにした。注目したのはコンピュータ創世期の天才が残した資料である。この資料には計算式が書かれておりその計算結果が知りたいのだが、残念ながらその一部の文字が薄れて読めなくなっている。仕方がないので計算結果としてありえる最も大きい数を求めることにした。

計算式は2進数で書かれており、演算は足し算・引き算・掛け算の3種類である。括弧も用いられているが括弧内が数字のみであることはない。正確には以下のBNFで定義された文法を満たしている必要がある。

<expression> ::= <number> | <expression> <operation> <expression>
| ( <expression> <operation> <expression> )
<number> ::= <digit> | <number> <digit>
<operation> ::= + | - | *
<digit> ::= 0 | 1

当時のコンピュータの計算能力の限界により、数字は0以上210未満の整数であり計算中もこの範囲を出ることはない。ただし計算は括弧内を先に行い、掛け算は足し算・引き算より先に行う。それ以外の場合は左から順に計算する。

Input

入力は1行からなり、解読すべき数式が1つ与えられる。数式は1文字以上100文字以下である。1つの数式について最大5文字が読めなくなっていて、「.」で表現されている。与えられる数式に含まれる文字は01+-*().のいずれかである。

Constraints

数式は1文字以上100文字以下

改行を除くすべての文字は01+-*().のいずれか

.の個数は5個以下

Output

元の数式として考えられるものの内、計算結果が最大となるものを求め、計算結果を10進法で出力せよ。読めなくなっている文字をどのように埋めても元の数式と考えられるものを作れないときは-1を出力せよ。

Sample Input 1

000

Output for the Sample Input 1

0

Sample Input 2

0.0

Output for the Sample Input 2

2

Sample Input 3

...

Output for the Sample Input 3

7

Sample Input 4

(1.1)

Output for the Sample Input 4

2

Sample Input 5

0-1.

Output for the Sample Input 5

-1

Solution in Scala (judge verdict: Accepted)

import scala.annotation.tailrec
import scala.collection.mutable

object Main extends App {
  import scala.io.StdIn._
  val str = readLine.trim
  val count = str.count(_ == '.')
  if (count == 0) {
    str match{
      case Expression(e) ⇒ println(e)
      case _ ⇒ println(-1)
    }
  }else {
    println((0 until count).foldLeft(List(str)){case (l, _) ⇒ List("0","1","+","-","*","(",")").flatMap{c ⇒ l.map{_.replaceFirst("\\.", c)}}}.collect{
      case Expression(e) ⇒ e
    } match {
      case e if e.nonEmpty ⇒ e.max
      case _ ⇒ -1
    })
  }
}
object Expression {
  def unapply(arg: String): Option[Int] = {
    arg.toList match {
      case f Formula Nil ⇒ f.value
      case _ ⇒ None
    }
  }
  object Number {
    def unapply(arg: List[Char]): Option[(Term, List[Char])] = {
      arg.span(_.isDigit) match {
        case (Nil, _) ⇒ None
        case (n, rest) ⇒ Some(new Number(n.foldLeft(0){case (acc, d) ⇒ acc * 2 + d.asDigit}), rest)
      }
    }
  }
  object Factor{
    def unapply(arg: List[Char]): Option[(Term, List[Char])] = {
      arg match {
        case n Number rest ⇒ Some(n, rest)
        case '('::(t Formula ')'::r) if t.count > 1 ⇒ Some(Bracket(t), r)
        case _ ⇒ None
      }
    }
  }
  object Formula {
    def unapply(arg: List[Char]): Option[(Term, List[Char])] = {
      arg match {
        case left Term rest ⇒ Some(takeAll(rest, left))
        case _ ⇒ None
      }
    }
    @tailrec private[this] def takeAll(arg: List[Char], left: Term): (Term, List[Char]) = {
      arg match {
        case '+'::(right Term rest) ⇒ takeAll(rest, new Add(left, right))
        case '-'::(right Term rest) ⇒ takeAll(rest, new Sub(left, right))
        case _ ⇒ (left, arg)
      }
    }
  }
  object Term {
    def unapply(arg: List[Char]): Option[(Term, List[Char])] = {
      arg match {
        case f Factor rest ⇒ Some(takeAll(rest, f))
        case _ ⇒ None
      }
    }
    @tailrec private[this] def takeAll(arg: List[Char], left: Term): (Term, List[Char]) = {
      arg match {
        case '*'::(right Factor rest) ⇒ takeAll(rest, new HighPriority(left, right))
        case _ ⇒ (left, arg)
      }
    }
  }
  sealed trait Term {
    def count: Int
    def value: Option[Int]
  }
  sealed trait BiOp extends Term
  class HighPriority(left: Term, right: Term) extends BiOp {
    override val count: Int = left.count + right.count
    override val value: Option[Int] = left.value.flatMap(a ⇒ right.value.map(a * _)).filter(v ⇒ 0 <= v && v < 1024)
  }
  class Add(left: Term, right: Term) extends BiOp {
    override val count: Int = left.count + right.count
    override val value: Option[Int] = left.value.map(a ⇒ a.+(_: Int)).flatMap(right.value.map).filter(v ⇒ 0 <= v && v < 1024)
  }
  class Sub(left: Term, right: Term) extends BiOp {
    override val count: Int = left.count + right.count
    override val value: Option[Int] = left.value.map(a ⇒ a.-(_: Int)).flatMap(right.value.map).filter(v ⇒ 0 <= v && v < 1024)
  }
  case class Bracket(term: Term) extends Term {
    override def count: Int = 1
    override def value: Option[Int] = term.value
  }
  class Number(v: Int) extends Term {
    override def count: Int = 1
    override def value: Option[Int] = Some(v).filter(v ⇒ 0 <= v && v < 1024)
  }
}