2016年センター試験英語(筆記)を解く

英語力の定点観測のために、今年のセンター試験英語(筆記)を解いてみました。結果からいうと183点で、期待よりも低い値でした。

以下、間違えた部分を中心としたメモです。ネタバレしてます。

第1問

B-3. charity, continent, demonstrate, opponentでアクセントの場所が異なる単語を選ぶ問題を間違えた。op-po-nentは2つ目の音節にアクセントがあり、他の単語は1つ目の音節にアクセントがあるので、opponentを選ぶのが正解。私はdemonstrateを誤選択。

第2問

A-9. "Wood (used to) be used as the main fuel, but nowadays fossil fuels (are used) widely."という文を完成させる問題。誤って(was used to), (are used)という選択肢を選んだ。正解すべき問題だった。

A-10. "(It) is so considerate (of) him to..."という、人の評価を述べるときに使う構文を完成させる問題。こんな構文の存在を完全に忘れていた。

C-3. PaulとYokoが結婚してる…? Johnではなく…?

第3問

  1. 不要な文を除く問題。英語力というより論理力が問われる。B-2とB-3はどの文もはっきりと不要といえる文はないように思えた。B-3で、罪悪感の話題が他と繋がらないため4を選んだが正解は1。納得できていない。

第4問

  1. 美術館のウェブサイトから情報を読み解く問題。TOEICみたいだ。

第6問

A-5. パッセージにタイトルを付ける問題。"The Difficulties Facing Opera"と"The Historical Context of Opera"とで迷って後者を選択。正解は前者。最近のオペラの問題以外の歴史的な話題もあったのでより広いタイトルを選んだのだが…。

Anacondaのcondaコマンドによる仮想環境の使い方のまとめ

Pythonパッケージ集として人気のあるAnacondaに付属するcondaコマンドを使って、クリーンなPython環境を作ったり破棄したりする方法についてまとめました。

環境を作る

myenvという名前のpython環境を作ってみましょう。

$ conda create --name myenv python

とすると、myenvという名前の環境が作成されます。以下、--nameの代わりに-nでもOKです。

Pythonのバージョンを指定したい場合はpython=x.xなどと書きます。

$ conda create --name myenv python=3.3

追加のパッケージを入れたい場合はパッケージ名を羅列します。

$ conda create --name myenv numpy scipy

パッケージ全部入りのpython環境を作るには最後をanacondaにします。

$ conda create --name myenv anaconda

すでに作成した環境をクローンして新たな環境を作成したい場合は--cloneを使います。ここではmyenvという環境をクローンしてclonedenvという環境を作成しています。

$ conda create --name clonedenv --clone myenv

作成した環境の一覧を見る

以下のコマンドを打ちます。

$ conda info --envs

自分が今いる環境にはアスタリスクが付与されています。

環境を切り替える

Linux, OS Xの場合は

$ source activate myenv

Windowsの場合は

$ activate myenv

とすると、作成した環境に入れます。

環境から出る

Linux, OS Xの場合は

$ source deactivate

Windowsの場合は

$ deactivate

とすると、作成した環境から出られます。

環境を消す

$ conda remove --name myenv --all

とします。

参考

Managing environments — Conda documentation

VirtualBOX + Ubuntuの環境構築メモ

Windows 10 + VirtualBOX + Ubuntuを動かすときのメモです。適宜更新します。

Ubuntuの仮想イメージを取得

Ubuntuの入手 | Ubuntu Japanese Teamから「日本語 Remix 仮想ハードディスクイメージのダウンロード 」をクリックして「Ubuntu 14.04 LTS」を入手します。

LTSはLong Term Supportの略。サポート期間が長いので、LTSのついたものを選ぶのがよさそうです。

もっさりの解消

Ubuntuを起動すると、Unityのあまりの遅さに驚きます。VirtualBox 上の Ubuntu がもっさりする件を解消するメモ - Qiitaに従って3D アクセラレーションを有効化すると、もっさりが解消しました。

よく使うソフトのインストール

まずパッケージを更新

$ sudo apt-get update
$ sudo apt-get upgrade

個人的によく使うソフトをインストール

$ sudo apt-get install emacs git lv nkf python-pip zsh

C言語でOpaqueポインタを使って構造体のメンバを隠蔽する

C言語で、自作の構造体のメンバをユーザに開示しないテクニックとして、Opaqueポインタというものが知られています。今回は、書籍「C++のためのAPIデザイン」の3.1.6節を参考に、Opaqueポインタを使う簡単なサンプルを紹介します。

Opaqueポインタを使わない場合

人に関するデータを集めた構造体Personと、その構造体を使ったライブラリを作成することを考えます。以下にPerson.hのコードを示します。

#pragma once

typedef struct _Person
{
    int age;
} Person;

// 以下、Person構造体に関するAPI

Person* createPerson(int age);    // Person構造体のオブジェクトを生成
void printPerson(Person* ptr);    // Person構造体を使った操作(メンバのプリント)
void destroyPerson(Person* ptr);  // Person構造体のオブジェクトを破棄

Person構造体のメンバがベタ書きされていることに注目してください。

Person.cppのコードを以下に示します。

#include "Person.h"
#include <stdio.h>

Person* createPerson(int age)
{
    Person* ptr = (Person*)malloc(sizeof(Person));
    if (ptr)
    {
        ptr->age = age;
    }
    return ptr;
}

void printPerson(Person* ptr)
{
    if (ptr) printf("age: %d\n", ptr->age);
}

void destroyPerson(Person* ptr)
{
    if (ptr) free(ptr);
}

と記述します。

このPerson構造体の呼び出し側のコードは以下のとおりです。

#include "Person.h"

int main(void)
{
    Person *p = createPerson(42); // オブジェクトを生成
    printPerson(p);
    destroyPerson(p); // オブジェクトを破棄

    return 0;
}

createPerson()を使ってPerson構造体のオブジェクトを新規作成し、Person構造体を利用する関数を呼び出した後、destroyPerson()を使ってオブジェクトを破棄しています。

この例ではPerson.hにPerson構造体のメンバをすべてベタ書きしているため、以下のような問題が生じます。

Personオブジェクトの中身を、呼び出し側が自由に変更できてしまう。 上記例では、呼び出し側がp->age = 100;などと内部の値を自由に変更できてしまいます。これはライブラリの作者が予期しない結果をもたらす可能性があります。

Person構造体の実装が外部に露出してしまう。 Person構造体の実装は呼び出し側が知る必要がない情報であっても、実装が露出してしまっています。

Person構造体に変化があるたびに、Person.hの呼び出し側で再コンパイル・再リンクが必要。 ビルドの時間が増加します。またライブラリ側と呼び出し側で異なる定義のPerson構造体を想定している場合、リンクすると危険なことが起こるはずです。

Opaqueポインタを使う場合

上述の問題を解決するためにOpaqueポインタが使われます。修正したPerson.hを以下に示します。

#pragma once

typedef struct Person *PersonPtr;

PersonPtr createPerson(int age);
void printPerson(PersonPtr ptr);
void destroyPerson(PersonPtr ptr);

上記では、Person構造体の定義はしていません。すなわち、Person構造体のメンバを具体的に書き下すことはしていません。そのかわりに、どこかに定義されているPerson構造体へのポインタを、PersonPtrという型名で呼ぶという約束だけをしています。こうすることでPerson.hの呼び出し側にPerson構造体の実装が漏れることがなくなりました。

修正したPerson.cppは以下です。

#include "Person.h"
#include <stdio.h>
#include <stdlib.h>

struct Person
{
    int age;
};

PersonPtr createPerson(int age)
{
    PersonPtr ptr = (PersonPtr) malloc(sizeof(struct Person));
    if (ptr)
    {
        ptr->age = age;
    }
    return ptr;
}

void printPerson(PersonPtr ptr)
{
    if (ptr) printf("age: %d\n", ptr->age);
}

void destroyPerson(PersonPtr ptr)
{
    if (ptr) free(ptr);
}

呼び出し側は以下です。

#include "Person.h"

int main(void)
{
    PersonPtr p = createPerson(42);
    printPerson(p);
    destroyPerson(p);

    return 0;
}

構造体の中身は呼び出し側からは知る由はないので、もし仮にここでp->age = 70;などと構造体の中身を書き換えようとしても、コンパイルが通りません。Opaqueポインタを使うことで実装の詳細を適切に隠蔽でき、安全性も向上していることがわかります。

メインPCをWindows 10にUpgradeした記録

自宅でメインPCとして5年以上使っているDell XPS 8100をWindows 7からWindows 10にアップグレードしました。大多数のアプリは問題なく動いており、おおむね満足です。

このエントリでは、アップグレードにまつわる記録を記します。

アップグレードできなかったソフト

Windows 7にインストールしていたDaemon ToolsはそのままWindows 10に移行できないようだったので、アンインストールしたあと手動で入れなおしました。

Windows 10にしてからの設定

グラボのドライバ

Windows 10へのアップグレード直後はグラボ(Radeon HD57XX)にドライバが当たっておらず、画面の解像度が低く、グラボのファンが高速回転してうなりを上げている状態でした。

AMDのサイトからCatalystの最新版を落として手動インストールするも、毎回ブルースクリーンになり失敗。結局、Windowsによる自動ドライバインストール?により、勝手にドライバが入るのを待たねばなりませんでした。

休止状態の復活

dynabook.com | サポート情報 | [電源](電源メニュー)に[休止状態]が表示されない<Windows 10> 【動画手順付き】

夜中にPCが休止状態から目覚める問題

従来、休止状態にしたPCは勝手に目覚めることはなかったはずですが、Windows 10にしてからは休止状態でも構わずお目覚めになるようになってしまいました。 Windowsでスリープ・休止状態・スタンバイなどの状態が勝手に解除されてしまう現象の回避方法 - 結果だけでなく過程も見てくださいに対策が網羅的に記されているので、順番に試して様子を見ているところです。

Google日本語入力をデフォルトにする

タスクバーの通知領域からGoogle日本語入力を選択しても、いつのまにか異なるIMEに切り替わってしまう現象が起きています。

Windows10で既定のIMEを変えられない? Google日本語入力やATOKに設定する方法 | アプリオの「既定の文字入力方式(IME)を変更する」を実行しましたが改善しません。

IMEが切り替わるたびWin + Spaceというショートカットを使ってGoogle日本語入力に戻していますが、正直面倒です。

(2016/01/26追記)Google日本語入力をアンインストール後にインストールし直すと、「押し間違えの多いホットキー (Ctrl + Shfit) による IME の切り替え機能を無効化する」というオプションの選択ダイアログが出てきました。これまでIMEが勝手に入れ替わると思っていたのは、知らずにこのホットキーを押していたことが原因だったかもしれません。このオプションをONにして様子を見ます。

ソフトのインストール

Travis CI にて、C++11のソースをgccとclangの両方でビルドする

githubレポジトリと簡単に連携できる継続的インテグレーションサービスであるTravis CIを使って、C++11で書かれたソースコードをテストできるようにしました。想像以上に大変だったのでメモしておきます。

ソースコードとテストコードの準備

Travis CIで提供される仮想マシンLinuxOS Xなので、Visual Studio向けのコードはビルドできません。MakefileやCMakeなどコンソールからビルドできる仕組みを用意する必要があります。

今回は以下のような簡単なMakefileを用意しました。

CXX = g++
CPPFLAGS = -I3rdparty/catch -IMyVector
CXXFLAGS = -std=c++11
TARGET = test

$(TARGET): MyVectorTest/main.cpp MyVectorTest/test_constructor.cpp
        $(CXX) $(CXXFLAGS) $(CPPFLAGS) $^ -o $@

clean:
        rm -r $(TARGET)

単に

$ make

とすればg++でビルドできますし、

$ make CXX=clang++

などと変数を引数で指定すればclangでもビルドできます。

今回は、このMakefileを使い、gccとclangの両方でC++11のコードをビルドすることを目標にします。

参考までに、テストフレームワークには、最近人気があるphilsquared/Catchを使っています。ただし本編には関係ありません。

.travis.ymlの作成

Travis CIで提供されるUbuntuマシンで使えるg++とclang++のバージョンは現時点でそれぞれg++ 4.6.3とclang++ 3.4と古く、C++11には対応してません。そこで、Travis CIの設定ファイル.travis.ymlに、新しいバージョンのg++とclang++が使えるよう設定を加える必要があります。

Web検索をしまくった結果できあがったのが以下の設定ファイルです。g++ 5とclang++ 3.7を使ってC++11のコードがビルドできるようになりました。

sudo: false
language: cpp
compiler:
  - clang++
  - g++

install:
  - if [ "$CXX" = "g++" ]; then export CXXFLAGS="-std=c++11"; fi
  - if [ "$CXX" = "g++" ]; then export CXX="g++-5" CC="gcc-5"; fi
  - if [ "$CXX" = "clang++" ]; then export CXXFLAGS="-std=c++11"; fi
  - if [ "$CXX" = "clang++" ]; then export CXX="clang++-3.7" CC="clang-3.7"; fi

  - make CXXFLAGS="${CXXFLAGS}" CXX="${CXX}"

addons:
  apt:
    sources:
      - ubuntu-toolchain-r-test
      - llvm-toolchain-precise-3.7
      - llvm-toolchain-precise
    packages:
      - clang-3.7
      - g++-5
      - gcc-5

script:
  - ./test

addonsの項で何が起こっているのか正確に理解していませんが、とにかくこれがミソのようです。後は変数CXX, CXXFLAGSに適当な変数を代入して、makeの引数として渡せばOKです。

蛇足ですが、このコードにたどり着く前は、以下のようにapt-getや自力ビルドを駆使してg++とclang++を用意していました。複雑な上に時間もかかり不経済なので、このコードを使う必要はまったくありません。

language: cpp
compiler:
    - clang++
    - g++
before_install:
  # g++4.8.1
  - if [ "$CXX" == "g++" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi

  # clang 3.4
  - if [ "$CXX" == "clang++" ]; then sudo add-apt-repository -y ppa:h-rayflood/llvm; fi

  - sudo apt-get update -qq

install:
  # g++4.8.1
  - if [ "$CXX" = "g++" ]; then sudo apt-get install -qq g++-4.8; fi
  - if [ "$CXX" = "g++" ]; then export CXXFLAGS="-std=c++11"; fi
  - if [ "$CXX" = "g++" ]; then export CXX="g++-4.8"; fi

  # clang 3.4
  - if [ "$CXX" == "clang++" ]; then sudo apt-get install --allow-unauthenticated -qq clang-3.4; fi
  - if [ "$CXX" == "clang++" ]; then export CXXFLAGS="-std=c++0x -stdlib=libc++"; fi
  - if [ "$CXX" == "clang++" ]; then svn co --quiet http://llvm.org/svn/llvm-project/libcxx/trunk libcxx; fi

  - if [ "$CXX" == "clang++" ]; then cd libcxx/lib && bash buildit; fi
  - if [ "$CXX" == "clang++" ]; then sudo cp ./libc++.so.1.0 /usr/lib/; fi
  - if [ "$CXX" == "clang++" ]; then sudo mkdir /usr/include/c++/v1; fi
  - if [ "$CXX" == "clang++" ]; then cd .. && sudo cp -r include/* /usr/include/c++/v1/; fi
  - if [ "$CXX" == "clang++" ]; then cd /usr/lib && sudo ln -sf libc++.so.1.0 libc++.so; fi
  - if [ "$CXX" == "clang++" ]; then sudo ln -sf libc++.so.1.0 libc++.so.1 && cd $cwd; fi
  - if [ "$CXX" == "clang++" ]; then export CXX="clang++-3.4"; fi

  - cd ${TRAVIS_BUILD_DIR}
  - ls
  - make CXXFLAGS="${CXXFLAGS}" CXX="${CXX}"
  - ls

script:
  - chmod ugo+x test
  - ./test

ビルド例

githubminus9d/MyVectorTravis CIでテストできるようにしています。この記事執筆時点でのテスト成功例は Build #34 - minus9d/MyVector - Travis CI です。

参考リンク

makeで大量のメッセージが表示されるときは-dオプションを疑う もしくは変数展開についてのbash/zshの違い

ある私的プロジェクトでMakefileの変数$(CXXFLAGS)を変更して実行するために、以下のようなスクリプト script.sh

CXXFLAGS="-std=c++0x -stdlib=libc++"
make CXXFLAGS=${CXXFLAGS}

を書きました。このスクリプトの意図は、Makefileに記されたCXXFLAGSという変数を、"-std=c++0x -stdlib=libc++"という文字列で上書きして、Makeを実行することです。

このスクリプトを、bashで実行します。

$ bash script.sh

すると、以下のような数百行にも渡る大量のメッセージが表示されました。

GNU Make 4.1
このプログラムは i686-pc-cygwin 用にビルドされました
Copyright (C) 1988-2014 Free Software Foundation, Inc.
ライセンス GPLv3+: GNU GPL バージョン 3 以降 <http://gnu.org/licenses/gpl.html>
これはフリーソフトウェアです: 自由に変更および配布できます.
法律の許す限り、 無保証 です.
makefile を読み込みます...
makefile 'Makefile' の読み込み中...
makefile の更新中....
 ファイル 'Makefile' を検討しています.
  'Makefile' のための暗黙ルールを探します.
  語幹 'Makefile' とのパターンルールを試します.
  暗黙の必要条件 'Makefile.o' を試します.
  語幹 'Makefile' とのパターンルールを試します.
  暗黙の必要条件 'Makefile.c' を試します.
  語幹 'Makefile' とのパターンルールを試します.
  暗黙の必要条件 'Makefile.cc' を試します.
  語幹 'Makefile' とのパターンルールを試します.
  暗黙の必要条件 'Makefile.C' を試します.
  語幹 'Makefile' とのパターンルールを試します.
  暗黙の必要条件 'Makefile.cpp' を試します.
  語幹 'Makefile' とのパターンルールを試します.
  暗黙の必要条件 'Makefile.p' を試します.
  語幹 'Makefile' とのパターンルールを試します.
  暗黙の必要条件 'Makefile.f' を試します.
  語幹 'Makefile' とのパターンルールを試します.
  暗黙の必要条件 'Makefile.F' を試します.
  語幹 'Makefile' とのパターンルールを試します.
  暗黙の必要条件 'Makefile.m' を試します.
  語幹 'Makefile' とのパターンルールを試します.
  暗黙の必要条件 'Makefile.r' を試します.
  語幹 'Makefile' とのパターンルールを試します.
  暗黙の必要条件 'Makefile.s' を試します.
  語幹 'Makefile' とのパターンルールを試します.
  暗黙の必要条件 'Makefile.S' を試します.
  語幹 'Makefile' とのパターンルールを試します.
  暗黙の必要条件 'Makefile.mod' を試します.

(以下400行ほど続く)

   語幹 'test_constructor.cpp' とのパターンルールを試します.
   暗黙の必要条件 'MyVectorTest/SCCS/s.test_constructor.cpp' を試します.
   'MyVectorTest/test_constructor.cpp' のための暗黙ルールがありません.
   ターゲットファイル 'MyVectorTest/test_constructor.cpp' の必要条件を満たしました.
  ターゲット 'MyVectorTest/test_constructor.cpp' を再make する必要はありません.
 ターゲットファイル 'test' の必要条件を満たしました.
ターゲット 'test' を再make する必要があります.
ターゲットファイル 'test' の再 make に成功しました.

賢明な皆様はお気づきかもしれませんが、原因はbashの引数の展開方法にあります。

make CXXFLAGS=${CXXFLAGS}

の部分が

make CXXFLAGS=-std=c++0x -stdlib=libc++

と展開されてしまったおかげで、CXXFLAGSに代入される値が -std=c++0x だけになってしまいました。 残りの-stdlibの部分で、makeに-dオプションを渡したと誤解されてしまい、先ほどのような冗長なデバッグ情報が表示されてしまったようです。

初めの意図通りの処理をさせるには、変数の前後をクオートで囲むのが正解でした。

CXXFLAGS="-std=c++0x -stdlib=libc++"
make CXXFLAGS="${CXXFLAGS}"

bashスクリプトでのクオートについては Quoting Variables が詳しいです。以下のスクリプト

List="one two three"

for a in $List
do
  echo "$a"
done

echo "---"

for a in "$List"
do
  echo "$a"
done

を実行すると、クオートの有無による動きの違いがよくわかります。上記をshやbashで実行すると、

one
two
three
---
one two three

と表示されます。

なお、ややこしいことに、私の手元のzshでこのスクリプトを実行すると、

one two three
---
one two three

と、クオートがあろうがなかろうが同じ結果になってしまいました。shell - Variable expansion is different in zsh from that in bash - Stack Overflow によると、これがzshのデフォルトの振る舞いのようです。

zshでもbashと同じルールで変数展開したい場合は、

ls ${=args}

とするか

setopt SH_WORD_SPLIT

とすればよいようです(未確認)。