2024/02/12
ネットで例の終了条件を検索。同様の質問が3つくらい知恵袋にあったので「あるある」な疑問なのかも?
うーん?
なるほど、分かった気がする。素因数は元の数よりも確実に小さいはずなので、それら2つを掛けた数が元の数より大きいことはあり得ないってことで、コードではxは素因数なので更新されたnの平方根を超える段階でおかしいってことで終わりか・・
では実際の数値を見てみるか。ふんふん・・あれ?
あ、そうか・・最後は素数で割って終わりなんだから
終了条件をN=1でも良いんじゃないか?OK
という事でスッキリしたので次回から高校数学のやり直しの続きをやりますか!
前準備としてLRで脳の状態を「数学向き」に同調させてから取り組むぜ!
あ、ちなみに証明の件、Claudeにも質問したけど僕でさえ分かる無茶苦茶な証明をして煙に巻こうとしていたので呆れた。いや、マイナー言語でのプログラミングは仕方ないけど、数学は出来てくれよ!って改めて思いました。
2024/02/11 Unfoldの続き
楽しみにしていた素因数分解!
ほぉ〜・・割る数が素数で割り切れる場合、Initを返す関数を作っておいて・・Unfoldの終了条件以外は理解できるな(自分で書けるとは言っていない)。どんどん減っていく数値の平方根がInitよりも小さくなったら終了・・
実際の数値を見てみるか・・適当に決めた2024だけど分解する側で23とかまで出るとは。これは予め素数のリストを作っておいてってのは(テストの問題とか人力で解くこと前提の問題でない限りは)、厳しいかも知れんな〜
終了条件、普通にNが素数だったらでいいのでは?と思ったけど・・駄目か〜・・Nが素数になった時点でのXが必要か。
どうもこの条件式は数学的な匂いがするのでネットで検索したトコロ
結構な数がヒット。背理法を使うってのが共通してたけど・・これはまた後日納得できるまで考えよう。高校数学やるし!
九九の問題。仕組みは分かるんだけど気になったのがペアに対してのCadr。cdrじゃなくて?
ガビーン!こういう事か!いや〜今まで知らなかったのがスゴい!
Stepに(read)があるのが驚きポイント。確かに引数1ではあるけど意外な使用方法。でもこの使い方ってゲームとかの入力で実用性がある気がする。ちょっと覚えておこう
String-set!を使ってのアスキーアート的な表示のアイデアとして覚えておこう。
という訳で、いよいよ次回から高校数学のやり直しの再開を再開するか!まずはちょうど良いので例の背理法の証明の納得からやな
2024/02/10
話題1 Unfoldの続き
Unfoldの続きを。Lastで取り出すということはProc部分で作られた要素は末尾につくということか〜。StepがIdentityってことは何もしないって事だから・・xはずっと0って事か?
今度はStep部分が自作されているか・・いつもはSub1とかだから
Step部分は常に引数を1つだけ取るってことだな?
今まではProc部分で処理してたけど、今回はStep部分で初期値をいじってる?
次は例外処理が使われてるので・・With-handlersの書式をチェックするために前にKatanで書いた自作の部分を参照する
同じ範囲で反転するとこういう感じ。って事は(vector-set! ... のところでエラーが出ると例外処理・・でファウルの処理になってる模様。しかしエラーなんて出るところある?
よく見るとVectorにはIndex2が無いのでエラーが出てファウルとみなすってことか、なるほどなぁ
続いて素数の判定。これは難解・・・例によって日本語コメントを入れる作戦で行く。Lengthで1が来たら素数ってことで素数じゃない判定の場合には余計なものがリストに入れられていくってのは推測できるんだけど・・(expt x 2)が分からない。なんで2乗しないといかんのか?
4の場合のリスト
6の場合のリスト。む?
8の場合のリスト。なるほど・・割り切れる数の個数だけリストに出力されてる
って事は2乗しなくてもリストにされるのは一緒なのでそのままxを返すだけでも良いのでは?
うーん、やっぱり素数の場合要素は1つになるので。これなら理解できるんだが!しかし今回はStep部分に割り切れるかどうかの処理、全部をLambda・・と柔軟さに驚く。
実は23問の問題、事前に(Unfoldを使わない)普通の書き方で書けるか試してたんですけど次の問題「素因数分解」は詰まって書いてないんですよね!
諦めてからLoopの束縛で'(2 3 5 7 11)くらいまで素数のリストを入れておいて、割れればAccにCar素数リスト割り切れなくなったらCdr素数リストで回して次で割るという仕組みならいけそうか?と思っただけで放置してるので次の問題楽しみです!
話題2 Racketで実行ファイル作成
Cametanさんへ。いや〜Windows11のRacket環境で作ったものをWindowsで実行した結果がご報告の一瞬だけDos窓表示って結果だったんですよねぇ・・作成と実行を同じマシンでやったんですけど、まさかそのせいってわけでも無いでしょうし・・?
とりあえずテストプレイはバッテリーが生きてるWindowsマシン持ち込んでやらせてみますわ〜(^o^)
2024/02/09 Claudeショック
ほぉぉ~・・ってこういうのを一切知らないってのが、いかに学生時代に何もやってこなかったかって事です(-_-;)
こちらも。これ、まんまこないだのコードですもんねぇ
途中で学習塾のページを見たり
そ、そうだったのか!新鮮な驚きだけど・・うーん、もしかして以前にも微分の話でお聞きしてたかも知れん・・お忙しいのに申し訳ありませんm(_ _)m
更に「そうだったのか!」
更に更に・・・こういう基本的な言葉の定義とかを分かってるつもりでテキトーに使ってるのが恐ろしい。だから理解が遅くて浅いんじゃないかなぁ~
とにかく今度こそ高校数学やり(なおし)ますわ!
Cametanさん、今回もお手数おかけしましたm(_ _)m
しかし・・Scheme系のコードが正確に出てこないとかは「しょうがないか?」と思ってたけど、数学とかの解説が間違ってるとか・・もう信用できないなぁClaude2。
使えるのは「コレコレこういう関数ってありますか?」ってドキュメントの逆引き索引代わりと関数の命名アイデア出し・・くらいしか使えないか。英語学習には素晴らしいと思うけど。逆に言うと、まだまだ勉強する値打ちがあるってことですけどねぇ
2024/02/08
話題その1 Unfoldの演習問題
なんでLogが登場するの?ということでClaude先生にお聞きする。
なるほど〜・・3を底にして10000のLogを取る?事で累乗の限界値が分かるから・・うーん、数学的素養が無い僕には絶対に出てこない発想。
ところで、上の2つが同じ結果になるのが不思議なので
これ何を言ってるんだろう?10000は10の4乗だと思うんだが?
まあ、なんか知らんけど(/ (log 10000) (log 3)) = (log 10000 3) 1となる法則があるんだな。へぇ〜・・
ふーん、今ひとつピンと来ないな〜
なんだよd/dx とかlnって・・これは前にPythonde学び直す高校数学の続きをやらんといかんな〜
だからlnって何だって聞いてるのに。うーん、つまり変化率が対数になるような関数の場合にネイピア数を使うとグラフ化したりしたときに表記が単純になるので出来るだけ使っていこうという共通認識があるって事か?
うーん、この解説が正しいとしても謎が残るな・・それは
ふーん・・ちょっと納得した。
結論、やっぱりここらで高校数学の学び直しを再開するべきだな!と。Racketでゲームなんかを書くのはライブラリを使ったりする必要がなく、泥臭い書き方であれば、もたもたしながら書けるようになってきてる気がするんで、ここはまた基本に戻って根っこの数学とかをやった方が良いかも知れん。
話題その2 Cametanさんの暗号化の記事
うーん、結局実行ファイルの作成なんですが、帰宅後Windowsマシンで実行ファイル作成までは出来たんですが(実行環境込みの最大サイズ)、いざ実行すると一瞬DOS窓みたいなのが出て、その後何も起きないという・・。まあ、相手にRacket入れてもらえば良いんだけど一般の人にはダブルクリックで一発起動でないとハードル高いだろうな〜と。
と、報告が終わったところで。
この暗号化の記事、その後自然な流れでUnfoldの解説になるところで「うおお、前記事のフリに回収が行われている!」と興奮いたしました(^o^)
2024/02/07
解説を読んでも全然ついていけなかったので今回は最初から解答例を拝見する。Case-lambda?わっ?なんだこの書き方は・・と思ったけど、なるほど・・これはスマート。Unfoldは、終了条件、手続き、ステップ、初期値って感じかな
うーん、込み入って見える!あと地味に数値の入力は(read)で良かったと今更知る。いつも(string->number (read-line)でやってましたw
Log? ということでココからは明日頭がスッキリしてから考えることにしよう。
2024/02/06
話題その1 対人トレード
対人トレード(Negotiate)のR部分を書く。正直、あんまり気乗りする作業では無かったw。入力ミスをした場合、最初から入力をしないといけないという仕様。ユーザーからしたら「なんでBボタンで1つ前の段階に戻れないんだよ!ミスしてもその回答からやらせろ!」と思うだろう。が、別に乗ってる作業ではないのでコレで行く。糞UIを作るゲーム製作者の気持ちがちょっと分かったぜ
上のでValuesして本体で受け取る。ここから新たなデータを再構成して返せば終わりか・・でも今日はココまで。
今日は朝から歯医者、昼からインフルで学校閉鎖になったお子さんの子守を頼まれてスライムを作っていたので時間が無かったのだ。
話題その2 例の23問のアレ
Cametanさんの記事を拝見して、アレやってます。Paizaでやってるので入力が出来ない。なのでちょっと入力関係は変則で・・
2024/02/05
画像をBitmap/fileで参照形式に変えてみた
結果、実行ファイルの作成に成功した!そういうことだったのか〜。けど、気になるのはこの圧縮ファイルの形式。tgzってよくLinuxのソフトをインストールするときに見るヤツだな?もしかしてLinuxで作ったらLinuxの実行フィル、Windowsで作ったらWindows形式のファイルが作られるんだろうか
宿直で戦国大名のルールを調べることも出来ないし、Katan-O細部の調整をやってみるか・・
マップ四隅の座標、0 4 20 24に町村を持つ場合、特典としてTradeでの交換比率を4:1から2:1に変えるようにする。
四隅に町村があるので同種の資源カードが2枚以上で任意のカードと交換できるようになった
続いて対人でのトレードも出来るようにしてみるか・・とメニューに追加する。折角だから原作版で出来ることはとりあえず実装してしまってボードやコマを用意しないでもカタンが出来るようなツールにしてみるか・・・?実際、広いテーブルにコマの整理、片付けなどが手軽に始められない原因ではあると思うし。
そうなるとマップもちゃんとヘックスにするかなぁ・・Memberでいちいちチェックするようにすればヘックスでも判定は可能だと思う。一番の難題は実は資源パネル画像の準備ではないかと
2024/02/04 Ver1こんなもんだろう
プレイヤー数を2~4で選べるバージョンを作る。コード内でPLAYERのインスタンスを作ってもいいけど、範囲が狭いので予めリストにしておけばよかろう
Initialの前にPlayer数と初期配置の町の数を決定する部分を差し込む
WORLD-PHASEはIndexに使ったりと大事な要素となるんですが・・ここもPLAYER人数によって設定すれば良いと。For/listなどでPHASEのLengthが必要になるのでCircular-listが使えない。とりあえず通常のリストにしておいて・・自作の疑似Circula-list的な動きをする関数を作るとしよう
PHASEをこのように使いたいので通常のリストにする必要があるんだよな〜
ここも同様。
For/listの特性として与えられた複数のリストの内「短い方」の数だけループするというのがあって「不思議だな?」と思ってたんですけど、今回大助かり。予め最大の場合のリストを用意しておいて実際はPLAYER数だけ回すことが出来るので
調子良く改造をしてたけど壁にぶつかる。あ〜そうか〜・・PLAYER全員のデータを一気に変更しないといけない部分(カード配分)なんだけど、それぞれを別の名前で束縛して処理してまた組み立てるという部分。ここ、ずっと前にも問題になった不定の数、内部で名前をつけた構造体をあらたに作るという処理が必要となる。
いや〜・・どうすっかなぁ・・なんとなくマクロだったら出来る気がするが・・・
うーん・・ちっとも分からん。こうなったら・・・
PLAYER数ごとにCondで無理やり条件分けしてしまうしかないか・・・うーん、力技
そう言えば、最初の選択で村設置数を反映させたいがWORLDに保存するスロットがない。また全部書き換えるのか・・とゲンナリ・・。
しかし解決策を思いついた。WORLD-TURNは使うとしてもゲームが始まってからなので、それまでの間は自由に使えるんだった。これに保存して使うとしよう
というわけでテスト。3人プレイだけど、ちゃんとSTATUS表示も3人分になってるな
3人全員が村を設置しおわると続いて道設置、これもOK
道が設置し終わるとゲームスタート
2人プレイもOK。結論!完成しました(^o^) やったぜ!
知り合いに配布して新たな追加・改造アイデアを募集するために実行ファイルにしてみるか!とClaudeに聞いてみる。コマンドプロンプトからRacoで実行できるのか〜
と、思ったらRacketのメニューから普通に実行ファイル作成が作成出来るじゃないか
だがエラー(-_-;) うーん?ネットでメッセージを検索すると3Dライブラリがからんでいると出るとかあったけど、これを見る限りでは中に挿入した画像データが原因ぽいかなぁ?前にナウシカかラピュタでこんなのあったような・・?もしかして直接挿入じゃなくて参照形式にすれば解決するかも?
ま、とにかく思ったよりはスムーズに人数選択式の実装も出来た。改造はまたカタン仲間や甥っ子にやらせてからにして、とっとと次行ってみようか!
2024/02/03 対人戦4人打ちVer完成
予定通り、ランダムではなくて任意で初期村配置ルーチンを作る。村の数は1つだけど、プレイヤー3から開始して続いての初期道路設置は0から開始で折り返しで2本作るという実験。For/foldが便利すぎる
道路候補の表示部分。村候補表示とほぼ一緒
村を全部配置後、道路を作っていくところ。For/foldに与える数値のリストでコントロール出来るのがナイス
出来上がった初期マップをMain-loop-diceにつないで・・・OK。いや〜とりあえずは完成した。面白くないけど!
折角なのでプレイ人数に初期の村数も選択出来るバージョンを作ろう。その後は・・COMの思考部分を作るか、追加要素(四隅に交換効率の良い「貿易港」を作るとか騎士セットみたいな特殊カードシステムを作ってバンバンやり合うような仕組みにするとか?)をやるのも楽しそうだし、とっとと次のゲームに行くのも良いかも。拾ってきた名作(という噂の)ボードゲーム「戦国大名」をRacket化するのも楽しそうだし、ちょっとRacketから離れてゲームエンジンで「トランキライザーガン」の作成に挑戦するのも良いなぁ・・
2024/02/02 テストプレイと別方式
というわけでテストプレイを開始。
お・・・面白くないw
まず全員を一人で操作するというのももちろんだけど、全然資源カードが集まらない。村はランダムで配置されるので四隅になると完全に詰み、端でも接する資源パネルは2つだけ、一方内陸に配置されると接するのは4枚ということで圧倒的有利。これはランダム方式は駄目だな。村の数を原作通り2つにするとまた違うだろうが・・
ちなみに、盗賊がいるパネルの四隅にはランダムでも配置されないようにはしてあるんだけどね。とにかくずっとパスばっかりしないといけないということでボツ!
対策としては
・村を2つずつにしてプレイヤー数を3人に減らす
くらいしかないかなぁ・・
というわけで今度は任意で初期配置を選ぶ方式の導入部を作ることにしました。今回は村配置を3から、道配置を0からって事でどうだろう。いや・・圧倒的に最初にパネルを選べるプレイヤーが有利だな・・原作では村を0123で1つ、3210で1つと合計2つ選ぶんだけど、よく出来てる。やっぱりプレイヤーを減らしてでも村を2つにするべきか・・?
ま、それは後で決めるとしてまずは開始。今回はC-MAP(交点のマップ)を読み込んで、プレイヤーが選んだ座標にv0とかv1とかをList-setしていけば良いわけで、対象となるリストが更新されていくパターンだからFoldの出番か。今までFor/foldを使ったことなかったので採用。ドキュメントの例文が込み入ったものなので分かりにくい。が、使ってみるとすごく便利だ!これ、もっと使いどころあったなぁ
メニューを表示、答えを入力してC-MAPを更新する部分。ForでIndexの回数だけ呼び出されてこの処理を行うんだけど、2個配置にするんだったら上のInitial-choice-readのIndexを'(0 1 2 3 3 2 1 0)にするだけでOK
テスト。最初のプレイヤー0は当然全部の場所が候補で
プレイヤー1以降は他の村と隣接するポイント以外ならば配置OK、ということで・・今回はここまで。
次回は道を配置する部分を書くけど・・前は一気に2つ置くようにしたけど、村と同じ方式で書けば道の数をIndexのリストで自由に設定できるので変更しようっと
2024/02/01
話題その1 別フレームへのグラフィック表示
教えてもらった別フレーでの表示を試してみる。おおお・・本当に出来てるやん!この最後のSEND部分だけを都度送れば更新表示できるわけだな?
ただ、表示されてる枠は常に最前面で表示という設定でもないので(出来るのかも知れない)、メイン枠を小さくしてかぶらないようにしないと常時チェック出来ない。枠の更新で位置が記録されないので出現する部分を空けるようにメイン枠を配置する必要がある・・と。
最前面表示のオプションがあるか調べてみよう
話題その2 初期化ループを作る
いよいよゲームをスタートする部分を書いていく。前回まではテスト用に作っていたデータだったので初期化するためのREPLを作る。
ゲームスタート時に各プレイヤーが村(開拓地)を2つと道を2つずつ作っていくんだったな・・
狭いマップに村を8つも配置するのもどうだ?とりあえず1つにしてみるか。配置は思い切ってランダムにしたほうが向いてるのでは?ということで各プレイヤーの座標をランダムで設定するという乱暴な試み。そのためのテスト。ちなみに、16はパネルの数なので間違ってます(交点なので25必要)
実際の関数、Initial-random-readに組み込んでいく。出来た座標を新たなC-MAPとして設定、それをForのループ源として回しそれぞれに道路を2つ作らせるという関数を回す、と言う計画。Forでのループ中に(read line)などの入力作業が可能なのかは謎なんだけど、出来れば非常に応用が効くだろうから試してみる
道を2本作るってことで発展カードのRoads関連を改変コピペでやってみる
ところがココで大ポカをやらかす。新たに更新された道データR-MAPの仮引数を適当mapとしてしまったのだ。高階関数Mapを上書きしてしまって謎のエラーが。
慌ててc-mapに書き換えたら、その前の関数で既にc-mapを使用してしまってた(そもそも道データなのでr-mapだろ、と)のでさらなる混乱に。結局ちゃんと動かすのは夜の部になるのだった。
仮引数と関数内束縛変数名だけ漢字混じりの日本語が使える仕様のプログラミング言語って無いのだろうか・・名前付けが難しすぎる!
書きながら気になったのでClaudeさんに聞いてみてびっくり、数少ない「出来る」言語がRacketだったw。Racketスゲェ!
気を取り直して初期化ループを書いていく。まずはWORLDに入れるための初期化データを設定する。Map問題で大いに懲りたので大域変数にはしっかりと**をつけることにした。実は関数内でPLAYER-LIST(関数内変数)をPLAYERS-LIST(初期化用大域変数)と間違えて使ってるせいでいつまで経ってもゲームが終わらないというバグが発生したのだった。
あと、資源マップだけど5種類あるのでそれぞれ3枚入れると15枚、1枚余る。なるほど、そこに砂漠を・・とも思ったけどマップが狭いので今回はランダムでどれかを1枚余分に入れるようにした。けど、その残り1枚を砂漠以外にも色々と変化させると面白そうかもな?と。
途中の試行錯誤画像は間違えて消してしまったので完成版を。いやいや・・大変でしたよ・・。
書いてる途中で、そう言えば道を2つ作るって部分で「1つ目の道が出来た結果、その先にも道を作れる」仕様になってないのに気づいてしまった(もちろん発展カードのRoadsも)。
という訳で、このRead部分にあたるMenu内に新たにWORLDを更新して、マップも表示して・・・という部分を詰め込むことに。
Initial-random-readからForで回すためにIndexの仮引数が必要になった以外、このNew-R-MAPを更新して返す部分は特に問題なし。
ではいよいよInitialループ部分をテストしてみよう!プレイヤーの順番は固定だけど、先に回ってくる方が有利なので、Initialでは実際のゲームの順番とは逆の3210で回すべきかも知れん
そして2つ目・・ちゃんと1つ目で作った道の先にも作れるようになってる~(感動)。これ、なかなかに大変だったんです(^_^;)
発展カードにも逆移植して動作も確認しました。
続いて次のプレイヤーへ。この時点で勝ち確定!やったぜ!
とにかく今回は作成時に仮で使っていたマップデータ(大域変数)をコード内に埋め込んだまま忘れていたり、先に書いたように仮引数の名前を間違ったりして大混乱したのが印象的だった。名前はマジで気をつけないと・・ただ、Racketの場合漢字が使えるのが分かったので作成時には仮引数を漢字で書いておいて、出来上がってから一気に英数字に置換するってのもアリだと思いました。
次回、いよいよ通しでテストプレイ