UTF-8エンコードの文字数は"8","9","A","B"を除いて数えろ

きっと専門予備校では常識になっていると思いますが、
ざっとググっても出なかったので。

良く出てくるこの手の問題:

16進数表示された、次のUTF-8エンコード結果は、何文字のUnicode文字列をエンコードしたものか。
CF 80 E3 81 AF E7 B4 84 33 2E 31 34 E3 81 A7 E3 81 99
(応用情報・平成24年春季の概要)

10秒で正答へたどり着く技が、タイトルの通りです。

数え方

①各バイトデータの先頭が"8","9","A","B"で始まるものを消す。
CF 80 E3 81 AF E7 B4 84 33 2E 31 34 E3 81 A7 E3 81 99

②残ったバイト数を数える。

すると、残ったものは9バイトあるので、9文字が答えになります。

解説

UTF-8は、Unicodeを8ビット単位で符号化するためのフォーマットです。
元々、ASCIIの規格で表せなかった世界各国の文字を表そうとしたのがUnicodeですが、

  • ASCIIが7ビットで表現されるのに対し、Unicodeは16ビットで表現される
  • 互換性がない

という問題がありました。

これを解決させたのがUTF-8で、

  • ASCIIにある文字は、ASCIIと同じように表し、先頭の1ビットは0とする。
  • ASCIIにない文字は、6ビットごとに分割し、各6ビットごとの塊について、
    • 最初の塊:11から始まるビット*1
    • 2つ目以降の塊:10から始まるビットとする。

というルールでエンコードされます。

ところで、16進数と2進数の関係は

16進数 2進数 16進数 2進数
0 0000 8 1000
1 0001 9 1001
2 0010 A 1010
3 0011 B 1011
4 0100 C 1100
5 0101 D 1101
6 0110 E 1110
7 0111 F 1111

となっていますから、UTF-8エンコードルールと照らし合わせると、

16進数 2進数 UTF-8 16進数 2進数 UTF-8
0 0000 ASCII文字 8 1000 非ASCII文字(2つ目以降)
1 0001 ASCII文字 9 1001 非ASCII文字(2つ目以降)
2 0010 ASCII文字 A 1010 非ASCII文字(2つ目以降)
3 0011 ASCII文字 B 1011 非ASCII文字(2つ目以降)
4 0100 ASCII文字 C 1100 非ASCII文字(先頭)
5 0101 ASCII文字 D 1101 非ASCII文字(先頭)
6 0110 ASCII文字 E 1110 非ASCII文字(先頭)
7 0111 ASCII文字 F 1111 非ASCII文字(先頭)

となります。

UTF-8の文字には、ASCII文字、非ASCII文字(先頭)、非ASCII文字(2つ目以降)の3種類しかなく、
Unicodeの文字数=ASCII文字の数+非ASCII文字の数
であり、また、
非ASCII文字の数=非ASCII文字の先頭の数
であるわけですから、
Unicodeの文字数=UTF-8の文字数−非ASCII文字(2つ目以降)
で答えが求まります。

余談

ちなみに、平成24年春季の応用情報で出たこのUTF-8のデータですが、
デコードすると、「πは約3.14です」となります。
確かに9文字ですね。

*1:UTF-8の規格の範囲では、エンコード対象のUnicodeは6で割ると余りが出る。この余りの部分の長さに応じて、110, 1110, 11110, 111110などを充てる。

ソートアルゴリズム9種を動画で学ぶ

応用情報技術者試験の試験範囲でもある、ソートアルゴリズムは、
疑似コードを見ても今一つピンと来ない。
そういうときは、動画で動きを把握してみましょう。


Visualization and Comparison of Sorting Algorithms


9種はそれぞれ

選択 シェル 挿入
マージ クイック ヒープ
バブル コム シェーカー

です。

メジャーなアルゴリズム9種によるソーティングを動画で見ることができます。

  • ランダムな順序のソーティングの他、
  • 逆順序のソーティング、
  • ほぼ整列済み数列のソーティングの

3種類が見られます。

というのが、よくわかりますね。

いかにバブルソートがダメなのかが良く分かります。

追記(2018/5/2)

別のWebサイトで、ソートアルゴリズムを視覚的に見られるものがあったので、
こちらも紹介します。
VisuAlgo - Sorting (Bubble, Selection, Insertion, Merge, Quick, Counting, Radix)visualgo.net

ここでは、

が見られます。

追記(2018/12/22)

動画を貼り換えました。

NANDゲートで構築されたXOR回路の覚え方

応用情報技術者試験受けようかと思ってテキストを買ったはいいのですが、
申し込みしようと公式HPに行ったら10月分は締め切っていました。なんてこったい。

ということで、次の試験を目指して応用情報の勉強をしていこうと思っています。
そもそも、4月のプロジェクトマネージャー試験の午前Ⅰの免除を狙って
応用情報取ろうと思っていたので、でしたらもう午前Ⅰの勉強ということで
応用情報の勉強をしていこうかなと。
目標は10月いっぱいで応用情報のテキストを終わらせる、にしましょう。
ちなみに購入したテキストは、
TAC出版「ニュースペックテキスト応用情報技術者 平成29・30年版」
です。

NANDゲートとXOR回路

さて、閑話休題
本題のNANDゲートで構築されたXOR回路の覚え方です。
ここでは、4つのNANDゲートで構築された、下図のXOR回路です。

この回路の導出方法は
A \oplus B
=A \cdot \overline{B} + \overline{A} \cdot B
=A \cdot \overline{A} + A \cdot \overline{B} + \overline{A} \cdot B + \overline{B} \cdot B
=A \cdot (\overline{A}+\overline{B}) + (\overline{A} + \overline{B}) \cdot B
=A \cdot \overline{A \cdot B} + \overline{A \cdot B} \cdot B
=\overline{\overline{A \cdot \overline{A \cdot B}}} + \overline{\overline{\overline{A \cdot B} \cdot B}}
=\overline{\overline{A \cdot \overline{A \cdot B}} \cdot \overline{\overline{A \cdot B} \cdot B}}
となっており、論理和記号(・)が5つなのでNANDゲートも5つ分ですが、
 \overline{A \cdot B}が共通なので1つ省略でき、NANDゲート4つで構築できるようになっています。

この式変形は A \cdot \overline{A} = B \cdot \overline{B} = 0を足すというトリッキーなことをしているため、
中々自分で編み出すのは難しく、先のテキストでも、回路を覚えた方が良いと述べています。
何しろ平成22年秋試験で出題されたということですから、覚えておきたい。

回路を図案化

回路図をじーっと眺めてみた結果、こんな図案化をしてみました。
これで幾分覚えやすくなったかな。

Javaの匿名内部クラスを比較する


javaの匿名内部クラスについて、いい比較があったのでご紹介します。
引用先は、金田浩明『超初心者でも大丈夫 はじめてのAndroidプログラミング 改訂版』です。

匿名内部クラスとは

匿名内部クラス(anonymous inner class:無名インナークラスとも)とは、
クラスの名前を決めずに(匿名)、外部から参照できない形で(内部)定義するクラスのことです。
上記参考書では「無名インナークラス」と紹介されていますが、
下記のサイトを見ると、一応クラスに名前はあるらしいので、ここでは「匿名」の方を採用しました。
最も、この「匿名されているクラス名」を使えば外部からクラスを使用することもできるので
(そこで宣言されたインスタンスは参照できないが)
内部/インナーを除いた「匿名クラス」「無名クラス」という言い方もあります。
irof.hateblo.jp

C言語の無名○○

ちなみに、似たようなものがC言語にもあります。
「無名構造体」「無名共用体」「無名列挙型」などがそれです。
(こちらは「匿名〜」よりも「無名〜」の方がメジャーですかね?)
それぞれの型の定義を、その型の変数の定義と同時に行ってしまうものです。

/* 無名構造体 */
struct{
    int a;
    int b;
} anonymous_struct;

/* 無名共用体 */
union{
    int k;
    int l;
} anonymous_union;

/* 無名列挙型 */
enum{
    int x,
    int y,
} anonymous_enum;

型の名前がないので、関数の引数などに使うことはできません。
ですので、余り使いどころがないという話もあるのですが、
私は、特にC言語にはクラスという概念がないので、
データをひとかたまりにしたい時に無名構造体を使ったり、
組み込みC言語で、複数の形式で変数の読み書きをしたい時に無名共用体を使ったり、
配列を連想配列的に使いたい時(なので型はいらない)に無名列挙型を使ったりします。

匿名内部クラスを使った場合と使わなかった場合

さて、本題に戻ります。
引用先では、JavaによるAndroidアプリ開発において、
OnClickListenerを設定するシーンを例に、匿名内部クラスを使用した場合と
使用しない場合とを紹介しています。

匿名内部クラス使用例
protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Button tapHere = (Button)findViewById(R.id.tapHere);
    tapHere.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v){
            TextView textView = (TextView)findViewById(R.id.textView);
            textView.setText("ボタンがタップされました");
        }
    });
}
//金田, 2017, pp58-59.
匿名内部クラス非使用例
protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Button tapHere = (Button)findViewById(R.id.tapHere);
    MyOnClickListener myOnClickListener = new MyOnClickListener();
    tapHere.setOnClickListener(myOnClickListener);
}

public class MyOnClickListener implements View.OnClickListener{
    @Override
    public void onClick(View v){
        TextView textView = (TextView)findViewById(R.id.textView);
        textView.setText(R.string.hello_world);
    }
}
//金田, 2017, pp60-61.

上記2例について、
相違部を赤枠、赤枠内の一致部を緑枠及び青枠で示したのが下の図です。
(純粋に使用例と非使用例を比較するため、非使用例の方は若干内容を変えています)

これを見ると、for文の条件式の中でイテレータを宣言・定義するC++Javaの構文を彷彿とさせます。

for(int i=0;i<num;i++){
    //繰り返し処理
}

このint iと同じように、
関数の引数の中で、新しいクラスを定義しているのが匿名内部クラスと考えると
わかりやすいと思います。
他ではそう目にしない

});

の括弧の並びも、これで納得でしょう。

C言語プログラマがスマホ用アプリ開発を始めるときに役立つWebサイト(適時更新)

C言語プログラマとしての経歴が長い私ですが、
スマホアプリ開発android, java)を始めるときに、お勉強になったWebサイトを適時紹介したいと思います。
(というか、ただの備忘録?)

世界観から再構成しましょう

C言語でPCソフトを作ったりすると、
すべての処理を自分で書かなくてはいけない
という固定概念が染みついてしまいます。
実際にはライブラリ等を使っているので、すべてのコードを自分で書いているわけではないのですが、
それでも、「ライブラリは意識的に使用する道具であり、手間の節約のために使っている」という認識があり、
原則的にはすべてを自分で書かなくてはいけない、と考えていました。

しかしアプリ開発は(一般的には)そうではないのです。

http://libro.tuyano.com/index3?id=495001libro.tuyano.com

上記リンク先を読んでいただければわかりますが、
原則は「追記」です。
まるで、既存の完成ソフトに追加機能を実装していく派生開発のようなスタイル、これがアプリ開発の基本です。

恐らくPCソフト開発も、大手が作る場合は同じスタイルなのだと思います。
基本となるベースソフト(OOP的にいえば継承元クラス)があり、
それを元に(継承して)新たなソフトウェアを作成していく、という感じなのでしょう。

それがわかっていないと、「extends」や[@Override」が一体何をしているのか、
なんでこんなことをしているのかが見えてこず、
たとえ今までのあなたがプログラマ経験が長い人だったとしても、
アプリ開発についてはド素人のコピペプログラマになってしまいます。

MainActivityの中身は把握しておきましょう

と言われても、C言語プログラマとしては気持ち悪いもの。
C言語を初めて勉強したときの「#includeはお・ま・じ・な・い♪」をあの時呑み込めたのは、
よくわからない気持ち悪いものが#include文ただひとつだけだったからで、
「MainActivity.javaとactivity_main.xmlがまるっとおまじないだよ♪」なんて、
C言語プログラマからすると吐き気を催すレベルです。
(あるいは「やだもう帰る!」と叫んでキーボードをクラッシュするレベル)

なので、せめてこの2つのファイルの中身くらいは意味や機能を知っておきたいものです。

nobuo-create.net

上記サイトでは、コードを一行一行、丁寧に解説してあります。
これを見ると、「あぁ、MainActivityってメインループ的存在なのね」というのがわかります。
(while文などの明示的なループ制御はありませんが、機能としてはメインループの各イベントが
 書かれているものですので、そう言っても間違いはないでしょう)

これらを理解していれば、とりあえずは落ち着いてアプリ開発が始められるかなと思います。

Android Studioでお天気WebサービスのWebAPIが利用できない→タイプミスでした、のオチ


Android Studioではじめる簡単Androidアプリ開発』で、
現在Androidアプリ開発のお勉強をしているのですが、
Chapter6の「WebAPIで情報を取得する天気予報アプリを作ろう」で躓いていました。

「6-4 スレッドからUIを変更する」を行っても、正しく情報を取得できないのです。

よくよく調べてみると、
ひとつ前の「6-3 スレッドからネットワークにアクセスする」にて、
logcatに表示されているエラーがCalledFromWrongThreadExceptionではなくて、
引き続きNetworkOnMainThreadExceptionではありませんか。

まさかWebAPIサービスが終了した?もしくはURLが変更されたのかも?
と思って、ソースコード上のURLを調べてみたら、しっかり運営されていました。

お天気Webサービス仕様 - Weather Hacks - livedoor 天気情報

ん?

URLの最後、「v1」って書いてあるな…。
僕、確か「vl」ってタイプした気がする。

「vl」を「v1」に直した結果、

無事動きました!
悲しいかなタイプミスでした。


余談:
この小文字の「l」と数字の「1」が区別しにくいフォント、
Windows標準搭載のcourierなんじゃないか?メジャーな英文の等幅フォント

こちらのサイトによりますと、
courierはタイプライター用のフォントだそうですね。
そりゃぁ「l」と「1」の区別はできないわ。
だって欧文タイプライターって、ものによっては「1」のキーがなくて、
「l」で代用するんだもの。

タイプライターの歴史に詳しい人に質問です。昔の英文タイプライ... - Yahoo!知恵袋

Remington Typewriter
Remington Typewriter / hellostanley

Android Studio 2.3.1でApplication Installation Failedが出た時に私がしたこと

相変わらずAndroid Studioアプリ開発のお勉強をしています。
今日はタイトルにあるように
「Application Installation Failed」というエラーが出てしまったので、
その時に私が行った解決方法をご紹介します。

と言っても、基本は以下のリンク先に従っただけです。

但し、Android Studioのバージョンが古いので、ちょっとだけ操作手順が異なるので、
そこだけ補足します。

  1. File→Settingsをクリック


  1. Build, Execution, Deployment→Instant RunのEnable...のチェックを外す

これで何とか、エラーを回避することができるようになりました。
原因はまた後で調べようと思います。