与えた条件を満たす候補
Posted feedbacks - awk
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | {
# and or not and --> x1&x2|!x3&x4
s = ""
cnt = 0
for (i=1; i<=NF; i++) {
op = $i
if (op ‾ /not/) {
s = s "!"
} else if (op ‾ /and/) {
s = s "x" ++cnt "&"
} else if (op ‾ /or/) {
s = s "x" ++cnt "|"
}
}
s = s "x" ++cnt
for (i=2^cnt-1; i>0; i--) {
expr = make_expr(s,i,x,cnt)
if (apply_expr(expr)) show(x,cnt)
}
}
function make_expr(s,n,x,digits, i)
{
for (i=digits; i>=1; i--) {
x[i] = n % 2
sub("x"i, x[i], s)
n = (n - x[i]) / 2
}
return s
}
function apply_expr(expr, n,tmp,i,result)
{
# not を先に処理
gsub(/!1/,"0", expr)
gsub(/!0/,"1", expr)
# これで and と or だけ考えればよくなる
n = split(expr,tmp,"")
result = tmp[1]
for (i=2; i<=n; i+=2) {
if (tmp[i] ‾ /&/)
result = result && tmp[i+1]
else
result = result || tmp[i+1]
}
return result
}
function show(x,cnt, i)
{
printf "("
for (i=1; i<=cnt; i++) {
printf("%s", x[i] == 1 ? "True" : "False")
if (i < cnt) printf ", "
}
printf ")¥n"
}
|
not だけの組合せが処理できないので改訂版。 % awk -f and-or-not-2.awk not (False) not not (True) not not not (False) not and not (False, False) not not and not (True, False) not or not (True, False) (False, True) (False, False)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | {
# and or not and --> x1&x2|!x3&x4
s = ""
cnt = 0
for (i=1; i<=NF; i++) {
op = $i
if (op ~ /not/) {
s = s "!"
} else if (op ~ /and/) {
s = s "x" ++cnt "&"
} else if (op ~ /or/) {
s = s "x" ++cnt "|"
}
}
s = s "x" ++cnt
# for (i=2^cnt-1; i>0; i--) {
for (i=2^cnt-1; i>=0; i--) { # i=0は (False,False,...,False)
expr = make_expr(s,i,x,cnt)
if (apply_expr(expr)) show(x,cnt)
}
}
function make_expr(s,n,x,digits, i)
{
for (i=digits; i>=1; i--) {
x[i] = n % 2
sub("x"i, x[i], s)
n = (n - x[i]) / 2
}
return s
}
function apply_expr(expr, n,tmp,i,result)
{
# not を先に処理
# gsub(/!1/,"0", expr)
# gsub(/!0/,"1", expr)
r = expr
gsub(/[^!]/,"",r) # expr の中の ! だけを抽出した文字列を得る
for (i=length(r); i>0; i--) {
gsub(r 1, (i + 1) % 2, expr)
gsub(r 0, i % 2, expr)
r = substr(r,2) # 1字短縮
}
# これで and と or だけ考えればよくなる
n = split(expr,tmp,"")
result = tmp[1]
for (i=2; i<=n; i+=2) {
if (tmp[i] ~ /&/)
result = result && tmp[i+1]
else
result = result || tmp[i+1]
}
return result
}
function show(x,cnt, i)
{
printf "("
for (i=1; i<=cnt; i++) {
printf("%s", x[i] == 1 ? "True" : "False")
if (i < cnt) printf ", "
}
printf ")\n"
}
|




にしお
#3399()
Rating0/0=0.00
元ネタの 充足可能性問題 - Wikipedia は、 同じリテラル(x1とかnot x2とか)が複数回出てくることを想定しているので、 今回の問題のようにそれぞれ別の変数でだと乗法標準形 - Wikipediaにした場合に、答えが…と色々悩みどころでした。
[ reply ]