お酒好きのおしりトラブル対策とは

よろしくお願いします。当方プログラミング初心者です。

ある配列a[]={1,1,2,2,3,3}があります。
この配列の重複組合せを全列挙したいのですが、
どういうプログラムを組めばいいのでしょうか?

よろしくお願いします!

A 回答 (2件)

その6個の要素から、重複を許して「何個の」要素を取り出したいのですか?

    • good
    • 0

各要素が、「ある」「なし」のすべての組み合わせと言うことですよね。


こんな感じで、intが32bitならaの要素が31個までは出来ると思います。


#include <stdio.h>
#include <math.h>
main()
{
int a[]={1,1,2,2,3,3};
#define N (sizeof a/sizeof a[0])
int i,j;

for(i=0;i<pow(2,N);i++){
printf("%d:",i+1);
for(j=0;j<N;j++){
if(i & 1<<j){
printf("%d ",a[j]);
}
}
printf("\n");
}
}
    • good
    • 1

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qn個の要素で出来る順列組み合わせを全て出力するアルゴリズム

次のようなプログラムをC++で書こうと思っているのですが、
どうも方法が思い浮かびません。
よいやり方、定番のやり方などがありましたら教えてください。

---------------------------------
n個の要素があるとき、
そのn個で出来る順列組み合わせ(計(n!)通り)を全て出力する。


例えばa[4] = {'A', 'B', 'C', 'D'}なら
順列組み合わせは
A B C D
A B D C
A C B D
A C D B
A D B C
A D C B
B A C D
B A D C
B C A D
B C D A
B D A C
B D C A



D C A B
D C B A
の、計24通り

Aベストアンサー

「順列組合せ」ではなく「順列の生成」ですね。

アルゴリズムの原理を知りたければ次のWlframのサイトでわかりやすく説明しています。下のほうのところで、再帰を使ったものが例示されています。
http://mathworld.wolfram.com/Permutation.html

ソースを見たいなら、
http://www.merriampark.com/perm.htm
あたりで。

ただし、C++では、順列生成は標準ライブラリに入っています。
next_permutation,prev_permutation
を使って下さい。
http://www005.upp.so-net.ne.jp/episteme/html/stlprog/_05.html

Q重複順列の結果を全て表示できるソフトをご存知ないでしょうか?

お世話になっております。

4桁、5桁、6桁の数字のそれぞれの重複順列(使用する数字は0~9の10個)の結果を全て表示する必要に迫られ、エクセルのマクロや、ビジュアルベーシックなどに関して全く無知なので方法が解らず困っています。

ためしにフリーソフトで検索してみましたが、順列の総数を
求めることはできても、結果を表示するソフト
(例えば4桁であれば10000通り全て表示できるようなソフト)
は探せませんでした。

私の探し方が足りないのかもしれません。
どなたか左様なソフト、またはその方法をご存知でしたら教えていただけないでしょうか。

尚、このサイト内で検索したところ、下記のページ
http://oshiete1.goo.ne.jp/kotaeru.php3?q=96618

がほぼ求めている回答ではないかと自分なりに考えたのですが、それではこのプログラムをどうしたらいいのかがわかりません(それくらい初心者です)

ちなみにパソコンのOSはWINDOWS98、使用できるソフトは
EXCEL2000です。
無茶を言っているのは重々承知なのですが、どうぞよろしくお願いいたします。

お世話になっております。

4桁、5桁、6桁の数字のそれぞれの重複順列(使用する数字は0~9の10個)の結果を全て表示する必要に迫られ、エクセルのマクロや、ビジュアルベーシックなどに関して全く無知なので方法が解らず困っています。

ためしにフリーソフトで検索してみましたが、順列の総数を
求めることはできても、結果を表示するソフト
(例えば4桁であれば10000通り全て表示できるようなソフト)
は探せませんでした。

私の探し方が足りないのかもしれません。
どなたか左様なソフト、またはそ...続きを読む

Aベストアンサー

要するに4桁の場合は、
0以上9999以下の全ての整数が欲しいということですよね?
エクセルを使うなら0から始まる連続データにするだけで良いと思います。
http://www.noa-prolab.co.jp/dict/excel.html#e2_002
(0の時0000と表示したいなら書式を変更してください。)

エクセルは65536行までしかないので
6桁だと2回に分ける必要が出てきますが。

Q重複しない組み合わせのプログラム

0から9のうち4つの数字を取り出すというC言語のプログラムをつくりたいのですが、ランダム関数を用いると重複してしまいます。どのようにしたらよいでしょうか?

Aベストアンサー

取り出した数字を配列にでも保存しておいて、取り出すたびにそれと比較して、重複があったら取り出しをやり直す、ではダメですか?

Q複数桁10進数の*桁目だけを抽出したい

タイトルがすべてと言えてしまうのですが、
例えば、int宣言された"4287"(この値は変動します)という数値があったとして、1桁目の"7"だけを別の変数へ引き抜きたいのですが、その場合にはANDによるマスク処理による演算で処理可能なのでしょうか?
また、他に良い方法などありましたら教えていただけますでしょうか?

Aベストアンサー

★10進数ですので AND は使えませんね。
・簡単なサンプルを載せますので読み取って下さい。

サンプル1:
int value = 4287;
int a[ 4 ];

a[0] = (value % 10); value /= 10; // 1桁目を取り出す
a[1] = (value % 10); value /= 10; // 2桁目を取り出す
a[2] = (value % 10); value /= 10; // 3桁目を取り出す
a[3] = (value % 10); value /= 10; // 4桁目を取り出す

サンプル2:
int value = 4287;
int a;

a = (value % 10);
value -= a;

value → 4280
a → 7
になります。

Q配列に順列を入れ、その順列を使いルール通りの組合せを作るには

配列nを用意して、2*nの配列に1~Z、又は1~9までの数字を格納します。3の場合、123,132,213,231,312,321の順列で、ルールは1の時は1つ間を空けて1を、2の時は2つ間を空けて2を・・・
つまり、3の場合は 231213,312132 の二つがルールと合致しているので答えとなります。
1~Zまでで、上記のようにルールに当てはまる場合のみを出力するプログラムを書きたいのですがうまくいきません。下に考えてみたものを載せます。どなたか分かる方ご教授願います。

#include<stdio.h>
int p[99]={0},a[99]={0};
int n;
int count;
main(){
int i;
void perm(int k);
while(1){
scanf("%d",&n); if(n<=0){break;}
for(i=1;i<=n;i++){p[i]=i;}
count=0;
perm(1);
}
}
void perm(int k){
int i,w;
if(k>n){
count++;
for(i=1;i<=n;i++){a[i]=p[i];}
for(i=1;i<=n;i++){a[i+a[i]+1]=a[i];}
printf("[%d]:",count);
for(i=1;i<=2*n;i++){printf("%3d",a[i]);} printf("\n");
}

else{
for(i=k;i<=n;i++){
w=p[k];p[k]=p[i];p[i]=w;
perm(k+1);
w=p[k];p[k]=p[i];p[i]=w;
}
}
}

配列nを用意して、2*nの配列に1~Z、又は1~9までの数字を格納します。3の場合、123,132,213,231,312,321の順列で、ルールは1の時は1つ間を空けて1を、2の時は2つ間を空けて2を・・・
つまり、3の場合は 231213,312132 の二つがルールと合致しているので答えとなります。
1~Zまでで、上記のようにルールに当てはまる場合のみを出力するプログラムを書きたいのですがうまくいきません。下に考えてみたものを載せます。どなたか分かる方ご教授願います。

#include<stdio.h>
int p[99]={0},a[...続きを読む

Aベストアンサー

★追記。
・調べる組み合わせの数式は『(n*2-2)P(n)』です。
 4つでは、6P4=6×5×4×3=360通り
 5つでは、8P5=8×7×6×5×4=6,720通り
 6つでは、10P6=10×9×8×7×6×5=151,200通り
 7つでは、12P7=12×11×10×9×8×7×6=3,991,680通り
 8つでは、14P8=14×13×12×11×10×9×8×7=121,080,960通り
 9つでは、16P9=16×15×14×13×12×11×10×9×8=4,151,347,200通り
 ※8つまでは計算終了するが、9つは時間がかかりすぎて確認できなかった。

#include <stdio.h>
#include <string.h>

// パズル型
typedef unsigned long puzzle_t;

// 定数
#define OK 1
#define ERR 0
#define SPC 0x20

// 文字列の反転
char *reverse( char buff[] )
{
 char *head = buff;
 char *tail = buff + strlen(buff) - 1;
 char temp[ 1 ];
 
 while ( head < tail ){
  temp[ 0 ] = head[ 0 ];
  head[ 0 ] = tail[ 0 ];
  tail[ 0 ] = temp[ 0 ];
  head++;
  tail--;
 }
 return( buff );
}

// 表示文字列の作成
char *make( char buff[], puzzle_t x[], int max, puzzle_t msb )
{
 int i;
 
 memset( buff, SPC, BUFSIZ );
 buff[ BUFSIZ - 1 ] = '\0';
 
 for ( i = 0 ; i < max ; i++ ){
  int no = 0;
  
  do {
   if ( x[i] & ((puzzle_t)1 << no) ){
    buff[ no ] = (char)(i + '1');
   }
  } while ( !(msb & ((puzzle_t)1 << no++)) );
  
  buff[ no ] = '\0';
 }
 return( reverse(buff) );
}

// チェック
int check( puzzle_t x[], int max, puzzle_t ans )
{
 puzzle_t check = 0;
 int i;
 
 for ( i = 0 ; i < max ; i++ ){
  check |= x[ i ];
 }
 return( (check == ans) ? OK : ERR );
}

// シフト
int shift( puzzle_t x[], int max, puzzle_t msb )
{
 int i;
 
 for ( i = 0 ; i < max ; i++ ){
  if ( msb & x[i] ){
   while ( !(x[i] & (puzzle_t)1) ){
    x[i] >>= 1;
   }
  }
  else{
   x[i] <<= 1;
   return( 1 );
  }
 }
 return( 0 );
}

int main( void )
{
 char buff[ BUFSIZ ];
 puzzle_t x[ 50 ];
 puzzle_t ans;
 puzzle_t msb;
 int max = 0;
 int cnt = 0;
 int i, n;
 
 do {
  printf( "3~15を入力して下さい:" );
  scanf( "%d", &n );
  printf( "\n" );
 } while ( (n < 3) || (n > 15) );
 
 ans = ~((~(puzzle_t)0) << (n * 2));
 msb = ((puzzle_t)1 << (n * 2 - 1));
 
 // ビットイメージの作成
 for ( i = 0 ; i < n ; i++ ){
  x[ i ] = (((puzzle_t)1 << (i + 2)) | (puzzle_t)1);
 }
 do {
  if ( check(x,n,ans) == OK ){
   printf( "%s⇒○\n", make(buff,x,n,msb) );
   cnt++;
  }
  else{
//   printf( "%s⇒×\n", make(buff,x,n,msb) );
  }
  max++;
 } while ( shift(x,n,msb) );
 
 if ( cnt == 0 ){
  printf( "%d通り中、1個も解はなかった。\n", max );
 }
 else{
  printf( "\n%d通り中、%d個の解が見つかった。\n", max, cnt );
 }
 return( 0 );
}

★追記。
・調べる組み合わせの数式は『(n*2-2)P(n)』です。
 4つでは、6P4=6×5×4×3=360通り
 5つでは、8P5=8×7×6×5×4=6,720通り
 6つでは、10P6=10×9×8×7×6×5=151,200通り
 7つでは、12P7=12×11×10×9×8×7×6=3,991,680通り
 8つでは、14P8=14×13×12×11×10×9×8×7=121,080,960通り
 9つでは、16P9=16×15×14×13×12×11×10×9×8=4,151,347,200通り
 ※8つまでは計算終了するが、9つは時間がかかりすぎて確認できなかった。

#include <stdio.h>
#include <...続きを読む

Q総当りの配列を返す関数の作成

総当りの配列を返す関数の作成が上手くいきません。
関数にしてほしいことは、与えられた配列arrからnum個取り出す組み合わせを配列で返してもらうことです。

下記が例です。関数の名前をtotalHitとします。
********************************************
var arr = [0,1,2,3,4];
var num = 2;
var arr2 = totalHit(arr,num);
/*
arr2に[[0,1],[0,2],[0,3],[0,4],[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]が
代入されてほしい
*/
********************************************
ネットでもずいぶん探しましたが、目的のものは見つかりませんでした。
アルゴリズムが分かる方、ヒントでもかまいませんので、ご教示願います。

Aベストアンサー

樹形図を書き出してみると分かりやすいかと思いますが、きれいなツリー構造をしているので、再起関数でできると思いますよ。

例えば、[0, 1, 2, 3] から 3 つを選ぶ場合の、樹形図は(掲示板の関係少し見ずらいかもしれません)
0-1-2
|*|-3
|-2-3

1-2-3

というツリーが出来上がります。ツリー構造の場合、隣と下を順にたどっていけば、全ての枝を通ることができます。
例えば、最初の 0 の位置の場合、隣の 1 と 下の 1 を発火させます。
隣の 1 はさらに隣の 2 と下の 2 を発火。後は適度に終了判定を入れるだけです。

function totalHit(ary, num){
var r = [];

(function(m, n, p, c){
if(n < 1){
r.push(c);
}else if(m - p >= n){
arguments.callee(m, n - 1, p + 1, c.concat(ary[p])); // 下のノード
arguments.callee(m, n, p + 1, c); // 隣のノード
}
})(ary.length, num, 0, []);

return r;
}

引数の p は現在位置、m は配列数、n は取り出す個数(ツリーの下へ行くほど、取り出す個数は減っていきます)
先の例の場合、最初の n は 3、ひとつ下の n は 2 という具合です。
最後の c は組み合わせごとの部分配列です。

もう少し実行速度を上げれると思いますので、色々工夫してみてください。

樹形図を書き出してみると分かりやすいかと思いますが、きれいなツリー構造をしているので、再起関数でできると思いますよ。

例えば、[0, 1, 2, 3] から 3 つを選ぶ場合の、樹形図は(掲示板の関係少し見ずらいかもしれません)
0-1-2
|*|-3
|-2-3

1-2-3

というツリーが出来上がります。ツリー構造の場合、隣と下を順にたどっていけば、全ての枝を通ることができます。
例えば、最初の 0 の位置の場合、隣の 1 と 下の 1 を発火させます。
隣の 1 はさらに隣の 2 と下の 2 を発火。後は適度に終了判定...続きを読む

Q辞書順にソートしたいのですが・・・

C言語を始めたばかりの無知な自分で申し訳ないのですが学校で課題が出て分からなくて困っています。
課題は任意の長さの文字列(英字のみ)データをファイルから読み込み、辞書順に並べ替えるプログラムの作成です。文字列の最大長は64、データの最大個数は1000です。
一応自分で以下の状態まで作成したのですが、データが1000まで読み込んでくれません。申し訳ありませんが締め切りは明日なのでなるべく早くよろしくお願いします。
#include<stdio.h>
#include<string.h>
#include<strings.h>
#define MAX 67

int main(void)
{
FILE *fp;
char ex[1000][MAX],tmp[MAX],a[100];
int i,j,b;

printf("Input filename:");
scanf("%s",a);
fp = fopen(a,"r");
if(fp == NULL){
printf("Not open\n");
}

for(i=0;!feof(fp);i++){
fgets(ex[i],MAX,fp);
}

for(i=0;i<=MAX-2;i++){
for(j=i+1;j<=MAX-1;j++){
b = strcasecmp(ex[i],ex[j]);
if(b>0){
strcpy(tmp,ex[i]);
strcpy(ex[i],ex[j]);
strcpy(ex[j],tmp);
}
if(b==0 && *ex[i]<='z' && *ex[i]>='a' && *ex[j]<='Z' && *ex[j]>='A'){
strcpy(tmp,ex[i]);
strcpy(ex[i],ex[j]);
strcpy(ex[j],tmp);
}
}
}

for(i=0;i<=MAX-1;i++){
printf("%s",ex[i]);
}

fclose(fp);

return 0;
}

C言語を始めたばかりの無知な自分で申し訳ないのですが学校で課題が出て分からなくて困っています。
課題は任意の長さの文字列(英字のみ)データをファイルから読み込み、辞書順に並べ替えるプログラムの作成です。文字列の最大長は64、データの最大個数は1000です。
一応自分で以下の状態まで作成したのですが、データが1000まで読み込んでくれません。申し訳ありませんが締め切りは明日なのでなるべく早くよろしくお願いします。
#include<stdio.h>
#include<string.h>
#include<strings.h>
#define MAX ...続きを読む

Aベストアンサー

バージョンによるかもしれませんが。
BorlandCで strings.hとstrcasecmpはエラーになりませんか。存在しないようなので。
strcasecmpをstrcmpにして通しましたけど。

1 メモリモデルはラージにしておきましょう。
  char ex[E_sizeMax][E_subMax] が大きいです。

2 char ex[E_sizeMax][E_subMax]はmainの外に出した方がよいです。

3 printf("Not open\n");
  の下に exit()を追加しましょう。
  ファイルが無くてもそのまま進んでしまいますよ。

4 word_num の定義を忘れずに。
5 malloc はHelpを読みましょう。

#include<mem.h>
char *cp;
cp=malloc(E_sizeMax * E_subMax );//メモリ確保

if(cp!=NULL){
for(i=0; i<E_sizeMax; i+=E_subMax ){
cp[i] =i; //以下も同じ位置のアクセスです。
*(cp+i) =i;//どれもE_subMax 毎にiを書いています。
//ただし*cpはcharなのでintの下位8bitしか 書き込めませんが。
}
free(cp); //メモリ解放
}

PCのOS上で動かす場合と組み込みCPUでOSなしの場合などメモリ環境により変数の確保の仕方も変わりますのでそれに応じて考えなければなりません。

バージョンによるかもしれませんが。
BorlandCで strings.hとstrcasecmpはエラーになりませんか。存在しないようなので。
strcasecmpをstrcmpにして通しましたけど。

1 メモリモデルはラージにしておきましょう。
  char ex[E_sizeMax][E_subMax] が大きいです。

2 char ex[E_sizeMax][E_subMax]はmainの外に出した方がよいです。

3 printf("Not open\n");
  の下に exit()を追加しましょう。
  ファイルが無くてもそのまま進んでしまいますよ。

4 word_num の定義を忘れずに。
...続きを読む

Qアルファベットの並べ替え

C言語で文字を読み込んで並べ替えをしたいのですが、
void mojiSort(char *h[ ], int n){
int i, j;
char *temp;

for (i = 0; i < n - 1; i++) {
for (j = i + 1; j < n; j++) {
if (strcmp( h[j], h[i]) < 0) {
temp = h[i];
h[i] = h[j];
h[j] = temp;
}
}
}
return ;
}
とすると大文字、小文字を分けて並べ替えてしまいます。
「A」の後に「a]がくるようにするにはどうしたらよいでしょうか?

Aベストアンサー

比較をする際に、小文字ないし大文字に両者を統一したものを比較することによって回避できると思います。同じだった場合は大文字を先にすればいいと思います。

QExcelですべての組合せ(重複組合せ)を出力するには?

Excelですべての組合せ(重複組合せ)を出力するには?

次の条件のような場合、Excelですべての組合せ(重複組合せ)をVBAで出力するにはどうしたらいいのでしょうか?

10種類のお菓子の中から、好きなものを3個選んでセットにするとします。
同じものを複数選ぶのはありですが「菓子A、菓子B、菓子C」と「菓子B、菓子C、菓子A」は選んだ順が違うだけで同じ組合せなので、どちらか片方だけにします。

この場合、すべての組合せの数は Excelの関数で求めることができるようで COMBIN(10+3-1,3) = 220 通りあることまではわかりましたが、このすべての組合せの一覧をどのようにして出力したらいいのかがわかりません。

いろいろ検索した結果、順列という方法は見つかりましたが、重複組合せでの方法は見つけることができませんでした。
また、Accessを使っても似たようなことができるのでしょうか? 直積?

できれば、3個固定ではなく5個の場合も出来るとうれしいです。
よろしくお願いします。

Aベストアンサー

>同じものを複数選ぶのはありですが「菓子A、菓子B、菓子C」と「菓子B、菓子C、菓
つまり「菓子A、菓子A、菓子A」も「菓子A、菓子A、菓子B」もあり ですね。
№2さんのコードをお借りして
Sub Test()
  Dim myStr As Variant
  Dim rowX As Long
  Dim i As Long, j As Long, k As Long
  Const MaxNum = 10

  myStr = Split("A B C D E F G H I J")
  rowX = 1
  For i = 0 To MaxNum - 1
    For j = i To MaxNum - 1
      For k = j To MaxNum - 1
        Cells(rowX, 1).Value = myStr(i)
        Cells(rowX, 2).Value = myStr(j)
        Cells(rowX, 3).Value = myStr(k)
        rowX = rowX + 1
      Next k
    Next j
  Next i
End Sub

>同じものを複数選ぶのはありですが「菓子A、菓子B、菓子C」と「菓子B、菓子C、菓
つまり「菓子A、菓子A、菓子A」も「菓子A、菓子A、菓子B」もあり ですね。
№2さんのコードをお借りして
Sub Test()
  Dim myStr As Variant
  Dim rowX As Long
  Dim i As Long, j As Long, k As Long
  Const MaxNum = 10

  myStr = Split("A B C D E F G H I J")
  rowX = 1
  For i = 0 To MaxNum - 1
    For j = i To MaxNum - 1
      For k = j To MaxNum - 1
       ...続きを読む

Q「○○通りのパターンがある」の計算のしかた

よくこの組み合わせは全部で1万通りのパターンが存在するというようなことを聞きますが、
あれの方程式などはあるのでしょうか。

以下の例で説明をお願いします。

1. [a,b,c]の3つだけの文字列を作った時のパターン数
2. 英数字のみのパスワード4桁のパターン数
3. [a,b,c,d,e,f,g]の中から4文字をつかった文字列のパターン数。

Aベストアンサー

ちゃんと中学で確率を勉強しましたか?
方程式というか中学生で習う確率の授業をちゃんとやればわかります。難しいとこは
全くなく基本です。

(1)(a.b.c)の3つだけの文字列を作った時のパターン数

▼3つだけを使うので同じものは2回使えない
▽最初にa.b.cの3つのうちのひとつが選べる
▽次に最初に選んだもの以外の2つのうちのひとつが選べる
▽最後に1つ残る

従って
3×2×1=6

で答えは6通り

▽検証
下記がその6通り
a.b.c
a.c.b
b.a.c
b.c.a
c.a.b
c.b.a

(2)英数字のみのパスワード4桁

アルファベットは26文字
数字は10種類

▼同じ英数字を二度使ってもかまわないので

選べる英数字は毎回36通り

ここから4桁を選ぶのだから

36×36×36×36=1679616

1679616通り

(3)(a.b.c.d.e.f.g)の中から4文字を使った文字列のパターン

▼同じ文字を二度使わない場合
▽最初は7つ選べる
▽二回目は6つから選べる
▽三回目は5つから選べる
▽四回目は4つから選べる

7×6×5×4=840

840通り

ちなみに
▼同じ文字を二度使ってもよい場合なら
▽毎回7つから選択できる

7×7×7×7=2401

2401通り

ちゃんと中学で確率を勉強しましたか?
方程式というか中学生で習う確率の授業をちゃんとやればわかります。難しいとこは
全くなく基本です。

(1)(a.b.c)の3つだけの文字列を作った時のパターン数

▼3つだけを使うので同じものは2回使えない
▽最初にa.b.cの3つのうちのひとつが選べる
▽次に最初に選んだもの以外の2つのうちのひとつが選べる
▽最後に1つ残る

従って
3×2×1=6

で答えは6通り

▽検証
下記がその6通り
a.b.c
a.c.b
b.a.c
b.c.a
c.a.b
c.b.a

(2)英数字のみの...続きを読む


人気Q&Aランキング

おすすめ情報