雑記

ものを書く練習。学びをまとめる場。

Chromiumを手探る

思いつき

シークレットウィンドウって便利ですよね。

でもあれなんでウィンドウしかないんでしょうね。タブごとにモード切り替えとかできたら便利だろうに。


ということで、chrome code searchを用いてソースを探って弄って、chromiumにそんな機能を搭載してみようじゃないか、という初心者の無謀なチャレンジです。1

(GDBとかでデバッグしようとしたり、XCodeで追っかけたりしようかと思ったが無理だった。XCodeに至ってはなぜかbuildもできなかった。つらい)


codeをひたすら追ってみる

まずは「とりあえずwindowかtabをopenするのに関連してる関数を見つけてそれを追っていけばなんか見つかるやろ」作戦です。2 いやいやこれがつらいのなんのその。

適当に "new_window command" とかで検索かけると/src/chrome/app/chrome_command_ids.h L.31 からそれっぽいものが見つかりました。

 // Window management commands
#define IDC_NEW_WINDOW                  34000
#define IDC_NEW_INCOGNITO_WINDOW        34001

/src/chrome/browser/app_controller_mac.mm L.1046 から

switch (tag) {
    case IDC_NEW_TAB:
      // Create a new tab in an existing browser window (which we activate) if
      // possible.
      if (Browser* browser = ActivateBrowser(lastProfile)) {
        chrome::ExecuteCommand(browser, IDC_NEW_TAB);
        break;
      }
      FALLTHROUGH;  // To create new window.
    case IDC_NEW_WINDOW:
      CreateBrowser(lastProfile);
      break;

まずはTABについて見てみます。
ActivateBrowser(lastProfile) について/src/chrome/browser/app_controller_mac.mm L.138にて

Browser* ActivateBrowser(Profile* profile) {
  Browser* browser = chrome::FindLastActiveWithProfile(
      profile->IsGuestSession() ? profile->GetOffTheRecordProfile() : profile);
  if (browser)
    browser->window()->Activate();
  return browser;
}

ExecuteCommand(browser, IDC_NEW_TAB) について
/src/chrome/browser/ui/browser_commands.cc L.336にて

bool ExecuteCommand(Browser* browser, int command) {
  return browser->command_controller()->ExecuteCommand(command);
}

command_updater_impl.h のL.34に
// Overriden from CommandUpdater: 
とあったので見てみると、L.40にて

bool CommandUpdaterImpl::ExecuteCommand(int id) {
  return ExecuteCommandWithDisposition(id, WindowOpenDisposition::CURRENT_TAB);
}

ExecuteCommandWithDisposition(id, WindowOpenDisposition::CURRENT_TAB) について
/src/chrome/browser/ui/browser_command_controller.cc L.288にて

bool BrowserCommandController::ExecuteCommandWithDisposition(
    int id, WindowOpenDisposition disposition) {

すると同じソースにswitch(id)から

L.340

 // Window management commands
    case IDC_NEW_WINDOW:
      NewWindow(browser_);
      break;
    case IDC_NEW_INCOGNITO_WINDOW:
      NewIncognitoWindow(browser_);
      break;

とか

L.351

  case IDC_NEW_TAB: {
      NewTab(browser_);

を発見。ようやくそれらしいものを見つけました。
おそらくbrowser_というのはWindowOpenDisposition dispositionで指定されたWindowOpenDispositonの二個上のclass(?)を表しているっぽいですね。
とりあえずWindowについて、/src/chrome/browser/ui/browser_commands.cc L.576にて

void NewWindow(Browser* browser) {
  NewEmptyWindow(browser->profile()->GetOriginalProfile());
}

"NewEmptyWindow"で検索をかけると/src/chrome/browser/ui/browser_commands.cc L.382にて

void NewEmptyWindow(Profile* profile) {
  bool incognito = profile->IsOffTheRecord();
  PrefService* prefs = profile->GetPrefs();
  if (incognito) {
    if (IncognitoModePrefs::GetAvailability(prefs) ==
          IncognitoModePrefs::DISABLED) {
      incognito = false;
    }
  } else if (profile->IsGuestSession() ||
             (browser_defaults::kAlwaysOpenIncognitoWindow &&
              IncognitoModePrefs::ShouldLaunchIncognito(
                  *base::CommandLine::ForCurrentProcess(), prefs))) {
    incognito = true;
  }

  if (incognito) {
    base::RecordAction(UserMetricsAction("NewIncognitoWindow"));
    OpenEmptyWindow(profile->GetOffTheRecordProfile());
  } else {
    base::RecordAction(UserMetricsAction("NewWindow"));
    SessionService* session_service =
        SessionServiceFactory::GetForProfileForSessionRestore(
            profile->GetOriginalProfile());
    if (!session_service ||
        !session_service->RestoreIfNecessary(std::vector<GURL>())) {
      OpenEmptyWindow(profile->GetOriginalProfile());
    }
  }
}

Browser* OpenEmptyWindow(Profile* profile) {
  Browser* browser =
      new Browser(Browser::CreateParams(Browser::TYPE_TABBED, profile, true));
  AddTabAt(browser, GURL(), -1, true);
  browser->window()->Show();
  return browser;
}

これやん。やったぜ。 この枠組みをopen tabみたいなところに流用すればいいのでは? ということで今度はtabの方を見てみます。

"NewTab"で検索をかけると、すこし関係なさそうではあるのですが、いろんなタブの開き方をまとめているような感じのソースを見つけました。(上の方にAddTabTypesとか書いてる)
/src/chrome/browser/ui/tabs/tab_strip_model.h L.101にて

  // Enumerates different ways to open a new tab. Does not apply to opening
  // existing links or searches in a new tab, only to brand new empty tabs.
  enum NewTab {
    // New tab was opened using the new tab button on the tab strip.
    NEW_TAB_BUTTON,

    // New tab was opened using the menu command - either through the keyboard
    // shortcut, or by opening the menu and selecting the command. Applies to
    // both app menu and the menu bar's File menu (on platforms that have one).
    NEW_TAB_COMMAND,

    // New tab was opened through the context menu on the tab strip.
    NEW_TAB_CONTEXT_MENU,

    // Number of enum entries, used for UMA histogram reporting macros.
    NEW_TAB_ENUM_COUNT,
  };

同様に検索すると/src/chrome/browser/ui/browser_commands.cc L. 594にて

void NewTab(Browser* browser) {
  base::RecordAction(UserMetricsAction("NewTab"));
  // TODO(asvitkine): This is invoked programmatically from several places.
  // Audit the code and change it so that the histogram only gets collected for
  // user-initiated commands.
  UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_COMMAND,
                            TabStripModel::NEW_TAB_ENUM_COUNT);

  if (browser->is_type_tabbed()) {
    AddTabAt(browser, GURL(), -1, true);
    browser->tab_strip_model()->GetActiveWebContents()->RestoreFocus();
  } else {
    ScopedTabbedBrowserDisplayer displayer(browser->profile());
    Browser* b = displayer.browser();
    AddTabAt(b, GURL(), -1, true);
    b->window()->Show();
    // The call to AddBlankTabAt above did not set the focus to the tab as its
    // window was not active, so we have to do it explicitly.
    // See http://crbug.com/6380.
    b->tab_strip_model()->GetActiveWebContents()->RestoreFocus();
  }
}

共通なのはAddTabAt()なのでここを見ればいいのかも?
とりあえず現時点の動作としては、
・windowを開くときにincognitoかどうか判断
→profileを決定 (GetOffTheRecordProfile()かGetOriginalProfile()か)
→OpenEmptyWindowの中でBrowser *browserを決定 (引数にprofileあり)
→AddTabAt(browser, GURL(), -1, true)でTabが作られてshow();で多分Tabが表示

・tabを開くときはprofileがwindowと違いprofileについてincognitoかどうか判定がない
→なぜならwindowを開く時点(NewEmptyWindow())でincognitoの値を決定しているから
→ならばtabを開くときにNewEmptyTab()みたいな関数を入れてincognitoの判定をtab作成のステップに移せばいけるのでは

まとめ

ソースを見る限り意外と実装は簡単そう...?
だが現実はそんな甘くないんだろうな、と想像しつつ次回へ続きます。


  1. 実は大学の後期実験 大規模ソフトウェアを手探る だったりします。

  2. これペアプログラミングなんですが相方は真面目に起動時からデバッガで追跡してました。ほんますまん。

overleafのテンプレート設定

はじめに

資料やレポートを PDF にまとめるときに LaTeX を利用される方も多いと思います。

LaTeX は数式などを含む資料でも綺麗に表示してくれるツールです。
別に Microsoft Word でも資料作りには困らないとは思うのですが、個人的には LaTeX を利用した PDF 作成の方が期待した通りに整頓できるため好みです。軽いし。

そんな LaTeX ですが、何が面倒って環境を構築する過程なんですよね。
私の場合は特に、やる気がわいたときに所持している端末でレポートを書いたりしているので、複数端末で環境を構築する必要があり尚更面倒でした。
そうでなくても、PC を買い替えた場合など環境構築をやり直す必要があったりと、地味に面倒。

そんな面倒くさがりのために、オンライン上で LaTeX 編集ができるツール overleaf があります。
私もこの overleaf を利用しているのですが、慣れるまで日本語入力での資料作成に手間取っていたので、個人的におすすめの設定・テンプレートのつくり方をお伝えしたいと思います。

*英語設定で利用しているため、以下で述べる機能の名称が異なる可能性が大いにあります。ご了承ください。

テンプレートプロジェクトの作成

まず初めにテンプレートプロジェクトを作成します。
以下、手順を説明します。気に入らない部分は適宜アレンジしてください。

0. プロジェクトの作成

リンクからサインアップをした後は、左上から新しいプロジェクトを作成します。
今回は全てのプロジェクトの基本となるテンプレートを作成するので「テンプレート」とでもしておきましょう。

1. コンパイラの変更

初期設定ではコンパイラが pdfLaTeX になっているため日本語対応していません。
そのため、左上の「メニュー」から「設定」「コンパイラ」を "XeLaTeX" に変更しましょう。
それ以外の設定は特に触れなくて大丈夫です。

2. main.tex の作成

おそらく初めから main.tex というファイルが存在していると思います。
この中身を以下のようにしてください。

\documentclass[11pt]{article}
\usepackage[top=15mm, bottom=15mm,right=15mm,left=15mm]{geometry}
\usepackage{graphicx}
\usepackage{xeCJK}
\setCJKmainfont{IPAMincho}
% \setCJKsansfont{IPAGothic}
% \setCJKmonofont{IPAGothic}


\title{template}
\author{name}
\begin{document}

\maketitle

\section{}

% \includegraphics[width=\textwidth]{ファイル名}

% \begin{verbatim}
% このテキストは、別のフォントを持つことになります

% This is a verbatim environment with mono-space font
% \end{verbatim}


\end{document}

簡単に内容を説明すると、

  • 「%」がある行はコメントアウトしている
  • 「graphicx」パッケージで図の挿入が可能に
  • 「includegraphics」で実際に図を挿入(コメントアウト
  • 「xeCJK」パッケージで中国語・日本語・韓国語の字が利用可能に
  • 「setCJKmainfont」で本文のフォントを選択
  • 「setCJKmonofont」で「verbatim」タグで囲まれた部分のフォントを変更できる(コメントアウト

みたいな感じです。
残りの部分は本当に好みなので、適宜ググりながら良いと思うレイアウトを探していくのがいいと思います。意外と楽しいし。

3. ディレクトリ fig の作成

別にこれは無くてもいいのですが、プロジェクトのルートディレクトリに図が散らばっているのがうざかったので、私は図を入れるためのディレクトリ fig を作成してその中にまとめています。

例えば、ディレクトリ fig の中に入っている sample.png というファイルを挿入したければ

\includegraphics[width=\textwidth]{fig/sample.png}

と書けば挿入されます。

ちなむと、この \textwidth というコマンド。これが結構便利で、大きめのスクショなど貼るときにはとりあえずこれ指定しとけば綺麗にしてくれる感覚があります。
もちろん \centering するなど、図のサイズに合わせて適宜調整してください。

4. プロジェクトの生成

以上でテンプレートプロジェクトの作成は終了なので、あとはこれをどうコピーするかです。

私が軽く探した限りでは、新規プロジェクトを作成するときに自身で作成したテンプレートプロジェクトを利用する、みたいなやり方が見つかりませんでした。
どなたか詳しい方がいらっしゃれば教えてください。

ですので、私は少々面倒ですが以下の手法を取っています。

  1. まず新規プロジェクトの作成を行うのではなく、テンプレートプロジェクトを開く
  2. その後、左上の「メニュー」から「プロジェクトのコピー」を行う

あとは適当に名前をつければ完成です
少し手間ですが、いちいちテンプレートの内容をクリップボードにコピーして、みたいなことをするよりかは遥かに楽になりました(経験談)。

おわりに

一時期は迷走して markdown から pandoc で PDF に変換して、とかやってましたが普通に overleaf が楽なので気に入ってます。

ちなみになんで XeLaTeX を使っているかなんですが、よくある latexmkrc を作成するやり方では図の挿入が上手くいかなかったんですよね...
結局、図を挿入したいときにコンパイラを XeLaTeX に変更するのであれば、初めから全部 XeLaTeX にすればよくね?という安直思考です。

overleaf で躓いている方の一助になれば幸いです。

参考

Japanese - Overleaf, オンラインLaTeXエディター
Overleaf v2 で日本語を使用する方法

折り紙

はじめに

皆さんは子供のころに折り紙に勤しんだことはあるでしょうか。
私は小学生のころにやった記憶がおぼろげにあるようなないような...

この折り紙、日本で昔から非常に多くの人に親しまれてきた文化ですが、 真剣に向き合ってみると非常に奥が深く、惹き込まれてしまいました。

そこで、私が感じた折り紙の魅力を皆さんにお伝えします!

いくら折り方を学んだとしても実際折ってみないと分からない部分も多いので、 ひとつテーマを設けて作品を作成していく過程とともに、そこで用いられている技術や考え方を説明していきたいと思います。

*本記事では折り紙の展開図がいくつか出てきますが、基本的に赤線が山折り・青線が谷折りを表しています。

この記事を作成するにあたり、大部分で三谷純先生の折り紙研究ノートを参考にさせていただきました。
折り紙に魅力を感じた方は、三谷先生のHP1からより深く学ばれると良いと思います!

今回の目標

折り紙にも色々芸術作品が存在すると思いますが、素人が挑戦するものはそこまで高度ではなさそうな物が良いな、ということで

照明のカバー作り

に挑戦していきたいと思います。 折り紙単体で物を作るのではなく日用品とコラボさせることで、具体的に作りたいものが見えてくるのでは、というアプローチです。

ただ、自分の部屋のメインの電灯のカバーを折り紙で作るのはちょっと大きすぎる気が...
自信がなかったので今回はこちらのデスクライトのカバーを作っていきます。

f:id:RHys:20200731142954j:plain

吉村パターン

まず1つめでは吉村パターンをそのまま利用してみました。

吉村パターンとは、円筒をつぶしたときに現れるパターンと同じ構造を持ったパターンです。
具体的に言うと、某氷が結ばれている缶チューハイの表面にある柄のやつです。 (ダイヤカット缶)

展開図は下の図のように、これを丸めた立体がその次の図のようになります。

f:id:RHys:20200731180611j:plain

f:id:RHys:20200731145311j:plain

非常にシンプルながら、私のような折り紙素人にはこれですら新鮮な感じがします。 というのも私は折り紙と聞くと、平らに折って平坦に何かの形をつくるものをイメージするし、立体的なものといっても「四つ折りにしたものを三角に開く」くらいしか知らなかったからです。

各正方形の四辺が凸に、曲がる方の対角線が凹になることで、外観は円筒のままに各カーブを角張ったものにさせられる。 このようなアイディアが、しかもこんなにシンプルな展開図で表されるのは非常に面白いですね!

さて、ではこれをデスクライトにはめてみるとどうなるでしょうか。

f:id:RHys:20200731145321j:plain ...。
とりあえず、補助線が非常にダサいですね...
あとは、立体的過ぎてこのタイプのライトカバーには合わないような気がします。

次、いきましょう。

蛇腹折り

続いて、皆さんもご存じだとは思いますが、蛇腹折りに挑戦します。
といっても蛇腹折りとはジグザクに折るだけなので、サクッと作ってカバーとして使ってみたいと思います。

f:id:RHys:20200731180450j:plain

まあ、そうなりますよね、って感じです。
敗因は、筒状でないので垂れ下がって蛇腹でなくなってしまうことでしょう。

であれば蛇腹自体を折ってしまえば良いのでは。
ということで、用意しましたのはこちら。

f:id:RHys:20200731180443j:plain

まあ単に蛇腹を折り返しただけなんですが。

ただ、この展開図を見ていただくと非常に面白い性質が発見できます。

f:id:RHys:20200731180748j:plain

各頂点に着目すると、そこから伸びている辺で山折りの数が3つ・谷折りの数が1つと数が異なります。
吉村パターンの展開図を見てもらうと、同じく各頂点で山折り・谷折りの数が異なりますよね。
これはどうして発生するのでしょうか。

これは私の考察なので誤りがあれば教えていただきたいのですが、私はこの理由を「面を頂点にしているから」だと考えました。
例えば皆さん、手ごろな紙を四つ折りにしてから開いてみてください。
その真ん中の折れ線がクロスしている点を見ると、山折り・谷折りの数が異なりませんか?
これを拡張すると、一枚の紙の四辺を含まない領域内の任意の点を「折る」という動作のみで頂点にしようとすると、開いたときに必ず山折りと谷折りの数の差が2になるという性質があると考えられます。
面が頂点になった後は、その点は頂点であるので面という属性から外れるため、それ以上は増えないのでは、と。

これをさらに掘り下げて、今度はn枚の重なりがある状態での考察などを進めていくのも楽しそうですが、これ以上は幾何学の素人が進むべき領域ではないような気もするので、

閑話休題。上の考察が気になった人は ”前川定理” を調べてみるといいんじゃないでしょうか。

では、実際に蛇腹を折り返したものをライトカバーにしてみましょう。
こんな感じになりました。

f:id:RHys:20200731180427j:plain

意外といい感じかも...? 少なくとも私は気に入りました。

平折り(ねじり折り)

最後に、自分の全く知らない技術としてねじり折りに挑戦しました。
ねじり折りは平折りの一種で、言葉通り紙をねじるように折りたたむ折り方の一種です。

まずはオーソドックスな、正方形を基本としたねじり折りを紹介します。
といっても私が挑戦してみて感じたのは、これこそ自分で折ってみないとわからないな、と。

というわけで三谷先生の折り紙研究ノートの図を引用させていただいて、これを見て折ってみてください。
なぜかちょっと気持ちいいと思います。

f:id:RHys:20200731180429j:plain

作った方は、ねじれた正方形が後ろに来るようひっくり返して見てください。
4つの長方形が重なり合っているようになってますよね。
これは、はじめに紙の真ん中に書いた正方形が奇麗に真ん中にあるから裏面も中心が揃うそうです。

では、真ん中の正方形を少し傾けて折るとどうなるのでしょうか?
また、一枚の紙で複数のねじり折りを行いたい場合はどのようにするのでしょうか?

詳細は三谷先生の折り紙研究ノートに分かりやすく書かれているのでそちらをお読みください。

というわけで、これらを組み合わせて実際に折ったものがこちらです。

f:id:RHys:20200731180909j:plain

本当に何かの模様でありそうなパターンが折れてしまいました...感動。
一応展開図も載せておくと、

f:id:RHys:20200731181013j:plain

このレベルで不器用な私にはとてつもなくきつかったです。(約四時間の格闘)


で、本題です。
こんなに頑張って作った模様ですが、ライトカバーとして合わなければなんの意味もない...!!

気合を入れて(?)ライトにつけてみると

f:id:RHys:20200731180434j:plain

良い!!
もともとの模様もきれいですが、光にあてると陰影が出てより奇麗になりますね...

努力が報われて嬉しいです。

まとめ

紙って良いですね。

普段は紙使いを全くやめてしまった自分ですが、こうして紙に直接触れ1つの作品を作る過程を通じて、紙でのものづくりに芽生えてしまいそうな気がしています。

さて、この記事をなんの迷いか読んで、紙でのものづくりに興味がわいた方はぜひ、さまざまな折り紙に挑戦して自分の制作を楽しんでください!

あぁ、片づけるのが惜しいなぁ...


おまけ:コンピュータ折り紙

実はねじり折りに挑戦した後、コンピュータ折り紙を利用してもう1作品挑戦する予定でしたが、ソフトウェア対応OSを所持しておらず断念...
代わりに紹介だけしておきます。

私が利用しようとしていたのはORI-REVOというソフトウェアです。
これまた三谷先生が開発されたソフトウェアです。

このソフトウェアでは回転体の輪郭線を入力することで、回転により作成できる立体とその展開図を表示してくれます。
私も利用できていないので詳細は分かりませんが、デモ動画を見る限りでは様々なパターンの立体が作成できるようです。(デモ動画もORI-REVOのHPにあります)
また、展開図はdxfやpdfで保存できるため、そのまま印刷することも、少しアレンジをしてから印刷することもできます。

非営利目的であれば個人使用は自由とおっしゃっているので、興味ある方で利用できる方は一度チェックしてみると良いのではないでしょうか。

paizaスキルチェックをやってみた

おはようございます。今日はコーディングの日です。

先日教えてもらった「paizaスキルチェック」というものをやってみました。

できそうで出来ないという。。。

ちなみに自分はまともに書けるのがC言語くらいなのでCで挑戦しています。

A009:ビームの反射

下みたいなコードを書いたのですが80点しかもらえませんでした。なんでだ。。。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define OUT 0
#define IN 1
#define RIGHT 2
#define UP 3
#define LEFT 4
#define DOWN 5

int main(void)
{
    // 自分の得意な言語で
    // Let's チャレンジ!!

    char str[1000];
    char *tp;
    int H, W;
    fgets(str, sizeof(str), stdin);
    tp = strtok(str, " ");
    H = (int) strtol(tp, NULL, 10);
    tp = strtok(NULL, " ");
    W = (int) strtol(tp, NULL, 10);
    // printf("%d %d\n", H, W);
    
    int i, j;
    char field[H][W];
    for ( i = 0; i < H; i++ ){
        fgets(str, sizeof(str), stdin);
        for ( j = 0; j < W; j++ )
            field[i][j] = str[j];
    }
    
    int count = 1;
    int flag = IN;
    int vector = RIGHT;
    int h = 0; int w = 0; // current position
    while ( flag ){
        switch ( vector ){
            case RIGHT:
                if ( w+1 == W )
                    flag = OUT;
                else if ( field[h][w+1] == '_' ){
                    w++;
                    count++;
                }
                else if ( field[h][w+1] == '/' ){
                    w++;
                    vector = UP;
                    count++;
                }
                else if ( field[h][w+1] == '\\' ){
                    w++;
                    vector = DOWN;
                    count++;
                    // printf("CP:%d %d", h, w);
                }
                break;
            case LEFT:
                if ( w-1 < 0 )
                    flag = OUT;
                else if ( field[h][w-1] == '_' ){
                    w--;
                    count++;
                }
                else if ( field[h][w-1] == '/' ){
                    w--;
                    vector = DOWN;
                    count++;
                }
                else if ( field[h][w-1] == '\\' ){
                    w--;
                    vector = UP;
                    count++;
                }
                break;
            case UP:
                if ( h-1 < 0 )
                    flag = OUT;
                else if ( field[h-1][w] == '_' ){
                    h--;
                    count++;
                }
                else if ( field[h-1][w] == '/' ){
                    h--;
                    vector = RIGHT;
                    count++;
                }
                else if ( field[h-1][w] == '\\' ){
                    h--;
                    vector = LEFT;
                    count++;
                }
                break;
            case DOWN:
                if ( h+1 == H )
                    flag = OUT;
                else if ( field[h+1][w] == '_' ){
                    h++;
                    count++;
                }
                else if ( field[h+1][w] == '/' ){
                    h++;
                    vector = LEFT;
                    count++;
                }
                else if ( field[h+1][w] == '\\' ){
                    h++;
                    vector = RIGHT;
                    count++;
                }
                break;
            default:
                break;
        }
    }
    
    printf("%d\n", count);
    
    return 0;
}

わかったらまたupしようと思います。

レビュー: ぷしゅ よなよなエールがお世話になります

久々の投稿。

今回は勉強の話ではなく、タイトル通りレビューを書きたいと思います!

本の紹介

今回紹介したいのはこの本です。

ぷしゅ よなよなエールがお世話になります

ぷしゅ よなよなエールがお世話になります

よなよなエール」「水曜日のネコ」などを販売・製造しているヤッホーブルーイングの社長が書いた本で、エールビールを日本に普及させるために試行錯誤した話をまとめたビジネス書です。

感想

ビジネス書って聞くと大層なものをイメージするかもしれませんが、この本は他のビジネス書とは違ってすごく読みやすく「てんちょ」の経験が語られています。(「てんちょ」というのは著者井出さんのニックネームです)

もはやビジネス書というよりかは、ノンフィクションの小説、と言った方が伝わりやすいかもしれません 笑

さすがに小説ほど細かくストーリーがあるわけでもなく伏線が散りばめられているわけでもないですが、とにかく「てんちょ」の心が直接伝わってくるような、そんな文体です。

僕自身そこそこ本は読むのですが、ここまで惹きこまれた本は久しぶりでした。1


詳細は語りませんが、この本の中では「てんちょ」が経験から得た教訓をそれぞれの章でテーマに設定しながら、誰にでも伝わるような文章で読者にも大きな説得力を持って伝えてくれます。

例えば「スキルは挑戦しながら身につければいい」「ファンは100人に1人でいい」など、社会に出ていない自分2でさえ生きていく上での教訓となるような。

といっても堅苦しいものではなく、「てんちょ」のストーリーがあるからこそ柔軟に解釈ができて自らの体験に落とし込めやすい、そんな文章です。

読まなければ分からないと思いますし、簡単に読み切れるとも思いますので、是非みなさん読んでみてください!


  1. 「出会い系サイトで70人と実際に会ってその人に合いそうな本をすすめまくった1年間のこと」という本も非常におすすめです。

  2. まだ大学生です。社会に出たいような出たくないような…

配列のポインタについて

int a[10] = {1,2,3,4,5,6,7,8,9,0};
int *p = a;

前提

・aは要素数10の int型配列で、初めから10個 int型を入れるスペースを用意
・pは配列のポインタで、「int型を指すもの」である宣言しかしていない。今回は int型配列のアドレスを代入


printf("a[0]: %d\n",a[0]);     // a[0]: 1
printf("p[0]: %d\n",p[0]);     // p[0]: 1
printf("a: %d\n", *a);         // *a: 1
printf("*p: %d\n",*p);         // *p: 1
printf("&a[0]: %p\n", &a[0]);  // &a: 0x7ffee04b4b40
printf("&p[0]: %p\n", &p[0]);  // &a: 0x7ffee04b4b40
printf("a: %p\n",a);           // a: 0x7ffee04b4b40
printf("&a: %p\n",&a);         // &a: 0x7ffee04b4b40
printf("p: %p\n", p);          // p: 0x7ffee04b4b40
printf("&p: %p\n",&p);         // &p: 0x7ffee04b4b20 (これだけ違う)

a[0] = 10;
printf("a[0]: %d\n",a[0]);  // a[0]: 10
printf("p[0]: %d\n",p[0]);  // p[0]: 10
printf("*p: %d\n",*p);      // *p: 10

p[0] = 100;
printf("a[0]: %d\n",a[0]);  // a[0]: 100
printf("p[0]: %d\n",p[0]);  // p[0]: 100
printf("*p: %d\n",*p);      // *p: 100

わかること

  • *p つまり「ポインタ p が指すもの」は配列の頭の要素 ( この場合だと 1 )
  • 配列のポインタは変数として配列と同様の形 ( この場合だとp[0] ) で入力できる ( *p = p[0] )
  • (ポインタでない)配列についてもポインタと同様の表記で値を返せる、つまり配列名はその配列のアドレスを表す ( a[0] = *a ) ( aはアドレス )
  • p はポインタだから a[0]が変われば p ( しつこいが「ポインタ p が指すもの」) も変わる。逆も然り ( a[0] = p[0] = a = *p )
  • 「ポインタが指すもの」が 配列なだけであって、そのポインタのアドレスと配列のアドレスは異なる ( &a != &p )

html, css, js 初心者がいきなり D3.js に手を出した話

おはようございます。

今日はタイトルの通り D3.js という、情報の可視化に適したライブラリを使う話をしたいと思います!

ただ今回も Chromium を手探ると同じように「javascript ? 聞いたことある」状態からスタートなのでとても苦労ですね...笑1

D3.js とは

D3.js is a JavaScript library for manipulating documents based on data. D3 helps you bring data to life using HTML, SVG, and CSS. D3’s emphasis on web standards gives you the full capabilities of modern browsers without tying yourself to a proprietary framework, combining powerful visualization components and a data-driven approach to DOM manipulation.

以上は公式サイトからの引用です。

端的にいうと、データセットの様々な可視化の為にもの凄い役に立つ js のライブラリってことですね。

以下どんな可視化があるか例をあげますと、

f:id:RHys:20181103075039p:plain

こうやってノードごとの関係を可視化したり、

f:id:RHys:20181103075137p:plain

こうやって地図を色分けしたり、

f:id:RHys:20181103075214p:plain

こうやって頻出ワードを抽出したりすることができます。

すごいですよね。こちらから色々なデモが見られるのでよかったらどうぞ。


それでは次回以降 少しずつ D3.js のお話をしていきますね!


参考

D3.jsの概要と使い所について - Qiita


  1. 察しの良い方ならわかる通り、これも後期実習の一環 情報可視化とデータ解析です

git のキソのキソ 2

おはようございます。今日は寝坊してしまいました...

早起きを習慣化していきたいのですが、前日の夜にこなすタスクがしっかりあるとなかなか難しいですね。

(あと朝起きた時、尋常じゃないほど鬱なのどうにかしたい)

では、前回に引き続き git についてお話ししていきたいと思います!

リポジトリ

前回、git のホスティングサービスを利用してオンライン上に他の人と共有できるディレクトリを作成できることをお話ししたと思います。

この「他の人と共有できるディレクトリ」という表現は、実は間違っているんですよね 笑

どういうことか説明していきたいと思います。

ディレクトリとリポジトリ

そもそも git というのは、少し難しい表現にはなってしまいますが一言でいうと、「分散型バージョン管理システム」です。

どういうことかというと、サーバに Git というアクセスできるデータベースが一つある、というわけではなくて、サーバにも各々のPCにもデータベースが存在している、ということです。

ここでいうデータベースとは、ソースコードなど全てのデータのバージョンを管理・保持しているものを指します。1

データベースが貯蓄されているのが文字通り「リポジトリ」であり、当然のことながら「ディレクトリ」とは全く別物です。
( 筆者はこのことの理解をせずに git を使おうとしてはうまく行かず失敗ばかりしてました )

ここで、サーバにある Git というデータベースのことを「リモートリポジトリ」、各々のPCにある Git というデータベースを「ローカルリポジトリ」と呼びます。

実際の動き

ではどのようにデータがリポジトリに記録されていくのか、仕組みを簡単に説明します。実際に使うコマンドも記載しておきますね。

例えばあるプロジェクトに参加することになり、そのバージョンが git で管理されていたとします。

まずはそのリモートのリポジトリを自分のPCにコピーしてローカルリポジトリを作成します。
コマンド: git clone (リモートリポジトリのurl)

そこには今までにあった変更が全て記載されているので、もちろん自分のPCには今のディレクトリに、そのプロジェクトで作成されたデータと隠しディレクトリとして .git ファイルが存在します。

そのデータに自分が変更を加えたなら、ローカルリポジトリに変更した内容を書き加えます。
コマンド: git add (変更したファイル) 2

さらにリモートリポジトリにその変更を書き加える前に、その変更についてのコメントを書き加えます。
コマンド: git commit -m "こんな変更をしました"

ここまでしたらリモートに push したいところですが、筆者はその前にコンフリクトを起こさない為にも、先にリモートリポジトリの変更をローカルリポジトリに書き加えます。
コマンド: git pull origin master

これが全て確認できてから、リモートに push します。
コマンド: git push -u origin master

まとめ

これが git のキソのキソだと思います。これさえ分かっておけば、とりあえずは困らないかと。

正直これより先の git の基礎の内容は自分もまだ勉強中なので、理解し次第 git シリーズとしてまとめていきたいですね!

参考

まずはGitの仕組みを理解することから - Qiita


  1. もっとわかりやすくいうと、ソースコードが書き換えられたとき「それが変更されたこと」の記録もデータベースの一部です。

  2. git add .で全てのファイルを add できます。