2016年03月19日

paickというスマートウォッチを購入したのですが日本語の(英語も?)情報がほぼないのでちょっと使ってみてわかったことをまとめておきます。
面倒だったしあまり意味はなさそうなので写真などは無いです。

とりあえず長くなったので買うか迷ってる人のためのまとめ

見た目はあまり悪くないです。1万円の時計と言われてがっかりするような質感では無いです(activite popより高級感はあります)。
連携アプリはかなり怪しいです。Androidは権限の管理とかすればギリギリ?iOSは審査も通ってるのである程度安心?
最初から電池が減っている場合があります。電池が減るとただの時計になります。
歩数計はやや少なめに出る気がします。
電池の問題かわかりませんが一部の機能が動かないです。
結論:セキュリティ的に問題ない端末とペアリングして時計として使えるおもちゃが欲しい以外なら買わないほうが良いです。

電池を交換したら歩数計の誤差が少なくなって通知類も来るようになりました。交換費用はヨドバシカメラで2000円ほどでした。最初から電池がかなり減っている場合があるので調子が悪い場合は電池の交換を検討してみましょう。


ここから適当な話

値段はexpansysで送料含めて1万円ほどです。
なんか安かったので勢いで注文。
注文したら3日か4日ほどで届きました(詳しいことは忘れました)。
これだけ買った場合は税金はかかりませんでした。


届いてから

まず箱を開ける。
高級感はそれなりにあります。
1万円の時計としてがっかりするような質感ではないです。
意外と悪く無いです。
バンドも革製で安っぽい感じはないです。
まあ気に入らなければ交換すればいいでしょう。
同梱品は分解用の工具と説明書です。
説明書を読んで連携アプリの確認。



ここから連携アプリの話

googleplayにはなく野良アプリです。
まあ想定内です。
説明書にQRコードがあるのでそこから適当にダウンロードする感じです。
apkのダウンロード先が怪しいですURLが
***.com/***.com/***.apk
みたいな感じです。この時点で怪しさマックスですね。
とりあえずダウンロードしてインストールします。
インストール時に怪しい権限が要求されます。予想通りですね。
ちなみに要求される権限は予想通りに
・電話帳
・SMS
・ネットワークのフルアクセス
・bluetoothの設定
・システム設定の変更
は当然のようにありますが更に
・ストレージへのアクセス
があります。珍しい権限ですね。危ない匂いがすごいです。
まあスマートなウォッチとして使えないのでインストールしちゃいます。
権限は止めちゃえばいいし。
と、ここで思いましたが権限をコントロールできるような端末以外にインストールするのはかなり危険です。
よくわからない人はやめておきましょう。
とりあえずインストールしたら開く前に権限の設定をしておきます。
まあその前にバックグラウンドで権限を止める前に怪しいデータを送信される危険性はあります。
慎重になるならネットワークを止めてからインストールをしてそこから権限を止めるくらいしても良いかもしれません。
まあここまで進んだらアプリを起動します。
メニューとかが中国語です。
とりあえずペアリングをします。
よくわかりませんがとりあえず見れる設定とかを見たら電池残量が20%ほどでした。倉庫に眠っている間もスマートウォッチとして動いていたと考えるとまあしょうがないような気もしますがペアリングするまでは止めておいても良いような気もします。損した気分です。
アプリをいろいろいじっていたらなんかアプリのバージョンアップができるところを見つけました。
とりあえずアップデートしてみます。
そしたらなんとそのアップデートのapkのダウンロード先が内部ストレージです。怪しさしかありません。
URLがhttp://***ではなくstrage0/***みたいな感じです。非常に危ない感じしかありません。
ちなみに最初入れた端末だとこれに気づかず違う端末に入れた時にこの事に気づきました。
Android6.0以上(だったっけ?)で権限設定でストレージのアクセスの権限を止めておくとアップデート出来ません。もうこの時点でアプリに対する信頼度は任意のε未満です。
まあとりあえずアップデートします。危ないですが。
アップデートしたら電池残量が%表記ではなくnormalと表示されるようになりました。しばらく使ったらlowみたいな表示になったのでなんかわかりにくくなったのでアレですね。
ちなみにバックグラウンドで通信していたので安全性は完全にアウトですね。

とこのくらい書けば連携アプリがどのくらい危ないかわかると思います。わからないようならそういう人は買わないほうが良いです。

iOSの連携アプリは審査も通っているのである程度は安心できるかもしれませんがまあ自己責任でお願いします。(ちなみにアップデート確認でアップデートが存在しなくてもappstoreに飛ばされます)


ここまで連携アプリの話


ここから機能の話

はい、連携アプリの話はこのくらいにしておいて実際に使った感じの感想です。これまでに使ったスマートウォッチ的なデバイスだとhuaweiのtalkband b1があるのでそれとの比較した感じで。
スマートウォッチ的な機能として以下のものがあります。
・活動量計
・電話の通知
・スマートアラーム
くらい?買ってから気づいたんですが睡眠ログとか無いんですね。この手のものには標準装備なので意外でした。
活動量計ですが歩数がやや少なく出るようです。huaweiのtalk band b1とくらべて2割から3割ほど少なく出ます。まあ相対的に測るなら問題なさそうですね。時計をダブルタップするとおおまかな活動量がLEDで表示されます。talkbandでボタンを何回か押して歩数を表示させるより簡単なので便利ですね。細かくは出ませんが。
電話の通知はちゃんとしてくれるようですが電池が少ないとダメみたいです。購入直後に交換が必要かもしれません。ただ振動が弱めで気づきにくいです。
スマートアラームはなんか設定しても動かないです。不良品?と思いつつもなんかいろいろやってたら振動はしたのでモーターが壊れているわけではなさそう。
電池を交換したらちゃんと機能するようになりました。


結論:機能としてはまあまあですがアプリが非常に危険なので取り扱いには注意が必要ですね。

(15:21)

2015年11月17日

月姫打ONLINE(以下TOL)の対戦で使えそうな小ネタです。

1. ローマ字入力関連
TOLの入力はちょっと特殊で入力されたアルファベットをひらがなに変換して打つべき文字と同じかどうかを判定しているようです(たぶん)。
それの判定アルゴリズムの問題で正しくひらがなに変換できないようなローマ字入力でもゲームとしては正しい入力として処理される場合があります。
というわけで見つけたローマ字的には正しくなくてもゲーム的には正しい入力方法で見つけたやつをまとめます。

1.1 大文字の扱い

英語を打つときは大文字小文字は区別しないといけませんがひらがなを打つときは大文字でも大丈夫です。なので「ねこ!ねこ!ねこ」というワードをシフト押しっぱなしで「NEKO!NEKO!NEKO!」と打っても問題無いです。

1.2 「ん」関連
普通のローマ字入力では「あ行」や「な行」や「や行」や「にゃ行(?)」では「ん」を打つためには2回Nを打つ(またはXN)必要がありますがこのゲームでは1回で打てる場合があります。
「な行」や「にゃ行」のNを三連打するパターンでは普通に3回打たなければいけませんがそれ以外では1回のNで打てませんがそれ以外だと「んい」を「NI」と打てたり「んや」を「NYA」と打てたりします。
Nを三連打する場合も「n;」などと関係ない文字を打つことで「ん」が確定されて「んの」を「n;no」と打てたりします(;はミス扱いされるので注意)。
あと大半のIMEや一部のゲームで使える「n'」という入力方法は使えない(とはいえ上の例の;のようにミスが増えて「ん」が確定されるので一応使えないとはいえない)です。

1.3 「っ」関連
基本的に「っ」は同じキーを連打したら「っ」に変換されるようです。というわけで次に打つべきキー以外の適当なキーを二連打しても大丈夫な場合があるようです。
大半の場合は次の文字を打つときにミス扱いされて速くもないのであまり使えませんが有効な例が少しあります。
「っい」→「lli」
「っ?」→「ll?」「???」
「っ!」→「!!!」
「っな」→「nna」

どういうわけかわかりませんが上のように打てます。「l」の代わりに「k」とか適当なキーでも大丈夫だったと思いますが「aiueo」あたりはダメだった気がします(大丈夫かもしれないです)。
「っな」なんて出てくるワードあるの?と思うかもしれませんが翡翠の反転技で出てきます。


2. 状態を変えるSP技について
さつきのパワーアップやアルクや式のデッドライン固定、琥珀のブラインドなどステータス異常(自分のでも相手のでも)を起こすSP技は基本的に上書きができます。
というわけで琥珀のブラインドをアルクのデッドライン固定で解除できますし、さつきのパワーアップをシエルの無色化や翡翠の反転で上書きすることができます。
唯一の例外はアルクのデッドライン固定は式のデッドライン固定で上書きができないというパターンだけです。式のデッドライン固定中にアルクのデッドライン固定は上書きできます。
なので特技を発動するタイミングが悪いとあまり効果が無いということもあります。


これらを知っておくとちょっと対戦で対戦で有利になるかもしれません。

(01:36)

2015年09月19日

デスマコロシアムが終わってしまいました。
デスマコロシアムはコードゴルフとその他諸々の要素を組み合わせて戦うトーナメントです。
詳しくはググればいいと思います。

結果は目標の言語内最短を出すことができました。
そこまでにどうやって縮めていったかを書いていきます。
最終的なコードが見たい人はCodeiqMAGAZINEを見れば大丈夫です。

今回の問題は次のようなものでした。

abCDEfghIjklmnOpQrstuvwxyz
abcDEFghiJklmnoPqRstuvwxyz
abcdEFGhijKlmnopQrStuvwxyz
abcdeFGHijkLmnopqRsTuvwxyz
abcdefGHIjklMnopqrStUvwxyz
abcdefgHIJklmNopqrsTuVwxyz
abcdefghIJKlmnOpqrstUvWxyz
abcdefghiJKLmnoPqrstuVwXyz
abcdefghijKLMnopQrstuvWxYz
abcdefghijkLMNopqRstuvwXyZ
abcdefghijklMNOpqrStuvwxYz
abcdefghijklmNOPqrsTuvwxyZ
abcdefghijklmnOPQrstUvwxyz
abcdefghijklmnoPQRstuVwxyz
abcdefghijklmnopQRStuvWxyz
abcdefghijklmnopqRSTuvwXyz
abcdefghijklmnopqrSTUvwxYz
abcdefghijklmnopqrsTUVwxyZ
abcdefghijklmnopqrstUVWxyz
abcdefghijklmnopqrstuVWXyz
abcdefghijklmnopqrstuvWXYz
abcdefghijklmnopqrstuvwXYZ


を出力。実際にはアルファベット1周ごとの改行は必要ないです。というかしてはいけません(見やすいように勝手にアルファベット1周ごとに改行を追加してます)。
※最後に改行はあってもなくても良い。

内容は以下のとおりです(CodeiqMAGAZINEの記事より引用)。

"はじめは、aからzの文字でcodeiqに一致する文字のみを大文字に変換します。
次にaからzの文字でdpefjr(codeiqの次の文字)に一致する文字のみを大文字に変換します。
という風に、ループする度に大文字に置換する位置をずらす処理をaからzに対して22回繰り返します。"


ちなみにこの"codeiq"に一致したら大文字というルールは45byteの解ができるまで気づかずランダムなパターンだと思ってました。
まあこれが結果的に良かったのかもしれません。


まず考えたのは次のようなコードです。


a=[]
[2,3,4,8,14,16].map{|i|a[i]=1}
22.times{|i|26.times{|j|$><<(a[j-i]?j+56:j+97).chr}}

(改行が2byteとして全部で90byte)
これを動かすと間違った出力になります。
aは
[nil,nil,1,1,1,nil,nil,nil,nil,1,nil,nil,nil,nil,nil,1,nil,1]
となっていてa[j-i]が真(Rubyではnilとfalse以外は真です)だったら大文字、nilだったら小文字を出力です。
この配列の2,3,4,...に入れる値はnilとfalse以外ならなんでも良いですが文字数が短いので1桁の数を入れます(0でも大丈夫です)。
と思ったのですがj-iがマイナスの値になると配列の後ろからアクセスしてしまうためほしくない1が取得されてしまいます。
これを避けるためにa[99]=nilを加えて回避ということもできますが結構長くなりますね。
しかしaを配列ではなくハッシュにするだけで回避できます。
というわけでa={}とすればちゃんと動きます。


次に考えたのはループを二重ではなく1重(?)にする方法です

22.times{|i|26.times{|j|(なんとか)}}

ではなく

572.times{|i|(なんとか)}}

とするとまあ変数の使い方は変わってしまいますが結構ループの構造を短くすることができます。

a={};[2,3,4,8,14,16].map{|i|a[i]=1}
572.times{|i|j=i%26;$><<(a[j-i/26]?j+65:j+97).chr}

(87byte)
と3byte縮めることが出来ました。(と思ったら1つ改行の代わりに;を使っている(なぜ?)ので実質2byteです。←たぶんまだ途中だと思っていたので適当にやっていたんでしょう)


とこんな面倒な方法を考えていたのですが、このコードが何をしているかというとj-iが[2,3,4,8,14,16]に含まれているかどうかを探しているだけという事に気づきました。
というわけで直接探せる
[2,3,4,8,14,16].index(j-i)
を使います。
これなら扱うものはハッシュではなく配列ですがj-i<0でも全く問題ありません。
返ってくる値は先ほどと違いますがnil,falseとそれ以外が判断できればいいので問題ありません。
面倒な配列の宣言や書き換えがなくなって一気に短くできます。
というわけで次のようになりました。

572.times{|i|j=i%26;$><<([2,3,4,8,14,16].index(j-i/26)?j+65:j+97).chr}

(70byte)
ブロックも一つになっていい感じです。ここで満足して1回目の提出をしました。

テキストエディタを見るのも飽きてきたので過去のデスマコロシアムのまとめを読んでいたらputcを使う方法を見つけました。
$><<a.chr



putc a

と書く方法です。この例だと3文字しか短くなりませんが今回の場合は()も減らせるので5byte短縮です。
というわけでこうなりました

572.times{|i|putc (j=i%26)+(([2,3,4,8,14,16]&[j-i/26])[0]?65:97)}

65byteで提出です。
a.index(n)と(a&[n])[0]が同じ文字数だったので適当に書き換えてみました。
その他にも色々(jの宣言とか)違いますが5byte縮めた要素はputcを使っただけです。
これを出した直後にもう1つ縮める要素を見つけました。
出した直後に改善案が見つかるのはマーフィーの法則からすれば妥当なところです。

jはわざわざ宣言する必要はなくi%26をそのまま使えばよかったのです。
というわけでjに関するところをi%26に書き換えれば1byte短くなります。
というわけで64byteで提出しました。


ここで1回目の集計です。
できれば言語内最短、あわよくば全言語内最短という目標でしたが後者は達成できず(Perlで60がいた)、前者だけ。まあ目標が達成できたので良しとします。


次の目標はPerl(60)です。なんとか4文字短くしてみましょう。

とりあえずいまのコードを短くする方針を考えます。
なんとかPerl(60)に追いつこうと色々考えていたらちょっと短くする方法が見つかりました。

([2,3,4,8,14,16].index(i%26-i/26)?65:97)



([i%26-i/26,97,65]-[2,3,4,8,14,16])[1]

に置き換えます。配列の引き算を使います。
i%26-i/26が右側の配列に含まれるときはその要素が消え[97,65]という配列が返り、含まれない場合は[i%26-i/26,97,65]になります。この配列の(0から数えて)1番目の要素を取れば97か65の欲しい方が取得できるわけです。
これで2byte縮まります。62byteでまだ目標の60byteには届きません。
なんかすごい綺麗になったと思ったのですが意外と縮まらないものですね。
綺麗なアルゴリズムでコードが縮んだと思った時に限って文字数はあまり変わらない法則の発動です。

次に気になるのはi%26が2回出てるということです。できれば1文字の変数でなんとかしたいですね。
jを用意するのは失敗だったのでループ内変数のiを破壊してなんとかする方法にします。
次のループでは新しく正しい値が生成されるので破壊してもあまり問題無いです。
i%=26とすれば次にiを使うときには最初でいうi%26と同じになります。
というわけでこれらを用いるとループの中身は

putc ([i%26-i/26,97,65]-[2,3,4,8,14,16])[1]+i%26

から

putc ([-i/26+i%=26,97,65]-[1,2,3,7,13,15])[1]+i

になりました(1byte短縮で61byte)。

ちなみに-i/26は-(i/26)ではなく(-i)/26なので探す数は1つずれます。
"a"を出力するときだけずれないので問題ありそうですが今回はaが大文字になるケースが無いので問題無いですね。
60byteが目標でしたがここで力尽きてこの日はこれで提出。

ここで2回目の集計です。
Perlは(59)になり、Rubyは全言語最短の(56)になりました。言語内最短も陥落です。


ボツネタ
1,2,3,7,13,15って,使いすぎなので文字列にしてつないだらどうだろう?

"12371315".index(n.to_s)

と.to_sが長いためアウトです。しかもこれn==5で引っかかってしまいます。ダメ。
10進数を使うからダメなんだというわけで16進数を使います。幸いRubyでは16進数とかに簡単に変換できます。

"1237df".index(n.to_s 16)

1文字長くなってしまいましたがこれなら通ります。しかし
[1,2,3,7,13,15].index(n)
のが短いです。ダメでしたね。

"0111000100000101"[n]
を使ってみる。
→返ってくる値は"1","0"の文字列です。このまま使うのは厳しそうですね。to_iすれば使えますが長いですね。
"0"や"1"は数値と四則演算はできません。
あとn<0の時は逆からアクセスしてしまうのでダメです。

ここで一つひらめきました

このビットパターンを持つ数値とビット演算すればいいじゃん。


上の2進数の文字列は左から数えているので逆にしないといけませんがその2進数で表される数値を使います。
というわけで上の文字列を逆順にした物を10進数の数値に変換してみましょう。
irbを使って計算してみました。

#1と0で書かれた文字列を2進数と見て数値に変換する
"1010000010001110".to_i(2)
=>41102

というわけでこの数値を使います。
これの右からnビット目が1か0を調べたら良さそうです。というわけで
41102&(2**n)>0?

とかでしょうか。9byteも縮めることができます。やったぜ。と思ったらn<0でエラーですね。

41102&(1<<n)>0?

なら問題なく動くのでこれで良いようです。
ここまでかと思いましたがRubyにはもっと便利なメソッドがありました。Integer#[]というメソッドがあり、これは右から(0から数えて)nビット目の数値(返ってくるのは0または1の数値)を取得することができます。
さらにnがマイナスの場合は常に0が返ってきます。というわけで

41102[n]>0?

と更に短くすることができました。

572.times{|i|putc (41102[-i/26+i%=26]>0?65:97)+i}

(49byte)
というわけで50byteも切って大満足です。最高記録です。

ここでまた一つ気付きました。
返ってくるのは0,1(数値)なので配列のインデックスとして使えばいいじゃんということです。

572.times{|i|putc [97,65][41102[-i/26+i%=26]]+i}

(48byte)
短くなりました。すごく綺麗になったと思うのですが綺麗になった割には1byteしか縮まってないですね。
まだ括弧が多いような気がしますね。
さらにもう一つ気付きました。
0,1は配列のインデックスじゃなくて計算式に突っ込めるじゃん。
というわけで最終的に出来たのが次のコードです。

572.times{|i|putc 97-41102[-i/26+i%=26]*32+i}

(45byte)
48byteのコードのほうが美しいと感じますが短くなったので正解です。
もうこれ以上はムリだろうと思って提出しました。
ここで3回目の集計。
集計時点で全言語最短を達成です(この時点では単独1位でした)。
目標の(途中経過での)全言語最短の達成です。
オツカレサマデシタ。

ちなみにこの全言語最短記録は一晩でRubyで追いつかれ、数日でPerlによって抜かされてしまいました。
残念でしたね。
Rubyが全言語最短になれる問題だと思ったのに…


時は流れ…
最終結果はこちら
というわけで結果はRuby内最短でした(トーナメントはいきなり負け)。
目標の言語内最短と途中集計で全言語最短ができたので良かったです。


おまけ
1.Ruby(45)の別解
別解というほどでもありませんが

572.times{|i|putc 41102[-i/26+i%=26]*32^97+i}

としても同じ結果になります。中身がどうなっているかは簡単なビット演算の問題なので自分で考えてみましょう。


2.Cに移植してみる
なんか行けそうだったのでCにも移植してみました。
で、コードはこれ

i;main(){for(;i-572;putchar(i%26+(82204&1<<i%26-i++/26?65:97)));}

ループの中でiを破壊できなかったりするのでちょっと長いですが65byteでまあまあです。
ideoneで動かしてみました。
http://ideone.com/PuAQ0X

なんと最後の方で無駄に大文字変換されてしまっています。
どうやら32bitでループしてるようです。
適当にビットシフトでテストした結果がこちら。
http://ideone.com/TAgqBw
シフトしているわけではなく2のn乗をかけているのでしょうか。
オーバーフローしているように見えます。
もう少し詳しく調べてみたくなりますね。

(03:32)

2015年09月08日

デスマコロシアムが最終回ということで参加中です。
最終回だからという理由ではなくちょうどCodeIQとコードゴルフを始めたのでちょうどよかっただけですが。

現在開催中のデスマコロシアムはもうこれ(Ruby(45))以上短くできそうにないので過去問を解いてみました。
今回解く問題はデスマコロシアムの第9回です。

問題は

AbcdefghIjklmnopQrstuvwxYzabcdefGhijklmnOpqrst...

という文字を出力(a..zを8回繰り返し、8個ごとに大文字に変換)するという問題です。

Rubyだと簡単に

208.times{|i|putc (i%8<1?65:97)+i%26}

(37byte)
こういう解答ができますね。意外と簡単に思いつきますがなかなか縮められそうに無いですね。
Rubyの最短解もこれとほぼ同じでした。
なんとか削れそうなのはカッコと三項演算子でしょうか。
三項演算子を使う限りは短くできそうに無いのでビット演算でなんとか削る方法を考えます。

幸いなことに(?)大文字と小文字の整数コードの差は32で、a..zの間に6ビット目は変化しないのでここのビットをオン・オフすることでなんとかする方針を考えます。

i%8が0の時とそれ以外の時で6ビット目を切り替えられるようにします。
どこか一つのビットだけを見て0か1~7を判断する方法はありませんが一つ方法があります。
0と1~7の判断は難しいですが0と-1~-7は比較的簡単にできます。
-1~-7は4ビット目以上は1が並びます。当然6ビット目も1です。
というわけで
(-(i%8)&32)==(i%8>0?32:0)
はtrueになります
-i%8の結果は0~7になってしまうので-(i%8)とします。
というわけで-(i%8)&32でiが8の倍数の時は0、そうでなければ32になる計算式が出来ました。
これを使うと

208.times{|i|putc -(i%8)&32^65+i%26}

(36byte)
というわけで1文字縮まりましたね。大勝利ですがここで終わりではありません。
実はもう少し削れます。-i%8とカッコを消すと違う結果になってしまって使い物になりませんがi%-8とすることで(計算結果の値は違いますが8の倍数かそれ以外かを判断する上では)同じ結果を得られます。ということで。

208.times{|i|putc i%-8&32^65+i%26}

(34byte)
こうなりました。というわけでここで終了です。3文字縮まりましたね。i%-8&32と65+i%26はそのまま足し算しても大丈夫なのですが+を使うと演算の優先度の関係で違う結果になってしまう(もしくはカッコが必要)ので排他的論理和の^を使ってます。^じゃなくても|でも同じ結果になりますね。

(21:30)

2015年07月16日

飽きずにまたコードゴルフです。

今回の問題はyukicoderの192です。

この問題は101から1000の整数Nを入力してN-100からN+100の範囲に含まれる合成数を求める問題です。

範囲内の数を適当に選んで素数判定とかすれば良さそうですがもっと単純に考えられますね。
素数判定をしなくても最後の桁が4の整数は全て合成数です。というわけで入力した文字の最後を4に書き換えて終了です。
という解法で最初は通しましたがもっと簡単な方法があります。
解説(ログインが必要です)の通り近い偶数を見つければいいだけです。
最初Nの範囲が1からだと勘違いしていたので最後の桁を4にするという方法を使いましたが入力される数は101以上なので入力された数が奇数なら1を引いて出力、偶数ならそのまま出力すればいいようです。
Rubyで書くと

p (a=gets.to_i)%2<1?a:a-1

(25Byte)
とかでしょうか。aに足す数は-99から99までの奇数なら問題無いと思います。ちなみに3以上なら入力が一桁とかでも大丈夫のようですね。

こんなことしなくても単純に解説通りに

p gets.to_i/2*2

(15Byte)
とすれば終了です。ここまでならまあ普通に計算式がわかれば書けますね。入力が3以下だと合成数以外が出力されますが入力は3桁以上あるので問題無いです。
これをビット演算で縮めます。

この計算がどのようなことをしているかというとNが奇数ならN-1,偶数ならそのままを出力というのは解説通りですが内部のビットの様子をちょっと見てみましょう。入力が181だった時2進数で表した時の様子を見てみましょう。書くのが面倒なので下位8ビットのみ書きます(その左側の24ビット(?)は全部0です)

10110101

これを/2すると

01011010

となり、そこに*2すると

10110100

となります。10進数で言うと180になりました。
一番右の1が消えましたね。
というわけで/2*2というのは一番右の1のみを消していることになります。これをビット演算で行う場合どうやら最初の数の最後の1ビットを0にする操作を行えばいいようです。
というわけでXORを表す記号の^を使ってN ^ 1とすれば良さそうです。と書きましたがこれはNが奇数の場合は有効ですが偶数だとダメです。1回これでWAを出してしまいました。奇数の場合はN-1になってくれますが偶数だとN+1となってN+1が素数の場合はアウトです。
というわけで違う方法を使いましょう。ビット演算に引き算があればN(引き算の記号)1と書けば終わるのですが引き算の記号は残念ながらありません(たぶん)。同じことをやる方法としてN&(~1)が使えます。Rubyのコードにする時はカッコはいらないのでN&~1と書けますビット反転した分1文字長くなってしまいましたがまあこれはしょうがないですね。~1は-2なのでどちらを書いても同じです。というわけで

p gets.to_i&-2

(14Byte)
と書けば終了です。

p gets.to_i/2*2

より1文字短くすることが出来ました。
とここまでやってもう1文字短縮する方法がありました。-2ではなく~1を使う方法です。同じ数を表すもので同じ文字数なのですがpとの間のスペースを消すことができます。ということで

p~1&gets.to_i

(13Byte)
で終了です。


1の代わりに3,7,15,31,63などを入れれば同様に下位の何ビットかを消すことができますね。どこかで使えそうです。逆に同じ桁を1で埋めたい場合はAND演算の&ではなくOR演算の|です。
ここでRubyの話は終了で次はC言語。C言語は古くからある言語でショートコーディングの世界でも結構人気があります。なんとなくやってみました。

main(n){scanf("%d",&n);printf("%d\n",n&-2);}

という感じでしょうか。C言語のショートコーディングテクニックを適当にググればこの程度は普通ですね。ちなみにreturn文を省略してますが一部のオンラインジャッジなどでは通るようですが残念ながらyukicoderではランタイムエラーになってしまいます。
上のコードは削れないように見えますが少しだけ短くできます。scanfは入力するための関数で返り値を利用することはほとんどありませんが関数なのでちゃんと返り値があります。成功すると代入した数(今回は代入する変数が1個なので1)が、失敗したら-1が返ってきます。この-1という値は比較的よく使われてfor(;~scanf(););とすることでscanfが成功するうちはループを回す使い方です。今回は失敗した時の-1ではなく代入した時に返ってくる1を利用します。
ここまで来るとわかると思いますがこの1と言うのは意味のある数ですね。というわけでこの1をビット反転して-2にして使います。

main(n){printf("%d\n",~scanf("%d",&n)&n);}

先ほどのコードに比べて一つの式になったことで;が一つ減ったのと-2がなくなったので3文字減、ビット反転の演算子で1文字使ったので合計で2文字減らすことが出来ました。
ちなみに自分ではよくわかってませんがn&~scanf("%d",&n)と書いても動きます。
まあどっちにしてもyukicoderで通すにはreturn 0;する必要があります。



(17:22)

2015年07月12日

なんとなくやってみました。
今回やってみたのはAtCoderBeginnerContest(以下ABC)の過去問のA問題です。
今回も例によってRubyです。基本的にランキングとか最高記録というのはRubyの中のランキングです。
基本的に過去問では全てのコードが公開されるので複数のコードからいいところをコピペすれば記録は抜けるので微妙なところもあります。
なので記録を縮めるために自分が気づかなかったところとか自分が縮めたところをまとめていきます。最短コードを解説するわけではありません。
一応かなりの問題で新記録を出せているのでそれなりに有効だとは思います。
まあAtCoderはゴルフ場ではないのでどの程度プロゴルファーが参加しているかという問題もありますが。


というわけで1問ずつ

ABC001-A

2つの整数が改行を挟んで入力されてその差を取るだけの問題。何も考えず

p gets.to_i-gets.to_i

とすれば終了です。特に短くするためのテクニック等は必要なく普通に計算すれば終わりです。あえて言うなら出力にpを使うくらいでしょうか。普通に書いても似たようなコードになることも多いようです。数を出力したい時は特に問題なくputsと同じ出力をしてくれます。コード長ランキングを見ると同じ文字数の人が何人かいますね(コードも全く同じです)。

(21Byte→21Byte)

ABC002-A

2つの整数がスペース区切りで与えられ、それの大きいほうを出力すればいいみたいです。
文字列でソートすると辞書順になるので2つの数の桁が違うとちゃんとソートできません。なので比べるときは数に変換する必要があります。
というわけで

p (gets.split.map &:to.i).max

とやれば終了です。と思って提出してランキングを見ると1文字負けてしまいました。原因はカッコの付け方で

gets.split.map(&:to_i).max

と書いていれば一つスペースを減らせます。この書き方は気づきませんでした。ゴルファーにとっては常識なんでしょう(僕はゴルフ初心者です)。
まあ1位の記録とはなりませんでしたが結構短くするための要素はある問題になってます。
まず2つの値を数に変換する為に2つに分割します。この時splitを使いますがこのsplitは引数無しで使うとデフォルトでは半角スペースを指定したものになります。なのでsplit(' ')などとやる必要はないです。
あとよく使われるのがmap &:to_iです。コードゴルフに限らず特にAtCoderではこういう形で値を読み込むことが多いです。普通に使えるので便利ですね。今回は変数に入れずに使ってますが

a=gets.split.map &:to_i

とやれば整数を要素に持つ配列aが宣言できます。また、配列の要素が決まっている時、例えば2個の時は

a,b=gets.split.map &:to_i

とすればa,bは整数として使えます。変数は増えますがa[0]とかやる必要が無いので短く書けることが多いです。問題によってはabcとかとかxyzとかそのまま使えるのでこれも便利ですね。足したり引いたりするには便利です(ソートとかする場合は配列のが便利ですね)。

ちなみに最後のmaxは配列の要素の中から一番大きいものを取り出します。[配列].sort[-1]と同じですね。ちなみに小さいものが欲しいならminです。

(28Byte→29Byte)

ABC003-A

n面のサイコロの期待値の問題です。
サイコロの期待値は(n+1)/2です。
問題はこのサイコロの期待値に10000を掛けた値を出力します。
というわけで普通に考えると

p (gets.to_i+1)*5000

です。簡単ですね。とここで終る問題ではないです。この数式は実は短くなります。まず5000というのは5e3と書くことができます。1文字短くなりましたね。
次に(gets.to_i+1)ですがこれも短くすることができます。ゴルフではとにかくカッコは消せ!という感じで扱われます。かけ算より優先順位の低い足し算を先にやりたいのだから消せないように思えますが次の形で書けます

p 5e3.*gets.to_i+1

こうすることで先に足し算を行うことができます。なんでそうなるかはここに書いてあります。
ここまでで終わりかと思いきやまだ縮められます。
結構有名な方法ですがビット演算を使うことでnが整数の時、n+1を-~nと書くことができます。
n+1と-~nでは長さは変わりませんが式の中ではうまく機能することがあります。
例えば-(n+1)は~nとなるのでこの場合は3文字の削減ですね。
というわけで今回の問題は最終的には次のようになります。

p -~gets.to_i*5e3

ここまでは普通に出るかと思ったら自分が初めてのようです。ビット演算で短くする方法を使ってる人はいませんでした。まあ僕はその前に5000を書いたのを出した後他の人のソースをみて5e3に気づきました。それまでの最高記録のコードは一個前のです。

(19Byte→18Byte)


ABC004-A

単純に入力を2倍するだけなので特に注意することも無いですね。1位タイもけっこういます。

(13Byte→13Byte)


ABC005-A

2つの数字を入力してわり算をするだけです。何故か最高記録を出すことができました。
こんな感じです

a,b=gets.split;p b.to_i/a.to_i

ちなみに他の人とどこが違うかというと他の人は

a,b=gets.split.map &:to_i;p b/a

としてます。後者はまとめてto_iできるので短くなりそうですが実は.map &:to_iより.to_i.to_iのが1文字短いです。2つまでなら分けて書いた方がお得なのです。繰り返しはとにかく避けたくなりますがこういう場合もたまにはあるのです。というわけで2つの変数で合計2回しか.to_iが必要ない時はmapしてやるよりも別々に書いた方が短く書けます。

(31Byte→30Byte)


ABC006-A

入力が3の倍数だったらYES、違ったらNOと出力する問題です。
普通に考えると
puts=gets.to_i%3==0?:YES:"NO"
でしょうか。出力するYES、NOは文字列にするよりシンボルにした方が1文字短くできます。三項演算子では片方は使えない(またはスペースが必要)ので片方は文字列です。
これはまだまだ縮まるんですが、普通に考えるとこうですね。僕も最初はこれを提出しました。
さらにここから%3==0と言うのは1文字短くすることができ、%3<1と書けます。取る値は0,1,2しかないので<1なら0ですね。上の式にこれを加えた文字で1位タイでした。ちなみにタイの1位のコードは判定方法が違います。
ここまでかと思ったらもう一つ短縮する方法がありました。この問題では入力される数が一桁(1≦N≦9)という条件があります。これが実はもう1文字縮められる要因になってました。
ここで使うのはto_iではなくordというメソッドです。
ordは文字の文字コード(数)を返してくれるメソッドです。
例えば"0".ordをすると48が返ってきます。ちなみにgetsの値は"5\n"とかになりますが、複数の文字による文字列にordを使うと最初の文字を数値変換したものが返ってきます。なので"0\n".ordも48です。
"0".ordは48ですが1,2,3...と行くとordも49,50,51...となるのでto_iをそのままordにすれば問題なく同じ式として機能します。最終的にはこうなりました。

puts gets.ord%3<1?:YES:"NO"

記録を1文字更新しました。やったね。

(28Byte→27Byte)


ABC007-A

特に何も書くことがないですね。

(13Byte→13Byte)


ABC008-A

この問題もABC004のと同じようにto_iを分けたら最高記録になりました。ちなみにAtCoderでは改行が2バイト扱いなので改行せず;で1行にした方が1バイト短くなります。

s,t=gets.split;p t.to_i-s.to_i+1

最後の+1はビット演算で消せそうですが先頭に-~と二文字つける必要があるのでビット演算を使っても短くできないですね。

(33Byte→32Byte)


ABC009-A

N/2でNが奇数ならもう1足せばいいようです。というわけで(N+1)/2を使います。
先程も使った~nを使えば良さそうです。

p -~gets.to_i/2

これで終了です。例によってビット演算でn+1を作っていた人はいなかったので最高記録です。

(16Byte→15Byte)


ABC010-A

特に問題はないですね。
getsから改行を取り除くにはgets.chompを使うことが多いですが最後の1文字を消すchopでも問題ないです。1文字短いのでこちらを使います。

(19Byte→19Byte)


ABC011-A

複数の同じ最短コードが提出される簡単な問題です。省略。

(16Byte→16Byte)

ABC012-A

2つの要素を入れ替える問題のようです。splitして配列にした後reverseで逆向きにしてjoin(" ")すればいいようです。ちなみに配列のjoin(" ")は*" "と書くことができます。これで最短コード。結構簡単な問題なようです。
しかし僕はたまたまですが違う方法でやりました。ソースは次のようになります。

a,b=gets.split;puts b+" "+a

この方法を使った人はいませんでしたが次のコードと文字数は一緒です。

puts gets.split.reverse*" "

(27Byte→27Byte)


ABC013-A

gets.ordを使えば簡単に解ける問題でした。"A".ordは65なので

p gets.ord-64

でいいですね。ちなみに最初はordを知らず

p " ABCDE".index(gets.chop)

と書いていました。27文字で2倍以上です。今気づきましたがgets.chopは今回は1文字だけ取得したいのでgets[0]で良かったみたいです。こっちのが少し短いですね。

(20Byte→13Byte)


ABC014-A

2つの数字を入力してなんか計算をするようです。
余りとかを使いそうな雰囲気ですね。
a%bは使いそうですがなんだかちょっと違うようです。
答えは(b-a%b)%bのようです。b-a%bかと思ったら違いました(ちょうど配りきれる時にアウトになるようです)。変数はできるだけ使いたくないですがbは3回出てくるのでbだけ変数を使います。

p (-gets.to_i%(b=gets.to_i)+b)%b

aを先にgets.to_iするために余計なマイナス符号が付いてしまったりカッコが多いですが仕方ないような気がします。ちなみに(変数の文字は違いますが)ここまでの答えはありました(と思ったら無駄なカッコが1組ありました、なぜ?)。
実はもう少し短くする方法があります。もっと簡単な数式で答えが求められます。
でその数式は(-a)%bです。
マイナスの値の割った余りとはなんぞやと思ってしまいますが僕もよくわかってないです。まあこういう式が使える(場合がある)ということは頭の片隅に置いておきましょう。僕は適当に遊んでいたら発見しました。というわけでちょっと長かった数式が一気に短くなりました。使用も1回だけなので変数も使わなくてすみます。というわけでこうなりました。

p (-gets.to_i)%gets.to_i

一気に短くなりました。大勝利です。と思ったらこのカッコもいらないようです。

p -gets.to_i%gets.to_i

ここまでですね。

(34Byte→22Byte)


飽きてきた長くなったので今日はこのくらい。残りの問題はまだ適当です。

(22:00)

2015年07月09日

競技プログラミングをやっているとコードゴルフが楽しそうな問題があるのでたまにやっています。
コードゴルフは課題に対してとにかく短いコードを書けって感じの遊びです。
今回ちょっと頑張った問題はAOJの0060番です。ちなみに今回使う言語はRubyです。
とりあえず続きの文章を読む前に問題を読んでください。

とりあえず自分のカードの数をa,b,相手の見えているカードをcとします。
この問題はちょっと考えればわかりますが20-(a+b)以下の数字を引く確率が50%を超えればYES、そうじゃなければNOとすればいいですね。
残りのカードは7枚なので(山には6枚ですが相手の1枚は見えないので7枚として考えればいいです)見えてないカードの中から20-(a+b)以下のカードを数えて4枚以上ならいいわけです。
他のソースコードを見てみると実際このようにカードを数え上げる方法がよく使われています。
何となくいろいろなソースコード(言語によらず)を調べてみると面白いコードがありました。
コードゴルフ的にはやや不利なC言語で書かれてるにもかかわらずなんと全言語で1番短いです。
中身を見てみるとなんと判定に使われている式が

(a+b)*6-c<92

です。初め見た時「こんなんで判定できるの?」と思いましたが実際結構うまくいくようです。この式をRubyで書けば1番短いコードになって終了ですがしかし調べてみるとテストケースに含まれない一部のパターン(a+b=16のあたり)では間違った答えを出してしまうことが分かったのでこの式を使うのはやめました。ちなみにテストケースは変更される場合があるので今でもこの数式が通用するかはわかりません。

しかし数式一つで判定するという考えは参考になります。というわけで間違った部分に対応できるように新しい数式を探す方針でなんとかすることにしました。


まずa、b、cがどのような場合にYES、NOとなるかを調べてみることにします。

a+bが17以上の場合はどうやってもパターンがありません。つねにNOになります。Cに関係なく引いてもよいカードは山に3枚以下です。
a+bが16の場合はCが5以上ならYES、それ以外はNOです。
a+bが15の場合はやや複雑になります。AとBの大きいほうが10(つまり10と5の組)だった場合Cが5以上ならYES、それ以外ならNO。AとBの組が(6,9),(7,8)だったらYESです。
a+bが14以下の時はYESになります。

答えを出すためにCが関係あるのはA+Bが16または15の時(の一部)のみになります。
この時はCの範囲が同じなのでまとめてどうにかしたいですね。
式にすると
a+b==15||a+b==16
になりますがさすがに長いし返って来るのは真偽なので扱いにくいです。
なので
(a+b+1)/2
を使います。これならA+Bが15でも16でも同じ値になるので式の中でも扱いやすいです。ちなみにビット演算を使うことでコードゴルフ的にはこれはもう少し短くできます。
(a-~b)/2
と書くことで同じ値になります。~x=-(x+1)です。
これを使って計算式を立ててみます。
色々試行錯誤して出来上がった数式が次のです。(式の正しさを見るためなのでビット演算による文字列短縮はしていません)

(a+b+1)/2*6-c<45

最初のあの数式よりは長いですがそれなりに短いですね。これで終わりかと思ったらa+b==15の時の場合分けを忘れていました。これじゃ駄目です(6 9 4とかの場合に間違った答えが出ます)。

というわけでa,bの大きいほうの数を使って新しい計算式を作ることにしました。
ちなみにa,bの大きいほうを取得したい場合は[a,b].maxと書けばいいです。
というわけで次は(a+b+[a,b].max)の値を使うようにしてみます。
そうするとcによって場合分けする(a+b+[a,b].max)の値が25,26になります。これでなんとかなりそうかと思ったら実は(a,b)が(8,9)の時にも(a+b+[a,b].max)は26になってしまいます。ダメみたいですね。


というわけで1つの式でなんとかするのは無理そうだったので違うアプローチを使います。cの範囲を調べなきゃいけない範囲というのは(a+b+1)/2==8の時です。その時だけさらに判定をしてそうじゃなければ大きければNO、小さければYESを出力すればいいわけです。

Rubyの面白いメソッドとしてx<=>yと言うものがあります。これはxのが小さい場合は-1,同じだったら0,大きければ1が返ってきます。というわけでこれで3つの場合分けをすることができます。

(a+b+1)/2<=>8

とすればいいですね。これをさらにどうやって使うかというと配列のインデックスとして使います。配列の変数を宣言するのは(複数回使わなければ)文字数の無駄なので
[nantoka,:NO,:YES][(a+b+1)/2<=>8]
と書きます。配列[-1]は配列の最後の要素が取り出せるのでこれで8以外の場合は正しい結果、8の時はnantokaが評価された値が取得できます。ちなみにシンボルを使っても勝手に文字列に変換して出力してくれるので"NO",”YES”と書くより短くできます。これで8の場合のnantokaを書けば終了です。このnantokaを考えることにしましょう。

というわけでa+bが15または16の場合を考えます。
このとき(a,b)が(6,9),(7,8)(順番関係無し)ならYES、そうじゃなければcの値によって結果は変わります。
[a,b].max,[a,b].minを使っても場合分けできないので他の方法を考えます。
なんとかして考えた方法は次の式です

a*a+b*b>117&&c<5?:NO:"YES"

三項演算子を使う時は後の要素(falseの時の値)はシンボルが使えないのでここは文字列です。Rubyではx^nをx**nと書くことができますが2乗なら普通にかけ算のが短いですね。
これなら(6,9),(7,8)の時はa*a+b*bが117,113になり、他の場合(Cによって変える場合)は125以上になるので場合分けすることができました。以上をまとめると正しい結果を得るためには次のような式を書けばいいことになります。

[a*a+b*b>117&&c<5?:NO:"YES",:NO,:YES][(a-~b)/2<=>8]

これで正しい結果を得ることができました。入出力などの部分を含めて全部書くと

#!ruby -apl
a,b,c=$F.map &:to_i
$_=[a*a+b*b>117&&c<5?:NO:"YES",:NO,:YES][(a-~b)/2<=>8]

となりました。これで終わればよかったのですが実はこれRubyで一番短いコードに(10文字も!)負けています。苦労して違う方法を採ったのになんということでしょう。これを何とか短くします。できるのでしょうか。


これを見てなんか短くできそうなのは:NO:"YES",:NO,:YESと繰り返されている所です。同じ文(まあ文ではないですが)を繰り返すのはコードゴルフに限らず良くないことです。
というわけで繰り返されてるので変数を使いましょう。
y,n=:YES,:NO
とすれば
:NO:"YES",:NO,:YES を
n:y,n,y と書くことができそうです。短くなったような気がしますが実は長くなってます。駄目でした。あとこう書くと三項演算子の部分で構文エラーになってしまいます。これを回避しようとして次のような文にしました。

$_=[a*a+b*b>117&&c<5?n=:NO:y=:YES,n,y][(a-~b)/2<=>8]

これで2文字短くすることができました。ですがこれは実際には動きません。三項演算子の結果は片方しか評価されないのでyかnの片方の変数は宣言されません。動いたとしてもまだ文字数で負けています。


というわけで他の方法です。

そもそもなぜこんなこと(YESとNOが繰り返される)になっているかというとx<=>yを使って3つに場合分けをしたうちの一つをさらに条件分けしているためです。結構単純な3択なら配列で3つの要素にアクセスするのは悪くないかもしれません。
あとNOとYESの繰り返しもそうですが<=>という3文字も使う記号やアクセスするために[]を使っていたりとスマートな解法のように見えて意外と長いことにも気づきます。
結構有効に見えた[][x<=>y]作戦はコードゴルフ的には意外とダメなようです。

答えは2つなのだから3つから選ぶ方法は良くないような気がしてきました。なんとかならないかと考えていた時にあることに気づきました。
(a-~b)/2==8の場合に判定していた数式は他の範囲でも使える場合があるということです。
具体的に言うと(a*a+b*b>117&&c<5)という式はa+bが(15,16のときだけではなく)14以下の時にも使えます。というか常に条件を満たしません(条件を満たさないので正しい結果になる)。a+b>16の時は使えませんが3択が2択に減りました。というわけで3つの場合分けではなく2つの場合分けをすればいいという事に気づきます。これで[,:NO,:YES][(a-~b)/2<=>8]とかいう長い文字列を削除することができました(a+b>16を判定するための式は追加する必要がありますが)。


というわけで最終的にはa+b>16かどうか、a*a+b*b>117&&c<5かどうかということを判定すればOKということです。プログラムは最終的にはこうなりました。

#!ruby -apl
a,b,c=$F.map &:to_i
$_=a*a+b*b>117&&c<5||a+b>16?:NO:"YES"

これで69文字。他の言語も含めて1番短いコードを書くことができました。

(19:56)

2015年06月28日

なんかちょうどいい機会だったのでAtCoder Beginner Contest 025に参加してみました。
今回は楽なのでRubyで参加しました。
過去のBeginner Contestだと3問くらいは解けたのでなんとかなるかと思いましたが今回のは難しかったらしく2問(AとBだけ)しか解けませんでした。
C問題は最適な手を打つみたいな方法をプログラムできず終わり、D問題は総当たりでやれば部分点までは取れそうだと思ったもののコードがうまく書けず終了という感じでした。

C問題の最適な手順についてですがゲームのAIでよく使われる手法として相手が最適な手を打ってくる前提で自分が一番いい手を打つアルゴリズムについて話聞いたなーと思い出しました。大学の勉強ってちゃんと役に立つんですね。
方法がわかってもプログラムしないと問題は解けないのでまあ解けなかったわけですがこういうのをちゃんとプログラムできるようにしないとダメですね。

(01:16)

2015年06月19日

競技プログラミングを始めてみました。
プログラミングの能力を競うもののように聞こえますがプログラミングという範囲でパズルを解く様な感覚に近いです。パズルが好きなので結構楽しくやっています。
パズルが好きなら結構おすすめです。
レベルを上げてアイテムを集めてアイテムや魔法の使い方を考えてボスを倒していくようなゲームと似た楽しさもあります。

今まではRubyとC#がプログラミングのほとんどでしたがなんとなくC++でやっています。
理由は勉強の為とRubyだと簡単すぎる問題もあったりするからです。Rubyだと場合によっては簡単に答えが出せてしまうものもあるのである程度手ごたえがあった方が楽しいです。C++だと細かいことは何も考えなくていい現代的な言語と違って、使って行くとコンピュータがどう動いているかもイメージできるようになってくるような気がします。昔コンピュータの動く仕組みを勉強しましたが今更なるほどなぁとか思ってます。
あとビット演算で変数を振り回したり弱い型付けを利用して違う方のデータを計算したり他ではあまりできない(少なくとも自分が使った言語では)のでそういうので遊んだりうまく使えたりするのも楽しいですね。
よく使う例だと文字から数を引いたりbool以外の変数をif文の条件に使ったりできます。


//0が入力されるまでループ
int n;
scanf("%d", &n);
while(n){
//なんかの処理
scanf("%d", &n);
}


//改行が入力されるまでループ
char c;
scanf("%c", &c);
while(c - 10){
//なんかの処理
scanf("%c", &c);
}


//ファイルの終わりまでループ
int n;
while(scanf("%d", &n) + 1){
//なんかの処理
}

とかでしょうか。開発とかだとあまり良くない書き方とされそうですがまあこういう書き方のが楽しいのでこんな感じで書いています。
あとビット演算とかも面白いですね。最後のファイルの終わりまで読み込むループではビット反転の演算子を使って~scanf()としてもいいみたいです。


競技プログラミングを始めたところで面白い問題を見つけました。こちら
最初の問題じゃなくてちょっと進んだところ(16番)の本題です。
数学的に解ける問題らしい(読んでません)ですがちょうどいい機会(競技プログラミングの問題として扱えそう)だったのでプログラムで解いてみました。
適当な範囲で数列を作ってから条件を満たすNを順番に探していく方法で解けました。予想以上に答えが大きい数字で最初はエラーになりましたがそこそこ楽しかったです。


(00:36)

2015年06月10日

たまたまRealForce106S(All30)を入手してしまいました。

動作不能ジャンクとのことでしたが何故かつないだら動いたのでそのまま使ってます。
動けばこっちのもんです。

動作したのは運が良かっただけですが、さすがにかなり古く動きも悪かったのでオーバーホールしてみました。
オーバーホールする前はラバードーム以外の抵抗感もありましたがオーバーホールしたら結構スッキリした打鍵感になって復活しました。
タイプウェルを打ってもそこそこいい感じの記録が出てます。

ちょっと使ってみた感想ですが、タイピングには非常に向いているというか指の動きが邪魔されず”押しこむ”という感覚が全く必要なく”キーボードの上で指を動かす”という感覚で入力できます。
慣れてしまうとなかなか他のキーボードで打てませんね。指の動かし方が完全に変わってしまいます(個人差があります)。All45のリアフォですら結構重く感じます。
かすりミスが増えるとよく言われますが自分の場合はキーが打てなかった場合の詰まりミスが減るのと力が抜けて余分な指の動きが減るのでミスは減る(ピアニストはできるだけ力を入れないようにすることでミスしにくくしているらしいです)傾向が出ています。この辺りは個人差がありますね。

タイピング(と言うかタイプウェル)に関しては文句がないくらい打ちやすいのですがやはり106キーボードということで使いにくい部分もあります。
いろんなキーボードを使ってきましたが106キーボードというかWinキーがついていないキーボードを使った記憶はありません。
余計なキーはいらないとかいって頑なにWinキーがついてないキーボードを好む人もいますが今の時代はこのキーが無いと結構厳しいです。
Winキーを使ったショートカットは結構豊富でWin+E(エクスプローラを開く)とかWinキー+数字でピン止めしたアプリに飛べるとか使っていたのでなくなると結構困ります。ちなみにWindowsだけでなくLinuxとかでも結構使います。Windows以上にショートカットキーが豊富な気もします。

タイピング以外でしか困らないように見えますが実はタイピングで結構面倒なことになることが一つあります。それは言語の切り替えのショートカットキーに使われる(Winキー+Space)ことです。
日本語だけ使うなら使うことはないですが多言語タイピングのために外国語キーボードに切り替えようとするとこれを使うので切り替えられなくなってしまいました。

というわけで多言語タイピングはしばらくお休み。

(01:02)