Language detail: awk
Coverage: 36.55%
|
number of '+' ratings |
contribution for coverage |
Unsolved challenges
- 疑似並行処理 (Nested Flatten)
- '('と')'の対応 (Nested Flatten)
- 世界時計 (Nested Flatten)
- π (Nested Flatten)
- LL Golf Hole 9 - トラックバックを打つ (Nested Flatten)
codes
文字列の反転
(Nested
Flatten)
元の文字列は別のファイルに入れておき、下のスクリプトで各行をリバースして表示します。 …mawkでも普通にjlengthとか使えますね。対応していただいた方に感謝。
1 2 3 4 5 6 7 8 | >type reverse_str.awk
{print reverse_string($0)}
function reverse_string(target, str){
for (i = 1;i<=jlength(target);i++)
str = jsubstr(target,i,1) str
return str
}
|
漢数字で九九の表
(Nested
Flatten)
ベタなうえにダメな感じです。。。文字列の長さを数字代わりに使っています。
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 | BEGIN {
kanjis = "〇一二三四五六七八九"
for(i = "*"; i != "**********"; i = i "*") {
line = ""
for(j = "*"; j != "**********"; j = j "*") {
num = sprintf("%d", length(i "")*length(j ""))
while(length(num) < length("***")) {
num = " " num
}
line = line kanji(num)
}
print line
}
}
function kanji(s, result, i) {
result = ""
for(i = length(result "*"); i <= length(s); i++) {
c = substr(s, i, length("*"))
if(c == " ") {
result = result " "
continue
}
c++
result = result substr(kanjis, c, length("〇"))
}
return result
}
|
ごくごくベタに書きました。
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 | BEGIN {
kanjis[" "] = " "
kanjis["0"] = "〇"
kanjis["1"] = "一"
kanjis["2"] = "二"
kanjis["3"] = "三"
kanjis["4"] = "四"
kanjis["5"] = "五"
kanjis["6"] = "六"
kanjis["7"] = "七"
kanjis["8"] = "八"
kanjis["9"] = "九"
for(i = 1; i <= 9; i++) {
line = ""
for(j = 1; j <= 9; j++) {
line = line kanji(sprintf("%3d", i*j))
}
print line
}
}
function kanji(s, i) {
result = ""
for(i = 0; i < length(s); i++) {
result = result kanjis[substr(s, i + 1, 1)]
}
return result
}
|
LL Golf Hole 5 - 最上位の桁を数え上げる
(Nested
Flatten)
old awkです。 ほぼそのままC言語のコードになっちゃいました。
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!awk -f
{
max=$1
print 0
for(b=1;;b*=10) {
n=b
for(j=10;--j>0;n+=b) {
if(n>max) next
print n
}
}
}
|
LL Golf Hole 4 - 文章から単語の索引を作る
(Nested
Flatten)
awk -f word.awk gpl.txt
1 2 | {gsub(/[^a-zA-Z0-9]/, " ");for(i=1;i<=NF;i++)t[$i]=t[$i]":"NR}
END{for(k in t)print k t[k]}
|
gawk 一行野郎で。文章は標準入力、出力は標準出力です。
1 | gawk -F'\\W' '{ for (i=1; i<= NF; i++) { if ($i != ""){h[$i, NR] = NR; }}} END { for (k in h){split(k,s,SUBSEP);print s[1], h[k];}}'
|
コード中の文字の頻度分析
(Nested
Flatten)
出題者です。 こちらで用意していた回答は awk を使ったものでした。一応解説すると、組み込み変数FSを空にし、1行単位の文字毎に連想配列に格納しています。
1 2 3 4 5 6 7 8 9 | # 1文字版
BEGIN { FS="" }
{ for (i=1; i<=NF; i++) ht[$i]++}
END { for (c in ht) print ht[c],c }
# 3文字版
BEGIN { FS="" }
{ for (i=1; i<=NF-2; i++) { ht[$i$(i+1)$(i+2)]++}}
END { for (c in ht) print ht[c],c }
|
BFコンパイラー
(Nested
Flatten)
#3964-#3978を、optimize=2 を指定すると身も蓋もなく最適化を行うように改良(?)したもの。
- http://namazu.org/~takesako/ppencode/bpencode.html
- http://pc11.2ch.net/test/read.cgi/tech/1177988460/135
あたりのソースを通してみると面白いです。
% cat helloworld.bf
++++++++++[>+++++++>++++++++++>+++>+<<<<-]
>++.>+.+++++++..+++.>++.<<+++++++++++++++.
>.+++.------.--------.>+.>.
% awk -v optimize=1 -f bf2awk.awk < helloworld.bf
BEGIN {
ix = 0
st[ix] += 10
while (st[ix]) {
st[++ix] += 7
st[++ix] += 10
st[++ix] += 3
st[++ix]++
ix -= 4
st[ix]--
}
st[++ix] += 2
printf("%c", st[ix])
printf("%c", ++st[++ix])
st[ix] += 7
printf("%c", st[ix])
printf("%c", st[ix])
st[ix] += 3
printf("%c", st[ix])
st[++ix] += 2
printf("%c", st[ix])
ix -= 2
st[ix] += 15
printf("%c", st[ix])
printf("%c", st[++ix])
st[ix] += 3
printf("%c", st[ix])
st[ix] -= 6
printf("%c", st[ix])
st[ix] -= 8
printf("%c", st[ix])
printf("%c", ++st[++ix])
printf("%c", st[++ix])
}
% awk -v optimize=2 -f bf2awk.awk < helloworld.bf
BEGIN {
print "Hello World!"
}
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 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | #
# Brainf*ck to AWK compiler, written in AWK by naoya_t/
#
BEGIN {
inst_buf = ""
ix = 0
}
{
gsub(/#.*$/,""); # comment
gsub(/[^\[\]<>+\-.,]/,""); if (/^$/) next
inst_buf = inst_buf $0
}
END {
if (inst_buf ~ /,/) getchar_used = 1
# compile
if (optimize >= 1) reset_last()
output_buf = ""
indent = ""
print "BEGIN {"
indent_incr()
if (getchar_used) indent_print("read_buf = \"\"")
if (getchar_used || optimize < 2) indent_print("ix = 0")
diff_value[">"] = diff_value["+"] = 1
diff_value["<"] = diff_value["-"] = -1
incr_decr[">"] = incr_decr["+"] = "++"
incr_decr["<"] = incr_decr["-"] = "--"
N = split(inst_buf, ops, "")
eval(ops,1,N)
if (optimize >= 1) out_last()
flush_buf(0)
indent_decr()
indent_print("}")
if (getchar_used) output_getchar_funcs()
}
function eval(ops,begin,end, i,j,op,s,till)
{
for (i=begin; i<=end; i++) {
op = ops[i]
if (op ~ /[><]/) {
ix += diff_value[op] # emulation
if (optimize >= 1) {
if (last_inst == "ix") {
last_arg += diff_value[op]
} else {
out_last()
set_last("ix", diff_value[op])
}
} else {
if (getchar_used || optimize < 2) indent_print("ix" incr_decr[op])
}
} else if (op ~ /[+-]/) {
st[ix] += diff_value[op] # emulation
if (optimize >= 1) {
if (last_inst ~ /^st\[/) {
last_arg += diff_value[op]
} else {
s = set_incr_decr("st[ix]")
if (last_inst) out_last()
set_last(s, diff_value[op])
}
} else {
if (getchar_used || optimize < 2) indent_print("st[ix]" incr_decr[op])
}
} else if (op == ".") {
s = "printf(\"%c\", st[ix])"
if (optimize >= 1) {
s = set_incr_decr(s)
if (last_inst) out_last()
}
if (getchar_used || optimize < 2)
indent_print(s)
else
putchar(st[ix])
} else if (op == ",") {
s = "st[ix] = getchar()"
if (optimize >= 1) {
s = set_incr_decr(s)
if (last_inst) out_last()
}
indent_print(s)
} else if (op == "[") {
nest = 1
for (j=i+1; j<=N; j++) {
if (ops[j] == "[") nest++
if (ops[j] == "]") nest--
if (nest == 0) { till = j ; break }
}
while_loop(ops, i+1, till-1)
i = till
} else {
;
}
}
}
function while_loop(ops,begin,end, i,j,putchar_used)
{
putchar_used = 0
for (j=begin; j<=end; j++) if (ops[j] == ".") { putchar_used = 1; break }
if (getchar_used || optimize < 2) {
out_last()
indent_print("while (st[ix]) {")
indent_incr()
eval(ops,begin,end)
if (optimize >= 1) out_last()
indent_decr()
indent_print("}")
} else {
while (st[ix]) eval(ops,begin,end)
}
}
function putchar(ch)
{
if (ch == 10 || ch == 13) {
flush_buf(1)
} else {
output_buf = output_buf sprintf("%c", st[ix])
}
}
function flush_buf(cr)
{
if (output_buf) {
gsub(/\\/, "\\\\", output_buf)
if (cr)
indent_print("print \"" output_buf "\"")
else
indent_print("printf(\"%s\", \"" output_buf "\")")
output_buf = ""
}
}
function indent_incr()
{
indent = " " indent
}
function indent_decr()
{
indent = substr(indent, 3)
}
function indent_print(line)
{
print indent line
}
function set_last(inst,arg)
{
last_inst = inst
last_arg = arg
}
function reset_last()
{
last_inst = ""
last_arg = 0
}
function out_last( diff)
{
if (last_inst ~ /ix/) {
if (last_arg > 1)
diff = " += " last_arg
else if (last_arg == 1)
diff = "++"
else if (last_arg == 0)
diff = ""
else if (last_arg == -1)
diff = "--"
else if (last_arg < -1)
diff = " -= " (0 - last_arg)
if (diff && (getchar_used || optimize < 2)) indent_print(last_inst diff)
}
last_inst = ""
}
function set_incr_decr(s)
{
if (last_inst == "ix") {
if (last_arg == 1) { gsub(/ix/, "++ix", s); last_inst = "" }
else if (last_arg == -1) { gsub(/ix/, "--ix", s); last_inst = "" }
} else if (last_inst ~ /^st\[/ && s ~ /printf/) {
if (last_arg == 1) { gsub(/st\[ix\]/, "++" last_inst, s); last_inst = "" }
else if (last_arg == -1) { gsub(/st\[ix\]/, "--" last_inst, s); last_inst = "" }
}
return s
}
function output_getchar_funcs()
{
print "function getchar( ch)"
print "{"
print " if (read_buf ~ /^$/) {"
print " if (eof) return -1"
# print " if ((getline read_buf) < 1) { eof = 1; return -1 }"
print " if (getline != 1) { eof = 1; return -1 } ; read_buf = $0" # a2p
print " }"
print " ch = ord(substr(read_buf,1,1))"
print " read_buf = substr(read_buf,2)"
print " return ch"
print "}"
print "function ord(ch, ofs)"
print "{"
print " if (ch == \"\\t\") return 9"
print " if (ch == \"\\n\") return 13"
# print " ofs = index(\" !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\", ch)"
print " if (ch == \"@\") return 64" # a2p
print " ofs = index(\" !\\\"#$%&'()*+,-./0123456789:;<=>?.ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\", ch)" # a2p
print " return ofs ? 31 + ofs : 0"
print "}"
}
|
うう駄目だ、getchar() の定義が出力されないので、#3976の ,+[-.,+] をコンパイルしても動かない。 しかも getchar() が文字コードを返すようになってない。ord() を実装。 全面書き換え。 a2pをかましても動くように getline, index 回りを微調整。
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 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | BEGIN {
if (optimize) reset_last()
indent = ""
print "BEGIN {"
indent_incr()
indent_print("read_buf = \"\"")
indent_print("ix = 0")
}
{
gsub(/#.*$/,""); # comment
gsub(/[^\[\]<>+\-.,]/,""); if (/^$/) next
N = split($0, op, "")
for (i=1; i<=N; i++) {
if (op[i] == ">") {
if (optimize) {
if (last_inst == "ix") {
last_arg++
} else {
out_last()
set_last("ix", 1)
}
} else {
indent_print("ix++")
}
} else if (op[i] == "<") {
if (optimize) {
if (last_inst == "ix") {
last_arg--
} else {
out_last()
set_last("ix", -1)
}
} else {
indent_print("ix--")
}
} else if (op[i] == "+") {
if (optimize) {
if (last_inst ~ /^st\[/) {
last_arg++
} else {
s = set_incr_decr("st[ix]")
if (last_inst) out_last()
set_last(s, 1)
}
} else {
indent_print("st[ix]++")
}
} else if (op[i] == "-") {
if (optimize) {
if (last_inst ~ /^st\[/) {
last_arg--
} else {
s = set_incr_decr("st[ix]")
if (last_inst) out_last()
set_last(s, -1)
}
} else {
indent_print("st[ix]--")
}
} else if (op[i] == ".") {
if (optimize) {
s = set_incr_decr("printf(\"%c\", st[ix])")
if (last_inst) out_last()
indent_print(s)
} else {
indent_print("printf(\"%c\", st[ix])")
}
} else if (op[i] == ",") {
if (optimize) {
s = set_incr_decr("st[ix] = getchar()")
if (last_inst) out_last()
indent_print(s)
} else {
indent_print("st[ix] = getchar()")
}
} else if (op[i] == "[") {
if (optimize) {
s = set_incr_decr("while (st[ix]) {")
if (last_inst) out_last()
indent_print(s)
indent_incr()
} else {
indent_print("while (st[ix]) {")
indent_incr()
}
} else if (op[i] == "]") {
if (optimize) out_last()
indent_decr()
indent_print("}")
} else {
;
}
}
}
END {
if (optimize) out_last()
indent_decr()
indent_print("}")
print "function getchar( ch)"
print "{"
print " if (read_buf ~ /^$/) {"
print " if (eof) return -1"
# print " if ((getline read_buf) < 1) { eof = 1; return -1 }"
print " if (getline != 1) { eof = 1; return -1 }" # a2p
print " read_buf = $0" # a2p
print " }"
print " ch = ord(substr(read_buf,1,1))"
print " read_buf = substr(read_buf,2)"
print " return ch"
print "}"
print "function ord(ch, ofs)"
print "{"
print " if (ch == \"\\t\") return 9"
print " if (ch == \"\\n\") return 13"
# print " ofs = index(\" !\\\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\", ch)"
print " if (ch == \"@\") return 64" # a2p
print " ofs = index(\" !\\\"#$%&'()*+,-./0123456789:;<=>?.ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\", ch)" # a2p
print " return ofs ? 31 + ofs : 0"
print "}"
}
function indent_incr()
{
indent = " " indent
}
function indent_decr()
{
indent = substr(indent, 3)
}
function indent_print(line)
{
print indent line
}
function set_last(inst,arg)
{
last_inst = inst
last_arg = arg
}
function reset_last()
{
last_inst = ""
last_arg = 0
}
function out_last( diff)
{
if (last_inst ~ /ix/) {
if (last_arg > 1)
diff = " += " last_arg
else if (last_arg == 1)
diff = "++"
else if (last_arg == 0)
diff = ""
else if (last_arg == -1)
diff = "--"
else if (last_arg < -1)
diff = " -= " (0 - last_arg)
if (diff) indent_print(last_inst diff)
}
last_inst = ""
}
function set_incr_decr(s)
{
if (last_inst == "ix") {
if (last_arg == 1) { gsub(/ix/, "++ix", s); last_inst = "" }
else if (last_arg == -1) { gsub(/ix/, "--ix", s); last_inst = "" }
}
return s
}
|
オプティマイズ時に ++ix st[ix]++ st[ix]++ st[ix]++ が st[++ix]++ st[ix] += 2 となっていたのを st[++ix] += 3 のようにちゃんとまとめるように修正するパッチ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | --- bf2awk.awk.orig 2007-11-14 00:43:07.000000000 +0900
+++ bf2awk.awk 2007-11-14 01:55:50.000000000 +0900
@@ -38,7 +38,7 @@
}
} else if (op[i] == "+") {
if (optimize) {
- if (last_inst == "st[ix]") {
+ if (last_inst ~ /^st\[/) {
last_arg++
} else {
s = set_incr_decr("st[ix]")
@@ -50,7 +50,7 @@
}
} else if (op[i] == "-") {
if (optimize) {
- if (last_inst == "st[ix]") {
+ if (last_inst ~ /^st\[/) {
last_arg--
} else {
s = set_incr_decr("st[ix]")
|
optimize=1 の時に while(st[ix]) の直前に ix++ や ix-- が来ると while(st[++ix]) のように誤ったオプティマイズが行われるバグを修正
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | --- bf2awk.awk.orig 2007-11-14 00:43:07.000000000 +0900
+++ bf2awk.awk 2007-11-14 01:46:46.000000000 +0900
@@ -77,15 +77,9 @@
indent_print("st[ix] = getchar()")
}
} else if (op[i] == "[") {
- if (optimize) {
- s = set_incr_decr("while (st[ix]) {")
- if (last_inst) out_last()
- indent_print(s)
- indent_incr()
- } else {
- indent_print("while (st[ix]) {")
- indent_incr()
- }
+ if (optimize) out_last()
+ indent_print("while (st[ix]) {")
+ indent_incr()
} else if (op[i] == "]") {
if (optimize) out_last()
indent_decr()
|
久しぶりに投稿します。
-v optimize=1 とするとオプティマイズされます(笑
helloworld.bf:
++++++++++[>+++++++>++++++++++>+++>+<<<<-]
>++.>+.+++++++..+++.>++.<<+++++++++++++++.
>.+++.------.--------.>+.>.
% awk -f bf2awk.awk helloworld.bf > helloworld.awk
% awk -f helloworld.awk
Hello World!
helloworld.awk:
BEGIN {
ix = 0
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
while (st[ix]) {
ix++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
ix++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
ix++
st[ix]++
st[ix]++
st[ix]++
ix++
st[ix]++
ix--
ix--
ix--
ix--
st[ix]--
}
ix++
st[ix]++
st[ix]++
printf("%c", st[ix])
ix++
st[ix]++
printf("%c", st[ix])
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
printf("%c", st[ix])
printf("%c", st[ix])
st[ix]++
st[ix]++
st[ix]++
printf("%c", st[ix])
ix++
st[ix]++
st[ix]++
printf("%c", st[ix])
ix--
ix--
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
st[ix]++
printf("%c", st[ix])
ix++
printf("%c", st[ix])
st[ix]++
st[ix]++
st[ix]++
printf("%c", st[ix])
st[ix]--
st[ix]--
st[ix]--
st[ix]--
st[ix]--
st[ix]--
printf("%c", st[ix])
st[ix]--
st[ix]--
st[ix]--
st[ix]--
st[ix]--
st[ix]--
st[ix]--
st[ix]--
printf("%c", st[ix])
ix++
st[ix]++
printf("%c", st[ix])
ix++
printf("%c", st[ix])
}
% awk -v optimize=1 -f bf2awk.awk helloworld.bf > helloworld-optimized.awk
% awk -f helloworld-optimized.awk
Hello World!
helloworld-optimized.awk:
BEGIN {
ix = 0
st[ix] += 10
while (st[ix]) {
st[++ix]++
st[ix] += 6
st[++ix]++
st[ix] += 9
st[++ix]++
st[ix] += 2
st[++ix]++
ix -= 4
st[ix]--
}
st[++ix]++
st[ix]++
printf("%c", st[ix])
st[++ix]++
printf("%c", st[ix])
st[ix] += 7
printf("%c", st[ix])
printf("%c", st[ix])
st[ix] += 3
printf("%c", st[ix])
st[++ix]++
st[ix]++
printf("%c", st[ix])
ix -= 2
st[ix] += 15
printf("%c", st[ix])
printf("%c", st[++ix])
st[ix] += 3
printf("%c", st[ix])
st[ix] -= 6
printf("%c", st[ix])
st[ix] -= 8
printf("%c", st[ix])
st[++ix]++
printf("%c", st[ix])
printf("%c", st[++ix])
}
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 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | BEGIN {
read_buf = ""
if (optimize) reset_last()
indent = ""
indent_print("BEGIN {")
indent_incr()
indent_print("ix = 0")
}
{
gsub(/#.*$/,""); # comment
gsub(/[^\[\]<>+\-.,]/,""); if (/^$/) next
N = split($0, op, "")
for (i=1; i<=N; i++) {
if (op[i] == ">") {
if (optimize) {
if (last_inst == "ix") {
last_arg++
} else {
out_last()
set_last("ix", 1)
}
} else {
indent_print("ix++")
}
} else if (op[i] == "<") {
if (optimize) {
if (last_inst == "ix") {
last_arg--
} else {
out_last()
set_last("ix", -1)
}
} else {
indent_print("ix--")
}
} else if (op[i] == "+") {
if (optimize) {
if (last_inst == "st[ix]") {
last_arg++
} else {
s = set_incr_decr("st[ix]")
if (last_inst) out_last()
set_last(s, 1)
}
} else {
indent_print("st[ix]++")
}
} else if (op[i] == "-") {
if (optimize) {
if (last_inst == "st[ix]") {
last_arg--
} else {
s = set_incr_decr("st[ix]")
if (last_inst) out_last()
set_last(s, -1)
}
} else {
indent_print("st[ix]--")
}
} else if (op[i] == ".") {
if (optimize) {
s = set_incr_decr("printf(\"%c\", st[ix])")
if (last_inst) out_last()
indent_print(s)
} else {
indent_print("printf(\"%c\", st[ix])")
}
} else if (op[i] == ",") {
if (optimize) {
s = set_incr_decr("st[ix] = getchar()")
if (last_inst) out_last()
indent_print(s)
} else {
indent_print("st[ix] = getchar()")
}
} else if (op[i] == "[") {
if (optimize) {
s = set_incr_decr("while (st[ix]) {")
if (last_inst) out_last()
indent_print(s)
indent_incr()
} else {
indent_print("while (st[ix]) {")
indent_incr()
}
} else if (op[i] == "]") {
if (optimize) out_last()
indent_decr()
indent_print("}")
} else {
;
}
}
}
END {
if (optimize) out_last()
indent_decr()
indent_print("}")
}
function getchar( ch)
{
if (read_buf ~ /^$/) getline read_buf
ch = substr(read_buf,1,1)
read_buf = substr(read_buf,2)
return ch
}
function indent_incr()
{
indent = " " indent
}
function indent_decr()
{
indent = substr(indent, 3)
}
function indent_print(line)
{
print indent line
}
function set_last(inst,arg)
{
last_inst = inst
last_arg = arg
}
function reset_last()
{
last_inst = ""
last_arg = 0
}
function out_last( diff)
{
if (last_inst ~ /ix/) {
if (last_arg > 1)
diff = " += " last_arg
else if (last_arg == 1)
diff = "++"
else if (last_arg == 0)
diff = ""
else if (last_arg == -1)
diff = "--"
else if (last_arg < -1)
diff = " -= " (0 - last_arg)
if (diff) indent_print(last_inst diff)
}
last_inst = ""
}
function set_incr_decr(s)
{
if (last_inst == "ix") {
if (last_arg == 1) { gsub(/ix/, "++ix", s); last_inst = "" }
else if (last_arg == -1) { gsub(/ix/, "--ix", s); last_inst = "" }
}
return s
}
|
変形Fizz-Buzz問題
(Nested
Flatten)
ifは全部試行するので条件6もみたしているはず。
1 2 3 4 5 6 7 8 9 | BEGIN{
for (x=1;x<=20;x++) str[x]=x ":hoge";
for (x=1;x<=20;x++) {
if (x%3==0) str[x]=x ":Fizz";
if (x%5==0) str[x]=x ":Buzz";
if (x%15==0) str[x]=x ":FizzBuzz";
}
for (x=1;x<=20;x++) { print str[x] }
}
|
重複無し乱数
(Nested
Flatten)
1〜nの要素を持つベクトルを作り,端から順に無作為に並べ替えてゆく。 ランダムさはそれで十分だろう。 スクリプト中のnへ値を渡すのは -v n=5 のように > awk -f p3402.awk -v n=10 4 10 9 1 2 6 5 8 3 7 > awk -f p3402.awk -v n=10 4 10 9 1 2 6 5 8 3 7 > awk -f p3402.awk -v n=10 3 2 5 4 7 9 10 1 6 8
1 2 3 4 5 6 7 8 9 10 11 12 | BEGIN {
srand()
for (i = 1; i <= n; i++) x[i] = i
for (i = 1; i <= n; i++) {
j = int(rand()*n)+1
t = x[i]
x[i] = x[j]
x[j] = t
}
for (i = 1; i <= n; i++) printf " %i", x[i]
print ""
}
|
文字列の反転
(Nested
Flatten)
split が文字列を分解するのは gawk に限られると思われ。。。 gawk -f p3414.awk -v string="split string array fieldsep" pesdleif yarra gnirts tilps スクリプト中の変数 string への値の受け渡しはgawk コマンドの -v オプションで
1 2 3 4 5 | BEGIN {
n = split(string, a, "")
for (i = n; i >= 1; i--) printf "%s", a[i]
print "\n"
}
|
exp(pi * sqrt(n))が整数に近くなるnを探す
(Nested
Flatten)
やはり,awk も倍精度実数までしか使えないから 37 と 58 しか捕まえられないなあ awk -f p3416.awk 37 : 199148647.99997794628 58 : 24591257751.999965668
1 2 3 4 5 6 7 8 9 | BEGIN {
PI = atan2(1,1)*4
for (n = 1; n < 100; n++) {
x = exp(PI*sqrt(n))
if (abs(x-int(x+0.5)) < 0.0001) printf "%i : %.20g\n", n, x
}
}
function abs(x) { return x < 0 ? -x : x }
|
逆転したビット列
(Nested
Flatten)
スクリプト中の変数 n に値を送り込むのは,-v オプションで,以下のようにする awk -f p3417.awk -v n=3 0 4 2 6 1 5 3 7
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | BEGIN {
for (i = 0; i < 2^n; i++) {
print foo(n, i)
}
}
function foo(n, i, sum, j, x) {
sum = 0
for (j = 0; j < n; j++) {
x = i%2
i = int(i/2)
sum += x*2^(n-j-1)
}
return sum
}
|
格子点の列挙
(Nested
Flatten)
ソート部分は単純なものを採用。 今はR,昔は awk を使っていたもので,R のプログラムと同様。でも,R は遙かに楽だなあ。
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 | BEGIN {
n = 0
for (i = -18; i <= 18; i++) {
for (j = -18; j <= 18; j++) {
x[n] = i
y[n] = j
d[n++] = sqrt(i^2+j^2)
}
}
for (i = 0; i < n-1; i++) {
mini = d[i]
minp = i
for (j = i+1; j < n; j++) {
if (d[j] < mini) {
mini = d[j]
minp = j
}
}
if (i != minp) {
d[minp] = d[i]
d[i] = mini
t = x[i]
x[i] = x[minp]
x[minp] = t
t = y[i]
y[i] = y[minp]
y[minp] = t
}
}
printf "%4s %3s %3s %10s\n", "No.", "x", "y", "r"
for (i = 0; i < 1000; i++) {
printf "%4i: %3i %3i %10.6f\n", i+1, x[i], y[i], d[i]
}
}
|
水の移し替えパズル
(Nested
Flatten)
next >>
A<=B<=Cとしたとき、 ・AとBから、Aが空になるまで汲み続け、 ・BとCからAに汲み、AとBからCに汲む、を繰り返す と、できると思ったんですが、最短なのかどうかよくわかりません。 正解はどこかにあります?
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 | {
# A, B, C を cups[0], cups[1], cups[2] とする
cups[0] = $1
cups[1] = $2
cups[2] = $3
# A <= B <= C にそろえる
sort(cups)
total = 0
# A と B からとり、C に移す。A が空になるまで
count = cups[0]
cups[0] = 0
cups[1] -= count
cups[2] += count * 2
total += count
# B が空になるまで、以下を繰り返す。
# B と C から取って A に移し、A と B からとって C に移す。
count = cups[1]
cups[0] = count % 2
cups[1] -= count
cups[2] += count * 2
total += count
if(cups[0] != 0) {
print "N/A"
} else {
print "Total :", total
}
}
# 3要素に限定したソート
function sort(cups) {
if(cups[0] > cups[1]) {
swap(cups, 0, 1)
}
if(cups[0] > cups[2]) {
swap(cups, 0, 2)
}
if(cups[1] > cups[2]) {
swap(cups, 1, 2)
}
}
function swap(a, i, j, tmp) {
tmp = a[i]
a[i] = a[j]
a[j] = tmp
}
|





tonio_antonio #7933() [ awk ] Rating0/0=0.00
はじめまして。最初awk向きなのになぜ未投稿?と思ったのですが、ソートが必要なのですね。 教科書どおりのqsortですが、整数値をソートする、ということで17行目で +0 してから比較してみました。 #最初の投稿時、言語を指定しそこない、otherに投稿してしまいました。申し訳ありません。
>type data.txt ID Surname Forename Age 0 Suzuki Taro 19 1 Sato Hanako 18 11 Kato Junko 40 3 Yamammoto Shingo 46 >type tab_sort.awk BEGIN{FS="\t";OFS="\t"} NR == 1{ print $1,$3,$2,$4 } NR > 1{t=$2;$2=$3;$3=t;$4=$4+1;A[NR]=$0;} END{qsort(A,2,NR) for(i=2;i<=NR;i++) print A[i] } function qsort(A,left,right){ if(left>=right) return swap(A,left,left+int((right-left+1)*rand())) last=left for(i=left+1;i<=right;i++) #if(A[i] < A[left]) swap(A,++last,i) if(A[i] + 0 < A[left] + 0) swap(A,++last,i) swap(A,left,last) qsort(A,left,last-1) qsort(A,last+1,right) } function swap(A,i,j){ t=A[i];A[i]=A[j];A[j]=t } >mawk32 -f tab_sort.awk data.txt > kekka.txt >type kekka.txt ID Forename Surname Age 0 Taro Suzuki 20 1 Hanako Sato 19 3 Shingo Yamammoto 47 11 Junko Kato 41Rating0/0=0.00-0+
[ reply ]