Nicotto Town


不思議ちゃん


鶏ドリアンさんの情報の講義のC言語の課題


鶏ドリアンさんのブログ
http://www.nicotto.jp/blog/detail?user_id=276870&aid=16610652

にある、「情報の講義のC言語の課題」をCではなくて、「なでしこ」で書いてみました。
所用時間およそ30分。

課題は以下の通り。

自然数nを入力させる。

そのnに対して、「1」、「2」、…「n-1」、「n」の番号が書かれたn枚のカードを仮定する。
このn枚のカードを「n」が最上面になるように番号の順に積む。

その後、「最上面のカードを最下面に移動し、その次に最上面になったカードを捨てる」

という操作を繰り返し、最後にのこったカードの番号を出力せよ。


##################################################
# トリさんの課題
# 2010/07/31

# 自然数 N の入力
「自然数 N を入力してください」で尋ねてNに代入する。

# 入力チェック
もし(Nの整数部分<>N)OR (N<=0)ならば
 「自然数って言ってるだろ、ボケェ!」と言う。
 終わる。

# カードの作成
N回
 カード【回数】=N-回数+1
# カード【1】が一番上(初期値 N)

# 1操作につき1枚減るので、N-1回繰り返せば終り。
# だけれども、一応変数「枚数」を作ってこれで管理してみることに。
枚数=N

枚数>1の間
 最下面移動
 最上面廃棄
 枚数から1を直接引く

カード【1】を言う。
終わる。

# main routine 終了
# 以下のサブルーチンは、メインルーチンの変数を直接使用して変更する
# お作法の悪いサブルーチン(^_^;)
# C なら引数を参照渡し。なでしこではそんな手数はいらない。

●最下面移動
 移動対象=カード【1】
 カードの1を配列削除
 カードの枚数に移動対象を配列挿入

●最上面廃棄
 カードの1を配列削除
##################################################
 なでしこは、実務系プログラミング言語なので、配列操作など簡単ですね。配列から一つ引っこ抜くとか配列に一つ挿入するとか、命令1個で出来ちゃいますから楽ちんですね~♫
 「100」を入れたら「28」でしたぁ(^o^)ノ

アバター
2010/08/02 22:37
#include <stdio.h>
#include <math.h>

main()

{

int n, i, j, flag = 0;


printf("仮定として~中略~を出力する。\n\n自然数nを入力せよ。\n\n");

while (flag == 0){

flag = 1;

printf("n = ");
scanf("%d", &n);

j = n;

if (n >= 1){

for (i = 0; flag == 1 && j != 1; i++){


if (j%2 == 1){

n -= pow(2, i)*2;
}

j /= 2;

/* 全項数が2以下になったら */

if (j <= 2){

/* ループ中断 */

flag = 2;

}

}
n -= pow(2, i)*(j - 1);

printf("result = %d \n", n);

}else{

printf("数値が不正です。\n最初からやり直してください。\n\n");
flag = 0;

}

}

}
アバター
2010/08/02 22:14
よく見直したらデバッグがまだ足りませんでした。

あとで、こっちのブログに貼っておきます。
アバター
2010/08/02 21:35
要約です

/*

・操作過程で 「2の(0以上の整数)乗×(-1)」の公差の等差数列(便宜上、最上面のカードを初項とする)
 が次々と出現するのを利用

・項数が奇数か偶数か、によって次の等差数列の初項、及び項数が異なるので
 (偶数→初項、項数は元の半分、
  奇数→第3項、項数は自身から1引いたものを半分、ただし整数で処理してるのであまりここでは関係ない)
 場合分けが生じる点に注意

*/
アバター
2010/08/02 21:13
 いったん数学的に煮詰めてからコーディングされてますね~~。コメントがないと何やってるのか良く分からないですぅ~~(;_;)
 人のプログラム読むより自分で最初から考えた方が早いので、私も考えてみました~~。

http://www.nicotto.jp/blog/detail?user_id=288939&aid=16691800

アバター
2010/08/01 10:00
うわお・・・・
なにがなんだかわからないです・・・(´・ω・`;)
アバター
2010/07/31 14:41
こんなもんでどうでしょう?


#include <stdio.h>
#include <math.h>

main()

{

int n, i, j, flag = 0;


printf("仮定として~中略~を出力する。\n\n自然数nを入力せよ。\n\n");

while (flag == 0){

flag = 1;

printf("n = ");
scanf("%d", &n);

j = n;

if (n >= 1){

for (i = 0; flag == 1; i++){


if (j%2 == 1){

n -= pow(2, i)*2;
}

j /= 2;

if (j <= 3){

flag = 2;

}

}
n -= pow(2, i)*(j - 1);

printf("result = %d \n", n);

}else{

printf("数値が不正です。\n最初からやり直してください。\n\n");
flag = 0;

}

}

}
アバター
2010/07/31 09:08
計算しましたが、100だと28を返しますねw

ボクの考えてたアリゴリズムに、余分な部分があったみたいです^^;


でも、大いにヒントになりました。
どっちにしろ、配列を使う必要はなさそうです。
アバター
2010/07/31 08:44
ちょっと待てよ・・・

デバッグが要るのはこっちかもしれんw
アバター
2010/07/31 08:22
1→1
2,1→1,2→2
3,2,1→2,1,3→1,3→3,1→1
4,3,2,1→3,2,1,4→2,1,4→1,4,2→4,2→2,4→4
5,4,3,2,1→4,3,2,1,5→3,2,1,5→2,1,5,3→1,5,3→5,3,1→3,1→1,3→3
ですよね?
アバター
2010/07/31 08:14
あら~デバグ必要(^◇^;

で、だんだん暗闇にぃ♫

デバクしといてぇ(←ぉぃ)
アバター
2010/07/31 08:12
いや、100だと66を返すはずですw




Copyright © 2024 SMILE-LAB Co., Ltd. All Rights Reserved.