はじめに
@gin_135 さんの「Project Eulerをシェル芸で解いてみる」シリーズが大変面白いです.
大抵は @gin_135 さんの Qiita 投稿, @eban さんの別解 on ブログ, @MasWag さんの別解 on Twitter を楽しく読ませていただき, 読んだだけで分からないものは, 手元で再現などして楽しんでいますが, 方針として大きく異なる別解を思いついたものについて, 自分のエントリを立てようと思います.
「Project Euler」の解説, 問題文の引用などは省略します.
本エントリは Problem 6 (問題原文, 問題文日本語訳) の解答です.
環境は
$ /bin/sh --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)
Copyright (C) 2007 Free Software Foundation, Inc.
です.
方針
本題は,
『数列に対して「和算」を「畳み込ん」で「二乗」したもの』から,『数列に対して「二乗」を「写像」したものを「和算」で「畳み込ん」だもの』を引けば良いです.
写像スクリプトと左畳み込みスクリプトを用意して解答します.
写像って何? という方は「写像 in シェル」をご覧ください.
畳み込みって何? という方は「左畳み込み in シェル」をご覧ください
九つのプログラミング言語で, 同じ方針でこの問題を解く例が「Ntmux を用いたマルチリンガル開発」にあります.
写像
#!/bin/sh
f=$1
while read line
do
set "$line"
echo `eval $f`
done
を map
として保存し, PATH に含まれるディレクトリに保存 (または保存したディレクトリを PATH に追加), 実行パーミションを与えてあるとします.
解説は「写像 in シェル」にあります.
解説にあるように, 写像は, スクリプトを用意しなくても xargs
でも実現できます.
左畳み込み
#!/bin/sh
f=$1
i=$2
if [ "X$i" = "X" ]
then
read i
fi
while read line
do
set "$i" "$line"
i=`eval $f`
done
echo $i
を reduce
として保存し, PATH に含まれるディレクトリに保存 (または保存したディレクトリを PATH に追加), 実行パーミションを与えてあるとします.
解説は「左畳み込み in シェル」にあります.
例題解答
1 から 10 までの自然数について, 二乗の和は 385 です.
$ seq 10 | map 'expr $1 \* $1' | reduce 'expr $1 + $2'
385
map
の代わりに xargs
を用いて
$ seq 10 | xargs -n 1 sh -c 'expr $0 \* $0' | reduce 'expr $1 + $2'
385
としても構いません.
1 から 10 までの自然数について, 和の二乗は 3025 です.
$ seq 10 | reduce 'expr $1 + $2' | xargs -I{} expr {} \* {}
3025
後者から前者を引くと 2640 です.
$ expr `seq 10 | reduce 'expr $1 + $2' | xargs -I{} expr {} \* {}` \
> - `seq 10 | map 'expr $1 \* $1' | reduce 'expr $1 + $2'`
2640
(>
は継続行入力のプロンプトです)
map
の代わりに xargs
を用いる場合は
$ expr `seq 10 | reduce 'expr $1 + $2' | xargs -I{} expr {} \* {}` \
> - `seq 10 | xargs -n 1 sh -c 'expr $0 \* $0' | reduce 'expr $1 + $2'`
2640
のようになります.
本題解答
本題, 1 から 100 までの自然数について, 和の二乗から二乗の和を引いたものは
$ expr `seq 100 | reduce 'expr $1 + $2' | xargs -I{} expr {} \* {}` \
> - `seq 100 | map 'expr $1 \* $1' | reduce 'expr $1 + $2'`
で求められます.
map
の代わりに xargs
を用いる場合は
$ expr `seq 100 | reduce 'expr $1 + $2' | xargs -I{} expr {} \* {}` \
> - `seq 100 | xargs -n 1 sh -c 'expr $0 \* $0' | reduce 'expr $1 + $2'`
とします.
参考
@gin_135 さんの解答「Project Eulerをシェル芸で解いてみる(Problem 6)」およびコメント欄
@eban さんの解答「Project Euler Problem 6 #シェル芸 - jarp」