# 漢字かななども使える(1 文字も可)バージョン
smm = function(str) {
str = gsub("[ \t]", "", str)
str = unlist(strsplit(str, ""))
if (grepl(str[1], "+-")) {
stop("Unary minus or plus is invalid.")
}
str = c(str, ".")
nChar = length(str)
operatorPosition = NULL
for (i in seq_len(nChar)) {
if (match(str[i], c("+", "-", "=", "."), 0) != 0) {
operatorPosition = c(operatorPosition, i)
}
}
nTerm = length(operatorPosition)
word = vector("list", nTerm)
op = rep("+", nTerm + 1)
start = 1
for (i in seq_len(nTerm)) {
position = operatorPosition[i]
word[[i]] = str[start:(position - 1)]
op[i + 1] = str[position]
start = position + 1
}
charSet = unique(unlist(word))
if (length(charSet) > 10) {
stop("Too many characters.")
}
library(e1071)
perm = t(e1071::permutations(10) - 1)
term = matrix(0, nTerm, ncol(perm))
nonZeroTop = rep(TRUE, ncol(perm))
for (i in seq_len(nTerm)) {
subscript = match(word[[i]], charSet)
term[i, ] = colSums(10^(length(subscript):1-1) * matrix(perm[subscript, ], ncol=ncol(perm)))
if (op[i] == "-") {
term[i, ] = -term[i, ]
}
nonZeroTop = nonZeroTop & perm[subscript[1], ] != 0
}
leftsideTerm = colSums(term[1:(nTerm - 1), ])
answerFlag = leftsideTerm == term[nTerm, ] & nonZeroTop
ans = unique(t(term[, answerFlag]))
if (nrow(ans) == 0) {
"No solution."
} else if (nrow(ans) == 1) {
op = op[-nTerm-1]
op[1] = ""
cat(gsub("--", "-", paste(op, ans, collapse="", sep="")))
} else {
ans
}
}
> smm("すももと+ももとは=ともだちだ")
9771+7713=17484
> smm("言葉たす+言葉たす言葉+言葉をたす=ふくめんざん")
6519+651965+65819=724303
> smm("ははの+ははは+ばあば+ちちの+ちちは=じいじ") # 自作
226+222+303+116+112=979