投稿
プチコン3号でBASICが少し分かってきた方を対象に軽い問題を出します。今回で6問目。今回は「応用編」です。 問題。次のプログラムを実行しましたが、些細というか微細レベルですが「処理が重く感じました」。どうすれば処理を早くすることが出来るのか、答えなさい。 CLS FOR I=0 TO 15 FOR J=0 TO 15 X=4:Y=4 COLOR 15 LOCATE X+J,Y+I:PRINT "●"; NEXT NEXT 答えが分かった方は「ネタバレ」で答えを書いて頂きたいです。正解した方にはそうだねで返します(私が見て無い時でも誰か分かる方がそうだねを押して頂けると助かります)。 ※今回は今までのエラー探しとは違い高速化、シェイプアップの方法についての問題です。全員満点を目指しましょう
6そうだね
プレイ済み
返信[1]
親投稿
ちなみに、過去の問題については私の活動でご確認下さい。解説付き
0そうだね
プレイ済み
返信[2]
親投稿
AGO tm0506
X=4:Y=4を最初の行のCLSの横に移動させてCLS:X=4:Y=4みたいにする(合ってるかな…)
1そうだね
プレイ済み
返信[3]
親投稿
>TMさん もう一つ移動できるポイントがありますよ。これだけだと及第点レベルですがギリギリ正解で。
0そうだね
プレイ済み
返信[4]
親投稿
AGO tm0506
あっ、COLOR 15も移動できますね。
1そうだね
プレイ済み
返信[5]
親投稿
>TMさん 大正解!詳しくは解説で書きますが「何周しても同じ結果ならループから出す」のがシェイプアップのポイントです。
1そうだね
プレイ済み
返信[6]
親投稿
pinfu ANNAININ
うーん。難しい・・・ 考えとしては、 X=4:Y=4 COLOR 15 CLS の後に持ってくる?? 16×16の●が書きたいのであれば FOR I=0 TO 15 を無くして、 LOCATE X,Y+J :PRINT¨●¨*16 ???(不安)
1そうだね
プレイ済み
返信[7]
親投稿
>pinfuさん 大正解!そういう事です。 まぁ"●"*16はあってもなくてもいいですが上の文が当たってますので。 ポイントは「何周しても同じならループから外させる」事です。
1そうだね
プレイ済み
返信[8]
親投稿
変数のX=4とY=4は最初の方にやっとけばいいから2つのFORよりも前に置いて、 CLSがあるならいろいろ初期化のためCOLOR 15も必要だとしてさっきのXとYにコロン(:)でつなげて、あと動作速度に関係あるかわからないけどPRINTを?に置き換える…っていうところでしょうか
2そうだね
プレイ済み
返信[9]
親投稿
>€(ò∀ó€)Ξ sさん 大正解!PRINTと?の速度差は計った事が無いのでいいのかどうか分かりませんが、BASIC脱初心者向けですのでPRINTで統一する事にしています。
0そうだね
プレイ済み
返信[10]
親投稿
おちゃめ ochame_nako
このプログラムにおいてX=4:Y=4とCOLOR 15をループ外に出すことで20%の高速化ができますが、A$="●"*16としてループを1つ減らせば3.4倍の高速化ができるためこちらの方が高速化としては重要ですね。 ちなみに「?」と「PRINT」では速度差はありませんでした。
2そうだね
プレイ済み
返信[11]
親投稿
ゆうたん yu-tan-sama
あぶないあぶない… CLS X=4:Y=4 COLOR 15 FOR I=0 TO 15 LOCATE X,Y+I:PRINT "●"*16; NEXT
1そうだね
プレイ済み
返信[12]
親投稿
>おちゃめさん 解析ありがとうございます。今回初心者というより「プチコン以外でもそのまま活用出来る」ように考えてましたのでA$="●"*16とかは採点しない方向で考えてましたので。 >ゆうたんさん そして全ての回答を総まとめした結果って感じですね。お疲れさまです。
0そうだね
プレイ済み
返信[13]
親投稿
くろちく FoliageLamp
とりあえず、挑戦してみました。 WAIT 30ほどかけた場合●が1個づつ表示され、時間がかかる 現状では2つFOR文でループさせている部分が問題なのかなと。 1つのFOR文で表示させればよいと考えてみました。 FOR J=0 TO 15  X=4:Y=4  COLOR 15  LOCATE X,Y+J:PRINT "●"*16; NEXT
0そうだね
プレイ済み
返信[14]
親投稿
>LAMPさん 惜しい・・・それだと「そうだね」はおあずけになります。 FORとNEXTの間にどれだけの処理が挟まれているか、また「あれ?よく見たら同じ事の繰り返しじゃね?」と思える部分がないかよく考えて下さい。
0そうだね
プレイ済み
返信[15]
親投稿
くろちく FoliageLamp
あ、FORの括りから抜いたほうがよい・・・のかなと思えたのは 勘違いでなければX=4:Y=4、COLOR 15と思ってはいました。 初期状態では文字色は白なのでそれは消してもいいのか とまでは考えてみました。(考えたけど自信が無かった><
1そうだね
プレイ済み
返信[16]
親投稿
あと今更ですが「FOR~NEXTを2重にしてるのを外してる回答が多いですが、外せないように組んでしまえばよかったかな」と考えてます。 例えば FOR I=0 TO 15 FOR J=0 TO 15 X=4:Y=4 COLOR 15 L$=MID$("0123456789ABCDEF",FLOOR((I*16+J)/17),1) LOCATE X+J,Y+I:PRINT L$; NEXT NEXT こんな感じで。これならJを省略出来なくなるかと。
0そうだね
プレイ済み
返信[17]
親投稿
>LAMPさん 問題の意図としてはそっちを抜いて欲しかったですね。極限に縮めるなら*16でも問題無いのですが。
0そうだね
プレイ済み
返信[18]
親投稿
ゆうたん yu-tan-sama
>こんな感じで。これならJを省略出来なくなるかと。 それよりはもっとシンプルに15という固定値をやめた方がいいんじゃないかなー 0~15という決めうちがある限り、実行結果を予測して、固定の文字列をPRINTするという回答が成立しちゃうし
0そうだね
プレイ済み
返信[19]
親投稿
うーん・・・それだと面白くないんですよね。 個人的な考えとして「他のプログラムや自作、他の言語でも臨機応変に対応できるレベルの『基礎』」を教えるのが問題を出す側の役目だと思ってます。 3号でのみ使えるテクニック「だけ」で縮めたり結果を先読みしてデータ化というのは理想とは思えないんですよ。とどのつまりRND命令で適当に読みだす様になってしまいますので。 今回はそういう回答も正解にしてますが、それを当たり前とされるとちょっと問題として失敗だったかなと思うようになってしまいます・・・
0そうだね
プレイ済み
返信[20]
親投稿
KU kerorinU
XとYの初期化、COLORの初期化をループ外に出してやる、ですかね。
1そうだね
プレイ済み
返信[21]
親投稿
おちゃめ ochame_nako
問題を作るというのは簡単なようで難しいですからね。 出題者の意図する解答と客観的にみてベターな解答が異なっている場合にはあまり良い問題とは言えません。 上のネタバレで書いているように意図した解答ならば1.2倍しか速くなりませんが、多くの人が気づいている解答ならば3.4倍くらい速くなるので後者の方に気づいた方を褒めるべきではないでしょうか? 他の言語での応用を考えたらスプライトやBGも他の言語でそのまま活かすことなんてできませんしBASICそのものが向かないと思います。
2そうだね
プレイ済み
返信[22]
親投稿
おちゃめ ochame_nako
この問題を意図する解答にするのならば「このプログラムは順番を並べ替えるだけで速度が速くなります。並べ替えたプログラムとその理由を書いてください。」とすれば良かったと思います。
0そうだね
プレイ済み
返信[23]
親投稿
>KUさん 大正解です!シンプルに考えましょう。 >おちゃめさん 私事になりますが、MSXBASICで色々と作ってた身から見て3号はあの時の基礎がそのまま生かせる、しかもあまり文面変えなくても(IFの==とかは別ですが)いいと思ってたので有難い+懐かしいという気持ちでして。その経験もあるので「BASICの基本」のみで解決する問題をいくつか出してきたつもりです。 まぁこちらの意図から外れた回答も「流石」と感心していますが、なんか魔改造に近い結果が送られて来ると反応に困ってしまうというのも一つであります。 ちなみに次回の問題はエラー探しでは無くて「リストを見ただけで何が起きるのか答えてもらう」のを考えてます。今回の問題のリストはちょっとした伏線でもありますが。
0そうだね
プレイ済み
返信[24]
親投稿
プチコン特有の命令を使わないとしても、 CLS X=4:Y=4 COLOR 15 FOR I=0 TO 15 LOCATE X,Y+I FOR J=0 TO 15 PRINT "●"; NEXT NEXT この方がベスト? もっとひねくれた回答もあるけど…
1そうだね
プレイ済み
返信[25]
親投稿
>でんぺんさん 正解というよりなんか嬉しいですねそういう魔改造でもなく基礎となる部分だけで組み上げて効率も良くなってる回答というのは。ありがとうございます。
0そうだね
プレイ済み
返信[26]
親投稿
けい kei0baisoku
おお!次は中級者さん向けくらいの高速化とか面白いかなと思ってたらミケランジェロさんから出題が(^O^) 決まった正解のない問題ですね。初心者さん向けの問題に回答者として入っていくのは自重してますが、これなら回答者として参加しても問題ないかなと思いますので挑戦してみます。 特に制限等書かれてませんので、「結果を変えないこと」「今よりも速くすること」の二点だけという前提で考えます。 まず問題を見て、意図は「ループの中でやる必要のない処理は、ループの外に出す」という原則を伝えるための出題だと推察しました。 あとはもしかしたら、プチコンだとJの方のループはしなくても出来るよ、という点かなと思います。 多分初心者さん向けにはこの辺までだと思いますが、あとそもそもの作りも改善できるので、その辺も踏まえてなるべく実戦的に考えてみました。
1そうだね
プレイ済み
返信[27]
親投稿
けい kei0baisoku
--------------- CLS X=4:Y=4 W=16:H=16 LINE$="●"*W COLOR 15 FOR I=0 TO H-1 LOCATE X,Y+I PRINT LINE$ NEXT --------------- このプログラムの機能は「4,4の位置から縦横16文字の範囲を四角形に、●で埋める」なので、文字列のセットやCOLOR命令はループの外に出せます。 また、文字列を作るのはループで一文字ずつ書くより1つの文字列にして一回で済ませた方が普通は速いので横方向のループはやめます。 縦横のサイズは直値でも書けますが将来変更する可能性も見越して変数にしておきます。プログラムの2ヶ所以上から使いそうなら、さらにこれを関数化して呼びます。 もし縦横で文字や文字の色を変える必要が出てきたら、作りから変える必要がありますね。
1そうだね
プレイ済み
返信[28]
親投稿
テル teru72ig.id
COLOR 15:X=4:Y=4:FOR I=0TO 255 LOCATE X+I MOD 16,Y+I DIV 16 ?MID$("0123456789ABCDEF",I DIV 17,1):NEXT
1そうだね
プレイ済み
返信[29]
親投稿
けい kei0baisoku
すみません、1つ書き忘れていました。 速度を最優先するならY方向のループすらやめてPRINT文たちを直値で16回並べる方が上ですが、この処理が呼ばれるのが1フレームに数千回とかでなければ無いに等しい差なのと、それよりもプログラムを見やすく、行数などを変えやすくしておくことの方がずっと重要なので、ループのままがベスト、という考えです。
0そうだね
プレイ済み
返信[30]
親投稿
ねこはち neko80001
CLS COLOR 15 FOR I=4 TO 19 FOR J=4 TO 19 LOCATE J,I:PRINT "●"; NEXT NEXT
1そうだね
プレイ済み
返信[31]
親投稿
ねこはち neko80001
XとYの初期化が外せない要素なら CLS COLOR 15 X=4:Y=4 FOR I=X TO 15+X FOR J=Y TO 15+Y LOCATE J,I:PRINT "●"; NEXT NEXT で、どうでしょう?
1そうだね
プレイ済み
返信[32]
親投稿
べー mmmggg
*16を排除したいなら一文字毎にZ座標とか色とかが変化している問題がよかったかもしれませんな
0そうだね
プレイ済み
返信[33]
親投稿
とどのつまりはどこまでやるかにもよるので、問題の幅が広すぎるのが難とも言えますね〜
0そうだね
プレイ済み
返信[34]
親投稿
CLS直後しか使えない手ですし、題意とは違う解とも思われますが、こんな書き方もできちゃいます、という参考例として。 "●●●●●●●●●●●●●●●●"は "●"*16 と書き換えると、僅かに遅くなりますが見通しは良くなります。
0そうだね
プレイ済み
返信[35]
親投稿
nyannzi CornedBeef
問題つくるのって難しいですよね 賛否両論あるようですが 初心者の自分的にはベーシックな答えがありつつ 解る人は他のアプローチの答えも出されてると いろいろな考え方や書き方が見られて新しい知識やきっかけに なるのでとてもありがたいです
2そうだね
プレイ済み
返信[36]
親投稿
ネタバレを覗いてみましたが、やはり自分の解は題意とは違ったもののようですね。 挑発的な意味合いで解を挙げたつもりではなかったのですが、失礼しました。
0そうだね
プレイ済み
返信[37]
親投稿
皆様ありがとうございます。プログラムの「ムダ」を取り除く回答から極限まで詰めて高速化を図る魔改造まで色々と参考、そして考えさせられた問題になってしまいました。 では簡単な解説。FOR~NEXTの間に「X=4:Y=4」「COLOR 15」が見えます。よく見るとこの2つ、「ループの中なのにずっと同じ事を設定して」いますよね。こういった部分が「足かせ」となりまして、処理を重くさせる原因になってしまいます。 なのでFOR I~の前にX=4:Y=4とCOLOR 15を移動させ、ループの中はLOCATEとPRINTという「ループさせることにより変化する」値のみ入れる事が高速化に繋がります。 FOR J~を抜いたさらなる高速化は今回あえて触れませんので。皆様もネタバレをチェックして自分のプログラムに合った手法で魔改造にチャレンジして下さい。 また次回、説明不足なのを勉強して出題しますので。
2そうだね
プレイ済み