プロが教える店舗&オフィスのセキュリティ対策術

以下のコードを再帰を使わない方法でやるにはどうしたらいいですか?
※インデントは全角空白になっています。

#define N(n) (a[n]*100+a[n+1]*10+a[n+2])
#define R(n) (a[n+2]*100+a[n+1]*10+a[n])

char a[9];

void sub(int n)
{
 int i;
 char c;

 if(n == 8){
  if(N(0) + N(3) * N(6) == R(6) * R(3) + R(0))
   printf("%d%d%d+%d%d%d×%d%d%d = %d%d%d×%d%d%d+%d%d%d\n",
    a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8],
    a[8], a[7], a[6], a[5], a[4], a[3], a[2], a[1], a[0]);
  return;
 }
 for(i = n; i < 9; ++i){
  c = a[i], a[i] = a[n], a[n] = c;
  sub(n + 1);
  c = a[i], a[i] = a[n], a[n] = c;
 }
}

int main(void)
{
 int i;

 for(i = 0; i < 9; ++i)
  a[i] = i + 1;
 sub(0);
 return 0;
}

gooドクター

A 回答 (3件)

何をやろうとしているのかが、今ひとつ解読できないのですが。


こういうのは、言葉で説明していただくと助かるんですが。
単に1から9の9個の数字の順列で、
(1*100+2*10+3)*(4*100+5*10+6)+(7*100+8*10+9)
=(9*100+8*10+7)+(6*100+5*10+4)*(3*100+2*10+1)
である順列を列挙する、ではいけないのでしょうか。
int main(){
for(int a0 = 1; a0 <= 9; a0++){
a[0]=a0;
for(int a1 = 1; a1 <= 9; a1++){
if(a1==a[0])continue;
a[1]=a1;
for(int a2 = 1; a2 <= 9; a2++){
if(a2==a[0] || a2==a[1])continue;
a[2]=a2;
for(int a3 = 1; a3 <= 9; a3++){
if(a3==a[0] || a3==a[1] || a3==a[2])continue;
a[3]=a3;
for(int a4 = 1; a4 <= 9; a4++){
if(a4==a[0] || a4==a[1] || a4==a[2] || a4==a[3])continue;
a[4]=a4;
for(int a5 = 1; a5 <= 9; a5++){
if(a5==a[0] || a5==a[1] || a5==a[2] || a5==a[3] || a5==a[4])continue;
a[5]=a5;
for(int a6 = 1; a6 <= 9; a6++){
if(a6==a[0] || a6==a[1] || a6==a[2] || a6==a[3] || a6==a[4] || a6==a[5])continue;
a[6]=a6;
for(int a7 = 1; a7 <= 9; a7++){
if(a7==a[0] || a7==a[1] || a7==a[2] || a7==a[3] || a7==a[4] || a7==a[5] || a7==a[6])continue;
a[7]=a7;
for(int a8 = 1; a8 <= 9; a8++){
if(a8==a[0] || a8==a[1] || a8==a[2] || a8==a[3] || a8==a[4] || a8==a[5] || a8==a[6] || a8==a[7])continue;
a[8]=a8;
if(N(0) + N(3) * N(6) == R(6) * R(3) + R(0))
   printf("%d%d%d+%d%d%d×%d%d%d = %d%d%d×%d%d%d+%d%d%d\n",
    a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8],
    a[8], a[7], a[6], a[5], a[4], a[3], a[2], a[1], a[0]);

} } } } } } } } }
}
9重ループです。
個々の添字ごとにすべての重複しない数字(0-9)を埋めます。
    • good
    • 0
この回答へのお礼

丁寧な回答まことにありがとうございました。

お礼日時:2021/10/10 17:17

再帰の除去を行うには、以下の方針で行うことになります。



* 関数 sub の中身を無限ループで囲む
* 変数 n や i などの値は、スタックに複数個を格納させる
* ループ内で使用する値はスタックの先頭(front)
* sub 内のループは排除して、無限ループに一本化する
* 再帰呼び出し(call)をスタックへの積み込み(push)に変更
* 再帰からの戻り(return)をスタックからの戻し(pop)に変更

ご提示のソースの場合、
sub(n+1) 後の戻し処理をどう行うかが肝となるでしょう。
    • good
    • 0

人力で再帰を展開する. まあ努力と根性だけの世界だな.

    • good
    • 0

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

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

gooドクター

このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング