ネタ元 → 中/はつね/あんどちん とこ。
ふつーに書いたらあんどちんのと大差なくなるだから
あんまし使われることのない valarray ちゅーので実装してみる。
戦略/戦術は以下のとおり:
1. ファイルを一行ずつまるっと読み出して配列に投げ込む。
2. 一番長い行(長さM)に合わせて各行のケツに空白を繋ぐ
これで全行同じ長さの文字列がN本並びます。
空白を#で表すと
"ABCD"
"EF##"
"GHI#"
みたいに(M=4,N=3)。
3. 全行を逆順に全部繋ぐ
"GHI#EF##ABCD"
↑こんなんができるよね。
これを valarray<char> にセットします。
4. スライスする。
valarray は X番目からY個をZおきにスライスした valarray を作ることができます。
0番目からN(=3)個をM(=4)おきにスライスすれば "GEA"
1番目からN(=3)個をM(=4)おきにスライスすれば "HFB"
2番目からN(=3)個をM(=4)おきにスライスすれば "I#C"
3番目からN(=3)個をM(=4)おきにスライスすれば "##D"
ほらできた♪
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <valarray>
#include <algorithm>
#include <numeric>
int main(int argc, char* argv[]) {
if(argc < 2) return 1;
std::ifstream ifs(argv[1]);
if ( !ifs.is_open() ) return 2;
std::vector<std::string> src;
std::string line;
std::string::size_type length = 0;
// 読み出してvectorにぶっこむ
while ( !std::getline(ifs, line).eof() ) {
src.push_back(line);
length = std::max(length, line.length());
}
// 長さを揃える
for ( int i = 0; i < src.size(); ++i ) {
src[i] += std::string(length-src[i].length(), ' ');
}
// 全行を逆順に繋いだ大きな文字列をvalarrayにセット
std::string whole = std::accumulate(src.rbegin(), src.rend(), std::string());
std::valarray<char> mtx(whole.c_str(),whole.size());
// スライスして表示
for ( int i = 0; i < length; ++i ) {
std::valarray<char> result = mtx[std::slice(i,src.size(),length)];
for ( int j = 0; j < result.size(); ++j ) std::cout << result[j];
std::cout << std::endl;
}
}