Problem:
C: 短絡評価

問題

直大くんと北大くんはゲームをしています。
北大くんは、まず以下の BNF で表される論理式を生成します。

<formula> ::= <or-expr>
<or-expr> ::= <and-expr>
| <or-expr> "|" <and-expr>
<and-expr> ::= <term>
| <and-expr> "&" <term>
<term> ::= "(" <or-expr> ")" | "?"

& は論理積を、| は論理和を表し、& の方が | より先に評価されます。

直大くんは、この論理式を（文字列として見て）左から読んでいき、? を見つけたとき以下の行動をします。

その ? を 0 にしても 1 にしても論理式の評価結果が変わらないことが確定しているなら、何もせず読み進める。

そうでないなら、北大くんに 1 円払い、その ? を 0 または 1 に書き換える。

論理式は以下のように評価されます。いわゆる普通の論理式です。

(0 & ?) == 0
(1 & 0) == 0
(1 & 1) == 1
(0 | 0) == 0
(0 | 1) == 1
(1 | ?) == 1

直大くんが論理式の評価結果を確定させるために支払う必要がある最小金額はいくらでしょう？ 評価結果を 0 にする場合と 1 にする場合でそれぞれ求めてください。

入力形式

上の BNF に従う論理式が一行で与えられます。

制約

論理式の長さは 2\times 10^5 を超えない。

出力形式

評価結果を 0、1 にするために必要な最小金額を空白区切りで出力してください。

入力例1

?&?|?&?|?&?

出力例1

3 2

0 にしたい場合は 0 0 0 で書き換えて 0&?|0&?|0&? とし、
1 にしたい場合は 1 1 で書き換えて 1&1|?&?|?&? とするのが最適です。

入力例2

?&?&?|?&?&?

出力例2

2 3

それぞれ 0&?&?|0&?&?、1&1&1|?&?&? となります。

入力例3

(?|?|?)&?&?&?&?|?&?|?&?

出力例3

4 4

Solution in Scala (judge verdict: Accepted)

import scala.annotation.tailrec
import scala.io.StdIn._
object Main extends App {
  readLine.trim match {
    case Formula(f) ⇒
      println(s"${f.minCostToBeFalse} ${f.minCostToBeTrue}")
    case _ ⇒ ???
  }

  object Formula {
    def unapply(arg: String): Option[Formula] = {
      arg.toList match {
        case o OrExpression Nil ⇒ Some(o)
        case _ ⇒ None
      }
    }
  }
  object OrExpression {
    def unapply(arg: List[Char]): Option[(OrExpression, List[Char])] = {
      arg match {
        case a AndExpression r ⇒ Some(takeAll(r, List(a)))
        case _ ⇒ None
      }
    }

    private def apply(arg: List[AndExpression]): OrExpression = {
      val trues = arg.map(_.minCostToBeTrue)
      val falses = arg.map(_.minCostToBeFalse)
      val (trueCost, falseCost) = falses.zip(trues).foldLeft((Int.MaxValue, 0)){
        case ((current, left), (f, t)) ⇒ (math.min(left + t, current), left + f)
      }
      new Impl(trueCost, falseCost)
    }

    @tailrec private[this] def takeAll(arg: List[Char], expression: List[AndExpression]): (OrExpression, List[Char]) = {
      arg match {
        case '|' :: (o AndExpression r) ⇒ takeAll(r, o :: expression)
        case _ ⇒ (OrExpression(expression.reverse), arg)
      }
    }

    class Impl(override val minCostToBeTrue: Int,
               override val minCostToBeFalse: Int) extends OrExpression
  }
  object AndExpression {
    def unapply(arg: List[Char]): Option[(AndExpression, List[Char])] = {
      arg match {
        case a Term r ⇒ Some(takeAll(r, List(a)))
        case _ ⇒ None
      }
    }
    private def apply(arg: List[Term]): AndExpression = {
      val trues = arg.map(_.minCostToBeTrue)
      val falses = arg.map(_.minCostToBeFalse)
      val (falseCost, trueCost) = trues.zip(falses).foldLeft((Int.MaxValue, 0)){
        case ((current, left), (t, f)) ⇒ (math.min(left + f, current), left + t)
      }
      new Impl(trueCost, falseCost)
    }
    @tailrec private[this] def takeAll(arg: List[Char], expression: List[Term]): (AndExpression, List[Char]) = {
      arg match {
        case '&':: (a Term r) ⇒ takeAll(r, a::expression)
        case _ ⇒ (AndExpression(expression.reverse), arg)
      }
    }
    class Impl(override val minCostToBeTrue: Int,
               override val minCostToBeFalse: Int) extends AndExpression
  }
  object Term {
    def unapply(arg: List[Char]): Option[(Term, List[Char])] = {
      arg match {
        case '('::(o OrExpression ')'::t) ⇒ Some(WithPer(o), t)
        case '?'::t ⇒ Some(Undefined, t)
        case _ ⇒ None
      }
    }
  }
  sealed trait Formula {
    val minCostToBeTrue: Int
    val minCostToBeFalse: Int
  }
  sealed trait OrExpression extends Formula
  sealed trait AndExpression extends OrExpression
  sealed trait Term extends AndExpression
  case object Undefined extends Term {
    val minCostToBeTrue: Int = 1
    val minCostToBeFalse: Int = 1
  }
  case class WithPer(inner: Formula) extends Term {
    val minCostToBeTrue: Int = inner.minCostToBeTrue
    val minCostToBeFalse: Int = inner.minCostToBeFalse
  }
  implicit class Scope[T](val value: T) extends AnyVal {
    def let[A](@inline func: T ⇒ A): A = func(value)
    def also(@inline func: T ⇒ Unit): T = {func(value);value}
    def minOption[A](implicit ev: T ⇒ Iterable[A], ord: Ordering[A]): Option[A] = if (value.isEmpty) None else Some(value.min)
  }
}