1

数字の代わりに単語を使って基本的な計算をするプログラムを開発しています。たとえば、5+2は7を出力します。

プログラムはより複雑になり、two_hundred_one + five_thousand_six(201 + 5006)などの入力を受け取ります。

演算子のオーバーロードメソッドを使用して、各数値を分割し、それを独自の配列インデックスに割り当てます。

2つは[0]、100は[1]、1つは[2]になります。次に、アレイは5006でリサイクルされます。

私の問題は、実際の計算を実行するために、配列に格納されている単語を実際の整数に変換する必要があることです。

私は単語のライブラリとしてこのようなconst文字列配列を持っています:

const string units[] = { "", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };

const string teens[] = { "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };

const string tens[] = { "", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" };

'token'配列がインデックス0、1、および2に21を格納している場合、これらをintに変換するための最良の方法が何であるかわかりません。

4

2 に答える 2

2

私にとっての秘訣の一部は、トークンを順方向ではなく逆方向に解析することでした。また、トークンをさかのぼってスケールファクターを維持するため。トークンごとに、遭遇するトークンに応じて、現在の値(scalefactorの現在の値でスケーリング)に追加するか、scalefactorを調整します。

これが私の実装です(一部のビットは含まれていません。数百万を処理するには、小さなロジックを追加する必要があります)。

#include <vector>
#include <string>

#include <assert.h>

int tokens_to_int( const std::vector<std::string> &s )
{
  int scale = 1;
  int rv=0;
  for(
      std::vector<std::string>::const_reverse_iterator it = s.rbegin();
      it!=s.rend();
      ++it
     )
  {
    std::string cw = *it;
    //Things that add to the current value
    if( cw == "one" )   { rv += 1 * scale; }
    if( cw == "two" )   { rv += 2 * scale; }
    if( cw == "three" ) { rv += 3 * scale; }
    if( cw == "four" )  { rv += 4 * scale; }
    // ...
    if( cw == "nine" )   { rv += 9 * scale; }
    if( cw == "ten" )    { rv += 10 * scale; }

    // Teens
    if( cw == "eleven" )  { rv += 11 * scale; }
    if( cw == "twelve" )  { rv += 12 * scale; }
    // ...
    if( cw == "nineteen" )  { rv += 19 * scale; }

    // Multiples of 10
    if( cw == "twenty" )    { rv += 20 * scale; }
    if( cw == "thirty" )    { rv += 30 * scale; }
    if( cw == "fourty" )    { rv += 40 * scale; }
    // ...
    if( cw == "ninety" )    { rv += 90 * scale; }

    //Things that effect scale for following entries
    if( cw == "hundred" ) { scale *= 100; }
    if( cw == "thousand" ) { if( scale==100) { scale=1000; } else { scale*=1000; } }
  }

  return rv;
}

template<typename T>
struct as_vec
{
  as_vec<T>& operator()(const T & t )
  {
    v.push_back(t);
    return *this;
  }

  std::vector<T> build() { return v; }

  std::vector<T> v;
};

int main()
{
  assert(421 == tokens_to_int( as_vec<std::string>()("four")("hundred")("twenty")("one").build() ) );
  assert(422 == tokens_to_int( as_vec<std::string>()("four")("hundred")("twenty")("two").build() ) );
  assert(11000 == tokens_to_int( as_vec<std::string>()("eleven")("thousand").build() ) );
  assert(21201 == tokens_to_int( as_vec<std::string>()("twenty")("one")("thousand")("two")("hundred")("one").build() ) );
  assert(100001 == tokens_to_int( as_vec<std::string>()("one")("hundred")("thousand")("one").build() ) );
  assert(101000 == tokens_to_int( as_vec<std::string>()("one")("hundred")("one")("thousand").build() ) );
  assert(411201 == tokens_to_int( as_vec<std::string>()("four")("hundred")("eleven")("thousand")("two")("hundred")("one").build() ) );
  assert(999999 == tokens_to_int( as_vec<std::string>()("nine")("hundred")("ninety")("nine")("thousand")("nine")("hundred")("ninety")("nine").build() ) );
}
于 2012-04-10T06:27:47.367 に答える
0

マップを使用して値を配列にマップすることについてJesseに同意します。その時点から、次のようなことができるようになります。

mymap["two"] * mymap["hundred"] + mymap["one"] 

もちろん、「五百二千五十七」のような場合には注意する必要があります。その場合、十代の若者以外の特別な場合をチェックする必要があります。

const string temp[] = {"five","hundred","two","thousand","fifty","seven"};

int handleThree(int start)  {
    if( mymap[temp[start+ 3]] > 100) //check for special case, in which case you handle 4 words instead of three
       return (myap[temp[start]] * mymap[temp[start+1]] + mymap[temp[start+2]]) * mymap[temp[start+3]];
    else
       return mymap[temp[start]] * mymap[temp[start+1]] + handleTwo(start+2)
}

int handleTwo(int start) {
    if(mymap[temp[start]] / 10 == 1) //check if it's a teen, return teen value
       return mymap[temp[start]]
    if(mymap[temp[start+1]] > 90) //check for another special case, "five thousand one hundred and fifty seven", for example should use this case
       return mymap[temp[start]] * mymap[temp[start+1]]
    else
       return mymap[temp[start]] + mymap[temp[start+1]];
}

もちろん、注意しなければならないケースもいくつかありますが(たとえば、「5,622,13」)、そのようなケースに対処するために、楽しみと学習の経験を盗むことになりますが、私はこれを信じていますあなたが始めるのに十分なはずです。

また、私はC ++が得意ではないので、コードに問題があった場合はお詫びしますが、テストの結果、これは私が書いたメインループで機能しました(必要に応じて提供しますが、私はそれを考えています)自分でそれを書くことはあなたに利益をもたらすでしょう)

于 2012-04-10T05:24:26.583 に答える