2014年8月17日日曜日

TopCoder SRM487 Div2 250Pts

このTopCoderの問題はこちらで見ることができる(要TopCoder登録 & 問題文は英語)。問題文についておおまかに説明する。

ウサギたちはプログラミングは好きだが、プログラミングの試験が好きではない。黒、グレー、白の3匹のウサギは最終試験を終えた。ウサギたちが問題について議論している間に、教授がやってきて、"黒いやつ、お前は0点だ、知識を確かなものにするために、グレーと白が取った点数の最大値の合計点を計算するプログラムを書け"といった。

試験はN問からなるものであった。ウサギたちは同じ問題を提示される。各問題に対し、その答えとしてA~Zのアルファベットの大文字を書かなければならなかった。問題に対し、1つの文字のみが正しいものとされ、他の25文字は正しくない回答となっている。正解は1点となり、ウサギの得た点数は問題に正解した数に一致する。

black、gray、whiteという黒、グレー、白のウサギが書いた回答を表す文字列が与えられる。それぞれの文字列はN文字からなり、文字列のi番目の文字はそれぞれのウサギのi番目の回答を表すものとする。黒ウサギの点数が0のときに、グレーと白のウサギが獲得しうる点数の合計の最大値を返せ。

私の回答は以下の通り。

public class BunnyExamAfter {

 public int getMaximum(String black, String gray, String white) {

  int points = 0;
  for( int i=0 ; i<black.length() ; i++ ){
   if( black.charAt(i) == gray.charAt(i) &&
    black.charAt(i) == white.charAt(i) ){
    // pass
   }else if( black.charAt(i) != gray.charAt(i) &&
     black.charAt(i) == white.charAt(i) ){
    points++;
   }else if( black.charAt(i) == gray.charAt(i) &&
     black.charAt(i) != white.charAt(i) ){
    points++;
   }else if( black.charAt(i) != gray.charAt(i) &&
     black.charAt(i) != white.charAt(i) &&
     gray.charAt(i) == white.charAt(i) ){
    points += 2;
   }else if( black.charAt(i) != gray.charAt(i) &&
     gray.charAt(i) != white.charAt(i) ){
    points++;
   }
  }
  return points;
 }

}

得点は220.72/250、1回のsubmitでシステムテストクリア。

2014年8月6日水曜日

TopCoder SRM486 Div2 250Pts

このTopCoderの問題はこちらで見ることができる(要TopCoder登録 & 問題文は英語)。問題文についておおまかに説明する。

奇妙な省略形が扱いにくい携帯機器でテキストを書くのにしばしば用いられる。アルファベットと空白からなるテキストをエンコードする方法の1つに次のものがある。

  • 空白はそのままで、各単語は単語ごとにエンコードされる。ここで単語とはアルファベットの続く連続した文字列をいう。
  • もし単語が母音のみからなる場合、それはそのまま書かれる。
  • もし単語が1つ以上の子音を含むのであれば、直前に別の子音がない子音のみ書く。母音を買い手はならない。
  • 上記の規則において、母音は'a', 'e', 'i', 'o'と'u'である。他の文字は子音と考える。

例えば、"ps i love u"というのは、"p i lv u"と省略され、一方、"please please me"は"ps ps m"と略されるであろう。 originalという文字列が引数で与えられたとき、先述の方法で省略されたメッセージを返すメソッドを作成せよ。

私の解答は以下の通り。

public class TxMsg {

 public String getMessage(String original) {
  StringBuilder msg = new StringBuilder("");
  String[] strs = original.split(" ");
  for( int i=0 ; i<strs.length ; i++){
   if( isAllVowel(strs[i]) ){
    msg.append(strs[i] + " ");
   }else{
    msg.append(makeEncodedMessage(strs[i]) + " ");
   }
  }
  // if文の後者により、最後に空白ができる可能性があるので、trimを行う
  return msg.toString().trim();
 }

 private static boolean isAllVowel(String s){ // 入力がすべて母音か判断
  char[] vowels = {'a', 'e', 'i', 'o', 'u'};
  for( int i=0 ; i<s.length() ; i++ ){
   boolean isvowel = false;
   for( int j=0 ; j<vowels.length ; j++ ){
    if( s.charAt(i) == vowels[j] ){
     isvowel = true;
     break;
    }
   }
   if( ! isvowel ) return false;
  }
  return true;
 }

 private static String makeEncodedMessage(String s){
  char[] vowels = {'a', 'e', 'i', 'o', 'u'};
  StringBuilder sb = new StringBuilder();
  boolean prevConsonant = false;
  boolean currentConsonant = true;

  for( int i=0 ; i<s.length() ; i++ ){
   currentConsonant = true;
   for( int j=0 ; j<vowels.length ; j++ ){
    if( s.charAt(i) == vowels[j] ){
     currentConsonant = false;
     break;
    }
   }
   if( !prevConsonant && currentConsonant ){
    sb.append(s.charAt(i));
   }
   prevConsonant = currentConsonant;
  }
  return sb.toString();
 }

}

得点は158.01/250、1回のsubmitでシステムテストクリア。

2014年7月30日水曜日

Raspberry PIでSSHの初期設定時に発生したエラーを回復する方法

Raspberry PIの初期設定中に、「Initial ssh key generation still running. Please wait and try again.」 というメッセージが出てきて困ったことがありました。何が原因で発生したのかよく分からないのですが、 最初の起動時に接触が悪かったのため、一度設定前に電源を落とすなどしたことが可能性として考えられました。 さて、この状態になった場合、次の鍵を作り直すためのコマンドを入力することによってSSHが使えるようになります。

作業時には初期状態(User:pi、Password:Raspberry)のアカウントを利用しました。なのでsudoでコマンドが実行ができます。

# rm /var/log/regen_ssh_keys.log
# sudo rm /etc/ssh/ssh_host*
# sudo ssh-keygen -A

個人的にはログを消すとうまく動作するというのはあまり納得できません。 logではなくlockという拡張子のファイルを削除するのであれば理解できるのですが。

2014年7月19日土曜日

Firefoxで戻るボタンを押した際に二重送信防止を解除する

今回はFirefox(テストで利用したバージョンは30.0)における厄介な挙動をJavaScriptで解決しようというお話。 IE 11や最新のChrome(35系)では特に気にする必要はないものです。

フォームで二重押下を防止するために、1度ボタンを押すとボタンの状態をdisabledにするということがあります。 そこまでは何も問題ないのですが、Firefoxではボタンを押してsubmitをした後に、戻るボタンを押すとdisabledの状態が継続しており、 再度submitができない状態になってしまいます。もう一度戻るボタンを押すとsubmitできるようになるのですが、 その挙動は一般的にユーザが想定していないものであるはず。

そこで、jQuery(利用したバージョンは1.11.0)を利用して、 一度戻るボタンを押すだけでdisabledの状態が解除できるようにしてみました。コードは以下のようになります。

<script type="text/javascript"><!--
$(document).ready(function() {
    $(window).unload(function(){});
    $('#button').attr('disabled', false);
});
--></script>

1行目はDOMを構築した後に実行せよという意味です(おまじないと思って差し支えないでしょう)。 2行目はBackForwardCacheを無効にせよという意味になります。元のページに遷移した際にキャッシュを使うなという意味になります。 つまり、ボタンを押したという状態を使うなということになります。 3行目はボタンにdisabled属性をfalseにせよという意味で、ボタンを利用可能にするという意味になります。 初期状態はfalseでなければならないので、明示的に設定しました。

これにより、ボタンを1度叩いてdisabledになった状態でブラウザの戻るボタンを押しても、disabledの状態にならなくなります。 ただし、フォームにあった情報(入力したテキスト等)はすべて落ちてしまうので、再入力が必要になります。 もっとも、それは仕様としてしまっても良いとは思いますが。

2014年4月26日土曜日

jQueryの個人的メモその2

$(document).ready(function(){..})は$(function(){...})のように省略できる。

要素を指定して何かをする場合は次のように書く。セレクタについてはクラス、ID、要素が指定できる。

 $(セレクタ).メソッド(パラメータ);

何かの要素の下にある要素を指定する場合はセレクタをスペースを空けて並べればよい。以下の例ではpタグの下にある.warn要素で囲まれた箇所の色を赤に変更している。

 $("p .warn").css("color", "red");

*(ユニバーサルセレクタ)を使うと、ワイルドカードのように振る舞うことになる。pタグの下にある要素で囲まれたものすべてについて色を赤に変えることになる。pタグの下にあるセレクタ以下にある要素が変わるのであって、pタグの直下にあるものについては変わらない。

 $("p *").css("color", "red");

セレクタの箇所はカンマで区切ることで、複数の要素をまとめて指定することができる。

 $(".left, .right").css("color", "red");

チャイルドセレクタは直下にあるものに絞る。上の例は子孫セレクタであり、深さを問わない指定方法であるという点で異なる。

 $("p > .warn").css("color", "red");

隣接セレクタは連続する2つの要素を指定し、2つ目に指定したものが指定されたものになる。以下ではh2要素に隣接するh3要素が指定されることになる。

 $("h2 + h3").css("color", "blue");

間接セレクタは同じ親を持つ要素で指定した要素より後ろにあるものすべてを指定する。以下ではliにsecondというidを割り振っておけば、ulという親があるため、secondより後ろにあるli要素の色がすべて赤になる。

 $("#second ~ li").css("color", "red");

CSSにおける要の素指定方法とjQueryのセレクタ指定方法は良く似ていることが確認できる。

2014年4月21日月曜日

jQueryの個人的メモその1

HTMLのヘッダにjQueryのライブラリへのパスを設定しておくことが多い。ページの表示速度を考慮してjQueryの読み込み後回しにするため、bodyタグの一番最後に書くこともある(=多くの場合、その後ろはhtmlタグを閉じるだけであろう)。ローカルにダウンロードしてそのパスを設定してもよいし、CDN(Contents Delivery Network)に置かれているjQueryのライブラリを指定して読み込んでも良い。CDNは例えば以下に挙げたURLを指定することになる(詳しくはこちらを参照)。なお、外部との通信が発生するので、通信内容を暗号化する目的でhttpsでURLを指定することも考慮すべきである(以下のURLの場合、Googleの方ではできる)。

  • http://code.jquery.com/jquery-1.11.0.min.js
  • http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js

以下の例ではwarnクラスの要素を赤にする。例えば注意書きを囲うときに使える。

$(document).ready(function(){
 $(".warn").css("color", "red");
}

上のコードの1行目の意味はページがjQueryを実行する準備ができたらという意味である。これを書かないでいると、読み込む前にwarnクラスの要素が出てこないので、warnクラスの要素の色を変えることができない。なお、readyを用いた場合、画像の読み込みは後回し(jQueryのライブラリを読み込んだ後)となる。画像を読み込んでからjQueryのライブラリの読み込みを実行したい場合は次のようになる。画像をjQueryで変化させたいときに使うことになる。

$(window).on("load", function(){
 $(".warn").css("color", "red");
}

ただし、画像に手を加えないのであれば、パフォーマンスを考慮して前者の書き方を採用することが一般的である。

2014年3月15日土曜日

TopCoder SRM485 Div2 250Pts

このTopCoderの問題はこちらで見ることができる(要TopCoder登録 & 問題文は英語)。問題文についておおまかに説明する。

マナオはすべての商品が正の整数の価格を持つ国に住んでいる。彼は電子レンジを売る会社を立ち上げており、それらを売るのに最適な価格を決める必要がある。最近彼は新しい心理学的な発見を聞いた。それは価格の小さい方の桁に9が続くにつれて、消費者に魅力的になるというものである。たとえば9099は9が2つ、8909は1つ9が最後にあるので、前者が魅力的ということになる。

マナオはminPriceを下回らない価格でのみ売る余裕があり、消費者はmaxPriceを超えない価格でしか電子レンジを買わないということを把握している。minPriceとmaxPriceの間で9が最大限後ろに続く数のうち最大のものを見つけることでマナオを手助けせよ。

public class MicrowaveSelling {

 public int mostAttractivePrice(int minPrice, int maxPrice) {
  int nNine = 0;
  int price = minPrice;
  for( int i=minPrice ; i<=maxPrice ; i++ ) {
   int nCurrent = trailing(i, 9);
   if( nCurrent >= nNine ) {
    price = i;
    nNine = nCurrent;
   }
  }
  return price;
 }
 private int trailing(int num, int target){
  int n = 0;
  while( num >= 1 ){
   if( num % 10 == 9 ){
    n++;
   }else{
    return n;
   }
   num /= 10;
  }
  return n;
 }

}

得点は173.37/250、3回目のsubmitでシステムテストクリア。ちなみにtrailingは「後端の」という意味です。

フォロワー

ページビューの合計