labunix's blog

labunixのラボUnix

「LLまつりでシェル芸人をジェネレートしてきた」を参加していないのに解いてみた。

■「LLまつりでシェル芸人をジェネレートしてきた」を参加していないのに解いてみた。

 LLまつりでシェル芸人をジェネレートしてきた
 http://www.usptomo.com/PAGE=20130824LL

Q. 09までの数字で欠けているものは?

 4 3 5 9 8 2

■普通に解く。

$ echo "4 3 5 9 8 2 `seq 0 9`" | sed s/" "/"\n"/g | sort | uniq -c | \
  awk '($1==1){printf "%s ",$2}';echo
0 1 6 7 

■「cat - <(seq 0 9)」を使う。

$ echo "4 3 5 9 8 2" | cat - <(seq 0 9) | sed s/" "/"\n"/g | sort | uniq -c | \
  awk '($1==1){printf "%s ",$2}';echo
0 1 6 7 

■「uniq -u」を使う。

$ echo "4 3 5 9 8 2" | cat - <(seq 0 9) | sed s/" "/"\n"/g | sort | uniq -u | \
  xargs echo -n;echo
0 1 6 7

■第1問 文字の選別

 次の文字列について、濁点の文字、半濁点 の文字、その他の文字(記号含む)
 の数を数 えてください

   「どんどこどん、ぱらぱっぱ、ぴろぴろぴー、すっとこどっこい。」
   (注意:特に意味はない。)

■普通に解く。
 「半*濁点文字」の文字数を除外する手段をどうするかがポイント。
 「man nkf」で。

$ echo  "どんどこどん、ぱらぱっぱ、ぴろぴろ ぴー、 すっとこどっこい。" | \
  nkf -h2 | nkf -Z4 | \
  sed s/"."/"&\n"/g | grep -v "^\ *$" | sed s/"[^\|]"/"_"/g | \
  sort | uniq -c | \
  awk '{if($2=="_"){t1=$1;t2=$2}else{sum+=$1;print $1-0,$2}};END{print t1-sum,t2}'
4619 _

■第2問 横にcatする

$ echo "犬もおだてりゃ
論より
年寄りの
テキサス
" > A

$ echo "織田信長
暴力
トライアスロン
クローバーホールド" > B

■普通に解く。
 pasteのdelimitersのデフォルトはタブなので、
 ※「or条件の半角スペース」は何も変換していない。

$ paste A B | sed s/"[ \|\t]*"//g
犬もおだてりゃ織田信長
論より暴力
年寄りのトライアスロン
テキサスクローバーホールド

■第3問 小町算

 次のechoから始めて4つの数字の間に +  - *  /  の符号を入れ、
 100になる計算式をワンライナーで一つ作ってください

■普通に解く。
 単純で分かりやすい方が良いかと。。。

$ a=("+" "-" "*" "/"); \
  komachi=("56" "2" "8" "9"); \
  for l in 0 1 2 3;do \
    for m in 0 1 2 3;do \
      for n in 0 1 2 3;do \
        TMP="${komachi[0]}${a[$l]}${komachi[1]}${a[$m]}${komachi[2]}${a[$n]}${komachi[3]}";
        echo "$TMP" | bc | grep 100 &&  echo "$TMP" ; \
      done; \
    done; \
  done
100
56/2+8*9

■第4問 ネットから拝借

 http://ja.wikipedia.org/wiki/ISO_3166-1のページから、
  アイスランド IS
  アイルランド IE
  アゼルバイジャン AZ
  アフガニスタン AF
  ...
  のように、国名と2レターコードの対のリストを作りましょう。

■普通に解く。

$ wget -O - "http://ja.wikipedia.org/wiki/ISO_3166-1" 2>/dev/null | \
  grep "^<td><a href=\"\/wiki\/\|^<td>]<\/td>" | \
  sed s/".*title=\""//g | sed s/"\".*"//g | grep -v ^ISO | \
  sed s/"<[\/]*td>"//g | xargs echo -n | sed s/"[A-Z][A-Z] "/"&\n"/g | \
  head -10
アイスランド IS 
アイルランド IE 
アゼルバイジャン AZ 
アフガニスタン AF 
アメリカ合衆国 US 
アメリカ領ヴァージン諸島 VI 
アメリカ領サモア AS 
アラブ首長国連邦 AE 
アルジェリア DZ 
アルゼンチン AR 

■第5問 フィボナッチ数

 延々とフィボナッチ数を出力するワンライナーを記述してください。
 ただし桁数が増えてもなるべく正確に。

■普通に解くとアルゴリズムはほぼ同じになってしまうので。。。
 変数の数で制限する。

$ a=c=0;b=1;while [ ${#c} -le 180 ];do c=$(echo "$a $b" | awk '{printf "%d\n",$1+$2}');echo $a;a=$b;b=$c;done

■ちなみにbcでは正しく動作しないし、私の環境では「tr -d '\n\'」も正しく動作しない。
 そもそも変数の数を正しく数えることが出来ないので、大きな値にbcは使えない。

$ a=0;b=1;while [ ${#c} -le 180 ];do c=$(echo "$a+$b"| bc);echo $a;a=$b;b=$c;done | tail -1

41505733030349875599942168299716793497054143143751575205826222961703\ 65532539102850704189127531565307835180063787257025149050715550944101\ 1827371957348905671587089441714682258321

$ a=c=0;b=1;while [ ${#c} -le 180 ];do c=$(echo "$a $b" | awk '{printf "%d\n",$1+$2}');echo $a;a=$b;b=$c;done | tail -1
388037102540331516120526065982609117160101926935144389669649979075617821826131566907128761928648684594809159565293203564361097500965379400172351180100949172050028191608365234782208

■変数の長さの違いは19行もの違いとなって現れる。

$ a=c=0;b=1;while [ ${#c} -le 180 ];do c=$(echo "$a $b" | awk '{printf "%d\n",$1+$2}');echo $a;a=$b;b=$c;done | nl | tail -1 
   862	388037102540331516120526065982609117160101926935144389669649979075617821826131566907128761928648684594809159565293203564361097500965379400172351180100949172050028191608365234782208

$ a=c=0;b=1;while [ ${#c} -le 180 ];do c=$(echo "$a $b" | awk '{printf "%d\n",$1+$2}');echo $a;a=$b;b=$c;done | nl | grep 41505733
   843	41505733030349863206496271433517561063234720667388099882145877147635083216353640942689183525283694141585862308861328646295261200475793935731466128939883490530787279763356516352

$ echo "843 862" | awk '{print $2-$1}'
19

■第650音の取得

 以下の出力を得てください。
 (echo  あいうえお・・・以外で)
 あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをん

■Unicodeから普通に解く。

$ for n in `seq 12354 12435`;do  \
    echo -n "$n" | awk '{printf "%c\n",$1}' | \
    nkf -h2 | nkf -Z4 | sed s/"\|"//g | nkf -h1; \
  done | uniq | grep -v "\|\|\|\|\|\|\|\|\|\|\|\|" | xargs echo -n | tr -d ' ';echo
あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわをん

■ユニコード一覧表

 下のようなUnicodeとひらがな(U+3041「ぁ」〜   U+3094「ゔ」)の
 リストを作成してください。
  この問題もiconvを使います。

■iconvを何に使うのか良く分からなかった。。。
 16進数のseq版。 

$ for n in `seq 0x3041 0x3094`;do \
    echo "$n" | awk '{printf "U+%x %c\n",$1,$1}'; \
  done | awk '(NR<4)||(NR>80){print}'
U+3041 ぁ
U+3042 あ
U+3043 ぃ
U+3091 ゑ
U+3092 を
U+3093 ん
U+3094