1から4までの数字の順列をすべて印刷するプログラムを作りたいのですが、
ちょっとてこずっています。上級者から見れば簡単だと思います。
1234
1243
1324
1342
1423
1432 
  ・
  ・
  ・  というプログラムです。
誰か教えていただけないでしょうか。お願いします。

A 回答 (3件)

 「直ぐに回答がほしい」にマークしつつ、5日経っても回答に何の補足もお礼もないというのは、どうなんでしょう。

(最低限のマナーは守りましょう。)

 一応未解決と解釈して、下記2件の4重ループとは異なる、他の順列にも適用できるプログラムを挙げます。
 全部ループでやるのは面倒なので再帰を使ってます。(一応補足ですが、ループで実現できない再帰はありません)

#include <stdio.h>

void permu(int n, int r, int *a, int m, int b);
void let_permu(int r, int *p);

int main(void)
{
  int a[32], n, r;
  scanf("%d", &n);
  if (n < 1 || 32 < n) return 0;
  scanf("%d", &r);
  if (r < 1 || n < r) return 0;
  permu(n, r, a, 0, 0);
  return 0;
}

void permu(int n, int r, int *a, int m, int b)
{
  int i;
  if (r == m) {
    let_permu(r, a);
    return;
  }
  for (i = 0; i < n; i++) {
    if (!(b & (1 << i))) {
      a[m] = i + 1;
      permu(n, r, a, m+1, b|(1<<i));
    }
  }
}

void let_permu(int r, int *p)
{
  int i;
  for (i = 0; i < r; i++)
    printf("%d%c", p[i], (i+1<r ? '-' : '\n'));
}

∇解説
・n個からr個を選んで並べる順列を、すべて求めます。
・最初に入力を求められる n には、全体の数を入力します。
・次に入力を求められる r には、その中から幾つ選ぶかを入力します。
・32までの順列は作れるようになっています。(が、せいぜい10までぐらいにしないと、相当時間がかかります)

・関数permuのforループで、階層mの値を求めます。
・b はバイナリフラグで、i ビット目が0の時のみ処理を行います。
・求めた値 i+1を、a[m]に格納します。
・次の階層m+1と、a[m]ビット目を1にしたフラグをパラメータにセットし、関数permuを呼び出します。これ以外のパラメータは、同じ値を使い回します。
 これの繰り返しで順列を求めることが出来ます。
・順列が1つ求まるたびに let_permu 関数が呼ばれるので、そこでバッファにためるなり、印刷するなりの処理を行ってください。(ここでは単純に表示しています)
・表示上の都合で、全角スペースを使っています。コピペした際は半角へ変換してください。
    • good
    • 0
この回答へのお礼

詳しく説明してもらってありがとうございます。参考になりました。
ところで、4重ループを使ったプログラムはどのようなものなのでしょうか?
もし教えていただけるなら幸いです。

お礼日時:2001/07/02 02:51

考え方


配列をつかう。
4重ループ
それぞれのループでは、配列にマークされてない
数字をえらぶ。
そして、そのループで使用した数字の配列にマーク
(一番そのループは配列サーチはいらない)

っていうのはどうでしょ。
    • good
    • 0

簡単にやり方だけ。



(1)4重ループを作って、4桁にそれぞれ1~4を突っ込む。
(2)各桁の掛けた合計が24であったら、その値を保存。(24になる場合は常に1,2,3,4の組み合わせ)
(3)最後に全部を並べて印刷

これで良いんじゃないでしょうか?(1~4の組み合わせ限定的なものがあるので、実用的ではありませんが・・・)

私に勘違いがあったら申し訳ありません。
    • good
    • 0

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

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

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打ち込んだ数字が素数かどうか判断するプログラム

数字をキーボードから入力し、その数字が素数がどうかを判断するプログラムを打ちたいのですが、うまくできません。
コンパイルはできるのですが…。
どなたか間違っているところを教えてください。

#include<stdio.h>

int main ( void )

{

int a,b,indicator=1;


printf("正の整数:");
scanf("%d", &a );

/* indicator=1.......素数でない
indicator=0.......素数である */

if(a<=1){
indicator=1;
}



else
{
for(b=2;b<=(a-1);b++)
{
if(a%b == 0){
indicator=0;
}
}

if(indicator==1)
{
printf("%dは素数ではありません\n",a);
}
else if (indicator==0)
{
printf("%dは素数です\n",a);
}
}

return 0;
}

数字をキーボードから入力し、その数字が素数がどうかを判断するプログラムを打ちたいのですが、うまくできません。
コンパイルはできるのですが…。
どなたか間違っているところを教えてください。

#include<stdio.h>

int main ( void )

{

int a,b,indicator=1;


printf("正の整数:");
scanf("%d", &a );

/* indicator=1.......素数でない
indicator=0.......素数である */

if(a<=1){
indicator=1;
}



else
{
for(b=2;b<=(a-1);b++)...続きを読む

Aベストアンサー

>どなたか間違っているところを教えてください。

★変数の宣言で、全てを「素数でない」としておいて、判定部分でも「素数でない」ものだけを抽出しているからです。

>どんなものでも素数でないと判断されてしまいます。

 質問者様のソースを実行すると、判断は「逆」になるだけで・・。
 
 111 ( 3 X 37 ) を入れると「素数です」となりますよ。
--------------------------------------------------------
・ else を省いて書き直してみました。
・判断部分で、「でない」ものを抽出するのだから・・・(▼)
--------------------------------------------------------
#include <stdio.h>

int main( void )
{
 int a, b, c, indicator;

 printf( "正の整数:" );

 scanf( "%d", &a );

// indicator = 1.......素数でない(◆)
// indicator = 0.......素数である

 indicator = 0; // 一旦、全てを「である」(▼)

 for( b = 2; b <= ( a - 1 ); b++ ){

  if( 0 == ( a % b ) ){ // 「でない」の判定(◆)

   indicator = 1; // ≠0

   c = b;

//   break; // 「必須」ではない。「 c 」のみに影響
  }
 }
 if( indicator == 1 ) printf( "%dは素数ではありません(%d)\n", a, c );

 if( indicator == 0 ) printf( "%dは素数です\n", a );

 return 0;
}
注:インデントに全角空白を用いています。
  タブに一括変換して下さい。

>どなたか間違っているところを教えてください。

★変数の宣言で、全てを「素数でない」としておいて、判定部分でも「素数でない」ものだけを抽出しているからです。

>どんなものでも素数でないと判断されてしまいます。

 質問者様のソースを実行すると、判断は「逆」になるだけで・・。
 
 111 ( 3 X 37 ) を入れると「素数です」となりますよ。
--------------------------------------------------------
・ else を省いて書き直してみました。
・判断部分で、「でない」ものを抽出するのだ...続きを読む

Qプログラムでの数字につく”f”の意味

こんばんは。
プログラムで数字に"f"が付いている(4.0fなど)ものを見かけるのですが
この"f"の意味はなんなのでしょうか?

よろしくお願い致します。

Aベストアンサー

float型を意味します
一応float型は単精度/double型は倍精度なので、
コンパイラ(場合によっては同じコンパイラでも対象CPU毎に)によって
割り当てられるBit長(精度)が異なる場合があります。

Q数字の位ごとの値を表示するプログラム

scanfで入力した数字の位ごとの値を表示するプログラムを作りたいのですがどうしたらいいですか?

例えば1234という数字を入れたら
10の位・・・3
1の位・・・4
という感じです

Aベストアンサー

> 10の位・・・3

1234を10で割って小数点以下を切り捨て。→123.4→123
123を10で割った余りを求める。→3

> 1の位・・・4

1234を1で割って小数点以下を切り捨て。→1234
1234を10で割った余りを求める。→4

とか。

Q数字文字をカウントするプログラムの動作について

良い質問のタイトルが思い浮かばず、分かりづらいタイトルで申し訳ありません、C言語について質問させて頂きます。
C言語の参考書を買って夏休み中にプログラムの勉強をしているのですが、何故動作するのかがわからない例があります、ソースは以下の通りです。

#include <stdio.h>

int main(void)
{
int i,ch;
int cnt[10] = {0};

while(1)
{
ch = getchar();
if (ch==EOF) break;

switch(ch)
{
case '0' : cnt[0]++;printf("%d\n",ch);break;/* printfは確認の為 */
case '1' : cnt[1]++;printf("%d\n",ch);break;
case '2' : cnt[2]++;printf("%d\n",ch);break;
case '3' : cnt[3]++;printf("%d\n",ch);break;
case '4' : cnt[4]++;printf("%d\n",ch);break;
case '5' : cnt[5]++;printf("%d\n",ch);break;
case '6' : cnt[6]++;printf("%d\n",ch);break;
case '7' : cnt[7]++;printf("%d\n",ch);break;
case '8' : cnt[8]++;printf("%d\n",ch);break;
case '9' : cnt[9]++;printf("%d\n",ch);break;
}
}

puts("数字文字の出現回数");
for(i=0;i<10;i++)
printf("'%d':%d\n",i,cnt[i]);
getchar();getchar();

return(0);
}

といったプログラムです。

実行し、数値を入力、CTRL+Zで入力を終了し、出現回数を表示させる、という動作自体は無事にできるのですが、何故chの値が変更していくのかがわかりません、数値を入力した時点で51や49といったそれぞれ違う数値が表示されるのですが、chの値を変更させる命令を、何が引き起こしているのかが理解できません、3(51)と判定されて同じ数が無限にカウントされないのは何故なのでしょうか・・・・?

また、その後の無限ループからの脱出をCTRL+Zがどうして引き起こすのかも理解できず困っています、教科書には「CTRL+Zは入力の終了を意味する」とあるのですが、これは一体どういう意味なのでしょうか、強制的に割り込んでEOFを代入するということなのでしょうか・・・?

お時間がある時にでも、教えて頂けると助かります、よろしくお願いします。

良い質問のタイトルが思い浮かばず、分かりづらいタイトルで申し訳ありません、C言語について質問させて頂きます。
C言語の参考書を買って夏休み中にプログラムの勉強をしているのですが、何故動作するのかがわからない例があります、ソースは以下の通りです。

#include <stdio.h>

int main(void)
{
int i,ch;
int cnt[10] = {0};

while(1)
{
ch = getchar();
if (ch==EOF) break;

switch(ch)
{
case '0' : cnt[0]++;printf("%d\n",ch);break;/* printfは確認の為 */
case '1' : cnt[1]++;printf("%d\n",ch);b...続きを読む

Aベストアンサー

>getchar関数とは入力した文字を順番に3、.、1、4、と返す関数ということなのでしょうか・・?

基本的にはそれで合ってます。
ただ、'3'、'.'、'1'、'4'という文字そのものを返す訳ではなく、アスキーコードを返します。
http://e-words.jp/p/r-ascii.html

平たくいうと、コンピュータは0と1の世界ですから、'a'などの文字も数値としてハードディスクに保存する必要があります。人間が見て分かる文字とコンピュータの世界のコードとの対応表がアスキーコード表です。
OSを始め様々なソフトが、この保存された数値を人間が見て分かりやすい文字に変換してくれてるわけです。


今回の例で言うと、入力された数値をアスキーコードではなく、配列の添字として使いたいので、
int index = ch - '0';
としています。

int index = ch - 48;
でもいいんですが、マジックナンバー(プログラム中に書かれた0, 1以外の数値)を嫌う人もいますので、'0'としています。



printfで%dで出力すると、アスキーコードの値がそのまま出力されます。
これを入力した文字そのものを出力したい場合は、%cを使用します。

>getchar関数とは入力した文字を順番に3、.、1、4、と返す関数ということなのでしょうか・・?

基本的にはそれで合ってます。
ただ、'3'、'.'、'1'、'4'という文字そのものを返す訳ではなく、アスキーコードを返します。
http://e-words.jp/p/r-ascii.html

平たくいうと、コンピュータは0と1の世界ですから、'a'などの文字も数値としてハードディスクに保存する必要があります。人間が見て分かる文字とコンピュータの世界のコードとの対応表がアスキーコード表です。
OSを始め様々なソフトが、この保存された数...続きを読む


人気Q&Aランキング

おすすめ情報