import scala.
util.
parsing.
combinator.
_
def expr
= chainl1
(term, parseIffImp
) ; def parseIffImp
= "<=>" ^^^
{Iff
} |
"=>" ^^^
{Imp
} def term
= chainl1
(factor, parseAndOr
) ; def parseAndOr
= "/\\" ^^^
{And
} |
"\\/" ^^^
{Or
} def factor
: Parser
[Expr
] = "~" ~
> factor ^^
{Not
} | primary
def primary
= "#T" ^^^
{Const
(true)} |
"#F" ^^^
{Const
(false)} | ident ^^
{Atom
} |
"(" ~
> expr
<~
")" }
def toStr
(expr
: Expr, p
: Int, r
: Int
): String
= {
def par
(p0
: Int, s
: String
) = if (p
> p0 ||
(p
== p0
&& r
== 1)) s
else ""
case Atom
(name
) => name
case Not
(e
) => "~" + toStr
(e,
3,r
) case And
(e1, e2
) => par
(2,
"(") + toStr
(e1,
2,
0) +
"/\\" + toStr
(e2,
2,
1) + par
(2,
")") case Or
(e1, e2
) => par
(2,
"(") + toStr
(e1,
2,
0) +
"\\/" + toStr
(e2,
2,
1) + par
(2,
")") case Imp
(e1, e2
) => par
(1,
"(") + toStr
(e1,
1,
0) +
"=>" + toStr
(e2,
1,
1) + par
(1,
")") case Iff
(e1, e2
) => par
(1,
"(") + toStr
(e1,
1,
0) +
"<=>" + toStr
(e2,
1,
1) + par
(1,
")") } }
def simplify
(expr
: Expr
): Expr
= {
def simplifyH
(expr
: Expr
) = expr
match {
case Not
(p
) => simplifyH
(Not
(simplify
(p
))) case And
(p, q
) => simplifyH
(And
(simplify
(p
), simplify
(q
))) case Or
(p, q
) => simplifyH
( Or
(simplify
(p
), simplify
(q
))) case Iff
(p, q
) => simplifyH
(Iff
(simplify
(p
), simplify
(q
))) case Imp
(p, q
) => simplifyH
(Imp
(simplify
(p
), simplify
(q
))) case e
=> e
} }
def nnf
(expr
: Expr
): Expr
= expr
match { case And
(p, q
) => And
(nnf
(p
), nnf
(q
)) case Or
(p, q
) => Or
(nnf
(p
), nnf
(q
)) case Imp
(p, q
) => Or
(nnf
(Not
(p
)), nnf
(q
)) case Iff
(p, q
) => Or
(And
(nnf
(p
), nnf
(q
)), And
(nnf
(Not
(p
)), nnf
(Not
(q
)))) case Not
(Not
(p
)) => nnf
(p
) case Not
(And
(p, q
)) => Or
(nnf
(Not
(p
)), nnf
(Not
(q
))) case Not
( Or
(p, q
)) => And
(nnf
(Not
(p
)), nnf
(Not
(q
))) case Not
(Imp
(p, q
)) => And
(nnf
(p
), nnf
(Not
(q
))) case Not
(Iff
(p, q
)) => Or
(And
(nnf
(p
), nnf
(Not
(q
))), And
(nnf
(Not
(p
)), nnf
(q
))) case e
=> e
}
def cnf
(expr
: Expr
): Expr
= {
def distr
(expr
: Expr
): Expr
= expr
match { case Or
(And
(p, q
), And
(r, s
)) => And
(And
(distr
(Or
(p, r
)), distr
(Or
(p, s
))),
And(distr(Or(q, r)), distr(Or(q, s))))
case Or
(p, And
(q, r
)) => And
(distr
(Or
(p, q
)), distr
(Or
(p, r
))) case Or
(And
(p, q
), r
) => And
(distr
(Or
(p, r
)), distr
(Or
(q, r
))) case e
=> e
}
case Or
(p, q
) => distr
(Or
(cnf
(p
), cnf
(q
))) case And
(p, q
) => And
(cnf
(p
), cnf
(q
)) case e
=> e
} }
def lcnf
(expr
: Expr
): List
[List
[Expr
]] = {
def lcnfH1
(list
: List
[Expr
], expr
: Expr
): List
[Expr
] = expr
match { case And
(p, q
) => list
::: lcnfH1
(List
(), p
) ::: lcnfH1
(List
(), q
) case e
=> e
:: list
} def lcnfH2
(list
: List
[Expr
])(expr
: Expr
): List
[Expr
] = expr
match { case Or
(p, q
) => list
::: lcnfH2
(List
())(p
) ::: lcnfH2
(List
())(q
) case e
=> e
:: list
}
lcnfH1(List(), expr) map lcnfH2(List())_
}
def resolution
(clist
: List
[List
[Expr
]]): Boolean
= {
def splitClause
(clause
: List
[Expr
]) = { val (pos, neg
) = clause partition
(isAtom
_) ; List
(pos, neg map
(removeNot
_)) } def isTrueClause
(clause
: List
[Expr
]) = { val List
(lits, nlits
) = splitClause
(clause
) ((lits map
((e
: Expr
) => nlits exists
( _ == e
))) :\
false)(_||
_) } def isLitTrueClause
(clause
: List
[Expr
]) = clause
match { def simplifyClause
(clause
: List
[Expr
]) = if (isTrueClause
(clause
)) List
(Const
(true)) else clause
def simplifyLcnf
(clist
: List
[List
[Expr
]]) = { (clist map (simplifyClause _)) remove (isLitTrueClause _) }
def s2l
[T
](set
: Set
[T
]) = set.
toList ; def l2s
[T
](list
: List
[T
]) = list.
toSet
def resolutionH2
(tp4
: (List
[Expr
], List
[List
[Expr
]], List
[List
[Expr
]], Boolean
), lit
: Expr
) = { val (c, cs, d, b
) = tp4
; if (d
== List
()) (c, cs, d, b
) else { val nlit
= negateLit
(lit
) ; val c1
= c diff List
(lit
) val cs1
= (cs filter
((c
: List
[Expr
]) => c exists
(_ == nlit
))) map
(_ diff List
(nlit
)) var d1
= cs1 map
(_ ::: c1
) ; val cs2h
= ((cs map l2s
) union
(d1 map l2s
)).
distinct val cs2
= (cs2h map s2l
) remove
(isTrueClause
_) ; d1
= cs2 diff cs
val b1
= if (d1.
isEmpty) false else (d1 exists
(_ == List
()) ) ; (c, cs2, d1, b1
) }
}
def resolutionH1
(c
: List
[Expr
], cs
: List
[List
[Expr
]], d
: List
[List
[Expr
]], b
: Boolean
): Boolean
= case (List
(), c
::cs, d, b
) => resolutionH1
(c, cs, d, b
) val (c1, cs1, d1, b1
) = ((c, cs, d ++ List
(List
(Atom
(""))), b
) /
: c
)(resolutionH2
) resolutionH1(List(), cs1, d1, b1) } }
case _ => resolutionH1
(List
(), simplifyLcnf
(clist
) map
((c
: List
[Expr
]) => s2l
(l2s
(c
))), List
(),
false) } }
def main
(args
: Array
[String
]) {
do { input
= readLine
() ; if (input
!= null && input
!= "") {
val output
= parseAll
(expr, input
) match { case Failure
(msg,
_) => "failure: " + msg
case Error
(msg,
_) => "error: " + msg
case Success
(parsed,
_) => { val nResRet
= resolution
(lcnf
(cnf
(simplify
(nnf
(simplify
(Not
(parsed
))))))) val pResRet
= resolution
(lcnf
(cnf
(simplify
(nnf
(simplify
(parsed
)))))) toStr(parsed, 0, 0) + "\n" +
(if (nResRet
) "true" else if (pResRet
) "false" else "it depends") }
}
println(output) }
}
}
aW1wb3J0IHNjYWxhLnV0aWwucGFyc2luZy5jb21iaW5hdG9yLl8KCmFic3RyYWN0IGNsYXNzIEV4cHIKY2FzZSBjbGFzcyBDb25zdCh2YWx1ZTogQm9vbGVhbikgZXh0ZW5kcyBFeHByCmNhc2UgY2xhc3MgQXRvbShuYW1lOiBTdHJpbmcpIGV4dGVuZHMgRXhwcgpjYXNlIGNsYXNzIE5vdChleHByOiBFeHByKSBleHRlbmRzIEV4cHIKY2FzZSBjbGFzcyBBbmQobGVmdDogRXhwciwgcmlnaHQ6IEV4cHIpIGV4dGVuZHMgRXhwcgpjYXNlIGNsYXNzICBPcihsZWZ0OiBFeHByLCByaWdodDogRXhwcikgZXh0ZW5kcyBFeHByCmNhc2UgY2xhc3MgSWZmKGxlZnQ6IEV4cHIsIHJpZ2h0OiBFeHByKSBleHRlbmRzIEV4cHIKY2FzZSBjbGFzcyBJbXAobGVmdDogRXhwciwgcmlnaHQ6IEV4cHIpIGV4dGVuZHMgRXhwcgogCmNsYXNzIE15UGFyc2VyIGV4dGVuZHMgSmF2YVRva2VuUGFyc2VycyB7CgogICAgZGVmIGV4cHIgPSBjaGFpbmwxKHRlcm0sIHBhcnNlSWZmSW1wKSA7IGRlZiBwYXJzZUlmZkltcCA9ICI8PT4iIF5eXiB7SWZmfSB8ICI9PiIgXl5eIHtJbXB9CiAgICBkZWYgdGVybSA9IGNoYWlubDEoZmFjdG9yLCBwYXJzZUFuZE9yKSA7IGRlZiBwYXJzZUFuZE9yID0gIi9cXCIgXl5eIHtBbmR9IHwgIlxcLyIgXl5eIHtPcn0KICAgIGRlZiBmYWN0b3I6IFBhcnNlcltFeHByXSA9ICJ+IiB+PiBmYWN0b3IgXl4ge05vdH0gfCBwcmltYXJ5IAogICAgZGVmIHByaW1hcnkgPSAiI1QiIF5eXiB7Q29uc3QodHJ1ZSl9IHwgIiNGIiBeXl4ge0NvbnN0KGZhbHNlKX0gfCBpZGVudCBeXiB7QXRvbX0gfCAiKCIgfj4gZXhwciA8fiAiKSIKfQoKb2JqZWN0IE1haW4gZXh0ZW5kcyBNeVBhcnNlciB7CgogICAgZGVmIHRvU3RyKGV4cHI6IEV4cHIsIHA6IEludCwgcjogSW50KTogU3RyaW5nID0gewogICAgCiAgICAgICAgZGVmIHBhcihwMDogSW50LCBzOiBTdHJpbmcpID0gaWYgKHAgPiBwMCB8fCAocCA9PSBwMCAmJiByID09IDEpKSBzIGVsc2UgIiIKICAgIAogICAgICAgIGV4cHIgbWF0Y2ggewogICAgICAgICAgICBjYXNlIENvbnN0KHRydWUpID0+ICIjdHJ1ZSIgY2FzZSBDb25zdChmYWxzZSkgPT4gIiNmYWxzZSIKICAgICAgICAgICAgY2FzZSBBdG9tKG5hbWUpID0+IG5hbWUgY2FzZSBOb3QoZSkgPT4gIn4iICsgdG9TdHIoZSwzLHIpCiAgICAgICAgICAgIGNhc2UgQW5kKGUxLCBlMikgPT4gcGFyKDIsIigiKSArIHRvU3RyKGUxLDIsMCkgKyAiL1xcIiArIHRvU3RyKGUyLDIsMSkgKyBwYXIoMiwiKSIpCiAgICAgICAgICAgIGNhc2UgIE9yKGUxLCBlMikgPT4gcGFyKDIsIigiKSArIHRvU3RyKGUxLDIsMCkgKyAiXFwvIiArIHRvU3RyKGUyLDIsMSkgKyBwYXIoMiwiKSIpCiAgICAgICAgICAgIGNhc2UgSW1wKGUxLCBlMikgPT4gcGFyKDEsIigiKSArIHRvU3RyKGUxLDEsMCkgKyAiPT4iICArIHRvU3RyKGUyLDEsMSkgKyBwYXIoMSwiKSIpCiAgICAgICAgICAgIGNhc2UgSWZmKGUxLCBlMikgPT4gcGFyKDEsIigiKSArIHRvU3RyKGUxLDEsMCkgKyAiPD0+IiArIHRvU3RyKGUyLDEsMSkgKyBwYXIoMSwiKSIpIH0KICAgIH0KCiAgICBkZWYgc2ltcGxpZnkoZXhwcjogRXhwcik6IEV4cHIgPSB7CiAgICAKICAgICAgICBkZWYgc2ltcGxpZnlIKGV4cHI6IEV4cHIpID0gZXhwciBtYXRjaCB7CiAgICAgICAgICAgIGNhc2UgTm90KCAgIENvbnN0KHRydWUpKSAgPT4gQ29uc3QoZmFsc2UpIGNhc2UgTm90KENvbnN0KGZhbHNlKSkgICAgPT4gQ29uc3QodHJ1ZSkKICAgICAgICAgICAgY2FzZSBBbmQocCwgQ29uc3QoZmFsc2UpKSA9PiBDb25zdChmYWxzZSkgY2FzZSBBbmQoQ29uc3QoZmFsc2UpLCBwKSA9PiBDb25zdChmYWxzZSkKICAgICAgICAgICAgY2FzZSBBbmQocCwgQ29uc3QodHJ1ZSkpICA9PiBwICAgICAgICAgICAgY2FzZSBBbmQoQ29uc3QodHJ1ZSksICBwKSA9PiBwCiAgICAgICAgICAgIGNhc2UgIE9yKHAsIENvbnN0KGZhbHNlKSkgPT4gcCAgICAgICAgICAgIGNhc2UgIE9yKENvbnN0KGZhbHNlKSwgcCkgPT4gcAogICAgICAgICAgICBjYXNlICBPcihwLCBDb25zdCh0cnVlKSkgID0+IENvbnN0KHRydWUpICBjYXNlICBPcihDb25zdCh0cnVlKSwgIHApID0+IENvbnN0KHRydWUpCiAgICAgICAgICAgIGNhc2UgSW1wKHAsIENvbnN0KHRydWUpKSAgPT4gQ29uc3QodHJ1ZSkgIGNhc2UgSW1wKENvbnN0KHRydWUpLCAgcCkgPT4gcAogICAgICAgICAgICBjYXNlIEltcChwLCBDb25zdChmYWxzZSkpID0+IE5vdChwKSAgICAgICBjYXNlIEltcChDb25zdChmYWxzZSksIHApID0+IENvbnN0KHRydWUpCiAgICAgICAgICAgIGNhc2UgSWZmKHAsIENvbnN0KHRydWUpKSAgPT4gcCAgICAgICAgICAgIGNhc2UgSWZmKENvbnN0KHRydWUpLCAgcCkgPT4gcAogICAgICAgICAgICBjYXNlIElmZihwLCBDb25zdChmYWxzZSkpID0+IE5vdChwKSAgICAgICBjYXNlIElmZihDb25zdChmYWxzZSksIHApID0+IE5vdChwKSAgICAgICAgICAgICAgICAKICAgICAgICAgICAgY2FzZSBOb3QoTm90KHApKSA9PiBwICAgICAgICAgICAgICAgICAgICAgY2FzZSBlID0+IGUgfQogICAgICAgIAogICAgICAgIGV4cHIgbWF0Y2ggewogICAgICAgICAgICBjYXNlIE5vdChwKSAgICA9PiBzaW1wbGlmeUgoTm90KHNpbXBsaWZ5KHApKSkKICAgICAgICAgICAgY2FzZSBBbmQocCwgcSkgPT4gc2ltcGxpZnlIKEFuZChzaW1wbGlmeShwKSwgc2ltcGxpZnkocSkpKQogICAgICAgICAgICBjYXNlICBPcihwLCBxKSA9PiBzaW1wbGlmeUgoIE9yKHNpbXBsaWZ5KHApLCBzaW1wbGlmeShxKSkpCiAgICAgICAgICAgIGNhc2UgSWZmKHAsIHEpID0+IHNpbXBsaWZ5SChJZmYoc2ltcGxpZnkocCksIHNpbXBsaWZ5KHEpKSkKICAgICAgICAgICAgY2FzZSBJbXAocCwgcSkgPT4gc2ltcGxpZnlIKEltcChzaW1wbGlmeShwKSwgc2ltcGxpZnkocSkpKSBjYXNlIGUgPT4gZSB9CiAgICB9CgogICAgZGVmIG5uZihleHByOiBFeHByKTogRXhwciA9IGV4cHIgbWF0Y2ggewogICAgICAgIGNhc2UgQW5kKHAsIHEpID0+IEFuZChubmYocCksIG5uZihxKSkgY2FzZSAgT3IocCwgcSkgPT4gIE9yKG5uZihwKSwgbm5mKHEpKQogICAgICAgIGNhc2UgSW1wKHAsIHEpID0+ICBPcihubmYoTm90KHApKSwgbm5mKHEpKQogICAgICAgIGNhc2UgSWZmKHAsIHEpID0+ICBPcihBbmQobm5mKHApLCBubmYocSkpLCBBbmQobm5mKE5vdChwKSksIG5uZihOb3QocSkpKSkKICAgICAgICBjYXNlIE5vdChOb3QocCkpID0+IG5uZihwKQogICAgICAgIGNhc2UgTm90KEFuZChwLCBxKSkgPT4gIE9yKG5uZihOb3QocCkpLCBubmYoTm90KHEpKSkKICAgICAgICBjYXNlIE5vdCggT3IocCwgcSkpID0+IEFuZChubmYoTm90KHApKSwgbm5mKE5vdChxKSkpCiAgICAgICAgY2FzZSBOb3QoSW1wKHAsIHEpKSA9PiBBbmQobm5mKHApLCBubmYoTm90KHEpKSkKICAgICAgICBjYXNlIE5vdChJZmYocCwgcSkpID0+ICBPcihBbmQobm5mKHApLCBubmYoTm90KHEpKSksIEFuZChubmYoTm90KHApKSwgbm5mKHEpKSkgY2FzZSBlID0+IGUgfQogICAgCiAgICBkZWYgY25mKGV4cHI6IEV4cHIpOiBFeHByID0gewogICAgCiAgICAgICAgZGVmIGRpc3RyKGV4cHI6IEV4cHIpOiBFeHByID0gZXhwciBtYXRjaCB7CiAgICAgICAgICAgIGNhc2UgT3IoQW5kKHAsIHEpLCBBbmQociwgcykpID0+IEFuZChBbmQoZGlzdHIoT3IocCwgcikpLCBkaXN0cihPcihwLCBzKSkpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFuZChkaXN0cihPcihxLCByKSksIGRpc3RyKE9yKHEsIHMpKSkpCiAgICAgICAgICAgIGNhc2UgT3IocCwgQW5kKHEsIHIpKSA9PiBBbmQoZGlzdHIoT3IocCwgcSkpLCBkaXN0cihPcihwLCByKSkpCiAgICAgICAgICAgIGNhc2UgT3IoQW5kKHAsIHEpLCByKSA9PiBBbmQoZGlzdHIoT3IocCwgcikpLCBkaXN0cihPcihxLCByKSkpIGNhc2UgZSA9PiBlIH0KCiAgICAgICAgZXhwciBtYXRjaCB7CiAgICAgICAgICAgIGNhc2UgIE9yKHAsIHEpID0+IGRpc3RyKE9yKGNuZihwKSwgY25mKHEpKSkgY2FzZSBBbmQocCwgcSkgPT4gQW5kKGNuZihwKSwgY25mKHEpKSBjYXNlIGUgPT4gZSB9CiAgICB9CgogICAgZGVmIGxjbmYoZXhwcjogRXhwcik6IExpc3RbTGlzdFtFeHByXV0gPSB7CiAgICAKICAgICAgICBkZWYgbGNuZkgxKGxpc3Q6IExpc3RbRXhwcl0sIGV4cHI6IEV4cHIpOiBMaXN0W0V4cHJdID0gZXhwciBtYXRjaCB7CiAgICAgICAgICAgIGNhc2UgQW5kKHAsIHEpID0+IGxpc3QgOjo6IGxjbmZIMShMaXN0KCksIHApIDo6OiBsY25mSDEoTGlzdCgpLCBxKSBjYXNlIGUgPT4gZSA6OiBsaXN0IH0KICAgICAgICBkZWYgbGNuZkgyKGxpc3Q6IExpc3RbRXhwcl0pKGV4cHI6IEV4cHIpOiBMaXN0W0V4cHJdID0gZXhwciBtYXRjaCB7CiAgICAgICAgICAgIGNhc2UgT3IocCwgcSkgPT4gbGlzdCA6OjogbGNuZkgyKExpc3QoKSkocCkgOjo6IGxjbmZIMihMaXN0KCkpKHEpIGNhc2UgZSA9PiBlIDo6IGxpc3QgfQoKICAgICAgICBsY25mSDEoTGlzdCgpLCBleHByKSBtYXAgbGNuZkgyKExpc3QoKSlfCiAgICB9CiAgICAKICAgIGRlZiByZXNvbHV0aW9uKGNsaXN0OiBMaXN0W0xpc3RbRXhwcl1dKTogQm9vbGVhbiA9IHsKICAgIAogICAgICAgIGRlZiBpc0F0b20oZXhwcjogRXhwcikgPSBleHByIG1hdGNoIHsgY2FzZSBBdG9tKF8pID0+IHRydWUgY2FzZSBfID0+IGZhbHNlIH0KICAgICAgICBkZWYgcmVtb3ZlTm90KGV4cHI6IEV4cHIpID0gZXhwciBtYXRjaCB7IGNhc2UgTm90KHApID0+IHAgCiAgICAgICAgICAgIGNhc2UgQ29uc3QoZmFsc2UpID0+IENvbnN0KHRydWUpIGNhc2UgQ29uc3QodHJ1ZSkgPT4gQ29uc3QoZmFsc2UpIH0KICAgICAgICBkZWYgc3BsaXRDbGF1c2UoY2xhdXNlOiBMaXN0W0V4cHJdKSA9IHsKICAgICAgICAgICAgdmFsIChwb3MsIG5lZykgPSBjbGF1c2UgcGFydGl0aW9uIChpc0F0b20gXykgOyBMaXN0KHBvcywgbmVnIG1hcCAocmVtb3ZlTm90IF8pKSB9CiAgICAgICAgZGVmIGlzVHJ1ZUNsYXVzZShjbGF1c2U6IExpc3RbRXhwcl0pID0geyB2YWwgTGlzdChsaXRzLCBubGl0cykgPSBzcGxpdENsYXVzZShjbGF1c2UpCiAgICAgICAgICAgICgobGl0cyBtYXAgKChlOiBFeHByKSA9PiBubGl0cyBleGlzdHMgKCBfID09IGUpKSkgOlwgZmFsc2UpKF98fF8pIH0KICAgICAgICBkZWYgaXNMaXRUcnVlQ2xhdXNlKGNsYXVzZTogTGlzdFtFeHByXSkgPSBjbGF1c2UgbWF0Y2ggewogICAgICAgICAgICBjYXNlIExpc3QoQ29uc3QodHJ1ZSkpID0+IHRydWUgY2FzZSBMaXN0KE5vdChDb25zdChmYWxzZSkpKSA9PiB0cnVlIGNhc2UgXyA9PiBmYWxzZSB9CiAgICAgICAgZGVmIHNpbXBsaWZ5Q2xhdXNlKGNsYXVzZTogTGlzdFtFeHByXSkgPSBpZiAoaXNUcnVlQ2xhdXNlKGNsYXVzZSkpIExpc3QoQ29uc3QodHJ1ZSkpIGVsc2UgY2xhdXNlCiAgICAgICAgZGVmIHNpbXBsaWZ5TGNuZihjbGlzdDogTGlzdFtMaXN0W0V4cHJdXSkgPSB7CiAgICAgICAgICAgIChjbGlzdCBtYXAgKHNpbXBsaWZ5Q2xhdXNlIF8pKSByZW1vdmUgKGlzTGl0VHJ1ZUNsYXVzZSBfKSB9CiAgICAgICAgZGVmIG5lZ2F0ZUxpdChlOiBFeHByKSA9IGUgbWF0Y2ggeyBjYXNlIE5vdChwKSA9PiBwIGNhc2UgcCA9PiBOb3QocCkgfQoKICAgICAgICBkZWYgczJsW1RdKHNldDogU2V0W1RdKSA9IHNldC50b0xpc3QgOyBkZWYgbDJzW1RdKGxpc3Q6IExpc3RbVF0pID0gbGlzdC50b1NldAogICAgICAgIAogICAgICAgIGRlZiByZXNvbHV0aW9uSDIodHA0OiAoTGlzdFtFeHByXSwgTGlzdFtMaXN0W0V4cHJdXSwgTGlzdFtMaXN0W0V4cHJdXSwgQm9vbGVhbiksIGxpdDogRXhwcikgPSB7CiAgICAgICAgICAgIHZhbCAoYywgY3MsIGQsIGIpID0gdHA0IDsgaWYgKGQgPT0gTGlzdCgpKSAoYywgY3MsIGQsIGIpIGVsc2UgewogICAgICAgICAgICAgICAgdmFsIG5saXQgPSBuZWdhdGVMaXQobGl0KSA7IHZhbCBjMSA9IGMgZGlmZiBMaXN0KGxpdCkKICAgICAgICAgICAgICAgIHZhbCBjczEgPSAoY3MgZmlsdGVyICgoYzogTGlzdFtFeHByXSkgPT4gYyBleGlzdHMgKF8gPT0gbmxpdCkpKSBtYXAgKF8gZGlmZiBMaXN0KG5saXQpKQogICAgICAgICAgICAgICAgdmFyIGQxID0gY3MxIG1hcCAoXyA6OjogYzEpIDsgdmFsIGNzMmggPSAoKGNzIG1hcCBsMnMpIHVuaW9uIChkMSBtYXAgbDJzKSkuZGlzdGluY3QKICAgICAgICAgICAgICAgIHZhbCBjczIgPSAoY3MyaCBtYXAgczJsKSByZW1vdmUgKGlzVHJ1ZUNsYXVzZSBfKSA7IGQxID0gY3MyIGRpZmYgY3MKICAgICAgICAgICAgICAgIHZhbCBiMSA9IGlmIChkMS5pc0VtcHR5KSBmYWxzZSBlbHNlIChkMSBleGlzdHMgKF8gPT0gTGlzdCgpKSApIDsgKGMsIGNzMiwgZDEsIGIxKSAKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICAKICAgICAgICBkZWYgcmVzb2x1dGlvbkgxKGM6IExpc3RbRXhwcl0sIGNzOiBMaXN0W0xpc3RbRXhwcl1dLCBkOiBMaXN0W0xpc3RbRXhwcl1dLCBiOiBCb29sZWFuKTogQm9vbGVhbiA9CiAgICAgICAgICAgIChjLCBjcywgZCwgYikgbWF0Y2ggewogICAgICAgICAgICAgICAgY2FzZSAoXywgTGlzdCgpLCBfLCBfKSA9PiBmYWxzZSBjYXNlIChfLCBfLCBfLCB0cnVlKSA9PiB0cnVlCiAgICAgICAgICAgICAgICBjYXNlIChMaXN0KCksIGM6OmNzLCBkLCBiKSA9PiByZXNvbHV0aW9uSDEoYywgY3MsIGQsIGIpCiAgICAgICAgICAgICAgICBjYXNlIChjLCBjcywgZCwgYikgPT4geyAKICAgICAgICAgICAgICAgICAgICB2YWwgKGMxLCBjczEsIGQxLCBiMSkgPSAoKGMsIGNzLCBkICsrIExpc3QoTGlzdChBdG9tKCIiKSkpLCBiKSAvOiBjKShyZXNvbHV0aW9uSDIpCiAgICAgICAgICAgICAgICAgICAgcmVzb2x1dGlvbkgxKExpc3QoKSwgY3MxLCBkMSwgYjEpIH0gfQogICAgCiAgICAgICAgY2xpc3QgbWF0Y2ggewogICAgICAgICAgICBjYXNlIExpc3QoQ29uc3QoZmFsc2UpOjpyZXN0KSA9PiB0cnVlIAogICAgICAgICAgICBjYXNlIF8gPT4gcmVzb2x1dGlvbkgxKExpc3QoKSwgc2ltcGxpZnlMY25mKGNsaXN0KSBtYXAgCiAgICAgICAgICAgICAgICAoKGM6IExpc3RbRXhwcl0pID0+IHMybChsMnMoYykpKSwgTGlzdCgpLCBmYWxzZSkgfSAgICAgICAgCiAgICB9CiAgICAKICAgIGRlZiBtYWluKGFyZ3M6IEFycmF5W1N0cmluZ10pIHsKIAogICAgICAgIHZhciBpbnB1dCA9ICIiCiAKICAgICAgICBkbyAgeyBpbnB1dCA9IHJlYWRMaW5lKCkgOyBpZiAoaW5wdXQgIT0gbnVsbCAmJiBpbnB1dCAhPSAiIikgewogICAgICAgICAgICAKICAgICAgICAgICAgdmFsIG91dHB1dCA9IHBhcnNlQWxsKGV4cHIsIGlucHV0KSBtYXRjaCB7CiAgICAgICAgICAgICAgICBjYXNlIEZhaWx1cmUobXNnLCBfKSA9PiAiZmFpbHVyZTogIiArIG1zZyBjYXNlIEVycm9yKG1zZywgXykgPT4gImVycm9yOiAiICsgbXNnCiAgICAgICAgICAgICAgICBjYXNlIFN1Y2Nlc3MocGFyc2VkLCBfKSA9PiB7CiAgICAgICAgICAgICAgICAgICAgdmFsIG5SZXNSZXQgPSByZXNvbHV0aW9uKGxjbmYoY25mKHNpbXBsaWZ5KG5uZihzaW1wbGlmeShOb3QocGFyc2VkKSkpKSkpKQogICAgICAgICAgICAgICAgICAgIHZhbCBwUmVzUmV0ID0gcmVzb2x1dGlvbihsY25mKGNuZihzaW1wbGlmeShubmYoc2ltcGxpZnkocGFyc2VkKSkpKSkpCiAgICAgICAgICAgICAgICAgICAgdG9TdHIocGFyc2VkLCAwLCAwKSArICJcbiIgKyAKICAgICAgICAgICAgICAgICAgICAgICAgKGlmIChuUmVzUmV0KSAidHJ1ZSIgZWxzZSBpZiAocFJlc1JldCkgImZhbHNlIiBlbHNlICJpdCBkZXBlbmRzIikKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICAKICAgICAgICAgICAgcHJpbnRsbihvdXRwdXQpIH0KICAgICAgICB9IHdoaWxlIChpbnB1dCAhPSBudWxsICYmIGlucHV0ICE9ICIiKQogICAgfQp9