ABC150参加
ABC150に参加しました.
unratedになってしまいましたね.
コンテスト成績はこちら
今回はPythonで3完でした.
A問題
かどうか判定して終わりですね. はい.
B問題
文字列中に"ABC"がいくつあるか数えて終わりでした.
C問題
制約から全列挙で行けることがわかったためPythonのitertoolsを使ってとりあえず全ての順列を列挙しました.
その後、線形探索で与えられた数列がどこにあるか探し、その差の絶対値を取って終わりでした.
D問題
問題文から式変形をし、となればいいことが分かり、そこからどうするか考えてたところでunratedが発表されたため、考えるのをやめました. はい()
今回久しぶりに全てPythonでのACでした.
できればどこかでFortranを使えばよかったかもしれません.
なんだかんだ17分で3完できたためratedだったら700超えてたかもですね…
とりあえず今年はレート1000超え目指してがんばります.
アマチュア無線について思うこと
あけましておめでとうございます.
すっかり寝正月ですね*1.
今年もよろしくお願いします.
さて、今日はアマチュア無線関連でTLが少しざわついたのでそのことについてつらつら書いていこうかと思います.
目次
わたしはだれ?
ぼくはアマチュア無線とプログラミングが好きな大学生です.
最近は卒研配属関連で鬱になってるよ.
アマチュア無線は大学に入ってから始めました.
もともと高校生の時にBCL*2をやってて、そこからアマチュア無線の存在を知りました.
現在は個人局(JJ1GUJ)や社団局(JR1ZTT)のコールサインで通常交信からコンテストまで幅広く出ています.
好きな周波数帯は遠くの局と通信できるHF帯で、好きなモードはCW*3です.
詳細はこちらを見てください.
元ネタというか事の発端と言うか…
元ネタはここら辺ですかね.
アマチュア無線ビギナーへ、ぜひ覚えておいて欲しいライフハックをお伝えします。
— Yasuki Okita (@JA1CCN) 2019年12月31日
交信中に変なのに絡まれたら、すぐに無線機の電源を切ればOK。交信が途切れることはよくあるので、相手は「あれ?いなくなった」と思うだけ。気にしなくて全然OK
不快感が増幅する前に電源オフ! これが基本ですm(__)m
まぁ今回はここら辺を受けて自分自身がアマチュア無線のことをどう思っているかつらつら書いていこうと思います.
アマチュア無線の利点
アマチュア無線をやる上での利点とするとここら辺があげられるかと思います.
・kHz帯からGHz帯まで幅広い周波数帯で免許を下ろし、運用することができる
・FT8やCWをはじめとするデジタルモードや電話など様々な変調方式で電波を出し通信を行うことができる
個人的にはAMラジオで使われている周波数帯からスマホで使われている周波数帯まで幅広く使えるのは素晴らしいことだと思っています.
アマチュア無線の欠点
欠点としてはここら辺が挙げられると思います.
・初期コストが高い
・(いろいろな意味で)ビギナーに優しくない
・やりたいことがあっても情報が見つからない
やはり初期コストの高さは学生ハムの参入を妨げている大きな要因かと思われます.
多くのビギナーがまず受けるであろう第3級アマチュア無線技士の試験手数料と免許申請料だけで7,000円近くになってしまいます.
そこからさらに開局しようとなると少なくともさらに2万円かかります.
よっぽどやる気がない限りなかなかやる気になれませんね.
一応弊社団では合格した場合や開局する場合には試験手数料や開局申請手数料をはじめとする各手数料は全て部費から支払ってくれる制度があります.
おそらく他社団でもこのような制度があるかと思われます*4.
(いろいろな意味で)ビギナーに優しくないというのは実際に自身で免許を取得し、交信するようになった時に最も実感したことです.
「この周波数帯はラグチュー*5するための周波数帯だからラグチューする気ないなら電波出すな(意訳)」と言われておじいちゃんのつまらない話に付き合わされたり「30年前のQSLカード*6が来てない、はよ送れ*7」と言われたりして正直やる気無くしました*8.
このような経験を回避するためにはCW等のデジタルモードに逃げるのが手っ取り早いのですが、別途申請が必要だったり訓練をしなくてはならなかったりとなかなか辛いものがあります.
最後にやりたいことがあっても情報が見つからないというのはぼく自身のサーチ能力がアレというのもあるかと思われます.
ただ仮に情報が見つかったとしても情報量がほぼゼロだったり内輪ネタが多かったり文体が読みづらかったり*9してとりあえずMPが削られます.
むすび的な何か
い か が で し た か 笑 ?
正直なところを述べると先に述べた欠点のうち初期コストの高さは仕方ないにしても残りの2点においてはなんとかしたいよねって感じです(そんな権限はないですが)
特に情報量の少なさについてはいろいろアマチュア無線使って遊んで(そんな余裕あるのか?)その記事を書いていって微力ながら貢献しようと思っています.
まぁこんな感じにいいとこも悪いとこもあるよねって感じです()
(ToDo: 言葉がまとまったら整備する)
参考文献
Github Pagesでテーブルを表示させる方法
Github PagesでMarkdown記法でテーブルを書くとうまく表示されないという問題があったため、これを解決する方法をメモっておきます.
あらまし
僕は自分のwebページをGithub Pagesを使って公開しています.
Github PagesとはGithubにMarkdownで書いたファイルをあげるとwebページで公開してくれるなんか、そう、すごいやつです(詳細はググってください).
そこで、自分が出場したアマチュア無線のコンテスト成績を公開しているのですが、その際に以下のように表示されてしまう問題がありました.
ちなみにリポジトリ上で見ると下のようにうまく表示されていました.
解決方法
どうやら上の事象からMarkdown記法では効かないっぽいのでHTMLで書いたところ、うまく表示されるようになりました.(なんでかは知らん)
HTMLでの表の書き方はこちらを参考にしてください.
HTMLのtableでテーブルを作る方法と応用テクニックを解説 | webliker
また、CSSで表のスタイルを指定することもできます.
MarkdownにCSSを適用させる方法はこちらを参考にしてください.
なんか原因を知っている方がいましたら教えてくださいm(_ _)m
知的・機能工学システム応用実験軌道生成ツールの解説
弊学では秋学期(10月~2月)にという各テーマごとに10人ほどに分かれ、3ヶ月間同じテーマに取り組む知的・機能工学システム応用実験という授業があります。
テーマはFPGAを使って何か実装したり跳躍ロボットを作ったりとハードからソフトまでかなり幅広いです。
僕はその中でロボットシステムという2軸マニピュレータを設計し、実際に動かすというテーマに取り組んでいます。
実際に動かしている様子はこちら↓
この綺麗な動きを見て! pic.twitter.com/1917BcVzO6
— JJ1GUJ@研究の進捗がまずい (@jj1guj) 2020年1月13日
このテーマでは実際に2軸マニピュレータを動作させる際に時間ごとの角度情報をプログラムする必要があります。
一応便利ツールとしてExcelファイルが配布されるのですが編集するのに時間がかかりかなり不便なため、これをC++で実装しました。
実装したものはこちらにあります↓
今回は実装したものの中身というか原理というかを解説しようと思います。
目次
課題の概要
今回の実験では指定されたコース(直線コースの往復とクランクコースの片道)をなるべく短い時間で動くよう、2軸のマニピュレータのリンク長を設計し、そのリンク長で最も早く動くプログラムを作成することとなっています。
リンク長は可動範囲がA4コピー用紙内全ての場所であればどのような長さ、幅でも問題ありません。
今回の軌道生成ツールはSolidWorksでのモーション解析や実機での動作用に作成したものとなっています。
手先速度の設計
まず、手先の並進速度をどのようにするかを決定します。
最初に思い浮かぶのは動作開始から動作終了まで終始一定速度で移動させることだと思います。
一定速度で終始動かすと下のグラフのように、動作開始時と動作終了時に加速度がとても大きくなります。
回転体の運動方程式から、モータにかかるトルクは加速度に比例します。
そのため、これだとモータに大きな負荷がかかってしまい、モータのパフォーマンスを十分に生かせなくなってしまいます。
これを解決するために動作開始時の加速度を小さくすることを考えます。
下のグラフのように加速度を小さくすると今度は加速時間を長くしなくてはならないことが分かります。
そして、このときの速度曲線は上のグラフのように台形となることが分かります。
このような速度曲線を台形速度曲線といい、今回の手先起動の制御ではこれを使用します。
各時間ごとでの手先位置の設計
並進速度の速度曲線を決定したら、次は各時間ごとのマニピュレーターの手先座標を考えていきます。
今回は指定されたコースをなるべく短い時間で動かすという目的であったため、加速度を調整するパラメータにしてしまうと直感的にどのくらい早くなるか見積もれません。
そこで、加速終了時刻と減速開始時刻を調整するパラメータとすることで簡単に動作時間を見積もれるようにします。
もし加速時の加速度の絶対値と減速時の加速度の絶対値が同じであれば動作時間は加速終了時刻と減速開始時刻の和になるためです。
この時、加速度と定速時の速度はどのように表すことができるか考えていきましょう。
下のグラフのように加速終了時刻を、減速開始時刻をとします。
また、加速時の加速度を、減速時の加速度を、定速時の速度をとします。
この時、マニピュレータが動く道のりは上の図の台形の面積に等しいので
$L= vt _ {2}$ 、
から
$$L=at _ {1}t _ {2}$$
$$a=\frac{L}{t _ {1}t _ {2}}$$
よって、となることがわかります。
次に、加速終了時刻と減速開始時刻はそのままとし、原点から点Pまで台形速度曲線に従い動かすことを考えます。この時、軸方向に進む道のりは、軸方向に進む道のりはであるため、軸方向の加速度は
$$\frac{p _ {x}}{t _ {1}t _ {2}}$$
軸方向の加速度は
$$\frac{p _ {y}}{t _ {1}t _ {2}}$$
となります。
加速終了時のマニピュレータの手先位置を、減速開始時のマニピュレータの手先位置をとすると各時間ごとのマニピュレータの手先位置は
$$
(x _ {t},y _ {t})=
\begin{cases}
(\frac{p _ {x}t^{2}}{2t _ {1}t _ {2}},\frac{p _ {y}t^{2}}{2t _ {1}t _ {2}}) & (0 \leqq t \leqq t _ {1}) \\
(p _ {xt1} + \frac{p _ {x}(t-t _ {1})}{t _ {2}},p _ {yt1} + \frac{p _ {y}(t-t _ {1})}{t _ {2}}) & (t _ {1} \leqq t \leqq t _ {2})\\
(p _ {xt2}+\frac{p _ {x}(t-t _ {2})}{t _ {2}}-\frac{p _ {x}(t-t _ {2})^{2}}{2t _ {1}t _ {2}},p _ {yt2}+\frac{p _ {y}(t-t _ {2})}{t _ {2}}-\frac{p _ {y}(t-t _ {2})^{2}}{2t _ {1}t _ {2}}) & (t _ {2} \leqq t \leqq t _ {1}+t _ {2})
\end{cases}
$$
となります。
2軸マニピュレータの逆運動学を解く
逆運動学を解くということは、簡単に言うと「与えられた座標から各モータのモータ角を求めること」です。
今回は座標とそれぞれのモータ角を下の図のようにとります。
この時、、はそれぞれ
$$
\begin{cases}
\ \theta _ {1}=\pi - \tan ^{-1} \frac{y}{x}- \cos ^{-1} \frac{x^{2}+y^{2}+L _ {1} ^{2}-L _ {2} ^{2}}{2L _ {1} \sqrt{x^{2}+y^{2}}}\\
\ \theta _ {2}=\sin ^{-1} \frac{x^{2}+y^{2}-L _ {1} ^{2}-L _ {2} ^{2}}{2L _ {1}L _ {2}}
\end{cases}
$$
となります。
実際にSolidWorksや実機で動かす際にはラジアンから度に変換しなくてはならないので注意してください。
プログラムへの実装
ここまできたらあとは実装するだけです!
基本的なアルゴリズムとしては時間ごとの座標を求め、それに対応するモータ角を算出するという方法で問題ありません。
CSVへのファイル出力は、
#include<fstream> #include<iostream> using namespace std; int main(){ ofstream output; output.open("hoge.csv",ios::out); output<<0<<","<<"Hello World!"<<endl; return 0; }
とすれば出力できるはずです。 なお、コンマと改行をつけ忘れると実機やSolidWorksに読み込ませることができなくなってしまうのでお忘れなきよう….
今後の展望
とりあえず時代はGUIなのでQtのお勉強してGUI化しようと思います。
あとは作成したプログラムだとクランク起動では各コーナーでいちいち停止してしまってるのでこれを解消するようにしようと思います。
参考文献
追記
- 2021/12/16 そういえばこのときに作成したリポジトリが南極に埋められました(今更)
三井住友信託銀行プログラミングコンテスト2019 参加
いつもとかわらず3完でした(4完したかった…) 今回はFortran、Python3、C++と全て違う言語で出しました~
A問題
Fortranで提出しました.
入力された2つの月が異なるとき末日になるのでこれで実装し提出しました.
B問題
Python3で提出しました.
ごちゃごちゃ考えるのが面倒だったのでとりあえず1円から 円までループを回して、税込価格が円と等しくなるが存在するときにはこれを出力し、ないときは':('と出力しました.
C問題
C++で提出しました.
入力された価格を100で割った商が買える品物の個数だと考えました. そのため、あとはの下二桁を作るには少なくとも何種類の品物を買えばよいか考え(ならを5で割った商、それ以外ならを5で割った商に1を加えたもの)、これが買える品物の個数を超えていたときには'0'、超えていないときには'1'を出力するようにしました.
D問題
ずっと考えていたのですが、時間切れで最後までわかりませんでした.
とりあえずコンビネーション計算を使えば良いと考えていて、あとは重複する組み合わせをどうやって排除するかでずっと悩んでいました(最終的にわからずに諦めてずっとついったやってた).
D問題、解説に書いてあった全探索の解法が頭良すぎてずっと泣いてました.
どうやったらあんな天才解法思いつくんだろう...
あとはF問題が解説読んでみた感じ割と簡単そうだったのでDを捨ててFでずっと考えてたほうが良かったかもですね...
とりあえず今回レートがちょっと回復したので学年変わるまでに緑色になれるよう頑張りたいと思います.
ラズパイ4を買った
レポートの現実逃避で書いてます…
11/25に発売されたラズパイ4、買いました!
手に入れた pic.twitter.com/BKawiMXakL
— JJ1GUJ@オセロソフト公開準備中 (@jj1guj) 2019年11月27日
あきばお〜で購入すると8 GB MicroSDもついてくるとのことだったので、ここで購入しました.
あとは千石でMicroHDMI-HDMIの変換ケーブル、ケース、USB TypeC-USB TypeAの変換ケーブル、ヒートシンクを購入しました.
お家に帰ったらとりあえずRaspbianをインストールすることに.
公式からダウンロードしてきたのですが、ありえんほど重い…
結局ダウンロードが完了するまでに4時間程かかりました.
f**k pic.twitter.com/Cvj9vZt9OG
— JJ1GUJ@オセロソフト公開準備中 (@jj1guj) 2019年11月27日
みんな、ミラーからダウンロードしような.
まぁそんなこんなあったものの、無事起動できました~.
とりあえず今は普段遣い的な感じで使ってます(Mなのかな?)↓
辞書敷いたらいい感じの高さになった pic.twitter.com/Ge4y1E2na8
— JJ1GUJ@オセロソフト公開準備中 (@jj1guj) 2019年11月28日
使い心地としてはちょっと重いかな?ってくらいで全然問題なく使えますね.
ただいかんせんCPU温度が高い(アイドル状態で50℃超える)のでお金たまったら専用ファン買ってつけます.
ABC145参加
ABC145参加しました~
結果はこちら
2完しかできず詰みました…
コンテスト中はすべてFortranで出しました.
A問題
円の面積はなのでを出力して終わりでした.
B問題
Nが偶数かつ文字列の前半分と後ろ半分が同じときのみYesと出力するようにしました.
C問題
とりあえず3と4のときの順列を列挙して手で数えてみたところ、特定の隣り合う2つの組み合わせが回出てくると勘違いして、各点間の距離の総和にをかければよいという結論に至り、実装して試してみたらサンプルケースで見事にコケてしまいました(それはそう). そのため、全探索するかぁってモチベーションになったものの、やりかたがよくわからず、時間がかかりそうだったのでしばらく迷ってから諦めました.
D問題
与えられた条件から、到達できる点は下の図のように格子状に存在することがわかりました.
ここから、入力された点が到達できるかどうか判定して、あとはで求めれば良いことがわかったので到達できる点かどうかの判定方法およびとの求め方を考えていくことにしました.
まず、到達できる点かどうかの判定法です.
図1から、
$$y= \frac{x}{2}+b \tag{1}$$
は必ず
$$(a, 2a) ただしa \in \boldsymbol{N} \tag{2}$$
を通ることがわかります. よって、ここから式(1)のを求めると、
$$2a= \frac{a}{2}+b$$
$$b=\frac{3a}{2}$$
これとを式(1)に代入し、について解くと、
$$Y= \frac{X+3a}{2}$$
$$a=\frac{2Y-X}{3} \tag{3}$$
よって、式(2)からが3の倍数でないと到達できないことがわかります.
次に、とを求めます. 図1において、目的地まで原点から上方向にいくつ進まなくてはならないかは、入力された点を通り傾きがである直線との交点の座標に等しいことがわかります. これは、式(3)と等しいので、これを使います. 横方向には、今度は点を通り傾きがである直線との交点の座標と等しいことがわかります. よって、これを求めていきます. 点を通り傾きがである直線を
$$y=2x+c \tag{4}$$
と置き、を代入してを求めると、
$$c=Y-2X$$
よって、式(4)との交点の座標は
$$2l+Y-2X=\frac{m}{2}$$
$$l=\frac{2(Y-2X)}{3}$$
よって、座標は
$$m=\frac{l}{2}=\frac{Y-2X}{3}\tag{5}$$
であることがわかります.
よって、式(3)および式(5)から、
$$n=a+m=\frac{X+Y}{3}$$
$$r=min(a,m)$$
であると求められました.
ここまできたら後は実装するだけだったのですが、効率のよいコンビネーションの求め方がわからず、ひたすらググっていました…
結局、こちらのサイトに載っていたコードを使用させていただきました.
【Python】組み合わせ(nCr) 計算の高速化 - Qiita
ただ、これで実装できたはいいものの、終わったのがコンテスト終了直後という悲しい結末… しかも、提出してみたら普通に通ってしまったという悲しさ…
供養しておきます pic.twitter.com/sU3dB41DhV
— JJ1GUJ@オセロソフト公開準備中 (@jj1guj) 2019年11月16日
終了20秒後に出したのが通るとかなんなん…
終わってからずっとほえてました…
反省とか
よかったところ: Fortranの実装速度が上がった
悪かったところ: B問題に見切りをつけるのがおそすぎた
結局レートはちょっと下がってしまいました...(100くらい下がるかと思ってたけどそうでもなかった)
とりあえず来週もABCあるのでレートを戻せるようにがんばります.
あと4~5回くらいで緑色になりたいなぁ…