目次: ゲーム
大昔にちょっとだけやって中断していたゲーム「農家はREPLACE()されました」を9割位までクリアしました。
実績の残り2個はランキングに載れ的なやつで、やる気が起きなかったのでこれにておしまいです。
序盤は適当にループを回して、文法系を全開放(list, dict, set_world_sizeなど)、迷路までの作物、複数ドローンを開放します。中盤は各種作物に最適化して組んだプログラムを動かす&放置&資源がたまったらレベルを適宜開放、を繰り返します。実装したらやることがなくなっちゃう。
プログラムは最大レベル(農場サイズ32x32、ドローン32機)に合わせて決め打ち実装した方が効率的で速いです。が、中盤は農場サイズやドローン数が少なく、32x32決め打ち実装だと動かなくて辛いです。個人的には農場サイズやドローン数が可変にできるように実装した方がゲーム進行的には楽でした。
カボチャとサボテンの実装を紹介します。一応、カボチャマスターとサボテンマスターは取れるはず、たぶん。
各ドローンは1機1行を担当します。西から東の一方向にスキャンし続け、割れたカボチャがあったら植え直し、一列全部がきれいなカボチャになったらドローンの処理おしまいです。これを全行に対して実行します。
最初のドローンは北に移動しながらドローンを複製できるだけ複製して、複製の上限に達したら自分も1行担当します。全面カボチャになって、ドローンが最初のドローン1機だけになったら収穫します。
def cond():
a = num_items(Items.Power) > MIN_POWER
b = num_items(Items.Carrot) > MIN_CARROT
c = num_items(Items.Pumpkin) < MAX_PUMPKIN
return a and b and c
def get_pline():
pline = 0
for i in range(get_world_size()):
if get_entity_type() == Entities.Pumpkin:
pline += 1
move(North)
return pline
def drone():
plist = []
pnum = 0
for i in range(get_world_size()):
plist.append(False)
while True:
if get_entity_type() == Entities.Grass:
till()
if get_entity_type() == Entities.Pumpkin and can_harvest():
if not plist[get_pos_x()]:
plist[get_pos_x()] = True
pnum += 1
if pnum == get_world_size():
return
else:
plant(Entities.Pumpkin)
if get_water() < 0.5:
use_item(Items.Water)
move(East)
def pumpkin():
clear()
while cond():
if not spawn_drone(drone):
drone()
if get_pline() == get_world_size():
while num_drones() > 1:
pass
harvest()
move(North)
動作を見たらすぐ気づかれますが、効率は良くないです。特に最初のドローンがスキャンする処理が長引くと、複数ドローンが出せない時間も長引いてしまいボトルネックになります。
全面にサボテンを植えて、東北側に大きなサボテン、南西側に小さなサボテンを集めるようにソートし、収穫します。ヒントにある通り、行ごとにソート、列ごとにソートの順に実行すれば全面ソート済みになります。
コードはこんな感じ。もっと短くできそうですけど気にしない。
def move_to(x, y):
ws = get_world_size()
dirx = East
if (x - get_pos_x() + ws) % ws > (ws / 2):
dirx = West
diry = North
if (y - get_pos_y() + ws) % ws > (ws / 2):
diry = South
while get_pos_x() != x:
move(dirx)
while get_pos_y() != y:
move(diry)
def cond():
a = num_items(Items.Power) > MIN_POWER
b = num_items(Items.Pumpkin) > MIN_PUMPKIN
c = num_items(Items.Cactus) < MAX_CACTUS
return a and b and c
def is_ready(l):
for i in range(get_world_size()):
if l[i] == -1:
return False
return True
def is_sorted(l):
for i in range(get_world_size() - 1):
if l[i] > l[i + 1]:
return False
return True
def get_west_x():
return (get_pos_x() - 1 + get_world_size()) % get_world_size()
def get_east_x():
return (get_pos_x() + 1 + get_world_size()) % get_world_size()
def get_south_y():
return (get_pos_y() - 1 + get_world_size()) % get_world_size()
def get_north_y():
return (get_pos_y() + 1 + get_world_size()) % get_world_size()
def swap_item(l, a, b, dir):
t = l[a]
l[a] = l[b]
l[b] = t
swap(dir)
def plant_water():
if get_entity_type() == Entities.Grass:
till()
plant(Entities.Cactus)
if get_water() < 0.5:
use_item(Items.Water)
def drone_x(st):
move_to(0, st)
xlist = []
for i in range(get_world_size()):
xlist.append(-1)
while cond() and not is_ready(xlist):
plant_water()
xlist[get_pos_x()] = measure()
move(East)
move_to(0, st)
vmax = get_world_size() - 1
while cond():
if is_sorted(xlist):
return
for i in range(vmax):
if get_pos_x() > 0 and xlist[get_west_x()] > xlist[get_pos_x()]:
swap_item(xlist, get_west_x(), get_pos_x(), West)
move(East)
for i in range(vmax):
if get_pos_x() < get_world_size() - 1 and xlist[get_east_x()] < xlist[get_pos_x()]:
swap_item(xlist, get_east_x(), get_pos_x(), East)
move(West)
move(East)
vmax -= 2
def drone_y(st):
move_to(st, 0)
ylist = []
for i in range(get_world_size()):
ylist.append(-1)
while cond() and not is_ready(ylist):
ylist[get_pos_y()] = measure()
move(North)
vmax = get_world_size() - 1
while cond():
if is_sorted(ylist):
return
for i in range(vmax):
if get_pos_y() > 0 and ylist[get_south_y()] > ylist[get_pos_y()]:
swap_item(ylist, get_south_y(), get_pos_y(), South)
move(North)
for i in range(vmax):
if get_pos_y() < get_world_size() - 1 and ylist[get_north_y()] < ylist[get_pos_y()]:
swap_item(ylist, get_north_y(), get_pos_y(), North)
move(South)
move(North)
vmax -= 2
def area(func, start, end):
for i in range(start, end):
spawn_drone(func, i + 1)
func(start)
while num_drones() > 1:
pass
def cactus():
clear()
while cond():
for i in range(0, get_world_size() - 1, max_drones()):
area(drone_x, i, min(get_world_size() - 1, i + max_drones() - 1))
for i in range(0, get_world_size() - 1, max_drones()):
area(drone_y, i, min(get_world_size() - 1, i + max_drones() - 1))
harvest()
ソートアルゴリズムは何でも良いですが、このゲームの大きな制約が2つあって、
おそらくバブルソート系のアルゴリズムを選択せざるを得ないでしょう。上記の実装ではシェイカーソートを使いました。シェイカーソートの存在は知ってましたが、実用的じゃないので実装したことなかったです。改めて実装してみるとなかなか新鮮でした。
この記事にコメントする
Xで50音順に「かに」で終わる形容動詞(正確には連用形ですが)を並べている人がいて、面白そうなので自分もやってみました。
やってみるとわかるんですけど、かなり難しいです。ぱっと思いつく範囲では半分も埋まりませんでした。圧倒的敗北を喫して悔しかったので辞書を解禁して調べました。が、それでも敗北しました……。以下が戦いの結果です。複数ある場合は2〜3つくらい書いてます。
あ→明らかに、艶やかに い→如何に、居丈高(いたけだか)に う→麗(うら)らかに え→ お→厳かに、穏やかに か→軽やかに き→煌(きら)びやかに く→ け→絢爛豪華に こ→腰高に、事細かに さ→ささやかに し→静かに、しなやかに す→健やかに、速やかに せ→背高に そ→ た→確かに ち→ つ→慎ましやかに、詳(つまび)らかに て→ と→年若に、ど真ん中に な→和やかに、なだらかに に→賑やかに、俄かに ぬ→ ね→根明に の→長閑(のどか)に、伸びやかに は→華やかに、遥かに、晴れやかに ひ→密かに、秘めやかに ふ→ふくよかに、不束(ふつつか)に へ→ ほ→朗らかに ま→実(まこと)しやかに、間近(まぢか)に、円(まろ)やかに み→身近に、雅やかに む→睦(むつ)まやかに め→目近(めぢか)に も→物静かに、物柔らかに や→安らかに、吝(やぶさ)かに ゆ→豊かに、緩やかに よ→ ら→ り→ る→ れ→ ろ→ わ→わずかに、割高に
文語を採用するともう少し埋まりそうでしたが、なんだか負けた気分なので文語は外してます。
まず、ら行が全滅なことに驚きました。しかしまあ、ら行と「ぬ」「へ」「よ」はこれらの文字で始まる単語自体が少なそうで、該当する形容動詞がなくてもさほど不思議ではないです。しかし「え」「く」「そ」「ち」「て」は意外でした。本当にないのかなあ?私の探し方が悪いだけかもしれません。
たぶん「かに」で終わる形容動詞で全て埋めるのは不可能なんじゃなかろうか?うーん??
この記事にコメントする
目次: Zephyr
Zephyr RTOSはツリー内にアプリケーションを持ちます(以降、In-treeアプリケーションと呼びます)。zephyr/sample以下にサンプルアプリがあります。別の場所に自分のアプリケーションを足すこともできます。FreeRTOSもアプリケーションの横にカーネルのソースコードを置く形でした。RTOSだと普通なんでしょうね。
zephyr |-- LICENSES |-- arch |-- boards |-- build |-- cmake |-- doc |-- drivers |-- dts |-- include |-- kernel |-- lib |-- misc |-- modules |-- samples ★アプリケーションのサンプルはここにある★ |-- scripts |-- share |-- snippets |-- soc |-- submanifests |-- subsys `-- tests
In-treeアプリケーションは簡単に追加できて便利ですが、LinuxやUnixに慣れた人はアプリケーションとカーネルコードが混ざることに違和感を感じるでしょう。小さめなFreeRTOSならまだしも、でかいZephyrを常にアプリの横に置かれるのは邪魔です。
ご安心ください、Zephyrはアプリとカーネルを別のディレクトリに置くことができます(以降、Out-of-treeアプリケーションと呼びます)。便利ですね。
続きはまた今度。
この記事にコメントする
目次: 射的
JTSA Unlimitedの大会に参加しました。
「水」ステージが大失敗、「木」もダメダメでした。他は結構良かったです。結果は72.1秒(前回は75.69秒)でした(総合78位/111人、LM 10位/17人)。60秒台はなかなか遠いです。
練習会の記録を見ても60秒台がほぼ出ないので75〜70秒くらいが実力ですが、去年よりは70秒台前半が出る回数が多いかなあ……?最近はあまり上達している感がありませんが、今後もゆるゆると続けていきます。
この記事にコメントする
目次: Zephyr
Zephyrのアプリケーションをビルドするには、Zephyrをビルドできる環境が必要です。最初はPython環境のセットアップを行います。
なんで初手がPythonかというと、ZephyrのツリーをダウンロードしたりビルドするときにwestというPython製のツールを実行するためです。基本的にはGetting Started Guideにあるとおりです。
私の環境はDebian Testingなのでcmake(> 3.20.5), Python(> 3.12), Devicetree compiler(> 1.4.6)のバージョンを満たしています。
$ cmake --version cmake version 3.28.3 $ python3 --version Python 3.12.3 $ dtc --version Version: DTC 1.7.0
Ubuntu 24.04 LTSも問題ありません。もし古めのディストリビューションを使っている場合は上記の3ツールの最小バージョンを満たしているかチェックしてください。
$ sudo apt install --no-install-recommends git cmake ninja-build gperf \ ccache dfu-util device-tree-compiler wget python3-dev python3-venv python3-tk \ xz-utils file make gcc gcc-multilib g++-multilib libsdl2-dev libmagic1 $ mkdir work_dir $ cd work_dir $ python3 -m venv .venv $ source .venv/bin/activate $ pip install west
Getting Started Guideには続きがありますが、In-treeアプリケーションをビルドするわけではないので今は実行しなくて良いです。以上がうまくいっていたら、ディレクトリはこうなっているはずです。
work_dir `-- .venv
続きはまた今度。
この記事にコメントする
目次: Zephyr
前回はPythonとwestの準備をしました。今回はZephyrをビルドするツールzephyr-sdkをインストールします。基本的にはZephyr SDKにあるとおりです。westを使える方はwestで良いですが詰みやすい(※)ので、インストーラを使う方法も知っておいて損はないでしょう。
SDKのバージョンは何でも良い訳ではなくZephyr Version Compatibilityにある通り、SDKのバージョンによってサポートしているZephyrのバージョンが違うのでご注意ください。
今回はSDK 1.0系とZephyr 4.4.0を使いましたが、特に理由はないので必要に応じて適切なバージョンを選んでください。
$ mkdir work_dir $ cd work_dir $ tar xf zephyr-sdk-1.0.1_linux-x86_64_minimal.tar.xz $ cd zephyr-sdk-1.0.1 Install GNU toolchain [y/n]? y Install GNU toolchains for all targets [y/n]? y → この問いにnと答えると、アーキテクチャごとに要るか/要らないかを聞かれるので、 要るものだけにyと答えると時間節約になります。 Install LLVM toolchain [y/n]? y Install host tools [y/n]? y Register Zephyr SDK CMake package [y/n]? y Create symbolic links for old Zephyr bisectability [y/n]? y → 以前はSDK直下にアーキテクチャのディレクトリ(例: x86_64-zephyr-elf)がありましたが、 llvmが導入されてgnu/以下に移動しました。 昔のディレクトリ構造を期待する古いZephyrを使うなら、yと答えてシンボリックリンクを作っておいたほうが良いです。
基本は全部yと答えれば良いはずです。インストール時間を短くしたい人は"Install GNU toolchains for all targets"にnと答えて要るものだけに絞りましょう。
(※)west sdk installでもインストールできますが、westだと何が起きたのか全くわかりません。成功するうちは良いものの、いざ失敗するとどうしようもなくなります。
Zephyr SDKを/optや/usr/localなどに置く場合はZephyrのビルドシステムが勝手にSDKを探してくれます。もし別の場所に置きたい場合はもうひと手間必要です。ホームディレクトリに下記の.zephyrrc設定ファイルを作ります。
export ZEPHYR_TOOLCHAIN_VARIANT=zephyr
export ZEPHYR_SDK_INSTALL_DIR=/home/ubuntu/work_dir/zephyr-sdk-1.0.1
設定を反映させるため、zephyrのディレクトリにあるzephyr-env.shをsourceで取り込みます。
$ cd work_dir/zephyr $ source zephyr-env.sh
先ほど作った設定ファイルの内容が環境変数に反映されていれば成功です。
$ env | grep -i zephyr ZEPHYR_BASE=/home/ubuntu/work_dir/zephyr PWD=/home/ubuntu/work_dir/zephyr ZEPHYR_TOOLCHAIN_VARIANT=zephyr ZEPHYR_SDK_INSTALL_DIR=/home/ubuntu/work_dir/zephyr-sdk-1.0.1 PATH=/home/ubuntu/work_dir/zephyr/scripts:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
注意点は、シェルを終了させると環境変数が消えてしまうことです。したがってシェルを立ち上げる度に、
$ cd work_dir $ source .venv/bin/activate $ cd zephyr $ source zephyr-env.sh
を実行する必要がありまして面倒です……。手間なく設定する方法がありそうなので、ご存じの方は教えてくださいませ。以上がうまくいっていたら、ディレクトリはこうなっているはずです。
work_dir |-- .venv `-- zephyr-sdk-1.0.1
またセットアップだけで話が終わってしまいました。Zephyrは本題に至るまでが遠いです。次こそアプリを作ります。
この記事にコメントする
wiki
Linux JM
Java API
2002年
2003年
2004年
2005年
2006年
2007年
2008年
2009年
2010年
2011年
2012年
2013年
2014年
2015年
2016年
2017年
2018年
2019年
2020年
2021年
2022年
2023年
2024年
2025年
2026年
過去日記について
アクセス統計
サーバ一覧
サイトの情報