LoginSignup
4
4

More than 5 years have passed since last update.

シェル芸 Project Euler - Problem 6

Posted at

はじめに

@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 を用いたマルチリンガル開発」にあります.

写像

map
#!/bin/sh

f=$1
while read line
do
  set "$line"
  echo `eval $f`
done

map として保存し, PATH に含まれるディレクトリに保存 (または保存したディレクトリを PATH に追加), 実行パーミションを与えてあるとします.

解説は「写像 in シェル」にあります.

解説にあるように, 写像は, スクリプトを用意しなくても xargs でも実現できます.

左畳み込み

reduce
#!/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

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4