• 締切済み

足し算の結果を求めるプログラム

はじめまして。 いま、int型の配列saが int sa[3][6]; として宣言されていて、その中身が sa[0][0] = 4; sa[0][1] = 1; sa[0][2] = 1; sa[0][3] = 5; sa[0][4] = 1; sa[0][5] = 3; sa[1][0] = 3; sa[1][1] = 1; sa[1][2] = 3; sa[1][3] = 1; sa[1][4] = 3; sa[1][5] = 1; sa[2][0] = 1; sa[2][1] = 5; sa[2][2] = 3; sa[2][3] = 1; sa[2][4] = 4; sa[2][5] = 1; となっているとき、この中身の足し算の結果が ちょうど9になる組み合わせを探したいのですが、 何かいいアルゴリズムはないのでしょうか? この中から、2つだけを足し合わせたときの結果ではなく、 3つや4つを足し合わせても9になるならば、 それも一つの結果としてカウントします。 下手な説明ですいません。回答お待ちしております。

みんなの回答

回答No.2

要素が正数という前提でいいんでしょうか? 再帰を使えばできますね。 今までとってきた合計が ・8以下ならば、もうひとつ値をとりにいく。 ・9ならば、成功。 ・10以上ならば、前にとってきたのを次の値にする。 最初の成功を見つけるまでの手順はこんな感じです。 (0,0) 4 (0,0),(0,1) 5 (0,0),(0,1),(0,2) 6 (0,0),(0,1),(0,2),(0,3) 11 失敗 (0,0),(0,1),(0,2),(0,4) 7 (0,0),(0,1),(0,2),(0,4),(0,5) 10 失敗 (0,0),(0,1),(0,2),(0,4),(1,0) 10 失敗 (0,0),(0,1),(0,2),(0,4),(1,1) 8 (0,0),(0,1),(0,2),(0,4),(1,1),(1,2) 11 失敗 (0,0),(0,1),(0,2),(0,4),(1,1),(1,3) 9 成功 プログラムにするとこんな感じです。 sa[i/6][i%6] として2次元配列を1次元配列っぽく扱ってます。 ************************************ #include <stdio.h> int sa[3][6] = { {4,1,1,5,1,3}, {3,1,3,1,3,1}, {1,5,3,1,4,1} }; int select[10]; /* 今までに選んだのはこれ */ void f(int start, int sum, int num) /* start - 次のは start 以降から選ぶ */ /* sum - 今までの合計は sum */ /* num - 今までに num 個選んだ */ { int i; /* 見つかった */ if(sum==9){ for(i=0;i<num;i++) printf("sa[%d][%d] ", select[i]/6, select[i]%6); printf("\n"); return; } /* おおきすぎた */ if(sum>9) return; /* まだ足りないから、つぎのを選ぶ */ for(i=start;i<3*6;i++){ select[num] = i; f(i+1, sum+sa[i/6][i%6], num+1); } return; } int main(int argc, char **argv) { /* 初期値は全部0 */ f(0, 0, 0); return 0; } ************************************

  • hamanyan
  • ベストアンサー率50% (2/4)
回答No.1

私の意見としては、全パターンを検索して答えを求めるしか無いと 思います。 つまり、sa[0][0]+sa[0][1] から sa[2][4]+sa[2][5]までの 足し算を順にやって、答えが9となるパターンを探します。 次に、sa[0][0]+sa[0][1] + sa[0][2] から順に計算して・・・ といった感じでしょうか? int の配列が巨大な場合は、パフォーマンスが悪くなるのが欠点 です。

関連するQ&A

  • C言語でcharの足し算

    char型の配列の中から数を取り出して足し算させたいです。 この配列には数字だけではなく英数字のどちらかが入るので、intではなくchar型の配列を作りました。 scanf("%c", &i); と、scan文をループさせてchar i[3]の中身を{1,1,a}と入れたとします。 このとき、i[0]+i[1]とやると、中の文字コード(?)を足してしまって98という結果が出てきてしまいます。 かといって、 scan("%d", &i);とやると、数字を入れているときはいいのですが英字を入れると「フ」という文字になってしまいます。 上手い具合に数字はコードじゃなく数字として、英字は英字のまま1つの配列の中に入れられないものでしょうか。 宜しくお願いします。

  • エクセル・解がある数字になるように足し算する数字を選ぶ方法

    いくつかの数字が並んでいて、その中から選んで足し算をします。 その足し算の答えがある範囲内に当てはまるような組み合わせを全部求めたいと思います。 分かりにくいので具体例を書きます。 0.5 1.1 1.8 2.3 3.8 4.2 上記の6個の数字からいくつか選んで足した結果が4.9~5.9になる組み合わせをすべて求めたいです。 この場合、 0.5+1.1+1.8+2.3=5.7 1.1+1.8+2.3=5.2 4.2+0.5=4.7 4.2+1.1=5.3 4.2+1.1+0.5=5.8 3.8+1.8=5.6 3.8+1.1=4.9 3.8+1.1+0.5=5.4 の8種類(もっとあったらごめんなさい)になると思います。 この8種類を書き出したいのですが、うまい方法が思い浮かびません。 ソルバーとかなのかと思って調べてみたのですが、計算式が確定していない場合は使えないみたいです。 やっぱりVBAを使わないと難しいでしょうか? なんとか簡単にできる方法があれば、アドバイス下さい。 よろしくお願いいたします。

  • このプログラムの説明合っていますか?

    /* 線形探索(for文で実現)*/ #include <stdio.h> /*--- 要素数nの配列aからkeyと一致する要素を線形探索 ---*/ int search(const int a[], int n, int key)    { int i;            /*iを宣言*/ for (i = 0; i < n; i++)     /*iの値を設定し宣言*/ if (a[i] == key)       /*iにkeyで入力*/ return (i); /* 探索成功 */ return (-1); /* 探索失敗 */ } int main(void)          /*main関数*/ { int i, ky, idx;/*i,ky,idxを宣言*/ int x[7]; /*xは配列で7つの数字を入れられる*/ int nx = sizeof(x) / sizeof(x[0]);/*配列を宣言*/ printf("%d個の整数を入力してください。\n", nx); for (i = 0; i < nx; i++) { printf("x[%d]:", i); scanf("%d", &x[i]); }printf("探す値:"); scanf("%d", &ky); idx = search(x, nx, ky); /* 配列xから値がkyである要素を線形探索 */ if (idx == -1) puts("探索に失敗しました。"); else printf("%dは%d番目にあります。\n", ky, idx + 1); return (0);      /*0の数字で戻る*/ } 1行ずつ理解したいのですが分からない個所多いんです。 分からないの文は説明が書いてないので教えてください。

  • PHPを使ったスピード重視の集計について

    以下のログがあります。 --- 日付   時分  A  B  C  カウント 2006/8/3 11:00 1  4  8  84 2006/7/4 17:04 3  5  4  47 2006/8/4 13:30 1  4  6  32 2006/3/3 15:15 5  1  8  8 2006/5/8 18:20 3  3  3  43 ・・・(以下、100万行位続く)・・・ --- このログを"時間"単位でA,B,C毎の"カウントを合計"したく、イメージとしては以下のテーブルを作りたいと思っています。(時間,A,B,Cの組み合わせでログに出て来なかったらテーブルに出力する必要無し。順番も特に問わない。) --- 日付   時間 A  B  C  カウント合計 2006/8/3 11  1  4  8  84323 2006/8/5 13  4  8  3  9793 ・・・・ --- 処理スピードを重視して、メモリ上で行う前提で以下の方式を考えました。 多段配列を使い、ログが出るたびに $count["2006/8/3"]["11"]["1"]["4"]["8"] = 7672 のような配列を作ります。もし、配列があるのならカウント部分を足し算します。 最後に配列全部をファイルに書き出すという方法です。 しかし、ログの量があまりにも多くやはり処理時間がかなりかかります。またプログラムも多段配列の表記にすると非常に見辛い状態です。何か別のアルゴリズムか手法により、スピード重視で処理する方法をご存知であればご教授ください。 前提がPHPを使わなければいけない&DB使えないという環境です。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • C言語の簡単なプログラム

    簡単な足し算のみの電卓をC言語で作っています。 /が入力されるまで足し算を繰り返すものです。 コンパイルをして、足し算を繰り返すところまでは上手くいったのですが、 /を入力してのループの抜け方がわかりません。 #include<stdio.h> int main(void) { int x=0,z; printf("数値を入力\n"); printf("終了は/を入力\n"); printf("\n結果 %d\n",x); while(1){ scanf("%d",&z); x=x+z; /* 足し算の計算 */ printf("結果 %d\n",x); /* 現在の計算結果を表示 */ } printf("終了 結果: %d\n",x); /* 計算の終了、合計値の表示 */ return 0; } while文のなかにifでいれればいいのでしょうか? その場合、 if(z=='/') break; でいいんでしょうか? if文以外のやり方がある場合も教えていただけたらと思います。 よろしくお願いします。

  • 数学の置換をプログラムで書くには?

    現在、C言語で置換を行うプログラムを書こうと思っています。 まずint型の要素数nの配列permutationを用意し、これを用いて、重複なく、不足なく、n!通り全ての置換を行うにはどのようにすればよいでしょうか? プログラムの形式としては、配列permutationが宣言されている状態で、 for(int i = 0;i < factorial(n);i++){ //permutationを用いた計算(permutationの値は変化しない) //ここでpermutationの値を置換する } という感じです(factorial(n)はnの階乗です)。 回答よろしくお願いします。

  • 関数の仮引数は宣言か式か

    ”関数の仮引数の宣言”は”変数の宣言・定義”と同じように”宣言”と明確に考えるべきなのか”関数の仮引数”を”式”と考えて良いのかという問題です。 私が迷ってしまったのは"配列を仮引数"にとった例です。 規則として ”int a[ ] が int *a と同じ意味になるのは、唯一、関数の仮引数の宣言のばあいだけである”という規則がありますが、これは”関数の仮引数の宣言”は変数の宣言・定義”と同じように”宣言”と明確に考えている例だとおもいます。 int a[ ] が int *a と型名 変数名(引数名)と宣言の形をとっているので当然だと思いますが、一方 配列は、式の中で「先頭へのポインタ」によみかえられる。               ↓ 関数の引数は式なので、配列は「先頭へのポインタ」に読み変えられる←引数部分を”宣言”ではなく”式”と捉えてる←ここが私の迷っているところ               ↓ よって、関数に渡ってくるのは、結局はつねにポインタだ。 という説明もあります。 私の今までの理解ではc言語では”宣言の部分”と”式”の部分は明確に区別されるものと考えていました。”宣言部分の初期化の="と”代入の=”とは明確に区別されていました。 それと同じように”関数の仮引数の宣言”は”宣言部分”と捕らえるのか”式”ととらえるのか ”宣言”と”式”が私の頭の中混乱しています。 宜しくお願いします。

  • C言語の文法(変数宣言)について

    C言語の文法の質問をさせていただきます。 int hoge; などと宣言しますが、このintというのは型指定子というものでしょうか。 int *piyo; という宣言のintも型指定子でしょうか。 この場合、* はなんと呼ばれるのでしょうか。(アスタリスクという記号です、という回答は期待していません。(^_^;)) ポインタ宣言子、でいいのでしょうか。これは「演算子」ではないんですよね? char c[10]; という宣言の[ ]やその中に入っている10はなんと呼ばれるのでしょうか。 いま、手元に「新ANSI C言語辞典」という本があるのですが、説明を読んでもよくわかりません。

  • c言語 int型の数字をchar型の配列に

    c言語についてです。 int型の数字をchar型の配列に入れたいです。 関数に対してint型の数字を文字列として渡し、 関数内でchar型の配列に格納したいです。 例として、 a(char a[]){  ~~  ~~ } int main(void){ int x = 5678;  ~~  a(x); } とできるようにしたいです。 しかしこれだと5678という値がそのままchar型の一つの配列に入る?ため正しくないです。 欲しい結果としてはちゃんとa関数内で、 a[1] = '5' a[2] = '6' a[3] = '7' a[4] = '8' となってほしいです。 もともと渡す値が”5678”となっていれば結果は正しく出るのですが、 渡す値がint型と決まっているためどうにかして5678を”5678”とすればいいのではないかと考えています。 つまり5678を単純に文字列に変換すればいいのでしょうか? またプログラム内ではsprintfやatolを使用しないで実現させたいです。 難しいかもしれませんがお願いします。 なんだか説明が下手ですみません。 お願いいたします。

  • 大きな配列データを複数ある場合のデータ保持の方法

    indowsXP VC++.net2003で開発をしています。 100*100程度の2次元配列が20から50程度ある場合、データはどう保持しているのが良いのでしょうか? 同時に使うのは1個のみですので、すべて宣言するのはメモリの無駄だと思っています。 思いついた方法は 1.テキストファイルに保持しておく 2.データベースに保持しておく の2つですが、ユーザーに配列の中身が見られたり変更されたりするのも困るので1の方法は却下しました。 2の方法ですがデータベースを用意するのは無理なのであきらめました。 また、配列データはツールから作成しており、以下のように宣言しやすいように表示されます。 値をひとつひとつ代入して初期化するのも大変なので、できればこの表示をいかしたまま、 必要な配列を取り出して扱うということをしたいのですが、何か良い方法はないでしょうか? それともint型の100*100の2次元配列 50個程度なら宣言したほうがいいのでしょうか? int test[32][32] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 以下省略

専門家に質問してみよう