力試しにナベアツのような判定をするプログラムを作ろうとしたところ、問題が発生しました。

3の倍数や5の倍数は考えるまでもないんですが、3のつく数字をどう判定したらいいのかわかりません。
どのように判定させればよいのでしょうか?

回答の条件
  • 1人2回まで
  • 登録:
  • 終了:2008/04/15 01:25:02
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答20件)

id:ksh No.1

回答回数315ベストアンサー獲得回数9

ポイント13pt

Ruby だと数値を to_s で文字列にできるので、そこで正規表現で 3 を含むかをチェックすればよいですね。

以下 ruby 1.8.6 (2007-06-07 patchlevel 36) [i386-mswin32] で確認したコードです。

#!/bin/env ruby

for i in 1..40
	printf( "%d ", i )
	if i.to_s =~ /3/ || i % 3 == 0
		printf( "aho" )
	end
	if i % 5 == 0
		printf( "wan" )
	end
	printf( "\n" )
end

C だと

   sprintf (str, "%d", num);

で文字列化して

   if( NULL != strchr( str, '3')) {
      /* 3を含む */
   }

でしょうか。(手元にコンパイル環境がないので、こちらは試してません)

id:Tomato-360

ソースコードつきの回答ありがとうございます。

Rubyには便利な機能がついてるんですね。

やはり文字列かしないと判定できないんでしょうか。

試してみます。

2008/04/08 21:00:12
id:wanderinpenguin No.2

回答回数167ベストアンサー獲得回数8

ポイント13pt

数字を何に格納するかによってくるでしょうが。

・3の倍数は、3で割ってあまりが0

・3の付く数は、1、10、100・・・と割っていって、あまり3になるかどうかの判断(割る数、この場合はforのループ数は、数値の型char,int,doubleなどによるでしょう、sizeof関数などと併用してもいいかもしれません)

で、よいと思います。

ほかにもやりかたはあると思いますが。

id:Tomato-360

割り算であまりが3になればいいですね。

こういう数学的問題になると勉強をしっかりとやっておけばよかったと思います。

ありがとうございます。

2008/04/08 21:02:16
id:BAZZ No.3

回答回数55ベストアンサー獲得回数0

ポイント13pt

判定対象の整数を x とする。

n = 0 TO 15 の範囲で

int(x / 10**n)を計算し 10以上なら n = n+1 として繰り上げてゆく。

 10 未満になったら、この値を y とする。( int : 少数点以下切捨ての意味)

 値 y は、n+1 桁目の 数字になるので、これに対して 3の倍数の判定をする。

 その後、対象の整数 x から y**n を引いて x とし、 n = n-1 にして再度

 int(x / 10**n) を求めるてゆけば、n=0 になるまで全ての桁について判定が可能。

id:Tomato-360

ありがとうございます。

少々難解ですけど、がんばりたいと思います。

2008/04/08 21:03:32
id:gekikawa No.4

回答回数110ベストアンサー獲得回数11

ポイント13pt

もう解答がでているでしょうが、数字自体を文字列として扱えばよいのでは?

PHPならば

if( ereg('.*3.*', $number){

  3がつく数字

}else{

  3はつかない数字

}

id:Tomato-360

やはり文字列ですね。

理想としては数学的な回答がほしいところです。

ありがとうございました。

2008/04/08 21:04:09
id:gon012 No.5

回答回数10ベストアンサー獲得回数0

ポイント13pt

正規表現をつかって処理をするのはどうでしょうか?

例:*3*

のような感じで

id:Tomato-360

まだ正規表現というものがよくわかっていないのでこれを機会に勉強したいと思います。

ありがとうございました。

2008/04/08 21:04:40
id:Gay_Yahng No.6

回答回数724ベストアンサー獲得回数26

ポイント13pt

例えば351

100で割って小数点以下切捨てると3

351/3=3.51→3

351から100の位なくして10で割って小数点以下切捨てると5

(351-100×3)/10=5.1→5

351から100の位と10の位をなくして1

351-100×3-5×10=1

ようはそれぞれの位をとりだして3かどうか判断すればよい。

id:Tomato-360

位ごとに考えるという発想はなかったです。

ありがとうございます。

2008/04/08 21:06:25
id:YOSIZO No.7

回答回数64ベストアンサー獲得回数1

ポイント13pt

最近流行りの「世界のナベアツ問題」ですね。

実際にcodepadで実行して確認してみました。

http://codepad.org/Q2afL4IP

int main()
{
  for(int val=1; val<50; val++){
    int tmp = val;
    if( val%3 == 0 ) { printf("%d\n",val);
    } else if( val%5 == 0 ) { printf("%d\n",val);
    } else {
      while( tmp>0 ) {
        if( tmp%10 == 3 ) {
          printf("%d\n",val);
          break;
        }
        tmp /= 10;
      }
    }
  }
}
id:Tomato-360

whileを使って判定するんですね。

これは結構簡単な答えで面白いです。

ありがとうございました。

2008/04/08 21:08:50
id:rakka74 No.8

回答回数19ベストアンサー獲得回数1

ポイント13pt

プログラムとして簡単なのは数値を文字列に変換し、その文字列に3という文字が含まれるかどうかを調べる方法です。


それとは別に数値のままで3が含まれるかどうかを調べるのであれば、以下のような方法でできます。


12312に3が含まれるかどうか調べる場合


1桁目について、

12312/10=1231 ←小数点以下切り捨て

12312-1231*10=2 ←1桁目が2で3ではない


2桁目について、

1231/10=123 ←小数点以下切り捨て

1231-123*10=1 ←2桁目が1で3ではない


のように10で割る数値が10未満になるまで繰り返すことで調べることができます。

id:Tomato-360

これも面白い回答ですね。

3の判定一つとってもいろいろな回答があるのだと感心させられます。

ありがとうございました。

2008/04/08 21:10:12
id:AKI-NAMI No.9

回答回数11ベストアンサー獲得回数0

ポイント13pt

int型をstring型に変更して、文字検索して合致すれば「アホになる」でいいと思います。

id:Tomato-360

やはり文字列にするという方法はメジャーなようですね。

ありがとうございます。

2008/04/08 21:11:04
id:imo758 No.10

回答回数121ベストアンサー獲得回数19

ポイント13pt
perl -e "while(++$i < 100){print ((!($i % 3) or ((sprintf '%d', $i) =~ /3/)) ? 'nabe! ' : $i.' ');}"
id:Tomato-360

ソースコードだけなんですね。

ちょっと触ったことのない言語を使っているようなのでよくわからないです。

2008/04/09 00:07:41
id:knj4484 No.11

回答回数2ベストアンサー獲得回数0

ポイント12pt

ある数Nが3を含むかどうかは以下のforループで判定できます。ahoがtrueになるのが、その場合です。

bool aho = false;
for (int x = 1; x < N; x *= 10){
  if((N / x) % 10 == 3){
    aho = true; //アホ度を測りたい場合はaho++;などに変更
    break;
  }
}

この中のif文では、xが10のときは10の位、xが100のときは100の位…が3かどうかを判定します。

xは、forの繰り返しの設定で、1、10、100…になるので、全ての桁を判定してアホ度を測ってもいいのですが、

いくらアホとはいえ、途中でbreakした方が賢明でしょう。

完全なC++のコードは以下のとおりです。

#include <iostream>

int main(int argc, char** argv){
  long N = 0;
  while (true){
    ++N;
    bool aho = false;
    if (N % 3 == 0 || N % 5 == 0){
      aho = true;
    } else {
      for (int x = 1; x < N; x *= 10){
        if((N / x) % 10 == 3){
          aho = true;
          break;
        }
      }
    }
    if (aho == true) { std::cout << "(‘3‘)"; } // 阿呆になる
    std::cout << N << std::endl;
  }
  return 0;
}

本物のナベアツと違って無限に繰り返す(PCのスペックが許す限り)ので、

覚悟して実行してください。

ちなみに、インターネット業界大手某社の新卒採用の筆記試験で、これと似た問題が出ました。

id:Tomato-360

C++での回答ありがとうございます。

筆記試験でこのような問題が出るのですか。

プログラマーを目指すものとして、ちゃんと理解したいですね。

2008/04/11 01:50:15
id:garyo No.12

回答回数1782ベストアンサー獲得回数96

ポイント12pt

整数型の変数A,Bを用意

1.Aに調べる数を入れる

2.B=A-A/10*10

3.Bが3になれば「3を含む」→終了

4.A>=10ならA=A/10 2へ

5.「3を含まない」→終了

id:Tomato-360

どうしてこうなるのかが気になりますが、自分で実行して調べたいと思います。

ありがとうございました。

2008/04/11 01:51:30
id:mamamoto No.13

回答回数1ベストアンサー獲得回数0

ポイント12pt

アルゴリズムはすでにほかの方が書いてるのと同じですが

こういう問題は再帰が似合うと思うので書いてみました。


#include <stdio.h>

int f(int n){
    return n >= 3 && (n%10 == 3 || f(n/10));
}

int main(){
    int i;
    for (i = 0; i < 1000; i++){
        if (f(i)) printf("%d\n", i);
    }

    return 0;
}

id:Tomato-360

再帰は考えてませんでした。

自分の苦手な分野なので、これを機に勉強していきたいところです。

ありがとうございました。

2008/04/11 01:52:31
id:ore_de_work No.14

回答回数6ベストアンサー獲得回数1

ポイント12pt

http://codepad.org/oKdE0Xsq

itoa使いました('A`)

char *itoa( const int num ,char* buf, const int ignore )

{

const char table[] = "0123456789";

char *p = buf;

int tmp;

for(tmp=num;tmp>0;tmp /= 10) *p++;

*p='\0';

for(tmp=num;tmp>0;tmp /= 10) *--p=table[tmp%10];

return buf;

}

int main()

{

char buf[99];

int aho;

for(aho=1; aho<50; aho++){

if( aho%3==0 || aho%5==0 ||

strchr(itoa(aho,buf,10),'3')) printf("%d\n",aho);

}

return 0;

}

id:Tomato-360

ソースコードでの回答ありがとうございます。

できれば説明がほしかったのですが、自分への試練と思い勉強します。

2008/04/11 01:55:33
id:satoumizu No.15

回答回数2ベストアンサー獲得回数0

ポイント12pt

たぶん、INT型でやろうとすると型があふれてすぐバグッちゃう気がします。

id:Tomato-360

なるほど。

あまり大きな数でやろうと思っていないのでそういうことはおきないと思っていたのですが、可能性を考慮することにします。

2008/04/11 01:56:36
id:jagging No.16

回答回数11ベストアンサー獲得回数0

ポイント12pt

各位が3であれば良いわけですよね。

159784163とかでも、

10で割ったあまり・・・この場合3

であるため当てはまります。

で、あとは

193999とかでも、

193999→×

19399→×

1939→×

193→○

という風に、10で割って少数切捨て(整数型なら、勝手に少数切捨てしますよね)を繰り返せばよいです。

終わり。

id:Tomato-360

10で割り続けて一の位が3になればよいという発想ですね。

なるほど、ありがとうございました。

2008/04/11 01:57:57
id:ken33jp No.17

回答回数928ベストアンサー獲得回数13

ポイント12pt

VBならINSTR関数を使えばよいのでは。

http://www.kanaya440.com/contents/script/vbs/function/string/ins...

どの言語でも文字列処理の関数はあるような。

id:Tomato-360

文字列処理を使ってもよいのですが、なんとなく数学的に判定したいと思いました。

時には文字列で処理することもあるのでしょうから、文字列も勉強したいと思います。

ありがとうございました。

2008/04/12 01:54:06
id:kmachu No.18

回答回数1ベストアンサー獲得回数0

ポイント12pt

http://www.machu.jp/diary/20080402.html#p01

すでに類似の回答が出ているかもしれませんが、ちょうど一週間前に再帰を使って書きました。

文字列に変換せずに、10で割りながら下一桁を判定する方法です。

CとRubyで書いていますので、よかったら参考にしてください。

(ここに貼付けようと思ったのですが、preを使うと余計な改行が入ってうまくいきませんでした)

id:Tomato-360

再起を使うと面白そうですよね。

URL先のソースを参考にして勉強したいと思います。

ありがとうございました。

2008/04/12 01:56:13
id:katetyan No.19

回答回数9ベストアンサー獲得回数1

ポイント12pt

//ナベアツ

//「3の倍数と3の付く数字だけアホになり、5の倍数だけ犬っぽくなります」


#include <iostream>

using namespace std;


#define MAX_NUM (100)


// しもの位から一桁一桁順に

// 3であるかをチェックする

//

// <戻り値>

// true : 対象の数の中に3がある

// false : 対象の数の中に3がない

bool check_obtain_three(int num){

   do{

      if(num % 10 == 3){ //対象の桁が3

         return true;

      }else{

         num /= 10; //次の桁チェックの準備

      }

   }while(num != 0); //チェックする桁がなくなるまで繰り返す

   

   return false;

}


void print_aho(void){

   cout << "あほ~" << endl;

   return;

}


void print_wan(void){

   cout << "ワン!" << endl;

   return;

}


int main(){

   int num;


   for(num=1; num<=MAX_NUM; num++){

      cout << num << " : ";

   

      if(num % 3 == 0){ //3の倍数?

         print_aho();

      }else if(check_obtain_three(num) == true){ //3を含んでいる?

         print_aho();

      }else if(num % 5 == 0){ //5の倍数?

         print_wan();

      }else{ //上記のどれでもない

         cout << endl;

      }

   }


   return 0;

}


C++で作ってみました。多分あっていると思います。

該当部分は、check_obtain_three関数です。

(自分でコンパイルする時は全角空白3つ→タブに

して下さい)


各桁に特定のものが含まれているかというのは、

定番のアルゴリズムの一つだと思われます。

情報処理の試験か何かでみた記憶があります。


「mod 10で一の位をみて、10で割って・・」

(modというのは、剰余を求めるもので、C++だと%です。)

を繰り返す感じです。

id:Tomato-360

ソースコードでの回答ありがとうございます。

C++は勉強中なので参考にさせていただきます。

定番アルゴリズムということで、単純ながら難しいプログラムだと実感しました。

ありがとうございます。

2008/04/12 01:59:36
id:weboo No.20

回答回数1ベストアンサー獲得回数0

ポイント12pt

Google App Engine で話題の Pythonで書いてみました。

文字列として扱ってもよいのならば,1行で書けます。

(num % 3 == 0) or ('3' in `num`)

あくまでも数値として扱うということであれば,こんな感じでしょうか。

def include3(num):
    if num % 10 == 3:
        return True
    if num > 10:
        return include3(num / 10)
    return False

(num % 3 == 0) or include3(num)

実行例は,ブログに書きましたので,こちらも参考にしてください。

id:Tomato-360

最近話題のGoogleAppですね。

どのようなものか深く知りませんが、勉強して深く知りたいですね。

ありがとうございました。

2008/04/12 22:14:19

コメントはまだありません

この質問への反応(ブックマークコメント)

トラックバック

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません