Hootsuiteを1週間使ってみた
TwitterのクライアントはiPhoneでEchofon使ってるってことでMacでもEchofonを使ってたのですが、Hootsuiteがよさそうだってことで1週間ほど使ってみました。
いい所
- マルチカラムの表示は見やすい
一つの画面でタイムラインとリプライ、リスト等が見れるのでわざわざページ移動したり、タブ変更したりみたいな手間がなくて使いやすかったです。
- Facebookにも投稿できる
最近Facebook使いはじめたので、同時に投稿できるってのは便利でした。Facebook側のTwitterアプリ使えば連携できるみたいなんですが、何故か認証でコケてしまって使えないので助かりました。
悪い所
- いちいち投稿するサービス、アカウントを選択しないといけない
TwitterとFacebookの複数アカウント使ってると(ひょっとすると一つでも?)postするときにどのアカウントでするか、を選択しないといけないのですが、これをpostするたびに選択しないといけないので不便でした。デフォルトで投稿するアカウントの設定とかも見当らなかったです。
- ちょっと重い
多機能っていうのがウリらしいので仕方ないのかもしれませんが、動作が多少重かったです。
- キーボード操作…
ブラウザベースに文句言うのもアレな上に激しく個人的なことなんですが、キーボードで全ての操作にアクセスできると嬉しいです。やっぱホームポジションから離れたくありません。
まとめ
結論としては、常用クライアントにはなりませんでした。postする度にアカウント選択しないといけないっていうのが一番のネックでした。でもマルチカラムの表示は非常に見やすくてよかったです。yoonoっていうクライアントが同じようなマルチカラム表示のクライアントのようなのでまたまたしばらく使ってみようと思います。
SRM275 Div2 Easy - HingedDoor
今日もDiv2 Easyから。
HingedDoor
いちいち英語載せても邪魔なので問題文はリンク参照(ログインしないと見れません)。
で、適当訳。
ヒンジ付きのドアの開いた角度と減衰率が与えられたとき、閉じた状態になるまでの往復の回数(片道を1回とカウント)を返す。ただし角度が5度以下になったら閉じた状態となる。
ということで何も捻るところはないのでそのまま実装。
プログラム
今回はクラスだけ。
class HingedDoor { public: int numSwings (int initialAngle, int reduction) { double presentAngle = initialAngle; int count = 0; while (presentAngle > 5.0) { presentAngle /= reduction; count++; } return count; } };
SRM168 Div2 Easy : StairClimb
書いてる途中で全選択→BSのコンボを決めてしまった…
TopCoder参戦のための練習として過去問から適当に問題を選んでC++で書いていきます。俺のC++経験は"Hello, World"止まりなので、C++の勉強も兼ねてます。
この記事を読んで「ここはこうした方がいい」とか「こんなコード書く奴はクソ」とか思ったらバシバシ指摘して頂けるとありがたいです。よろしくお願いします。
問題
Div2 Easyという一番簡単なところから。
You are climbing a staircase. The staircase consists of some number of flights of stairs separated by landings. A flight is a a continuous series of stairs from one landing to another. You are a reasonably tall athletic person, so you can climb a certain number of stairs in one stride. However, after each flight, there is a landing which you cannot skip because you need to turn around for the next flight (which continues in the opposite direction).
You will be given the number of stairs in each flight in a int[] flights. Element 0 of flights represents the number of stairs in the first flight, element 1 is the number of stairs in the second flight, etc. You will also be given an int stairsPerStride, which is how many continuous stairs you climb in each stride. If it takes two strides to turn around at a landing, return the number of strides to get to the top of the staircase. You do not need to turn at the top of the staircase.
適当に訳すと
踊り場の間の階段の段数教えてやるから、何歩で頂上まで行けるか教えれ。お前背高いから結構段飛ばしでいけるよな。でも踊り場はいくらお前でも2歩かかるんだわ。
ということで特に何も考えずそのまま実装。その実装がしんどかったんだけれども…。
プログラム
stairClimb.cpp
#include <sstream> #include <string> #include <vector> #include <map> #include <algorithm> #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <utility> #include <set> #include <cctype> #include <queue> #include <stack> #include <fstream> #include <cstring> using namespace std; class StairClimb { public: int stridesTaken(vector<int> flights, int stairsPerStride) { int i, n = flights.size(); int strides = 0; for (i = 0; i < n; i++) { flights[i] % stairsPerStride == 0 ? strides += flights[i] / stairsPerStride : strides += flights[i] / stairsPerStride + 1; } strides += (n - 1) * 2; return strides; } }; int main(int argc, char** argv) { vector<int> f; int sps = atoi(argv[1]); for (int i = 2; i < argc; i++) { int j = atoi(argv[i]); f.push_back(j); } StairClimb sc; int strds = sc.stridesTaken(f, sps); cout << strds << endl; }
実行例
./stairClimb.cpp 5 25 18 24 5 24 24 17 23 10 9 22 25 27 22 16 17 12 102
makeplex salon : 麻雀プログラム
久しぶりのブログ更新。よく見ると半年近く前に「再開します」とか高らかに宣言してるけど速攻で終了してました。僕はそういう人間です。
以前チラっと見て「あー俺こんなの無理っす無理っすムリポ・インザーギっす」とかほざいて何も手をつけなかったのだけど id:cou929_la さんがやってるのに刺激を受けてやってみました。
あなたのスキルで飯は食えるか? 史上最大のコーディングスキル判定 (1/2) - ITmedia エンタープライズ
自分の場合は方針決めに40分程度、コーディングに3時間ちょっと、計4時間弱かかりました。制限時間は3時間とのことで余裕でオーバーです。自分の実力はこんなもんだ、ということで要修行ですね。
問題
13枚の手牌が与えられたときにテンパイなら待ちを全て出力、テンパイしてないなら何も出力しない。萬子のチンイツ限定でいいとのこと。
解き終わってから他の方の解答を見てたら七対子考慮してたりしましたけど僕はアホなので一切そういうことを考えずに実装しました。今日実装してみようと思いましたが、そのうち気が向いたらやることにします。
方針
大きな方針としては、与えられた手牌から刻子、順子になり得る牌を候補として列挙して、候補を組み合わせて待ちを絞り込んでいきます。
七対子を除外した場合、待ちは
となります。
なのでまず列挙した候補の中から刻子or順子を4つ選ぶ場合と3つ選ぶ場合に場合分けして、それぞれで手牌の数を超えないかチェックしていきます。4つの場合は手牌の数を超えなければ残りの牌を待ちとして出力。3つの場合はさらにアタマの有無をチェックして、頭があってかつリャンメンorペンチャン又はシャボ待ちになっているかを調べます。
言語はできないなりに得意な言語、ということでPerlで書きました。
あとテストデータは適当にランダムに作ってやれー!と思ってたらほとんどテンパイじゃないものばかりで何の役にも立ちませんでした。
プログラム
majong.pl
#!/usr/bin/env perl use strict; use warnings; # 入力 my $input = shift; my @tehai = (0, 0, 0, 0, 0, 0, 0, 0, 0); my @machi = (); # 'random'が引数にくるとランダムな手牌を生成 if ($input eq 'random') { my $hai_num = 0; while ($hai_num < 13) { my $hai = int(rand(9)); if ($tehai[$hai] < 4) { $tehai[$hai]++; $hai_num++; } } } else { my @sample = split //, $input; for (my $i=0; $i<@sample; $i++) { $tehai[$sample[$i]-1]++; } } print "tehai:\t"; for (my $i=0; $i<@tehai; $i++) { for (my $j=0; $j<$tehai[$i]; $j++) { print $i+1; } } print "\n"; my @candi = &getCandidate(\@tehai); my @tmp_tehai = (0, 0, 0, 0, 0, 0, 0, 0, 0); for (my $i=0; $i<@candi; $i++) { for (my $j=$i+1; $j<@candi; $j++) { for (my $k=$j+1; $k<@candi; $k++) { # 順子・刻子が4つの場合 for (my $l=$k+1; $l<@candi; $l++) { my @tmp_hai = split //, $candi[$i] . $candi[$j] . $candi[$k] . $candi[$l]; for (my $l=0; $l<@tmp_hai; $l++) { $tmp_tehai[$tmp_hai[$l]-1]++; } # 入力の牌の数を超えていないかチェック my $check = 1; my $machi; for (my $l=0; $l<9; $l++) { $tmp_tehai[$l] = $tehai[$l] - $tmp_tehai[$l]; if ($tmp_tehai[$l] < 0) { $check = 0; } elsif ($tmp_tehai[$l] > 0) { $machi = $l + 1; } } if ($check) { print "($candi[$i])($candi[$j])($candi[$k])($candi[$l])[$machi]\n"; } @tmp_tehai = (0, 0, 0, 0, 0, 0, 0, 0, 0); } # 順子・刻子が3つの場合 my @tmp_hai = split //, $candi[$i] . $candi[$j] . $candi[$k]; for (my $l=0; $l<@tmp_hai; $l++) { $tmp_tehai[$tmp_hai[$l]-1]++; } # 入力の牌の数を超えていないかチェック my $check = 1; for (my $l=0; $l<9; $l++) { $tmp_tehai[$l] = $tehai[$l] - $tmp_tehai[$l]; if ($tmp_tehai[$l] < 0) { $check = 0; } } if ($check) { my ($head, $wait) = &getHead(\@tmp_tehai); if ($head && $wait) { for (my $l=0; $l<@$head; $l++) { for (my $m=0; $m<@$wait; $m++) { my @tmp_hai2 = split //, $$head[$l] . $$wait[$m]; my @tmp_tehai2 = (0, 0, 0, 0, 0, 0, 0, 0, 0); for (my $n=0; $n<@tmp_hai2; $n++) { $tmp_tehai2[$tmp_hai2[$n]-1]++; } # 入力の牌の数を超えていないかチェック for (my $n=0; $n<9; $n++) { $tmp_tehai2[$n] = $tmp_tehai[$n] - $tmp_tehai2[$n]; if ($tmp_tehai2[$n] < 0) { $check = 0; } } print "($candi[$i])($candi[$j])($candi[$k])($$head[$l])[$$wait[$m]]\n" if ($check); } } } if (@$head == 2) { print "($candi[$i])($candi[$j])($candi[$k])($$head[0])[$$head[1]]\n"; print "($candi[$i])($candi[$j])($candi[$k])($$head[1])[$$head[0]]\n"; } } @tmp_tehai = (0, 0, 0, 0, 0, 0, 0, 0, 0); } } } # 順子、刻子候補の取得 sub getCandidate { my @tehai = @{shift()}; my @candi = (); # 刻子 for (my $i=0; $i<9; $i++) { if ($tehai[$i] >= 3) { push @candi, $i+1 . $i+1 . $i+1; } } # 順子 for (my $i=0; $i<7; $i++) { if ($tehai[$i] != 0 && $tehai[$i+1] != 0 && $tehai[$i+2] != 0) { my @list = ($tehai[$i], $tehai[$i+1], $tehai[$i+2]); my $min = &getMin(\@list); for (my $j=0; $j<$min; $j++) { push @candi, $i+1 . $i+2 . $i+3; } } } return @candi; } # 対子と待ちの取得 sub getHead { my @tehai = @{shift()}; my @head = (); my @wait = (); for (my $i=0; $i<9; $i++) { # 対子 if ($tehai[$i] >= 2) { push @head, $i+1 . $i+1; } # 待ち # リャンメンorペンチャン if ($i < 8 && $tehai[$i] != 0 && $tehai[$i+1] != 0) { my @list = ($tehai[$i], $tehai[$i+1]); my $min = &getMin(\@list); for (my $j=0; $j<$min; $j++) { push @wait, $i+1 . $i+2; } } # カンチャン elsif ($i < 7 && $tehai[$i] != 0 && $tehai[$i+2] != 0) { my @list = ($tehai[$i], $tehai[$i+2]); my $min = &getMin(\@list); for (my $j=0; $j<$min; $j++) { push @wait, $i+1 . $i+3; } } } return \@head, \@wait; } sub getMin { my @list = @{shift()}; my $min = shift @list; for my $v (@list) { $min = $v if ($min > $v); } return $min; }
問題点
実はこのプログラムには重大なバグがありまして、それは待ちを重複して出力してしまうような入力が存在する、ということです。
perl majong.pl 1223344888999 tehai: 1223344888999 (888)(999)(123)(234)[4] (888)(999)(123)(234)[4] (888)(999)(123)(44)[23] (888)(999)(234)(234)[1]
実は候補を列挙するときに重複する要素(この場合234)は別の候補として列挙しちゃってるので、こういう入力の場合は重複して出力してしまいます。昨晩および今晩の段階では有効な解決法を見出せなかったので放置してます。候補を配列じゃなくてハッシュにすればなんとかなるかもしれません。
iPhoneからテスト
iPhoneから投稿テスト