HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2020
0821
CLCR繰り返しで中央のマスから外側に探索6解決


CLCR

リンク

2020/8/21(Fri) 00:15:41|NO.91215

 0 1 2 3 4
0□□□□□
1□□□□□
2□□★□□
3□□□□□
4□□□□□

dim x,5,5 がこんな座標で配置されたマスだとして、中央(★の箇所、x(2,2))からrepeatを使って
うまいこと外側に向けて参照していくことは可能でしょうか?
隣接マスのどれから探索を始めるかは特に気にしていません。



この記事に返信する


あらや

リンク

2020/8/21(Fri) 16:08:19|NO.91225

すみません。
質問が良くわからないのですが

>外側に向けて参照していく
これはどう解釈すれば良いのでしょうか?

表示がズレたら申し訳ないんですが。

例1

 0 1 2 3 4    0 1 2 3 4
0□□□□□   0□□■□□
1□□■□□   1□■■■□
2□■★■□ → 2■■★■■
3□□■□□   3□■■■□
4□□□□□   4□□■□□

このように
最初に隣接するマス4つを確認
次は最初に確認した4マスに隣接するマスを確認・・・
という探索をしたいのか




例2
 0 1 2 3 4    0 1 2 3 4    0 1 2 3 4
0□□□□□   0□□□□□   0□□□□□
1□□■□□   1□□■■□   1□□■■□
2□□★□□ → 2□□★□□ → 2□□★■□ →
3□□□□□   3□□□□□   3□□□□□
4□□□□□   4□□□□□   4□□□□□


 0 1 2 3 4    0 1 2 3 4    0 1 2 3 4
0□□□□□   0□□□□□   0□□□□□
1□□■■□   1□□■■□   1□□■■□
2□□★■□ → 2□□★■□ → 2□□★■□
3□□□■□   3□□■■□   3□■■■□
4□□□□□   4□□□□□   4□□□□□

このように
一筆書きで螺旋を描くように
中心から1マスずつ全体を確認していきたいのか

またはこれらの例以外なのか


そして探索や参照と言われましても、
配列の数値を参照したいだけなのか
中心からそれぞれのマスに移動する最短のルートを調べたいのか。。。
などなどを詳しくお願いします。



CLCR

リンク

2020/8/21(Fri) 18:19:26|NO.91231

確かに書き方が悪く伝わりようもない内容でした。失礼いたしました。

あらやさんの例で言う、例2のような形で配列の値をチェックしたい次第です。
例2のやり方ではどうしても効率が悪い、ということでしたら例1の方法でもいいのですが…。



あらや

リンク

2020/8/21(Fri) 20:30:47|NO.91234

少し雑かもしれませんが、
例2をソース化してみました。

デバッグ用に長めのウェイトを入れたり
描画をしているので処理としては遅いですが
効率が悪いという程ではないと思います。

#module // 2点間の距離を返す #defcfunc range int x1, int y1, int x2, int y2 return sqrt( (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) ); #global x_max = 5; // 配列の1次元目の要素数 y_max = 5; // 配列の2次元目の要素数 dim check_flag, x_max, y_max; // 確認済みフラグ center_x = 2: center_y = 2; // 中心のインデックス cx = 2: cy = 2; // 確認する配列のインデックス check_flag(center_x, center_y) = 1; // 中心を確認済みにする repeat find_flag = 0; // 未確認マスの検知フラグ dist = 100.0; // 最も中心に近い距離を代入する変数(比較用に大きい数値を入れておく) dist_2 = 0.0; // 距離の比較用変数 // 周囲4マスのうち未確認のマスと中心マスとの距離を調べ // 最も中心に近いマスを次に確認する if( (cy - 1) >= 0 ) { // 上のマスを確認 if( check_flag(cx, cy-1) == 0 ) { // 未確認の場合 cx_3 = cx; // 一時的な代入 cy_3 = cy - 1; // 一時的な代入 gosub *substitution; // 変数への代入処理(各マス共通) } } if( (cx + 1) < x_max ) { // 右のマスを確認 if( check_flag(cx+1, cy) == 0 ) { // 未確認の場合 cx_3 = cx + 1; cy_3 = cy ; gosub *substitution; // 変数への代入処理(各マス共通) } } if( (cy + 1) < x_max ) { // 下のマスを確認 if( check_flag(cx, cy+1) == 0 ) { // 未確認の場合 cx_3 = cx; cy_3 = cy + 1; gosub *substitution; // 変数への代入処理(各マス共通) } } if( (cx - 1) >= 0 ) { // 左のマスを確認 if( check_flag(cx-1, cy) == 0 ) { // 未確認の場合 cx_3 = cx - 1; cy_3 = cy ; gosub *substitution; // 変数への代入処理(各マス共通) } } gosub *debug; // デバッグ用の描画処理 if( find_flag ) { // 未確認マスを検知している場合 cx = cx_2; // 次に確認する配列の1次元目のインデックス cy = cy_2; // 次に確認する配列の2次元目のインデックス check_flag(cx, cy) = 1; // 確認済みにする } else { // 未確認のマスが無かった場合 break; // ループ終了 } loop pos 0, 0: mes "終了"; stop; // 各変数への代入処理 *substitution find_flag = 1; // 未確認マスを検知 dist_2 = range( center_x, center_y, cx_3, cy_3 ); // 距離を取得 if( dist > dist_2 ) { // 距離が近い場合 dist = dist_2; // 距離を更新 cx_2 = cx_3; // 次に確認する配列の1次元目のインデックス(暫定) cy_2 = cy_3; // 次に確認する配列の2次元目のインデックス(暫定) } return; // デバッグ用の描画処理 *debug redraw 0; color 255, 255, 255: boxf; color 0, 0, 0; repeat y_max y = cnt * 20 + 50; cnt2 = cnt; repeat x_max x = cnt * 20 + 100; pos x, y; if( check_flag(cnt, cnt2) ) { mes "■"; } else { mes "□"; } loop loop redraw 1; await 100; return;



CLCR

リンク

2020/8/21(Fri) 23:05:52|NO.91236

あらやさん、有難うございました!
参考にさせていただきます!



kanamaru

リンク

2020/8/21(Fri) 23:15:13|NO.91238

例2を作ってみました。
reという配列にらせん状に数字が順番に代入されていると思います。

m=0,1,0,-1 xmax=5 ymax=5 x=int(xmax/2) y=int(ymax/2) dim re,xmax,ymax size=xmax*ymax c=0 repeat c2=cnt repeat (c2+2)/2 re(x,y)=c if(c=size-1):break c++ x+=m(c2\4) y+=m(3-c2\4) loop if(c=size-1):break loop repeat size r=re(cnt\xmax,cnt/ymax) if(r<10):mes " ",1 mes ""+r,1 if(cnt\xmax=xmax-1){ pos 0:mes "" }else{ mes ",",1 } loop
多分きちんと動いていると思います。
xmaxとymaxが等しいとたぶん問題ないですが、
ymaxとxmaxが等しくない場合はエラーで実行できません。
一応大小関係なく動くようにもできますが、
そもそも縦横が違うサイズを想定しているかどうかわからないので
とりあえずこのままにしておきます。
縦横が違うサイズでも動くようにしたい場合は言ってください。
まあ大した書き換えは必要ないのですが。



kanamaru

リンク

2020/8/21(Fri) 23:32:56|NO.91240

すみません。一応検証したら縦横等しくてもエラー出る条件があるみたいです。
多分偶数の時にエラーが出てるのだと思います。
原因はわかったので、改良したのを公開します。
(縦横が等しければらせん状に必ず辿れると思ってたんですけど違うんですね。)
原因の解決のために先述の縦横等しくなくても動く版にしました。

onerror *p m=0,1,0,-1 xmax=5 ymax=5 x=int(xmax/2) y=int(ymax/2) dim re,xmax,ymax size=xmax*ymax c=0 repeat c2=cnt repeat (c2+2)/2 if((x=limit(x,0,xmax-1))&&(y=limit(y,0,ymax-1))){ re(x,y)=c if(c=size-1):break c++ } x+=m(c2\4) y+=m(3-c2\4) loop if(c=size-1):break loop *p repeat size r=re(cnt\xmax,cnt/ymax) if(r<10):mes " ",1 mes ""+r,1 if(cnt\xmax=xmax-1){ pos 0:mes "" }else{ mes ",",1 } loop



ONION software Copyright 1997-2023(c) All rights reserved.