• ベストアンサー

配列の時間発展のアルゴリズム

javaのプログラムで配列で行き詰ってます。 まず、1×n列の配列をつくって箱の中にいくつか玉があるとします。各箱の中には1つしか玉はないものとします。最初は時間をtと置き、 1.玉の存在する各箱において、玉のコピーをつくる 2.コピーの中の一番左の玉を最も近い右の空き箱に移動させる 3.残りのコピーの中の一番左の玉を最も近い右の空き箱に移動させる 4.全てのコピーを移動させるまで3を繰り返す 5.もとの玉を消す ここで時間をt+1とします。配列の一番右端のn番目の次は1番目にループさせることにします。 箱玉系というものの動きなんですが、値を大きくするとうまく思った通りに動かなくて困ってます。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

そう言えばそうですね。>kazsharpさん。 では、改造します。 // box[]をbox2[]に全部コピーする。 boolean[] box2 = (boolean[]) box.clone(); for (int i = 0; i < box2.length; i++) {  if (box2[i]) { // コピーの玉があったら   // 右方向に向かって空き箱を探す。   for (int j = 1; j < box.length; j++) {    int p = (i + j) % box.length;    if (! box[p]) {     // 空き箱を見つけたので玉を入れる(trueにする)     box[p] = true;     // 元の場所は玉を消す(falseにする)     box[i] = false;     // box2[i]はもう二度と調べないのでそのまま放置     break;    }   }  } } // この後 box2 はもう不要なのでメモリ解放 // (というか参照されないようにしてGCに解放を任せる)。 box2 = null;

kuropanda
質問者

お礼

ご指導ありがとうございました。なんとかプログラムが完成しました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (2)

  • kazsharp
  • ベストアンサー率37% (16/43)
回答No.2

「思ったとおりに動かない」ということは「プログラムが間違ってる」ということです。 これ以上の回答をもとめるなら、どう上手く動かないのか説明するか、ソースを提示するべきでしょう。 ちなみに、No.1の方の回答では「元の玉を移動してtrueになった箱」の玉も移動するのではないのでしょうか? 「元の箱の配列」と別に「移動のための箱の配列」を用意してそこに移動後の玉を置く(trueにする)必要があると思います。

全文を見る
すると、全ての回答が全文表示されます。
回答No.1

boolean[] box = new boolean[100]; というように配列が作ってあるとして、玉が入っている箱が true で入っていない箱が false だとすると、こんな風でいいんじゃないでしょうか。 for (int i = 0; i < box.length; i++) {  if (box[i]) { // 玉が入っている箱だったら   // 右方向に向かって空き箱を探す。   for (int j = 1; j < box.length; j++) {    int p = (i + j) % box.length;    if (! box[p]) {     // 空き箱を見つけたので玉を入れる(trueにする)     box[p] = true;     // 元の場所は玉を消す(falseにする)     box[i] = false;     break;    }   }  } } 一度に全ての玉をコピーしていませんが、これでも同じですよね?

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 配列のコピー

    BVA初心者です。 基礎の基礎なのですが、質問させていただけないでしょうか。 excel VBAで、いま画面に 12345678910 12345678910 12345678910 ・・・・・・ と、あります。 これと、同じ配列を、右端にも作りたいのですが、 ”A(i, 1) = A(i, JMAX + 1)” のような記述方法で、全体をコピーすることはできますか?(copyメソッドは使わないで、できるはずなのですが・・・。) コピーができずに困ってます、よろしくお願いします。 Const IMAX As Long = 10 Const JMAX As Long = 10 Sub A() Cells.Clear Dim A(IMAX + 1, JMAX + 1) As Long Dim B(IMAX + 1, JMAX + 1) As Long For i = 1 To IMAX + 1 For j = 1 To JMAX Cells(i, j) = j A(i, 1) = A(i, JMAX + 1) '左端の配列を一番右にコピーする A(i, JMAX + 2) = A(i, 2) '左から2番目の配列を右から2番目にコピーする Next Next End Sub

  • 配列の中に配列をセットし、呼び出したい

    配列@listの要素として@pickupの配列をセットしたいと思っています。 ループ文の中で繰り返し、$countというループの回数をカウントしている変数によってセットする場所を変えていきたいのです。 for($count=0;$count>100;$count++){ (中略しますが、ファイルを読み込み正規表現で値を吸い出しています) @pickup=("$1","$2","$3");#@pickupはループごとに中身が変わります。 @list[$count] = @pickup;#ここで@listの要素として@pickupをセット } 上記のように記述したとします。 print $list[80];とすると、@pickupの[0]の要素しか表示しません。 print @list[80];としても上に同じ。 質問1.どうやったら@list[$count]で配列の要素に配列を入れられますか? 質問2.その後どうやって配列の中の配列の要素を取り出せますか? イメージとしては@listの50番目の要素@pickupの0番目もしくは1番目の要素を取り出したいという感じです。

    • ベストアンサー
    • Perl
  • 配列の中から最大値だけ取り出す方法

    VB 2005,Framework2.0を使用しています。 複数のある配列の中から最大値の値だけを抽出するプログラムを作ろうと思っています。 For等のループを使うのは分かりますが、そこからどの様にコードを書けばいいのか分からなく困っています。 例えば配列にランダムに数値が入っていたとします。 Dim Hako(5) As Integer Hako(0) = 10 Hako(1) = 16 Hako(2) = 31 Hako(3) = 12 Hako(4) = 42 Hako(5) = 5 とあったらこの配列の中の最大値(42)のみを抽出したいです。 宜しくお願いします。

  • パチスロ花火の配列について

    最近、パチスロをやり始めた初心者ですがリール配列について質問です。 たとえば、花火ですが 左リール上段に19番のHANABIを狙って左にスイカが止まったとします。 ここで右リールを適当押しすれば必ずスイカが止まると聞きます。 ですが、右リールに14・13・12番をちょうど狙ったとき リールは4コマしか滑らないので 19番のスイカは滑ってこないと思うのですが、 これは適当押しで大丈夫なのですか?

  • 配列への大量コピーってあるの?

    今,単純に「,」で区切られたデータが大量に続くテキストファイルがあっとします。(もちろん有限ですが) 1,2,3,4,5,6,7,8,9,10,11,12・・・,9999兆 このテキストデータを,javascriptで読み込んでresponseTextに入れたものを, var res = oj.responseText; のようにresにします。 この後, rows = res.split(','); のように,それぞれの数字を配列に入れたとします。 このとき,この配列にデータを入れるという作業は,実際に,rows配列にデータがコピーされるのでしょうか。  それとも,何らかのポインタだけがrowsオブジェクトがに入って,rows[n]とかしたときに,rowsのメソッドが,を判断してn番目の数字を取得するようになっているのでしょうか。  また,それを確かめる方法(証拠)はありますでしょうか。 また,似たような質問ですが, 1,2,3,4,5,6,7,8,9,10,11,12・・・,9999 というデータから res.split(',')[n] のようにsplitメソッドでn番目を取り出す処理と, すでに配列になっているものからn番目を取り出す処理 rows[n] とでは,どちらの作業が軽い(高速)でしょうか? 感覚的には後者ですが,実際の処理はどうなのかなと

  • 配列

    適当な記述ですが、次を見てください。 void roll(int *c) { int n, b2[8]; if(t<3) { for(n=0; n<8; n++) b2[n]=c[n]; for(n=0; n<8; n++) c[b2[n]]=7-n; for(n=0; n<8; n++) printf("%d",c[n]); printf("\n"); t++; roll(c); } else t=0; } int main() { int b[]={3,6,4,0,7,2,5,1}; roll(b); for(n=0; n<8; n++) printf("%d",b[n]); //36407251が表示されるようにしたい。 return(0); } rollが何の関数かは省略しますが、rollにmainのb(ポインタ?)を渡し、ある処理をして,それでmainに戻ってきた時にb[]を表示すると、36407251が表示されません。 ポインタを引数にするってことはポインタでさしてるとこをrollで操作してるわけですよね? そうすれば変わって当然だとはおもいます。 でも関数1で関数2に配列1を渡し、その関数2の中でで配列1の値が変化しても、元の関数1にもどれば配列1のまま変化していないようにするにはどうすればいいですか? やはり もう1つ配列を用意しなきゃだめなのでしょうか。

  • ループの終わらせ方

    あるboolean配列でtrueなら■falseなら□を表示させ、時間とともにある規則で動かしていくプログラムを組みました。配列の宣言などを省略してますがこんな感じです。 do{ boolean[] box2 = (boolean[]) box.clone(); for ( i = 0; i < box2.length; i++) { if (box2[i]) { // コピーの玉があったら // 右方向に向かって空き箱を探す。 for (int j = 1; j < box.length; j++) { int p = (i + j) % box.length; if (! box[p]) { // 空き箱を見つけたので玉を入れる(trueにする)  box[p] = true; // 元の場所は玉を消す(falseにする) box[i] = false; // box2[i]はもう二度と調べないのでそのまま放置 break;   } }   } } box2 = null; for(h=0; h < box.length; h++){   if(box[h] == false) System.out.print("□"); if(box[h] == true) System.out.print("■"); } r++; }while(box == box && r<20); ちなみに表示結果は □■■□□■□□■□□■ ■□□■■□■□□■□□ □■□□□■□■■□■□ ・ ・ こんな感じになります。ここで質問なんですが、 過去と同じ配置の配列が出てきた時点でwhile文の ループを終わらせるにはどうすればよいでしょうか? 現時点ではループが20回になった時点で止めるようにしてます。

  • C#でPictureBox内での図形移動について

    例えばPictureBoxに縦棒グラフを10本描画し、それが時間の経過と共に全体的に1本づつ左に移動して右端には最新の情報が表示されている様なものが作りたい。 それで右の9本をコピーして左端に移動(上書き)し、右端に新しい棒グラフを描画すれば良いと思っているのですが、図形を移動する方法があれば教えて下さい。 コピーする領域とコピー先の基準点を設定して呼び出すだけのメソッドを期待して探したのですが見当たりませんでした。 TranslateTransform()がそれっぽい感じもするのですがよく分かりません。 宜しくお願いします。

  • アルゴリズムの名前を教えてください

    16ビットのデータが、たとえば1000個、配列で与えられているとします。 unsigned short data[1000]; このデータをしらべて、重複するものを除いて何種類の値があるかを数える場合、一番素朴な方法だと、次のようにやると思います。 int i, j; int count = 0; for(i = 0; i < 1000; i++) {  for(j = 0; j < i; j++) {   if(data[j] == data[i]) {    break;   }  }  if(i == j) {   count++;  } } この方法だと、2重のループがあって処理に時間がかかります。そこで、メモリに余裕があれば内側のループをやめて、 int i; int count = 0; int flag[0x10000]; int n; for(i = 0; i < 0x10000; i++) {  flag[i] = 0; } count = 0; for(i = 0; i < 1000; i++) {  n = data[i];  if(flag[n] == 0) {   flag[n] = 1;   count++;  } } これだと、2重のループを使うものよりは速くなりますが、データが1000個しかないのに、65536個のflagをクリアするのに時間がかかり、今ひとつです。 ところが、次のような賢い方法があり、2重のループも配列のクリアも無くすことができます。 int i; int count = 0; unsigned short flag[0x10000]; unsigned short link[0x10000]; int n; for(i = 0; i < 1000; i++) {  n = data[i];  if(flag[n] >= count || link[flag[n]] != n) {   flag[n] = count;   link[count] = n;   count++;  } } 私がこのアルゴリズムを知ったのはかなり昔なので、どこで知ったのか思い出せないのですが、これほど賢いアルゴリズムだから何か名前がついていると思うのですが、それがわかりません。 名前がわからないので、人に頼んだりする時、上のような長い説明をしなくてはなりませんが、名前がわかっていれば「??法でやっといて」、と言えばいいのですけど。

  • アルゴリズムの正当性について

    線形探索法のアルゴリズムの擬似コードを書いて、そのアルゴリズムの正当性をループ不変式を用いて証明するという課題があります。 擬似コードは以下のような流れにしようと思いますが、この場合成り立つループ不変はどのようなことになりますか? 配列A[a1..an]に対してv=A[i]ならば添字iを、vがAの中になければNILを出力するアルゴリズムです。 for i ←1 to N if A[i] = v return i return NIL

このQ&Aのポイント
  • クリーニングを何回もしても、印刷チェックも問題ないのに、請求書のようなものを印刷すると白い線が縦に何本も入る問題に悩んでいます。
  • 文章だけのようなものの印刷では線は入らない状況です。
  • 使用環境はWindows10で有線LAN接続、電話回線はJCOMです。関連ソフトやアプリは特にありません。
回答を見る