としおの読書生活

田舎に住む社会人の読書記録を綴ります。 主に小説や新書の内容紹介と感想を書きます。 読書の他にもワイン、紅茶、パソコン関係などの趣味を詰め込んだブログにしたいです。

647498_s


windowsでtimeGetTime関数を使用して時間計測のプログラムを作ろうとしたろころ、コンパイルの段階で

undefined reference to `__imp_timeGetTime'

というエラーが現れて少し苦戦したので対処法を残します。



コンパイルしたいコード


コンパイルしたいと思ったコードは、timeGettime関数を使って実行時間を計測するコードです。
ソースファイル名はsample.cppとします。

#include <iostream>
#include <windows.h>

int main(void){
    DWORD start_tm = timeGetTime();

    for(int i=0i<1000; ++i){
        for(int j = 0j<10000000; ++j){}
    }

    DWORD end_tm = timeGetTime();
    std::cout << end_tm - start_tm << std::endl

    return 0;
}



コンパイル失敗


何も考えずにコンパイルすると…

g++ -o sample sample.cpp

以下のメッセージがでて、そんなもの定義していないぞと怒られてしまいます。

undefined reference to `__imp_timeGetTime'




`__imp_timeGetTime'の対処法


エラーについて調べてみるとtimeGetTime関数を使用するためにはwinmm.libをリンクする必要があるということが分かりました。

なのでコンパイルコマンドを以下に直すと

g++ -o sample sample.cpp -lwinmm

コンパイルが成功しました。



まとめ


windows.hで定義しているAPIを使用するためには、必要に応じてライブラリをリンクする必要があるということが分かりました。

普段Visual Studioばかりつかっていたら、そのあたりをそこまで意識しなくていいので気をつけなければなりませんね…。




3753817_s


本記事では、デザインパターンの名著である結城浩さんの『Javaで学ぶデザインパターン入門』を参考にIteratorパターンをC++で実装してみました。

C++のSTLでは、すでにイテレータは実装されているので、改めて実装することはないのですが、今回は設計思想を学ぶために実装していきます。




イテレータパターンとは


イテレータパターンとは、何かが同じようなものがたくさん集まっているときに、それを順番に指し示していき全体をスキャンする処理を行うためのものです。

例えば、本棚から本の名前を順番に表示するといったときに使うことができます。

ちなみにイテレータ(Iterator)とは、日本語で繰り返すという意味です。



イテレータパターンの登場人物


イテレータパターンは以下のようなクラス構成になっています。



イテレータパターン


Iterator


要素を順番にスキャンしていくAPIを定める役。

次の要素を得るためのhasNextメソッドや次の要素を得るためのnextメソッドなどを定めます。


ConcreateIterator


Iterator役が定めたAPIを実際に実装する役。

この役はスキャンをするのに必要な情報をもっている必要があります。


Aggregate


Iterator役をCreateするためのAPIを定める役。

今回の場合、IteratorがIteratorを作成する、メンバ関数になります。


ConcreateAggregate


Aggregate役が定めたAPIを実際に実装する役。

ConcreateAggregateが自信をサーチしてもらうために必要な具体的なIteratorであるConcreateIteratorを作成します。





C++による実装


今回は、本棚から本の名前を順番に表示するといったイテレータパターンを使ったサンプルプログラムを実装していきます。

クラス構成は以下の通りです。


イテレータパターン (2)



Aggregateインタフェース


JavaでいうインタフェースはC++では抽象クラスとして実装していきます。

#ifndef AGGREGATE_H
#define AGGREGATE_H

#include <iostream>

class Iterator;

class Aggregate{
public:
    virtual Iterator* iterator() = 0;

    virtual ~Aggregate(){};
};
#endif // AGGREGATE_H



Iteratorインタフェース


こちらもAggregateインタフェースと同様に抽象クラスでの実装です。

#ifndef ITERATOR_H
#define ITERATOR_H

class Book;

class Iterator{
public:
    Iterator(){};

    virtual bool hasNext() = 0;

    virtual Book next() = 0;

    virtual ~Iterator(){};
};
#endif // ITERATOR



Bookクラス


Bookクラスは本を表すクラスです。

今回の場合できることは、本の名前を設定することと取得することだけです。

■ヘッダーファイル

#ifndef BOOK_H
#define BOOK_H

#include <iostream>

class Book{
public:
    Book();

    virtual ~Book();

    void setName(std::string name);

    std::string getName();

private:
    std::string m_name;
};
#endif // BOOK_H


■ソースファイル

#include "Book.h"

Book::Book()
m_name("")
{
    
}

Book::~Book(){
}

void Book::setName(std::string name){
    m_name = name;
}

std::string Book::getName(){
    return m_name;
}



BookShelfクラス


BookShelfクラスは本棚を表すクラスです。

こちらのクラスが先ほどのBookクラスの集合体になります。

■ヘッダーファイル

#ifndef BOOKSHELF_H
#define BOOKSHELF_H

#include <iostream>
#include "Aggregate.h"

class Book;
class Iterator;

class BookShelf : public Aggregate{
public:
    BookShelf(int maxsize);

    virtual ~BookShelf();

    Book getBookAt(int index);

    void appendBook(Book book);

    int getLength();

    Iterator* iterator();

private:
    Book *m_books;
    int m_last;
};
#endif // BOOKSHELF_H


■ソースファイル

#include <iostream>
#include <unistd.h>

#include "BookShelf.h"
#include "Book.h"
#include "BookShelfIterator.h"

BookShelf::BookShelf(int maxsize)
m_last(0)
{
    m_books = new Book[maxsize];
}

BookShelf::~BookShelf(){
    delete m_books;
}

Book BookShelf::getBookAt(int index){
    return m_books[index];
}

void BookShelf::appendBook(Book book){
    m_books[m_last= book;
    m_last++;
}

int BookShelf::getLength(){
    return m_last;
}

Iterator* BookShelf::iterator(){
    return new BookShelfIterator(this);
}



BookShelfIteratorクラス


BookShekfクラスのスキャンを行うクラスです。

■ヘッダーファイル

#ifndef BOOKSHELFITERATOR_H
#define BOOKSHELFITERATOR_H

#include "Iterator.h"
#include "BookShelf.h"

//class BookShelf;
class Book;

class BookShelfIterator : public Iterator{
public:
    BookShelfIterator(BookShelf* bookShelf);

    virtual ~BookShelfIterator();

    bool hasNext() override;

    Book next() override ;

private:
    BookShelf *m_bookShelf;
    int m_index;
};
#endif // BOOKSHELFITERATOR_H


■ソースファイル

#include "BookShelfIterator.h"
#include "BookShelf.h"
#include "Book.h"

BookShelfIterator::BookShelfIterator(BookShelf *bookShelf)
m_index(0)
{
    m_bookShelf = bookShelf;  
}

BookShelfIterator::~BookShelfIterator(){

}

bool BookShelfIterator::hasNext(){
    if (m_index < m_bookShelf->getLength()){
        return true;
    }
    else{
        return false;
    }
}

Book BookShelfIterator::next(){
    Book book = m_bookShelf->getBookAt(m_index);
    m_index++;
    return book;
}


main関数


今まで作成してきたクラスを使って実際に小さな本棚を作っていきます。

■ソースファイル

#include <iostream>
#include "BookShelf.h"
#include "Book.h"
#include "BookShelfIterator.h"

int main(void){
    BookShelf bookShelf(4);

    Book book1;
    book1.setName("Around the World in 80 days");
    bookShelf.appendBook(book1);

    Book book2;
    book2.setName("Bible");
    bookShelf.appendBook(book2);

    Book book3;
    book3.setName("Cinderella");
    bookShelf.appendBook(book3);

    Book book4;
    book4.setName("Daddy-Long-Legs");
    bookShelf.appendBook(book4);

    Iterator *it = bookShelf.iterator();

    while(it->hasNext()){
        Book book = it->next();
        std::cout << book.getName() << std::endl;
    }

    delete it;

    return 0;
}



■実行結果


Around the World in 80 days
Bible
Cinderella
Daddy-Long-Legs



まとめ


C++では既存の実装があるため、実装する必要のないイテレータパターンを作成することでイテレータの動きが以前より分かるようになりよかったです。

今後も勉強がてらデザインパターンを実装していきます。







3884509_s


勝間和代さんの『勝間式ネオ・ライフハック100』を読みました。

色々自分の生活に取り入れたいと思ったことがあったのですが、その中で特に自分の生活に取り入れたいと思ったライフハック7選を紹介していきます。



すぐ実践したいライフハック7選



毎日のルーティンの負担は秒単位で減らす


料理や掃除、洗濯といった家事や化粧や服選びなども毎日していて手慣れていることでも、負担に感じることがあります。

こうした毎日のルーティンにかけられる時間は決まっているのに、時間以上のことをしようとすると気持ちが疲弊してしまいます。

こうしたことで疲れをためないために、やることを決めてから時間を捻出するのではなく、時間内にできることを決めてやることを決めましょう。

例えば朝化粧にかけられる時間が4分しかない場合は、4分でできる化粧方法をみつけましょう。
化粧道具を持ちすぎると道具を選ぶのに時間がかかりすぎるので、最低限の道具を使うことで時間を節約できます。


毎日やる必要があるルーティンは、空いている時間内でしかできないことを自覚しましょう。

時間を節約するために便利な道具を使用するのも、毎日のルーティンの負担を減らすコツです。



時間を生む3つのコツを実践する


時間管理のコツは3つあります。

①完璧主義にしない

どんなことでも、最後の最後まで完璧に仕上げようとすると時間がかかります。

例えば洗濯物をたたむのでも、ショップのように綺麗にたたもうとすると時間がかかるので、ざっとたたむだけで大丈夫です。生活するのに困りません。

なので全てのことを完璧にこなそうとせず、だいたいこなすぐらいで過ごしましょう。


②移動時間をなるべく取らないようにする

移動時間は人生の中で非効率的な時間の1つです。

仕事でも遊びでも、移動時間をなるべく短くすることは重要です。

短くできないときは、移動時間を無駄にしないために、オーディオブックを聞いて情報収集するなど時間のクオリティをあげましょう。


③時間を1日単位で最適化しようとするのではなく、1年、5年、10年単位で徐々に最適化していく

時間を1日単位で最適化しても、その最適化はその場しのぎでしかありません。

毎日のルーティンを短くするなど長期的に見て時間を最適化していきましょう。

毎日の料理の時間が1分減れば、1日3食作ると考えると365日で1095分最適化することができます。

お金を貯蓄するように、時間も貯蓄していき好きなことに少しでも多くの時間を使えるようにしましょう。



3分以内にできることは積み残さずにやる


3分以内にできることは積み残しをしないようにしましょう。

すぐできるからと言って、色々なことを積み残していき後でまとめてやろうとするとすごく手間がかかり面倒に感じます。

また、どんなことでも、やった直後なら大して手間もかかりませんが、いったん時間を置くと余計に時間がかかります。

様々な作業を積み残していくと、自分が遊んでいるときもそのことを思い出してしまい心から楽しめなくなります。

食器洗いなどすぐに終わることは積み重ねずにすぐにやってしまうように心がけましょう。



本を速くたくさん読むための3つのコツ


本を買ったはいいけどなかなか読めないという方の悩みを解消するために、3つのコツを教えます。

①全部読もうと思わない

本1冊の文字数はだいだい7万~12万じなのですが、文字が少なすぎると本として成り立たないのでこれだけの文字数が書かれているだけです。

本当にいい情報は5000~1万字しかありません。

目次を見て興味がある部分だけ読むようにしましょう。


②1行1行熟読しない

本に書かれている内容を1行1行熟読しようとすると、1分間で500~600文字ほどしか読めません。

なので少しでも多くの情報をインプットしていくために本はどんどん斜め読みしていきましょう。

自分が気になるところだけ熟読すれば良いのです。


③読むのではなく聞く

最近はオーディオブックというものが存在しています。

移動時間などの暇な時間に、本を聞くようにしましょう。

聞くだけで理解できるのと思う方もいるかもしれませんが、分からない部分だけを本を開いて確認すればよいのです。

読書の最大の敵は完璧主義です。

全ての内容を覚えようとするのなんで不可能なので、キーアイデアだけを読み取るようにしましょう。





苦労・我慢・努力依存症から抜け出す


人の中には無駄な苦労や我慢、努力が好きな人が多くいます。

こうした人が多くいる理由は、何かを達成する報酬として分泌される、ドーパミングというホルモンが影響していると考えられます。

その結果、成果よりも我慢や苦労、努力の量が大事だというふうに履き違える人が生まれます。

もし、得られる成果が同じなら努力や苦労なんて少ないほうがいいに決まっています。

本当に大切なことは何かという視点で、仕事や家事を見直して無駄な苦労や我慢、努力を生活から排除していきましょう。



苦手な人との関係は積極的にマネジメントする


世間一般では、人の好き嫌いはよくないと言われていますが、好き嫌いがない人なんていません。

人によって知識や価値観が違うので、お互いに嫌いあうことはどうしても出てきます。

このことを前提に人間関係をマネジメントしていきましょう。

自分の先輩や上司だからと言って苦手な人に無理に話しかけにいく必要はありません。

その先輩や上司からどんなにすぐれたアドバイスなどを聞くことができても、自分が嫌いな人の意見なのでなかなか受け入れることはできません。

苦手な人とは必要な時だけコミュニケーションをとることができればOKです。

普段は自分が一緒にいたい人とか、一緒にいて苦にならない人とどんどんコミュニケーションをとるようにしましょう。



普段使わないものは、とにかく捨てる


冠婚葬祭の服などを除いて普段使わないものは基本的に必要のないものばかりです。

「使う・使わない」の基準は1ヶ月に1回以上使うかどうかで判断しましょう。

使わないものを捨てることで、収納にどんどん余裕がでてきます。

収納に余裕がでれば、探しているものも見つかりやすくなるため心にも余裕が生まれます。

使わないものでも捨てるのがもったいないと思うものは人にあげたり、メルカリなどで出品してしまいとにかく家に物を置かないようにしましょう。



まとめ


本記事では私が、『勝間式ネオ・ライフハック100』を読んで実践したいと思うライフハック7選を紹介していきました。

人によって実践したいと感じるライフハックは異なると思うので、他のライフハックにも興味がある人はぜひ本書を読んでみてください。

余談になりますが、本書でやたらとヘルシオが便利だとおしていたので少しほしくなりました…。






本記事を読んでくださった人には以下の記事もおすすめですので是非読んでみてください。








PXL_20210221_023209166.MP_1


本屋大賞受賞作である瀬尾まいこさんの『そして、バトンは渡された』 を読みました。

最初は、主人公の親が何度も変わっているということで鬱系な感じの小説を予想していたのですが、読み終わってみるととてもすっきりした作品で、爽やかな気持ちになることができました。

以下、あらすじと感想を書いていきます。



『そして、バトンは渡された』のあらすじ


幼いころに母親を亡くし、父とも海外赴任を機に別れ、継母を選んだ森宮優子。

その後も大人の都合に振り回され、優子は3人の父と2人の母を持つ女の子だ。

何度も住む場所や名字が変わり、高校生の今は、20歳しか離れていない、血のつながっていない"父"である森宮さんと一緒に暮らしている。

優子は、そんな複雑な家庭環境であるにも関わらず、健気で強い女の子だ。学校の先生などからは、家庭のことを気にされるが、彼女は気を使われることに困った様子を見せる。

なぜなら、血のつながらない親の間をリレーされながらも出会う家族皆に愛情をいっぱい注がれてきたため、家庭環境で困ったことがないからだ。

そんな優子自身についに伴侶を持つときが来た…。

優子の成長を描く中で、彼女の過去の回想がつづられる愛にあふれた家族小説。



感想(ネタバレあり)


読了後とりあえず感じたことは、
  • 森宮さんみたいな父親がほしい!
  • 森宮さんかっこよすぎる!
  • 優子のような幸せな人生が送れるならたくさんの親がいるということも悪いことではないかも!

ということでした(笑)

『そして、バトンは渡された』を読む前は、本屋大賞のほんだけどそこまで面白い」のかなと疑問に思っていました。

しかし、読了後は、こんな作品を発売してから1年以上読んでいなかったなんてどんだけもったいないことをしていたんだと感じさせられました。

瀬尾まいこさんの作品もいままで一度も読んだことがなかったのですが、『そして、バトンは渡された』をきっかけに他の作品も読んでみたいと思いました。


森宮さんと優子のW主人公


「そして、バトンは渡された」は優子と森宮さんのW主人公で描かれている作品です。

第一章では、大人の都合で振り回される優子が主役で、第二章では、娘を送り出す森宮さんが主役となっています。

W主人公の作品として書かれているのは、分かるのですが男性の私からしてみたら優子より森宮さんの方が主役という感じが強いような気がします。

森宮さんは、梨花さんとの結婚を機会に優子を娘として迎えます。自分が優子の本当の父親ではないけど、優子に父として認めてもらえるように本当の父親以上に父親らしくしようとします。

父親らしくしようとして、朝からかつ丼を作ったりなど少し空回りしている感じもありますが、優子と森宮さんの関係は、本当の家族以上に理想の家族なんだなという感じがします。

血がつながっていないからこそ、少しお互いに気を使いあうため、優子と森宮さんは良い距離感を保てているのかなと思います。

血がつながっている家族だといっても、お互いのことを完璧に分かりあうことはできないので少し距離感があるぐらいがもしかしたら理想の家族なのかもしれませんね。


第二章で森宮さんだけが、早瀬君と優子の結婚をなかなか認めないあたりも、森宮さんが優子の将来を本当に心配していることが分かりけっこうエモいです。

ラストシーンの優子がバージンロードを一緒に歩く相手に森宮さんを選んだときは、優子と森宮さんの信頼関係が分かりむちゃくちゃ泣いてしまいました。





たくさんいる優子の父と母


優子にはたくさんの父と母がいますが、全ての父と母に愛されている優子がすごく羨ましいです。

『そして、バトンは渡された』を読むまでは、再婚などがきっかけで義父や義母が増えることに関してマイナスのイメージしかありませんでした。

しかし、本作を読んでみんながみんな義父や義母が増えることにマイナスのイメージを持っているわけではないということが分かりよかったです。

優子の父と母で一番好きなのはもちろん森宮さんなのですが、私が二番目に素敵な人だなと思ったのは梨花さんです。

梨花さんは、優子と離れたくない一心で水戸さん(優子の実の父)からの手紙を優子に渡さないなどのマイナスのシーンもありましたが、それも優子を想う愛情故です。

個人的な偏見になりますが、今まで義母って血のつながっていない娘のことを邪魔に思うものだと思っていました。(グリム童話の読みすぎが原因かも…)

しかし、梨花さんそんな私のイメージを覆す良い母でした。

優子にピアノを弾かせたい一心で泉ヶ原さんと結婚したり、自分が病気になり優子を育てることができなくなると自分の代わりに優子を大切にしてくれる森宮さんを探したりして、梨花さんが自分の人生以上に優子のことを大切に思っていることが分かりました。

梨花さんや森宮さんを見ていると家族関係は血のつながりなんかより、相手のことをどれだけ大切に思っているかどうかということが大切であると分かりますね。



まとめ


『そして、バトンは渡された』は、『家族』というテーマをすごく上手に描いている作品ですごく面白かったです。

登場人物みんながいい人であり優子を大切に思っているので、終始涙が止まらない作品でした。

読了後はきっと、皆さん幸せな気持ちで胸がいっぱいになると思いますので未読の方がぜひ読んでみてください。

優子の人生を知って、皆で幸せを共感していきましょう。








DSC_3153


2016年に芥川賞を受賞した村田紗耶香さんの『コンビニ人間』が文庫化され本屋に大量に積まれていたので購入してみました。

様々な国で翻訳されている人気作品ということで読むのが楽しみでしたが、読んだ後はなんともいえない感情に襲われてしまいました。

以下あらすじと感想になります。





『コンビニ人間』のあらすじ


「いらっしゃいませー!」お客様がたてる音に負けじと私は叫ぶ。小倉恵子、コンビニバイト歴18年。彼氏なしの36歳。ひびコンビニ食を食べ、夢の中でもレジを打ち、「店員」でいるときのみ世界の歯車になれる。ある日婚活目的の新入り男性・白羽がやってきて……。




感想と考察(ネタバレあり)


ミステリー要素や恋愛要素などがなくただのコンビニ店員を主人公としてためリアルさがとても強い作品でした。リアルさゆえに人間の気持ち悪い部分や現代社会の問題などのメッセージが分かりやすい作品であったともいうことができます。

『コンビニ人間』というタイトルを見たときは変わったタイトルだなぐらいにしか捉えていませんでしたが、本作を読んだ方にはこのタイトルがどれだけこの作品にふさわしいタイトルであったのかが分かるでしょう。

本書は本当にメッセージ性が強い作品であるため、主人公である恵子や白羽を除く作中に登場する全ての人物が普通なように見えてとても気持ちの悪い存在でした。


恵子


恵子は、子ども時代の小鳥のエピソードから分かる通り子どもの頃から奇妙な思考回路を持つ人間です。

普通の子どもであればかわいい鳥が死んでいる、かわいそう、お墓を作ろうとなります。しかし恵子は鳥が死んでいる、お父さんは焼き鳥が好きだ、お父さんのために死んだ鳥を焼いて食べようとい発想がでてきます。

恵子の行動は合理的ですが一般的な社会で受け入れられないもので、このことから恵子はおそらく「サイコパス」であるということが分かります。

成長していくにつれて恵子も徐々に自分がおかしいということに気が付きます。しかし、どうすれば治るのかが分からないためコンビニで働くまでは自分から何もしない、しゃべらない人間になります。

人と関わらない生活を送っていた恵子に変化が現れたのは大学時代に "コンビニ店員" というアルバイトを始めたのがきっかけです。徹底的なマニュアルがあり店と客のために働き社会に沽券できる "コンビニ店員" という仕事は恵子にとって天職でした。

コンビニで働き始めたことをきっかけに人とどう関われば嫌がられないかという生き方も学んでいきます。

それから18年たち36歳になった現在でも他のことに興味を持たずコンビニのためのみに人生をささげており、正に "コンビニ人間" ですね。


白羽


白羽も客観的に見れば恵子と同じで人と関わるのが苦手な社会不適合者です。

しかし本質を見ると二人の違いは一目瞭然です。恵子が人の目などを全く気にしていないのにたいして、白羽は他人からどう思われているのかということを気にしています。

恵子が人間ではない新たな生物である "コンビニ人間" であるのに対して、白羽は普通の生活を送ることができる人間に憧れているだけという印象があります。

白羽という存在がいるおかげで恵子の異質感がより際立ちますね。


"普通" の人々


『コンビニ人間』に登場する恵子と白羽以外の人物は一見普通に見えますが、彼らは "異物を排除したい" という白羽のセリフで言うと縄文時代からプログラムされている人間の本能にしたがって生きています。

この本能こそが "普通" の人間を気持ち悪く見せる要因となっています。

おかしな存在である恵子や白羽に対して普通の人々はアドバイスをしようとするが、その行動の実態は彼らにとって異常な人間の内側に入り込み自身の異物を排除したいという欲求を達成しようとしているだけです。

社会では個性を尊重することができないということ作者の村田紗耶香さんが強調しているように感じます。

個性を尊重できない社会では恵子のような特別おかしな存在でもない限り、白羽が言うように少数派の人間は人生を他者に強姦されているように感じてしまうでしょう。

また作中で恵子は普通の人々は周りの人の行動と同じ行動をとると言うような発言をしていますがこれも人間の本能で人に嫌われないために同調行動をとろうとしているだけなんでしょうね。



まとめ


ここまでご覧になっていただきありがとうございます。

『コンビニ人間』は読む人によってとても後味が悪く感じる作品となってしまうのかもしれませんが、作者の村田紗耶香さんは社会の少数派の人を排除するためにこの作品を書いたのではないと思います。

世の中の多くの人に個性的な人も世の中にはいて個性を尊重するのは悪いことではないと伝えたかったのではないのでしょうか。

『コンビニ人間』を多くの人の手に取ってもらうことでいつか個性を尊重することができる社会になればいいですね。



4267000_s


本記事では、pythonのlambda(ラムダ式、無名関数)の使い方を紹介していきます。



lambda(ラムダ式、無名関数)とは


Pythonでは一般的に関数を定義するときは、def文を使用します。

しかし、関数には通常の関数の他に無名関数というものが存在します。

無名関数とは、その名前の通り、名前を持たない関数で、関数をその場に定義することができます。

pythonではこの無名関数を書くためにlambda(ラムダ式)というキーワードを使います。



lambdaの使い方


def文を使用して入力値の2倍の値を返す関数は以下のように書くことができます。

def calcDouble(num):
    return num*2

if __name__ == "__main__":
    num = calcDouble(5)


これをlambda式で書くと以下のように書くことができます。

if __name__ == "__main__":
    num = (lambda num: num*2)(5)


ここで「lambda num:」というのが「def calcDouble(num):」に相当する部分です。

そして「:」の区切りのあとに処理を書くのが、lambda式の使い方になります。



lambdaのメリット


lambdaを使うことのメリットは、リストなどの要素に対して何か特別な動作はしたいけれど、関数を定義するほどではないなというときにぱっと使うことができることです。

[1, 2, 3, 4]というリストの要素に対して先ほどdefで定義したcalcDouble関数を実行したいときは以下のように書けます。

def calcDouble(num):
    return num*2

if __name__ == "__main__":
    nums = [1234]
    nums = list(map(calcDouble, nums))


こんなことをするためだけに、毎回calcDouble関数のような関数を定義するのは面倒なのでlambdaを使います。

lambdaを使うと以下のように書くことができ、コードが先ほどよりすっきりしていますね。

if __name__ == "__main__":
    nums = [1234]
    nums = list(map((lambda num: num*2), nums))


lambdaは、map関数と合わせ使うことが多いです。
map関数の使い方については以下の記事をご覧ください。









lambdaのデメリット


lambdaを使うことのデメリットはコードの可読性が悪くなることです。

コードは基本的に他人が読めるように書かなければならないので、処理が複雑な関数などはlambdaを使わずにdefを使って定義するようにしましょう。
(他人が読めないコードは自分が読み返すときにも分かりづらく公開することになります)



まとめ


lambdaを使うことでコードが簡潔に書くことができることが分かりました。

ただ、lambdaには可読性が下がるというデメリットもあるため、状況を判断して使用するようにしましょう。



4267000_s


本記事では、pythonのmap関数の使い方を紹介していきます。




map関数とは


map関数とは配列などのイテラブルのすべての要素にアクセスし、関数を適応させることが可能にすることができる関数です。

ちなみにイテラブルとはlist、dict、strなどのfor文の後のinの部分に入れることができる要素のことです。

for i in イテラブル:


map関数を使うことで、for文などの繰り返し処理を使わずともすべての要素にアクセスすることができます。

そのためソースコードがシンプルになりfor文を使う場合よりも可読性があがります。



map関数の使い方


for文を使ってリストのすべての要素に対して、関数を適応させる場合、以下のように書くことができます。

def calcDouble(num):
return num*2

if __name__ == "__main__":
nums1 = [1, 2, 3, 4]
nums2 = []
for i in nums1:
nums2.append(calcDouble(i))
print(nums2)


上記と同じ処理をmap関数を使用して書くと以下のようになります。

def calcDouble(num):
return num*2

if __name__ == "__main__":
nums = [1, 2, 3, 4]
nums = list(map(calcDouble, nums))

print(nums)


for文を使った場合と比べるとかなりシンプルになったのが分かりますね。

また、for文では条件ミスのエラーがよく起こるため、そうしたミスを減らすのにもmap関数は有用です。





dictに対してmap関数を使う


map関数は、イテラブルのすべての要素にアクセスできると最初に紹介したので、以下でdictに対してmap関数を適用させるコードを紹介します。

ソースコード


def outputKey(dictType):
print(dictType[0]*dictType[1])

if __name__ == "__main__":
test = {"list": 2, "dict": 3, "map": 4}
list(map(outputKey, test.items()))


出力結果


listlist
dictdictdict
mapmapmapmap



キーの文字列を値の回数表示させるという単純なコードですが、dictに対してもmap関数がしようできるということが分かりましたか。



まとめ


map関数は配列などのイテラブルのすべての要素に対して関数を適応させたいときに有効であることが分かりました。

また、map関数はlambdaと組み合わせることでコードをさらにシンプルにさせることが可能です。

labbdaの使い方については以下で紹介しているので興味のある方は読んで見てください。






120777_s


FODでもドラマ化されたいぬじゅんさんの『いつか、眠りにつく日』を読みました。

結末が予想外でかなり面白かったし、強く生きようと感じさせる作品でした。

以下、あらすじと感想を書いていきます。



『いつか、眠りにつく日』のあらすじ


高校2年生の女の子・蛍は修学旅行の途中、交通事故に遭い命を落としてしまう。

命を落としてから約一か月後、蛍が自宅で目を覚ます。彼女の前に死者の案内人であるクロが現れる。

クロはこの世に残した未練を3つ解消しなければ、蛍が成仏できないことを告げる。

蛍は、自分の未練のひとつが中学のころから5年間片想いしている蓮に告白することだと気づいていた。

だが、蓮を前にすると、告白することで関係が崩れてしまうことを恐れ、どうしても想いを伝えられない・・・。

2つの未練を解消し、蓮に告白する決心ができた蛍の決心の先にあった秘密とは…。

予想外のラストに、温かい涙が流れるー。



感想(ネタバレあり)


とにかく結末が良かった。

クロ、蓮、栞、祖母の登場人物全員が今後三人を失って生きていく蛍のことを心配していたという結末がすごく良かったです。

実は、生き残っていたのは蛍だけだという結末を知ってしまうと物語の様々なところに伏線がちりばめられていたことが分かりますが、読んでいる途中はこの伏線に全く気が付きませんでした。

蛍の未練が他の死者と違い3つあった理由も、蓮、栞、祖母の未練を解消するためだったと分かったときは、感動しつつ伏線の張り方のうまさに感心してしまいました。


実際に自分が蛍の立場になり、全てを知っている状態でクロに生きるか、みんなと一緒に死ぬか選択しろと言われたらどちらを選んでいたのだろうか。

両親は生きているとはいえ、心から大好きな人たちを同時に失ってしまっていたら、もしかしたら自分ならみんなと一緒に死ぬことを選んだかもしれません。

もし、生きることを選んだとしても意識不明の重体なので、自分の身体がどうなっているのか分からないためこれまで通り生きられない可能性もありますし…。

蛍も皆が行ってしまう直前に以下のようなセリフを言っていました。

「やだ……。私も、みんなと一緒に行く。クロお願い!さっきの取り消す」

『いつか、眠りにつく日』より

このことから蛍も最初から全てを知っていたら、みんなと一緒に死ぬことを選んだということが想像できます。

それを分かっていた蓮、栞、祖母の三人はどうしても蛍に生きていてほしかったから協力したのでしょうね。


蛍が目を覚ました後にクロが記憶を残してあげていた演出も粋だなと感じました。

蛍が今後どんなにつらいことがあったとしてもこのことを思い出して、後悔しないように生きようと思うに違いありません。

若い世代の人ほど後悔しないように人生を謳歌するということに無頓着な気がするので、若い世代の人が読みやすい作品でこのような表現ができるいぬじゅんさんは素晴らしい作家ですね。





まとめ


今回は、いぬじゅんさんの『いつか、眠りにつく日』の感想をお届けしました。

この作品を読んで、私は死ぬときにクロのような案内人が現れてもやることがないと思わせられるぐらい、後悔しない人生を歩んでいきたいと思いました。

この作品を読んだ人には以下の作品もおすすめですので、未読の方はぜひ読んでみてください。











3753817_s


本記事では入力した値以下の素数を出力するプログラムを紹介します。



素数を求めるプログラム


素数とは1と自分以外に約数を持たない数のことです。

2, 3, 5, 7... などが素数になります。

ある値が素数かどうかプログラムで出力するには下記の関数のように、
「2 ~ ある値 - 1」の数までで割り切ることができる数がなければ素数であると判定することができます。

#include <iostream>

using namespace std;

bool isPrimeNum(int num){
    for (int i = 2; i < num; ++i){
        if (num % i == 0){
            return false;
        }
    }
    return true;
}

上記の関数を使い2~入力値まで順番に素数かどうか判定することで、入力した値以下の素数を全て出力することができます。

int main(void){
    int num;
    cin >> num;

    for (int i = 2; i <= num; ++i){
        if (isPrimeNum(i)){
            cout << i << endl;
        }
    }

    return 0;
}





プログラムを高速化する


先ほど紹介したプログラムは計算量がで効率が良いプログラムとは言うことができません。

そこでここでは先ほどのプログラムを高速化していきます。

まずはisPrimeNum関数を最適化しています。

先ほどの
isPrimeNum関数では「2 ~ ある値 - 1」の数までで割り切ることができる数がなければ素数であると判定していましたが、ある値が素数であるかどうか判定するには「ある値未満の素数」で割ることができるか計算するだけで大丈夫です。

なのでisPrimeNum関数を以下のように書き換えてしまいましょう。


bool isPrimeNum(int num){
    static vector primeNumVec = {2};
    for (auto itr = primeNumVec.begin(); itr != primeNumVec.end(); ++itr){
        if (num % *itr == 0){
            return false;
        }
    }
    primeNumVec.push_back(num);
    return true;
}

primeNumVecというベクターに素数と判定した数をため込んで、入力値がprimeNumVecの中の値で割り切れるかどうか判定します。


これだけでも十分早くなるのですが、main関数にも一工夫加えていきます。

素数は2以外の値は全て奇数なので、for文のiを1ずつ増やしてすべての数を見るのではなく、iを2ずつ増やして奇数だけを見るようにしましょう。

int main(void){
    int num;
    cin >> num;

    cout << 2 << endl;
    
    for (int i = 3; i <= num; i+=2){
        if (isPrimeNum(i)){
            cout << i << endl;
        }
    }

    return 0;
}


これで入力した値以下の素数を出力するプログラムを高速化することができました。


最後に


本記事を通して素数を求めるプログラムの作り方が分かりましたか。

他にもプログラムに関する記事を書いていますので興味のある方はぜひ読んでみてください。







3753817_s


本記事では入力した2個の整数から最小公倍数を求めるプログラムを2パターン紹介します。




「共通して割れる数」を探して、最小公倍数を求めるプログラム


最小公倍数を求めるシンプルな実装は共通して割れる数を元に最小公倍数を求める方法です。

入力値が24と36の場合、数のように共通して割れる数がなくなるまで割っていきます。


aa


共通して割れる数がなくなったら外側の数字をかけていきます。

aa


2 × 2 × 3 × 2 × 3 = 72

これにより24と36の最小公倍数は72だと求めることができます。

これをプログラムで実装していくと以下のようになります。 


#include <iostream>

using namespace std;

int main(void){
    unsigned int a, b, tmp;
    cin >> a >> b;
    if (b > a){
        tmp = b;
        b = a;
        a = tmp;
    }

    unsigned int Lcm = 1;
    int i = 2;
    while(b > i){
        if ((a % i == 0) && (b % i == 0)){
            a /= i;
            b /= i;
            Lcm *= i;
            i = 2;
        }
        else{
            i++;
        }
    }

    Lcm = Lcm * a * b;
    cout << Lcm << endl;

    return 0;
}





最大公約数から最小公倍数を求めるプログラム


上記の方法だとどうしても計算量が多くなります。

そこでここでは、ユークリッド互除法で最大公約数を求めてから、それをもとに最小公倍数を求める方法を紹介していきます。

入力値をaとb、aとbの最大公約数をrとすると最小公倍数は以下の式で求めることができます。


最小公倍数 = a × b ÷ r



ユークリッド互除法については以下の記事で紹介しているので参考にしてください。




最大公約数から最小公倍数を求めるプログラムは以下のとおりです。

#include <iostream>

using namespace std;

int calGcd(int a, int b){
    int tmp;
    if (a < b){
        tmp = b;
        b = a;
        a = tmp;
    }

    while(b != 0){
        tmp = b;
        b = a % b;
        a = tmp;
    }

    return a;
}

int main(void){
    int a,b,gcd, lcm;
    cin >> a >> b;
    
    gcd = calGcd(a, b);
    lcm = a * b / gcd;

    cout << lcm << endl;

    return 0;
}



最後に


本記事をとおして、最小公倍数を求めるプログラムの作り方が分かりましたか。

シンプルに「共通して割れる数」をもとに最大公約数を求める方法もいいですが、ユークリッド互除法で最大公約数を求めてから最小公倍数を求めることで計算量を減らすことができます。

プログラミングになれてきましたらぜひ計算量の小さいコーディングを意識していきましょう。




↑このページのトップヘ