Language detail: Bash
Coverage: 50.76%
|
number of '+' ratings |
contribution for coverage |
Unsolved challenges
- 文字列で+を表示する (Nested Flatten)
- 年賀はがきの当せん番号 (Nested Flatten)
- 箱詰めパズルの判定 (Nested Flatten)
- 関数やメソッドのソースの平均行数 (Nested Flatten)
- コレクションの実装 (Nested Flatten)
codes
バイナリクロック
(Nested
Flatten)
xbmで出力すればHHMMSSを16進にして流し込むだけで済むはず、との発想から。
xbmでは左から右に描くので、ビット左右反転をすべきなのですが ImageMagickで横着しています。
1 2 3 4 5 6 7 8 9 10 | #!/bin/bash
date=`date '+%H %M %S'`
echo -e "#define b_width 6\n\
#define b_height 3\n\
static char b_bits[] = {\n\
"`printf '0x%X,' $date`"\n\
};" \
|display -flop -sample 120x240 -
|
6桁固定、時分秒。
{0,1}を並べることで2進数の列が得られます。
$ echo {0,1}{0,1}
00 01 10 11
あとは配列に入れれば10進→2進変換のできあがり。
1 2 3 4 5 | bins=({□,■}{□,■}{□,■}{□,■}{□,■}{□,■})
time=(`date "+%H %M %S"`)
for i in 0 1 2; do
echo ${bins[time[i]]}
done
|
もう少し短くしてみました。 Linuxのprintf(シェルビルトインのものと /usr/bin/printf)では フラグ文字 0と変換指定子 sを組み合わせても意図した結果が得ら れなかったので、 dで代用しました。そのため、bcの返す値の最上 位桁が 0にならないことに依存します。 # AIX 4.3.3.0, HP-UX B.11.00, Linux 2.4.2, SunOS 5.5.1で動作 # を確認。
1 | for t in `date '+%H %M %S'`; do printf '%06d\n' `echo "obase=2; $t" | bc` | tr '01' '.*'; done
|
しつこく強引な1liner
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | function toBIN { \
v=$1; \
s=""; \
while [ $v -gt 0 ];do \
let "x = v>>1"; \
let "b = v ^ x<<1"; \
s=$b$s; \
v=$x; \
done; \
echo $s; \
}; \
d=`date '+%H %M %S'`; \
c=" "; \
for V in `echo ${d}`;do \
V=`toBIN $V`; \
while [ ${#V} -lt 6 ];do \
V=${c}${V}; \
done; \
echo ${V}|sed s/0/□/g|sed s/1/■/g; \
c="0"; \
done;
|
16進数から10進数の変換
(Nested
Flatten)
最大の整数は実装依存ですが、私の64bitマシンでは2^63-1が最大です。
1 2 3 4 5 6 7 8 9 | h2i(){
local -i i
if [[ "$1" == 0x* ]]; then
i="$1"
else
i=16#"$1"
fi
echo $i
}
|
手作業Grep
(Nested
Flatten)
1 2 3 4 5 6 | #!/bin/sh
file=$(mktemp /tmp/handgrep.XXXXXXXXXX)
trap "rm -f $file" EXIT
cat > $file
(${EDITOR:-vi} $file < /dev/tty > /dev/tty)
cat $file
|
複素数
(Nested
Flatten)
calc(apcalc)で。
see: Calc - C-style arbitrary precision calculator
1 2 3 4 5 6 7 8 9 10 | $ calc '( 3 + 1i ) + ( 4 - 1i )'
7
$ calc '( 5 - 9i ) - ( 2 + 6i )'
3-15i
$ calc '( 5 + 3i ) * ( 5 + 8i )'
1+55i
$ calc '( 9 - 7i ) / ( 9 - 3i )'
~1.13333333333333333333-0.4i
$ calc 'abs( 2 + 3i )'
3.60555127546398929312
|
割り算の筆算
(Nested
Flatten)
$ wari 12345 67
184
------
67)12345
67
------
564
536
------
285
268
------
17
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 | function wari() {
local -i m=$1
local -i n=$2
local r=$(printf '%*d' ${#m} $((m / n)))
write_head $m $n "$r"
write_body $m $n "$r"
}
function write_head() {
local m=$1
local n=$2
local r=$3
repeat_char ' ' $((${#n} + 1))
echo "$r"
write_bar $m $n
echo "$n)$m"
}
function write_body() {
local m=$1
local n=$2
local r=$3
local rest flag i
for ((i = 0; i < ${#r}; i++)) {
local c=${r:i:1}
rest="$rest${m:i:1}"
if [[ "$c" == [1-9] ]]; then
[ -n "$flag" ] && printf '%*d\n' $((i + ${#n} + 2)) $rest
printf '%*d\n' $((i + ${#n} + 2)) $((c * n))
write_bar $m $n
rest=$((rest - (c * n)))
flag=1
fi
}
[ -z "$flag" ] && write_bar $m $n
printf '%*d\n' $((i + ${#n} + 1)) $rest
}
function write_bar() {
local m=$1
local n=$2
repeat_char ' ' ${#n}
repeat_char - $((${#m} + 1))
echo
}
function repeat_char() {
local c=$1
local n=$2
while ((n--)); do
echo -n "$c"
done
}
|
例外処理
(Nested
Flatten)
以下の2要素を組み合わせました。 - エラーが起きた時点で実行を中断 → set -e - それ(とシグナル)を捕捉 → trap、サブシェル $ sh q245.sh beginning of program begenning of foo begenning of bar Catch! end of program
see: 例外処理 - Wikipedia
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #!/bin/sh
bar() {
echo 'begenning of bar'
[ 1 = 2 ] # raise error
echo 'end of bar'
}
foo() ( # () runs subshell
echo 'begenning of foo'
# catch
set -e
trap 'echo "Catch!"' EXIT
bar
echo 'end of foo'
)
echo 'beginning of program'
foo
echo 'end of program'
|
ACLの制御
(Nested
Flatten)
お題のタイトルに則って、POSIX ACLを設定します。
Linux 2.6 (POSIX ACL対応) + ext3 FS (mountオプションにaclを指定) で動作確認しました。
see: Linuxカーネル2.6で実現するACL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #!/bin/sh
filename=$1
if [ -e "$filename" ]; then
if [ -f "$filename" ]; then
chmod 600 "$filename"
setfacl -b "$filename"
setfacl -n -m u:$USER:rw "$filename"
else
echo "$filename is not file" 1>&2
exit 1
fi
else
tmpdir=$(umask 077; mktemp -d acl.XXXXXXXX)
(umask 077; touch "$tmpdir/$filename")
setfacl -n -m u:$USER:rw "$tmpdir/$filename"
mv "$tmpdir/$filename" .
rmdir $tmpdir
fi
|
ファイルサイズの取得
(Nested
Flatten)
stat(1)で。
1 2 3 4 5 | # GNU coreutils(Linux等)の場合
[ -f hoge.txt ] && stat -c %s hoge.txt
# FreeBSD系(Mac OS Xを含む)の場合
[ -f hoge.txt ] && stat -f %z hoge.txt
|
ローテートシフト
(Nested
Flatten)
tsekineさん、ナイスです。
ということでマージしてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | printf -v minus_one_in_hex %x -1
typeset -i sizeof_long="${#minus_one_in_hex} * 4"
unset minus_one_in_hex
function rotR() {
local i=$1
local w=$2
echo $((i >> w & ~(-1 << sizeof_long - w) | i << 64 - w))
}
function rotL() {
local i=$1
local w=$2
echo $((i >> sizeof_long - w & ~(-1 << w) | i << w))
}
|
キッチンタイマー
(Nested
Flatten)
1 2 | function timer { t=$1; while [ $t -gt 0 ]; do echo $t; t=`expr $t - 1`; sleep 1; clear; done; printf '\a'; }
timer 10
|
単にコマンドラインの次の行で、テキスト表示でカウントダウンするだけです。
キー操作:
- SPC: 一時停止/再開
- h、l: カーソルを左右(分・秒)に移動
- k、j: カーソル位置の値(分・秒)を1つ増減
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 | #!/bin/bash
function dsp_time() {
local t=$1
echo -ne '\r'
printf '%02.02d:%02d' $((t / 60)) $((t % 60))
echo -ne '\r'
[ "$cur_mode" = SEC ] && tput cuf 3
}
function timer_up() {
if [ "$cur_mode" = MIN ]; then
((t_end += 60))
else
((t_end += 1))
fi
}
function timer_down() {
if [ "$cur_mode" = MIN ]; then
(((t_end - SECONDS - offset >= 60) && (t_end -= 60)))
else
(((t_end - SECONDS - offset >= 1) && (t_end -= 1)))
fi
}
function key_command() {
case "$c" in
'h') cur_mode=MIN ;;
'l') cur_mode=SEC ;;
'k') timer_up ;;
'j') timer_down ;;
'') ((run_mode = run_mode == 1 ? 0 : 1)) ;;
esac
}
trap 'stty cbreak echo' EXIT
stty -cbreak -echo
tm=420 # 7 min
run_mode=1
cur_mode=MIN
offset=$SECONDS
t_end=$((offset + tm))
while ((tm > 0)); do
dsp_time $tm
read -n 1 -t 1 c && key_command "$c"
if [ $run_mode = 1 ]; then
((tm = t_end - SECONDS - offset))
else
((offset = t_end - tm - SECONDS))
fi
done
dsp_time 0
echo
echo -ne '\a'
|
ローテートシフト
(Nested
Flatten)
long の bit 数は -1 の hex 表現から簡単に得られますよ。
1 2 | local minus_one_in_hex=$(printf %x -1)
local -i sizeof_long="${#minus_one_in_hex} * 4"
|
整数(Cのlong)が64bitである前提です。 $ rotR 300 2 75 $ rotR -2 4 -1152921504606846977 $ rotL 300 4 4800 $ rotL -2 4 -17
1 2 3 4 5 6 7 8 9 10 11 | function rotR() {
local i=$1
local w=$2
echo $((i >> w & ~(-1 << 64 - w) | i << 64 - w))
}
function rotL() {
local i=$1
local w=$2
echo $((i >> 64 - w & ~(-1 << w) | i << w))
}
|
17歳教
(Nested
Flatten)
たぶんGNU coreutilsのdate専用。
「何か月」の解釈は、date依存です。
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 | #!/bin/bash
bd=$1
nw=$(date +%s)
d=$(date -d "$bd 17 years" +%s)
m=-1
while ((d < nw)); do
((m++))
ld=$d
d=$(date -d "$(date -d @$d +%Y-%m-%d) 1 month" +%s)
done
echo -n '17歳と'
echo -n "$mか月と"
echo "$(((nw - ld) / 86400))日"
masaka@ubuntu01:seventeen% jobs ~/work/doukaku/seventeen
masaka@ubuntu01:seventeen% cat 17.sh ~/work/doukaku/seventeen
#!/bin/bash
bd=$1
nw=$(date +%s)
d=$(date -d "$bd 17 years" +%s)
m=0
while ((d < nw)); do
((m++))
ld=$d
d=$(date -d "$(date -d @$d +%Y-%m-%d) 1 month" +%s)
done
echo -n '17歳と'
echo -n "$((m - 1)か月と"
echo "$(((nw - ld) / 86400))日"
|
ナベアツ算
(Nested
Flatten)
next >>
「アホになる」を縦ゆれ、「人探し」を横ゆれで表現してみました。
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 | #!/bin/bash
function AhoNiNaru() {
local -i i
for ((i = 0; i < 80; i++)) {
tput indn 3
tput rin 3
}
}
function HitoSagashi() {
local n=$1
local -i i
for ((i = 0; i < 70; i++)) {
tput el1
echo -n $n
}
echo
}
function NabeAtzz() {
local -i n=$1
tput clear
tput cud 3
local -i i
for ((i = 1; i <= n; i++)) {
if ((i % 8 == 0)); then
HitoSagashi $i
else
echo $i
fi
if ((i % 3 == 0)) || [[ $i == *3* ]]; then
AhoNiNaru
fi
sleep 1
}
}
NabeAtzz 100
|





?せんたくいた #9531() [ Bash ] Rating0/0=0.00
Rating0/0=0.00-0+
[ reply ]