challenge 文字列の均等分割

一行の文字列を指定した数の行にできるだけ文字数が均等になるように分割してください.
ただし,除算や剰余算を使わないで書いてみてください.

sample = "ゆめよりもはかなき世のなかをなげきわびつゝあかしくらすほどに四月十よひにもなりぬれば木のしたくらがりもてゆく"

divid 4 sample =>
 "ゆめよりもはかなき世のなかを"
 "なげきわびつゝあかしくらすほ"
 "どに四月十よひにもなりぬれ"
 "ば木のしたくらがりもてゆく"

divid 5 sample => 
 "ゆめよりもはかなき世の"
 "なかをなげきわびつゝあ"
 "かしくらすほどに四月十"
 "よひにもなりぬれば木の"
 "したくらがりもてゆく"

divid 6 sample => 
 "ゆめよりもはかなき"
 "世のなかをなげきわ"
 "びつゝあかしくらす"
 "ほどに四月十よひに"
 "もなりぬれば木のし"
 "たくらがりもてゆく"

この問題は、除算だけでははく算術演算とか、文字列の長さをstrlenの類いで測るとかをしなくても、多分書けるのではないかと思います。

Posted feedbacks - C++

strlen, 乗除算相当を抜きで、ということなので、 とりあえず null terminator を利用した素朴な方法でやってみました。

ブロックの長さを1から1ずつ増やしていって、あたえられた条件を満たすようになったら終わります。

divid(4, "ゆめよりもはかなき世のなかを") のケースだと、

"ゆ" "め" "よ" "りもはかなき世のなかを"  --> fail
"ゆめ" "より" "もは" "かなき世のなかを"  --> fail
"ゆめよ" "りもは" "かなき" "世のなかを"  --> fail
"ゆめより" "もはかな" "き世のな" "かを"  --> ok

て感じです。

 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
#include <iostream>
#include <vector>
#include <iterator>
#include <locale>

using namespace std;

vector<wstring> divid(uint size, const wchar_t* str, uint len) {
  vector<wstring> v;
  for ( int i = 0, n = 0; n < size; i += len, ++n ) {
    v.push_back(wstring(str, i, len));
  }
  return v;
}

vector<wstring> divid(uint size, const wchar_t* str) {
  for ( int len = 1; ; ++len ) {
    for ( int i = 0, n = 0; n < size; ++n ) {
      for ( int m = 0;  m <= len; ++i, ++m ) {
        if ( str[i] == L'\0' ) {
          return divid(size, str, len);
        }
      }
      --i;
    }
  }
  return vector<wstring>(1, L"FAIL");
}

int main() {
  locale::global(locale(""));
  const wchar_t* sample = L"ゆめよりもはかなき世のなかをなげきわびつゝあかしくらすほどに四月十よひにもなりぬれば木のしたくらがりもてゆく";
  vector<wstring> divided;
  divided = divid(4, sample);
  copy(divided.begin(), divided.end(), ostream_iterator<wstring, wchar_t>(wcout, L"\n"));
  divided = divid(5, sample);
  copy(divided.begin(), divided.end(), ostream_iterator<wstring, wchar_t>(wcout, L"\n"));
  divided = divid(6, sample);
  copy(divided.begin(), divided.end(), ostream_iterator<wstring, wchar_t>(wcout, L"\n"));
  return 0;
}

C++のまちがった例を書いてしまったので、書き直しました。

 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
#include <iostream>
#include <vector>
#include <iterator>
#include <locale>

using namespace std;

void divid(size_t size, const wchar_t* str) {
  vector<size_t> lengths(size);
  const wchar_t* p = str;
  for ( int i = 0; *p != L'\0'; ++p, ++i ) {
    if ( i == size )  i = 0;
    ++lengths[ i ];
  }

  vector<size_t>::const_iterator
    i = lengths.begin(),
    e = lengths.end();
  for ( ; i != e; ++i ) {
    wcout << wstring(str, *i) << endl;
    str += *i;
  }
}

int main() {
  locale::global(locale(""));
  const wchar_t* sample = L"ゆめよりもはかなき世のなかをなげきわびつゝ"
    "あかしくらすほどに四月十よひにもなりぬれば木のしたくらがりもてゆく";
  divid(4, sample);
  divid(5, sample);
  divid(6, sample);
  return 0;
}

Index

Feed

Other

Link

Pathtraq

loading...