C言語関係掲示板

過去ログ

No.1348 二次元配列の交換

[戻る] [ホームページ]
No.17930

二次元配列の交換
投稿者---ライガー(2004/11/10 14:14:43)


2次元配列を0と1の二つの数字で作って、ある初期解を与え、うまく0と1を交換し、横の1の並びを少なくさせたいのですが
ex)010111011     010101011 
  101000100  →  101010100
   (1,5)と(2,5)を交換

まず1次元配列だけの評価なら以下のように出来るのですが
#include<stdio.h>

int hyoka(int a[]);
main(){
    int a[10] = {1,0,1,1,0,0,1,1,1,0};
    int i = hyoka(a);
    printf("%d \n",i);
    return 0;
}

int hyoka(int a[]){
    int i;
    int hyoka = 0;
    int flg1 = 0;
    int flg2 = 0;
    int flg3 = 0;
    for(i=0; i<10; i++){
        if(a[i]==1){
            if(flg1 == 1){
                flg2 = 1;
                flg1 = 0;
            }else if(flg2 == 1){
                flg3 = 1;
                flg2 = 0;
            }else if(flg3 == 1){
                continue;
            }else{
                flg1 = 1;
            }
        }else{
            if(flg2 == 1)   hyoka += 1;
            if(flg3 == 1)   hyoka += 5;
            flg1 = flg2 = flg3 = 0;
        }
    }
    return hyoka;
}



このプログラムに、以下のような交換する作業を組み合わせ,
かつ二次元でやると何がどうなっているのやら、
わからなくなっている状況です。
どなたか良いやり方がわかる人がいれば教えてください。


#include<stdio.h>

main(){
    int a[3][5] = {
                    {1,0,1,0,1,},
                    {0,1,0,1,0,},
                    {1,0,1,0,1,},
                    };  
    int i,j,k,m,x,y;
    for(i=0; i<3; i++){
        for(j=0; j<5; j++){
            if(a[i][j] == 1){   //1の場所の検索
                for(k=0; k<3; k++){
                    for(m=0; m<5; m++){
                        if(a[k][m] == 0){   //0の場所の検索
                            a[i][j] = 0;
                            a[k][m] = 1;





                            for(x=0; x<3; x++){
                                for(y=0; y<5; y++){
                                    printf("%d ", a[x][y]);
                                }
                                printf("\n");
                            }
                            printf("\n");
                        }
                    }
                }
            }
        }
    }
    return 0;
}






No.17931

Re:二次元配列の交換
投稿者---REE(2004/11/10 14:32:30)


>2次元配列を0と1の二つの数字で作って、ある初期解を与え、うまく0と1を交換し、横の1の並びを少なくさせたいのですが
>ex)010111011     010101011 
>  101000100  →  101010100
>   (1,5)と(2,5)を交換

やりたいことがわかりません。ルールを明確にしてください。

交換出来る範囲や回数などの条件はありますか?
例:隣としか交換できない、

横の1の並びを少なくさせたいとのことですが、
並びを無くさなければいけないわけではないのですよね?
どの程度少なくさせたいのですか?

また、あなたの一次元の例では交換がありません。
まず、一次元で交換を入れてやってみては如何ですか?



No.17932

Re:二次元配列の交換
投稿者---ライガー(2004/11/10 15:19:45)


ルールとしては、交換の範囲は全てであり、1を全ての0と交換
してみて、評価が良くなれば交換する。
1が2連続なら−2点、3連続なら−4点などとし、全ての横の評価
をし、各行とも評価が良くなるようにしたいのですが・・・
この「評価が良くなった場合に交換する」という作業が
複雑でわからないのですが・・・
どのようにすればよろしいのでしょうか?


No.17933

Re:二次元配列の交換
投稿者---REE(2004/11/10 15:37:51)


>ルールとしては、交換の範囲は全てであり、1を全ての0と交換
>してみて、評価が良くなれば交換する。
>1が2連続なら−2点、3連続なら−4点などとし、全ての横の評価
>をし、各行とも評価が良くなるようにしたいのですが・・・
>この「評価が良くなった場合に交換する」という作業が
>複雑でわからないのですが・・・
>どのようにすればよろしいのでしょうか?

複雑で分からないのであれば、まず一次元でやってみて下さい。
「評価が良くなった場合に交換する」手順は、以下のようになるでしょうか
1.元の評価を求める
2.交換してみる
3.再び評価を求める
4.よくならなかった場合には交換を戻す



No.17989

Re:二次元配列の交換
投稿者---ライガー(2004/11/11 18:23:10)


ご指摘ありがとうございます。早速1次元をやってみたのですが、
指摘してもらった3と4のところがわからない
のですが・・・この後のアドバイスお願いします。
(元の評価と交換後の評価をどうやって比べるのでしょうか?)

pre>#include&lt;stdio.h&gt;

int hyoka(int a[]);
int m,n,x,y;
main(){
int a[10] = {1,0,1,1,1,0,1,1,1,0};
int i = hyoka(a);
m = printf(&quot;%d \n&quot;,i);
for(x=0; x&lt;10; x++){
if(a[x] == 1){ //1の場所の検索
for(y=0; y&lt;10; y++){
if(a[y] == 0){ //0の場所の検索
a[x] = 0;
a[y] = 1;

       ・・・・・・・・・・・・・・・・・・・・・
       ・・・・・・・・・・・・・・・・・・・・・
       ・・・・・・・・・・・・・・・・・・・・・

return 0;
}

int hyoka(int a[]){
int i;
int hyoka = 0;
int flg1 = 0;
int flg2 = 0;
int flg3 = 0;
for(i=0; i&lt;10; i++){
if(a[i]==1){
if(flg1 == 1){
flg2 = 1;
flg1 = 0;
}else if(flg2 == 1){
flg3 = 1;
flg2 = 0;
}else if(flg3 == 1){
continue;
}else{
flg1 = 1;
}
}else{
if(flg2 == 1) hyoka += 1;
if(flg3 == 1) hyoka += 5;
flg1 = flg2 = flg3 = 0;
}
}
return hyoka;
}
</pre>


No.18004

Re:二次元配列の交換
投稿者---REE(2004/11/11 20:10:31)


>ご指摘ありがとうございます。早速1次元をやってみたのですが、
>指摘してもらった3と4のところがわからない
>のですが・・・この後のアドバイスお願いします。
>(元の評価と交換後の評価をどうやって比べるのでしょうか?)

難しく考えすぎでは?
・hyoka関数で(交換後の)評価を求める。
・既に求めてある交換前の評価とif文で比較する。



No.18001

Re:二次元配列の交換
投稿者---ぽへぇ(2004/11/11 19:37:54)


結局0と1を市松模様状に並べれば得点が高くなるのだから

1.2次元配列をスキャンして0と1の数を数える。
2.0,1を交互に並べて表示

ではダメ?
評価関数を用意して交換…というのはそれはそれで面白いが。

>うまく0と1を交換し
「なるべく交換回数を少なくして」という条件なのかな。ひょっとして。


No.18112

Re:二次元配列の交換
投稿者---ライガー(2004/11/15 14:32:46)


ぼへぇさん、REEさんご指摘ありがとうございます。
>>「なるべく交換回数を少なくして」という条件なのかな?
とおっしゃられたのですが、私は最終的には何千回もこの交換を
繰り返して、より良い並びにしようと思っております。
(タブサーチというものなんですが・・・)
また交換後の評価を求めようとしたのですが、”交換後の評価を
比べる”というところが中々出来ません。途中まで頑張ったのですが
実行できなかったり、実行できても結果が意味不明だったり・・・
またまたアドバイスお願いします。
(”交換後の評価”のところが違うと思うのですが)

#include<stdio.h>

int hyoka(int a[]);
int m,n,x,y;
main(){
    int a[10] = {1,0,1,1,1,0,1,1,1,0};
    int i = hyoka(a);
    for(i=0; i<10; i++){
    printf("%d " , a[i]);
    }
    printf("\n");
    m = printf("%d \n",i);  //初めの評価
    printf("%d \n ",m);
    for(x=0; x<10; x++){
            if(a[x] == 1){  //1の場所の検索
                for(y=0; y<10; y++){
                        if(a[y] == 0){//0の場所の検索
                            a[x] = 0;
                            a[y] = 1;   //0と1を交換
                            n = printf("%d \n",i);
                            printf("%d \n",n);
            /*        for(i=0; i<10; i++){  //交換後の評価
                            printf("%d" , a[i]); 
                            }
                            if(m<n){       
                                a[x] = 1;   
                                a[y] = 0;               
                            }   */
                        }
                }
            }
    }
    for(i=0; i<10; i++){    //並び替え後のa[]の並び
    printf("%d" , a[i]);
    }

    return 0;
}
    

int hyoka(int a[]){
    int i;
    int hyoka = 0;
    int flg1 = 0;
    int flg2 = 0;
    int flg3 = 0;
    for(i=0; i<10; i++){
        if(a[i]==1){
            if(flg1 == 1){
                flg2 = 1;
                flg1 = 0;
            }else if(flg2 == 1){
                flg3 = 1;
                flg2 = 0;
            }else if(flg3 == 1){
                continue;
            }else{
                flg1 = 1;
            }
        }else{
            if(flg2 == 1)   hyoka += 1;
            if(flg3 == 1)   hyoka += 4;
            flg1 = flg2 = flg3 = 0;
        }
    }
    return hyoka;
}



No.18113

Re:二次元配列の交換
投稿者---REE(2004/11/15 15:10:22)


>また交換後の評価を求めようとしたのですが、”交換後の評価を
>比べる”というところが中々出来ません。途中まで頑張ったのですが
>実行できなかったり、実行できても結果が意味不明だったり・・・
>またまたアドバイスお願いします。
>(”交換後の評価”のところが違うと思うのですが)

難しく考えすぎですね。
折角hyoka関数があるのですから、それを使いましょう。

if(a[y] == 0){//0の場所の検索
    a[x] = 0;
    a[y] = 1;   //0と1を交換

    m=hyoka(a);  //交換後の評価
    if(m<i){

あと、本題とは関係ありませんが、変数名は意味の分かるものにしましょう。



No.18120

Re:二次元配列の交換
投稿者---ライガー(2004/11/15 16:15:03)


ご指摘ありがとうございます
>if(a[y] == 0){//0の場所の検索
a[x] = 0;
a[y] = 1; //0と1を交換

m=hyoka(a); //交換後の評価
if(m<i){
と教えてもらいましたので、以下のように評価(点数)が
高くなったら、また元に戻すというように直したのですが、
実行結果が?です。
また、10行めの
    m = printf("%d \n",i);

   11行目の
  printf("%d \n ",m);

何故結果が違うのですか?


#include<stdio.h>

int hyoka(int a[]);
int m,n,x,y;
main(){
    int a[10] = {1,0,1,1,1,0,1,1,1,0};
    int i = hyoka(a);
    for(i=0; i<10; i++){
    printf("%d " , a[i]);
    }
    printf("\n");
    m = printf("%d \n",i);  //初めの評価
    printf("%d \n ",m);
    for(x=0; x<10; x++){
            if(a[x] == 1){  //1の場所の検索
                for(y=0; y<10; y++){
                        if(a[y] == 0){//0の場所の検索
                            a[x] = 0;
                            a[y] = 1;   //0と1を交換
                            m=hyoka(a);  //交換後の評価
                            if(i<m){
                                a[x] = 1;
                                a[y] = 0;
                            }
                        }
                }
            }
    }
    for(i=0; i<10; i++){    //並び替え後のa[]の並び
    printf("%d" , a[i]);
    }

    return 0;
}
    

int hyoka(int a[]){
    int i;
    int hyoka = 0;
    int flg1 = 0;
    int flg2 = 0;
    int flg3 = 0;
    for(i=0; i<10; i++){
        if(a[i]==1){
            if(flg1 == 1){
                flg2 = 1;
                flg1 = 0;
            }else if(flg2 == 1){
                flg3 = 1;
                flg2 = 0;
            }else if(flg3 == 1){
                continue;
            }else{
                flg1 = 1;
            }
        }else{
            if(flg2 == 1)   hyoka += 2;
            if(flg3 == 1)   hyoka += 5;
            flg1 = flg2 = flg3 = 0;
        }
    }
    return hyoka;
}





No.18122

Re:二次元配列の交換
投稿者---REE(2004/11/15 16:57:29)


>と教えてもらいましたので、以下のように評価(点数)が
>高くなったら、また元に戻すというように直したのですが、
>実行結果が?です。

?では意味が分かりません。
具体的に希望と違う点を挙げてください。
ところで、点数が低い方が評価が高いのではなかったのですか?

>また、10行めの m = printf("%d \n",i);と
>   11行目の printf("%d \n ",m);は
>何故結果が違うのですか?

表示しているものが違うからです。
printfの戻り値は出力した文字数です。



No.18126

Re:二次元配列の交換
投稿者---ライガー(2004/11/15 17:19:19)


アドバイスありがとうございます。
>ところで、点数が低い方が評価が高いのではなかったのですか?

 そうです。点数が低い方が評価が良いのです。
 交換後の点数が高くなったら交換しても意味がないので
 一回交換したものをさらに交換するとしたのですが・・・
if(a[y] == 0){//0の場所の検索
                            a[x] = 0;
                            a[y] = 1;   //0と1を交換
                            m=hyoka(a);  //交換後の評価
                            if(i<m){
                                a[x] = 1;
                                a[y] = 0;
                            }


>printfの戻り値は出力した文字数です。
ありがとうございます。
では、
    m = printf("%d \n",i);

あっても意味ありませんね(笑)

実行結果はまず最初の配列が出てきて、
そのあと「10」と出てきて、1が10個でています。
なぜ?「10」は先ほど指摘された所を消したので
直ると思ったのですが・・・


No.18130

Re:二次元配列の交換
投稿者---REE(2004/11/15 19:57:44)


実行してみました。

ます、基本的なところでは、「最初の評価結果がすぐに上書きされている。」という点です。
これが起きた原因は変数名に意味のあるものをつけていないからです。

次に1が増える理由
 評価の改善によりa[x]とa[y]を交換したときに、a[x]が0になります。
 しかし、そのまま、yのループを続けてしまうために、
 次の交換でa[x]=0, a[y]=0 が a[x]=0, a[y]=1になってしまいます。

それ以外にも数点直さなければ、期待の動きはしないと思いますが、
ご自身でがんばってみてください。


No.18131

Re:二次元配列の交換
投稿者---ライガー(2004/11/15 20:19:21)


ありがとうございます。自力で頑張ってみます。
また何かあったらよろしくお願いします!


No.18136

Re:二次元配列の交換
投稿者---ライガー(2004/11/15 21:35:21)


たびたびすいません。(>_<)
例えばforループが以下のように三つあって、
三つめのループが終わったら一つ目のループに戻りたい時は
どうすればよろしいのでしょうか?Breakだったら一つのループしか
脱出できませんよね!?

for(     }
{
  for(    )
   {
    for(    )
     {

      }
   }
 ]




No.18139

Re:二次元配列の交換
投稿者---Hermit(2004/11/15 21:50:18)


今ひとつ意味が見えてきませんが?

三つ目のループが終わったのなら、二つ目のループにいるので
break だけで、一つ目のループに行ける筈ですが。

とりあえず、一気に二つループを抜けたいんだったら、
goto を使えばいいと思います。


No.18165

Re:二次元配列の交換
投稿者---ライガー(2004/11/16 18:20:43)


度々すいません。

>ます、基本的なところでは、「最初の評価結果がすぐに上書きされている。」 という点です。
初めの点数が一番高いので、これをminとしminより点数が低くなったら
交換して、minに新しい点数を代入して、また比べていくという風にしました。

>次に1が増える理由
> 評価の改善によりa[x]とa[y]を交換したときに、a[x]が0になります。
> しかし、そのまま、yのループを続けてしまうために、
> 次の交換でa[x]=0, a[y]=0 が a[x]=0, a[y]=1になってしまいます。

以下のようにしてbreakを使って元に(初めのループに)戻す作業を付け加えたら1は増えなくなりました。
if(n<min){
                                min = n;
                                break;
                            }


そして実行してみると、配列の並びは一切変わってませんでした。
しかし、評価の点数だけは最初より微妙に少なくなっていました。
何とかここまでやってみたのですが、うまくいきませんでした。
どこがおかしいのでしょうか!?

#include<stdio.h>
int hyoka(int a[]);
int min,n,x,y;
main(){
    int a[15] = {1,1,1,0,0,1,0,1,0,1,1,1,0,0,0};
    int i = hyoka(a);
    for(i=0; i<15; i++){
    printf("%d " , a[i]);
    }
    printf("\n");
    min = printf("%d \n",hyoka(a)); //初めの評価
    for(x=0; x<15; x++){
            if(a[x] == 1){  //1の場所の検索
                for(y=0; y<15; y++){
                        if(a[y] == 0){//0の場所の検索
                            a[x] = 0;
                            a[y] = 1;   //0と1を交換
                            n=hyoka(a);  //交換後の評価
                            if(min<=n){
                                a[x] = 1;
                                a[y] = 0;
                            }
                            if(n<min){
                                min = n;
                                break;
                            }
                        }
                }
            }
            for(i=0; i<15; i++){
                printf("%d " , a[i]);
                if(i ==14){
                printf("\n");
                }
            }
    }
    printf("\n");
    for(i=0; i<15; i++){    //並び替え後のa[]の並び
    printf("%d" , a[i]);
    }
    printf("\n");
    printf(" %d " , n);
    return 0;
}




No.18167

Re:二次元配列の交換
投稿者---REE(2004/11/16 18:58:12)



>int m,n,x,y;

これがグローバルになっているのは何故ですか?


>>ます、基本的なところでは、「最初の評価結果がすぐに上書きされている。」 という点です。

>int i = hyoka(a); // iに評価を代入
>for(i=0; i<15; i++){ // iを上書き

ここのことです。
使わなくなったのならば、単にint i;としましょう。

>初めの点数が一番高いので、これをminとしminより点数が低くなったら
>交換して、minに新しい点数を代入して、また比べていくという風にしました。

>min = printf("%d \n",hyoka(a)); //初めの評価

この行を見てがっかりしました。
No.18126の発言を見直してください。


>そして実行してみると、配列の並びは一切変わってませんでした。
>しかし、評価の点数だけは最初より微妙に少なくなっていました。

実行してみましたが、最初の2行でちゃんと並びは変わっていましたよ。



No.18169

Re:二次元配列の交換
投稿者---ライガー(2004/11/16 20:10:53)


返信いつもありがとうございます。

>実行してみましたが、最初の2行でちゃんと並びは変わっていましたよ。
どのプログラムで実行してくれたのですか?下に添付した今の私のままだったらちゃんと動かないと思うのですが・・・

>また基本的なところでは、「最初の評価結果がすぐに上書きされている。」 という点です。

int i = hyoka(a); // iに評価を代入
for(i=0; i<15; i++){ // iを上書き
ここのことです。
使わなくなったのならば、単にint i;としましょう。

ここが何か理解できないのですが。どういうことなのでしょうか?

#include<stdio.h>
int min,n,x,y;
int hyoka(int a[]);
main()
{
    int a[15] = {1,1,1,0,0,1,0,1,0,1,1,1,0,0,0};
    int i = hyoka(a);
    for(i=0; i<15; i++){
    printf("%d " , a[i]);
    }
    printf("\n");
    min = printf("%d \n",hyoka(a)); //初めの評価
    for(x=0; x<15; x++){
            if(a[x] == 1){  //1の場所の検索
                for(y=0; y<15; y++){
                        if(a[y] == 0){//0の場所の検索
                            a[x] = 0;
                            a[y] = 1;   //0と1を交換
                            n=hyoka(a);  //交換後の評価
                            if(min<=n){
                                a[x] = 1;
                                a[y] = 0;
                            }
                            if(i<min){
                                min = n;
                                break;
                            }
                        }
                }
            }
            for(i=0; i<15; i++){
                printf("%d " , a[i]);
                if(i ==14){
                printf("\n");
                }
            }
    }
    printf("\n");
    for(i=0; i<15; i++){    //並び替え後のa[]の並び
    printf("%d" , a[i]);
    }
    printf("\n");
    printf(" %d " , n);
    return 0;
}
    

int hyoka(int a[]){
    int i;
    int hyoka = 0;
    int flg1 = 0;
    int flg2 = 0;
    int flg3 = 0;
    int flg4 = 0;
    for(i=0; i<15; i++){
        if(a[i]==1){
            if(flg1 == 1){
                flg2 = 1;
                flg1 = 0;
            }
            else if(flg2 == 1){
                flg3 = 1;
                flg2 = 0;
            }
            else if(flg3 == 1){
                flg4 = 1;
                flg3 = 0;
            }
            else if(flg4 == 1){
                continue;
            }
            else{
                flg1 = 1;
            }
        }else
        {
            if(flg2 == 1)   hyoka += 1;
            if(flg3 == 1)   hyoka += 3;
            if(flg4 == 1)   hyoka += 6;
            flg1 = flg2 = flg3 = flg4 = 0;
        }
    }
    return hyoka;
}



No.18173

Re:二次元配列の交換
投稿者---ぽへぇ(2004/11/16 22:15:39)


ご自分の発言も忘れるようでは先が思いやられますが…。

No.18126
ライガーさん:
>では、
> m = printf("%d \n",i);
>は
>あっても意味ありませんね(笑)
って書いてますよね。

で、
> min = printf("%d \n",hyoka(a)); //初めの評価
これは何なんでしょうか?

書くのなら、
min = hyoka(a); //初めの評価
printf("%d \n", min);
とか。

それから、
1. >int i = hyoka(a); // iに評価を代入
2. >for(i=0; i<15; i++){ // iを上書き
>ここのことです。
>使わなくなったのならば、単にint i;としましょう。
>ここが何か理解できないのですが。どういうことなのでしょうか?

1. で hyouka(a) の結果をiに代入して、
2. の for 文で i に 0 を代入して。

それでは 1. で hyouka(a) を計算して i に代入した意図は何ですか?
すぐに消えて(上書きされて)しまうのに。
…という指摘です。



No.18185

Re:二次元配列の交換
投稿者---REE(2004/11/17 10:29:13)


>>実行してみましたが、最初の2行でちゃんと並びは変わっていましたよ。
>どのプログラムで実行してくれたのですか?下に添付した今の私のままだったらちゃんと動かないと思うのですが・・・

このプログラムでは変化しないですね。
前回のソースにはhyoka関数がなかったので、あなたがNo.18120で提示したhyoka関数で試しました。
あなたしか知らないソースで実行できる訳ありませんよね?


その他の点はぽへぇさんの説明の通りです。
他を修正すれば、変化するようになるでしょう。



No.18188

Re:二次元配列の交換
投稿者---江戸門電鉄(2004/11/17 11:41:12)


>(タブサーチというものなんですが・・・)

アルゴリズムに興味が有るので、ついここに反応してしまいました。
タブーサーチの間違いですよね。それとも長音記号の省略がはやっているのでこの形でも通用しているの?

タブーサーチならばタブーリストやその有効期間の管理が
ポイントになりますね。
その辺は大丈夫かな。


No.18196

Re:二次元配列の交換
投稿者---ライガー(2004/11/17 15:17:12)


ご返信ありがとうございます。
皆さんの協力で何とか希望通りに動くようになりました。
(hyoka関数の所の記述が曖昧で、最初の配列が
1,1,1,0,0,1,0,1,0,1,1,1,0,0,0 ならちゃんと動くのですが
1,1,1,0,0,1,0,1,0,1,1,1,0,0,1 とするとまた1が多くなるのですが・・)

#include<stdio.h>

int hyoka(int a[]);
int min,n,x,y,z;
main(){
    FILE *fp;
    int a[15] = {1,1,1,0,0,1,0,1,0,1,1,1,0,0,0};
    int i = hyoka(a);
    for(z=0; z<15; z++){
    printf("%d " , a[z]);
    }
    printf("\n");
    fp = fopen("narabi.txt", "w");
    min = hyoka(a); //初めの評価
    printf("%d \n", min);
    fprintf(fp,"%d \n", min);
    for(x=0; x<15; x++){
            if(a[x] == 1){  //1の場所の検索
                for(y=0; y<15; y++){
                        if(a[y] == 0){//0の場所の検索
                            a[x] = 0;
                            a[y] = 1;   //0と1を交換
                            n=hyoka(a);  //交換後の評価
                            if(min<=n){
                                a[x] = 1;
                                a[y] = 0;
                            }
                            if(n<min){
                                min = n;
                                break;
                            }
                            for(z=0; z<15; z++){
                                printf("%d " , a[z]);
                                fprintf(fp,"%d " , a[z]);
                                    if(z ==14){
                                        printf("\n");
                                        fprintf(fp,"\n");
                                    }
                            }
                        }
                }
            }
    }
    printf("\n");
    for(z=0; z<15; z++){    //並び替え後のa[]の並び
    printf("%d" , a[z]);
    fprintf(fp,"%d" , a[z]);
    }
    printf("\n");
    fprintf(fp,"\n");
    printf(" %d " , n);
    fprintf(fp," %d " , n);
    fclose(fp);
    return 0;
}
    

int hyoka(int a[]){
    int i;
    int hyoka = 0;
    int flg1 = 0;
    int flg2 = 0;
    int flg3 = 0;
    int flg4 = 0;
    for(i=0; i<15; i++){
        if(a[i]==1){
            if(flg1 == 1){
                flg2 = 1;
                flg1 = 0;
            }
            else if(flg2 == 1){
                flg3 = 1;
                flg2 = 0;
            }
            else if(flg3 == 1){
                flg4 = 1;
                flg3 = 0;
            }
            else if(flg4 == 1){
                continue;
            }
            else{
                flg1 = 1;
            }
        }else
        {
            if(flg2 == 1)   hyoka += 1;
            if(flg3 == 1)   hyoka += 3;
            if(flg4 == 1)   hyoka += 6;
            flg1 = flg2 = flg3 = flg4 = 0;
        }
    }
    return hyoka;
}

>>タブーサーチの間違いですよね。それとも長音記号の省略がはやっているのでこの形でも通用しているの?

タブサーチでもタブーサーチでも検索できたのですが、日本語の意味を
考えるとタブーサーチですよね?

>>タブーサーチならばタブーリストやその有効期間の管理が
>>ポイントになりますね。
>>その辺は大丈夫かな。

将来的にはこれを2次元配列にして、これをバイトなどの勤務表と見て
1が出勤日、0が休みとして、横の行が人で、縦の列が日にちを表すとし、
ある日に入らなければならないバイトの人数を拘束条件としたり、
1か月に入るバイトの日数にバラツキがでないようにしたりなどして
良いスケジュール表を作ろうと思っております。
このプログラムを2次元配列にしたり、条件を付けたりなどするので
またわからないことも出てくると思いますので、
そのときはご享受お願いします。


No.18201

Re:二次元配列の交換
投稿者---REE(2004/11/17 17:30:53)


ご参考にどうぞ

#include<stdio.h>

int hyoka(int a[]);
void print(FILE *fp, int a[]);
void print_str(FILE *fp, char *str);

int main(){
    FILE *fp;
    int a[15] = {1,1,1,0,0,1,0,1,0,1,1,1,0,0,0};
    int min = hyoka(a); //初めの評価
    int n,x,y;
    fp = fopen("narabi.txt", "w");
    print_str(fp, "Start:\n");
    print(fp, a);
    print_str(fp, "\nprocess:\n");
    for(x=0; x<15; x++){
        if(a[x] == 1){    //1の場所の検索
            for(y=0; y<15; y++){
                if(a[y] == 0){  //0の場所の検索
                    a[x] = 0;
                    a[y] = 1;   //0と1を交換
                    n=hyoka(a);  //交換後の評価
                    if(min<=n){
                        a[x] = 1;
                        a[y] = 0;
                    }else{
                        min = n;
                        print(fp, a);
                        break;
                    }
                }
            }
        }
    }
    print_str(fp, "\nLast:\n");
    print(fp, a);   //並び替え後のa[]の並び  と 最終評価

    fclose(fp);

    getchar();
    return 0;
}

void print(FILE *fp, int a[]){
    int i, n;
    FILE *fp_table[] = {fp, stdout};
    for(n = 0; n < 2; n++)
    {
        for(i=0; i<15; i++){
            fprintf(fp_table[n],"%d " , a[i]);
        }
        fprintf(fp_table[n]," (%d)\n", hyoka(a));
    }
}

void print_str(FILE *fp, char *str){
    int n;
    FILE *fp_table[] = {fp, stdout};
    for(n = 0; n < 2; n++)
    {
        fputs(str, fp_table[n]);
    }
}

int hyoka(int a[]){
    int i;
    int hyoka = 0;
    int count = 0;
    for(i=0; i<15; i++){
        if(a[i]==1){
            count++;
        }else{
            if(count == 2)   hyoka += 1;
            if(count == 3)   hyoka += 3;
            if(count >= 4)   hyoka += 6;
            count = 0;
        }
    }
    return hyoka;
}




No.18202

Re:二次元配列の交換
投稿者---ライガー(2004/11/17 18:06:58)


ありがとうございます。ムチャクチャかっこいいです。
評価の部分を
if(a[i]==1){
count++;
}else{
if(count == 2) hyoka += 1;
if(count == 3) hyoka += 3;
if(count >= 4) hyoka += 6;
count = 0;
}
としてくれたのですが、相変わらず
1,1,1,0,0,1,0,1,0,1,1,1,0,0,0 の部分を
1,1,1,0,0,1,0,1,0,1,1,1,0,0,1 としたら何故1が多くなるのですか?

これからこのプログラムを進化させようと、しばらく自力で頑張ってみようと
思います。そこで2次元配列にする時に、違う行の「0」とも交換できるように
して、各行とも評価を良くしていこうと思うのですが、2次元にするにあたって
各行ごとに評価値を出すやり方など、良いやり方などがあったらお願いします。

P.Sしばらく自力でやろうと思っているので、各行ごとの評価値の出し方以外にも
  参考になることがありましたら、よろしくお願いします。  
  お世話になりました。





No.18208

Re:二次元配列の交換
投稿者---REE(2004/11/17 21:06:33)


>評価の部分を
(略)
>としてくれたのですが、相変わらず

この部分は同じ機能のまま書き換えただけですので、変化しないはずです。

>1,1,1,0,0,1,0,1,0,1,1,1,0,0,0 の部分を
>1,1,1,0,0,1,0,1,0,1,1,1,0,0,1 としたら何故1が多くなるのですか?

最初から最後まで9個のままで、別に多くなってはいませんし、
ちゃんと評価関数に基づいて評価値が0にまで改善してますよ。


No.18301

Re:二次元配列の交換
投稿者---ライガー(2004/11/22 17:41:23)


頑張ってみたのですが、わからない所がやはり出てきたので、アドバイス
お願いします。

前に教えてくださった一次元配列だと
1、1の場所を検索
2、0の場所を検索
3、交換
4、評価が良くなればそのままで、悪くなれば交換したものを戻す
5、繰り返し
で良かったのですが、二次元配列になると
「各行ごとに評価値を出し、交換した行と評価値を比べる」
という事をするのですが、一次元配列だと評価値が一つしかなかったのですが、
初めの配列を2行20列とすると、構造体の部分(評価値のところ)が1行20列の配列になります。二次元配列にした時の評価値の比べ方はどうすればよろしいのでしょうか?
(ここのホームページの11−2も読んだのですが、自分のプログラムせ応用
できませんでした)


No.18304

Re:二次元配列の交換
投稿者---REE(2004/11/22 19:28:32)


>初めの配列を2行20列とすると、構造体の部分(評価値のところ)が1行20列の配列になります。二次元配列にした時の評価値の比べ方はどうすればよろしいのでしょうか?

構造体の部分ってどこですか?


No.18305

Re:二次元配列の交換
投稿者---ライガー(2004/11/22 20:48:46)


すいません。構造体ではなく関数の以下のところです。
int hyoka(int a[]){
    int i;
    int hyoka = 0;
    int count = 0;
    for(i=0; i<20; i++){
        if(a[i]==1){
            count++;
        }else{
            if(count == 2)   hyoka += 1;
            if(count == 3)   hyoka += 3;
            if(count >= 4)   hyoka += 6;
            count = 0;
        }
    }
    return hyoka;
}


例えば2行20列の二次元配列にしたとき、各行ごとの評価値を出して、行ごとで評価値を比べたいのですが、ここの関数のところを以下のようにしようと思ったのですが・・・

int hyoka(int a[][20]){
    int i,j;
    int hyoka = 0;
    int count = 0;
    for(i=0; i<2; i++){
        for(j=0; j<20; j++){
            if(a[i][j]==1){
                count++;
            }
            else{
            if(count == 2)   hyoka += 1;
            if(count == 3)   hyoka += 3;
            if(count >= 4)   hyoka += 6;
            count = 0;
            }
        }
    }
    return hyoka;
}




「C言語では,関数から配列を返す(returnする)ことはできない.
 return で指定できるのは,値(int, char, double 等)だけ.
 そのため,
 結果を格納する配列を,呼び出し側で宣言しておく.
 関数呼び出し時に,結果格納用の配列も引数で渡す.
 呼ばれた関数は,結果格納用の配列に,結果を格納する」

ということがネットに書いてあったので、このやり方ではダメだと
思うのですが・・・ご享受お願いします。




No.18310

Re:二次元配列の交換
投稿者---REE(2004/11/23 10:06:48)


>「C言語では,関数から配列を返す(returnする)ことはできない.
> return で指定できるのは,値(int, char, double 等)だけ.
> そのため,
> 結果を格納する配列を,呼び出し側で宣言しておく.
> 関数呼び出し時に,結果格納用の配列も引数で渡す.
> 呼ばれた関数は,結果格納用の配列に,結果を格納する」
>
>ということがネットに書いてあったので、このやり方ではダメだと
>思うのですが・・・ご享受お願いします。

そう思ったのであれば、その説明の様に変更すればいいでしょう。
それによって、プログラムの全体の流れが変わることもないでしょう。

もし、変更方法で分からないの部分があったのであれば、その個所を明確にしてください。



No.18327

Re:二次元配列の交換
投稿者---ライガー(2004/11/23 22:26:04)


「2次元配列を関数に渡す場合、列の指定をする」と書いてあったので
以下のようにしました。(関数のところの表記は違ってますが)
#include<stdio.h>

int hyoka(int a[][20]);

 main(){
    int i;
    int a[2][20] = {
                    {1,1,0,0,0,1,0,1,0,1,1,1,0,0,0,1,1,0,1,1},
                    {1,0,0,1,1,1,0,1,1,0,0,1,1,1,0,0,1,0,1,0},
    };
//  int min = hyoka(a); //初めの評価
//  printf("%d",min);
}

int hyoka(int a[][20]){
    int i,j;
    int hyoka = 0;
    int count = 0;
    for(i=0; i<2; i++){
        for(j=0; j<20; j++){
            if(a[j]==1){
                count++;
            }
            else{
            if(count == 2)   hyoka += 1;
            if(count == 3)   hyoka += 3;
            if(count >= 4)   hyoka += 6;
            count = 0;
            }
        }
   }
    return hyoka;
}




一次元配列の時は、returnで値を返して
// int min = hyoka(a); //初めの評価
// printf(&quot;%d&quot;,min);
で結果が出てきたのですが、returnは配列を返せないので
関数部分の表記を直す必要があるのですが・・・
以前
「結果を格納する配列を,呼び出し側で宣言しておく.
 関数呼び出し時に,結果格納用の配列も引数で渡す.
 呼ばれた関数は,結果格納用の配列に,結果を格納する」
というのを調べたのですが、「結果格納用の配列に,結果を格納する」
ということは結局配列を返すのではないのでしょうか?
どのようにすれば、一次元配列の
// int min = hyoka(a); //初めの評価
// printf(&quot;%d&quot;,min);
のときのように、行ごとに値が出せるようになるのですか?


No.18330

Re:二次元配列の交換
投稿者---rvrdriver(2004/11/23 23:12:06)


>どのようにすれば、一次元配列の
>// int min = hyoka(a); //初めの評価
>// printf(&quot;%d&quot;,min);
>のときのように、行ごとに値が出せるようになるのですか?

上記の部分だけを考慮すると一次元のkyoka()関数が出来ているのだから
呼び出し側でkyoka(a[0])、kyoka(a[1])をmain()内で行えばよいのでは?

#include<stdio.h>

#define ARY_SIZE(x)  (sizeof(x)/sizeof(x[0]))

int hyoka(int a[]);

int main()
{
    int i;
    int a[2][20] = {
                    {1,1,0,0,0,1,0,1,0,1,1,1,0,0,0,1,1,0,1,1},
                    {1,0,0,1,1,1,0,1,1,0,0,1,1,1,0,0,1,0,1,0},
    };

    /**************************************************/
    /* 呼び出し側で一次元の配列を渡すのはだめですか? */
    /**************************************************/
    for (i=0; i < ARY_SIZE(a); i++) {
        int min = hyoka(a[i]); //初めの評価
        printf("%d\n",min);
    }

    return 0;
}

int hyoka(int a[]){
    int i,j;
    int hyoka = 0;
    int count = 0;
    for(i=0; i<2; i++){
        for(j=0; j<20; j++){
            if(a[j]==1){
                count++;
            }
            else{
                if(count == 2)   hyoka += 1;
                if(count == 3)   hyoka += 3;
                if(count >= 4)   hyoka += 6;
                count = 0;
            }
        }
    }
    return hyoka;
}




No.18306

Re:二次元配列の交換
投稿者---shu(2004/11/22 21:07:21)


>頑張ってみたのですが、わからない所がやはり出てきたので、アドバイス
>お願いします。

その前に、今まで受けたアドバイス通りにできていますか?
返信する前に、頭からスレッド内容を確認してみてください。

>前に教えてくださった一次元配列だと
>1、1の場所を検索
>2、0の場所を検索
>3、交換
>4、評価が良くなればそのままで、悪くなれば交換したものを戻す
>5、繰り返し
>で良かったのですが、二次元配列になると
>「各行ごとに評価値を出し、交換した行と評価値を比べる」
>という事をするのですが、一次元配列だと評価値が一つしかなかったのですが、
>初めの配列を2行20列とすると、構造体の部分(評価値のところ)が1行20列の配列になります。二次元配列にした時の評価値の比べ方はどうすればよろしいのでしょうか?

↑何度読み課しても理解しがたい文章です。
とりあえず、客観的に見てはっきりと意味のわかる内容にしてください。
内容を整理しているうちに、理解できる場合も良くあります。


No.18307

Re:二次元配列の交換
投稿者---ライガー(2004/11/22 21:23:18)


すいません。今まで教えてくれた人が、自分のしていることを
理解していると勘違いしてました。
簡単に言うと、関数を作って値を返す時、return文では配列を返せないので
どのようにすれば良いか知りたいです。
(私のしているプログラムは、関数で何十行一列かの配列を返して、
各行ごとに関数部分で返した値を比べたいと思っております。