フロントエンドデベロッパーのメモ

スキル: HTML/Jade/Jinja2, CSS/SCSS, JavaScript(ES6), Angular, React,Next, Redux, Node, Express, Python, Flask, Postgres, Redis, MongoDB, Kafka, Knex, SQLAlchemy, React Native, EXPO, GraphQL/Apollo, REST, AWS, Heroku, Docker, CircleCI, SCRUM, XP, Vim, TDD

ハッシュ法 オープンアドレス ダブルハッシング法

ハッシュ法は検索アルゴリズムの一つ。 各データ(keyと呼ぶ)の挿入するべき位置をハッシュ関数を用いて求める。 ハッシュ関数で求めた値、ハッシュ値が配列の挿入するべき位置(インデックス)を示す。

ハッシュ関数 Hash(key)=key mod m ここでmをテーブルサイズとする。

弱点は、ハッシュ関数を用いて求めた値が以前に求めた値と重複する場合がある。 この時に、ダブルハッシュ法を用いる。 ダブルハッシュ法は、ハッシュ関数に一回目のハッシュ値とは別のテーブルサイズmのハッシュ関数を含めた関数 関数は、 H(key) = (h1(k) + j*h2(k))%m ここで、 h1(k) = key mod m h2(k) = 1 + key mod n n: mとは異なる値 j: 1(今回の場合) とする。

また、重複した場合にh1(k)からh2(k)分だけ位置を移動させることになることから、mとh2(k)が互いに素でないと挿入出来ない位置が生じます。これはmを素数としてh2(k)をmより小さい値にすることで回避することができる。

参考資料

Hashing - Double Hashing - YouTube

Double Hashing - GeeksforGeeks

クローラーの写経してみた

前からクローラー作ってみたいなって思ってたけど、なかなか余裕がないし設計アイデアが浮かばなかったからとりあえずググってみたらわかりやすいのが見つかった。 How to make a web crawler in JavaScript / Node.js とりあえず完璧に写経しただけやけど、非常にシンプルで考え方がわかりやすかった。 ここからさらに外部リンクまで検索してくれるようにアップデートしてみたいな。

var request = require("request");
var cheerio = require("cheerio");
var URL = require("url-parse");

var START_URL = "http://www.arstechnica.com";
var SEARCH_WORD = "stemming";
var MAX_PAGES_TO_VISIT = 10;

var pagesVisited = {};
var numPagesVisited = 0;
var pagesToVisit = [];
var url = new URL(START_URL);
var baseUrl = url.protocol + "//" + url.hostname;

pagesToVisit.push(START_URL);
crawl();

function crawl() {
  if (numPagesVisited >= MAX_PAGES_TO_VISIT) {
    console.log("Reached max limit of number of pages to visit.");
    return;
  }
  var nextPage = pagesToVisit.pop();
  if (nextPage in pagesVisited) {
    // We've already visited this page, so repeat the crawl
    console.log("Run the crawler again");
    crawl();
  } else {
    // new page we haven't visited
    console.log("pagesVisited: ", pagesVisited, nextPage);
    visitPage(nextPage, crawl);
  }
}

function visitPage(url, callback) {
  // add page to our set
  pagesVisited[url] = true;
  numPagesVisited++;
  // make the request
  console.log("candidates... ", pagesVisited);

  console.log("Visiting page " + url);
  request(url, function(error, response, body) {
    // check status code (200 is HTTP OK)
    console.log("Status code : " + response.statusCode);
    if (response.statusCode !== 200) {
      callback();
      return;
    }
    // Parse the document body
    var $ = cheerio.load(body);
    var isWordFound = searchForWord($, SEARCH_WORD);
    if (isWordFound) {
      console.log("Word " + SEARCH_WORD + " found at page " + url);
    } else {
      collectInternalLinks($);
      // in this short program, our callback is just calling crawl();
      callback();
    }
  });
}

function searchForWord($, word) {
  var bodyText = $("html > body").text();
  return bodyText.indexOf(word.toLowerCase()) !== -1;
}

// search internal links
function collectInternalLinks($) {
  var relativeLinks = $("a[href^='/']");
  console.log("Found " + relativeLinks.length + " relative links");
  relativeLinks.each(function() {
    pagesToVisit.push(baseUrl + $(this).attr("href"));
  });
}

転職しました!

転職してからしばらく時間が経ったのでダラダラと転職記について更新します。

前回投稿した時は、まだ転職活動中でした。当時は相変わらず転職活動のために面接、コーディングテスト、プログラミングコンテストに参加などして慌ただしい毎日を過ごしていました。 結論から申し上げると、7社から内定を頂くことができ、そのうちの1社であるサンフランシスコ発のIT会社MightyHiveの内定を承諾することにしました!理由はこの会社がAdTech業界の最先端にいること、上司が他の会社(日本企業)に比べてserving managementを意識しており仕事に極力関係のないストレスをためずに効率良く仕事ができそうであること、AdTech業界というまだまだ成長中の業界でエンジニアとしてのキャリアを築くことで業界の最先端に立てる可能性があること(特に日本ではまだまだ若い業界)、アメリカの企業風土を経験できること、海外コミュニティや業界関係者とのネットワーキングができることなどのメリットがあると考えたからです。

毎日激務で仕事の後や週末も勉強することがたくさんありますが、徐々に人脈も形成できており楽しく仕事しています。今後はもう少し気持ちと時間に余裕が出てくるようであれば、Web開発に止まらずハードウェア開発やRTB(Real Time Bidding)のシステム開発、パブリックスピーチやMeetupの開催などにも挑戦してみたいところです。 さらに時間が出来次第、前から習得したかった修士号取得にも挑戦したいところです。

Python error message: There was a problem confirming the ssl certificate: [SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol

ERROR: There was a problem confirming the ssl certificate: [SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol

If you got this error message, update your pip at first. Update pip with curl https://bootstrap.pypa.io/get-pip.py | python

Could not fetch URL https://pypi.python.org/simple/google-cloud-storage/: There was a problem confirming the ssl certificate: [SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version

Why? What's going on? Python org decided to stop supporting TLS, that is, macOS user who use version Sierra or older version needs to upgrade to pip(9.0.3) by yourself.

Reference:

python - 'pip install' fails for every package ("Could not find a version that satisfies the requirement") - Stack Overflow

SeleniumとChromedriverを使ってみた

web developerのJD見てるとわりとSeleniumの使用経験について問われてることが多かったこともあり、前から気になっていました。 Pythonで書きたかったのでSeleniumPython bindingsをインストールしました。 まず最初は pip install selenium しましたが、ここで早速詰まって There was a problem confirming the ssl certificate: とエラーが吐かれてました。 pipのバージョンに関する問題かななどと調べて見ましたがイマイチ適切な原因が見つからなかったのでファイルダウンロードすることにしました。

pypi.org

そしてwebdriverのインストール、webdriverはブラウザと同じpathにないといけない点を気をつけないといけません。 僕の場合は/usr/bin/の直下でした。 ただwebdriverのインストールした時も問題が。 mvコマンド使ってdriverファイルを移動させようとしたものの

mv: rename chromedriver to ../../../usr/bin/chromedriver: Operation not permitted

のメッセージが。 どうやらセキュリティ機能によってSystem Integrity Protectionが発動したことが原因でした。 この辺は「system integrity protection disable」とかググったらmacのサポーターたちが丁寧な回答を出してくれています。 ここまできたらあとは例を試すことができました。

import time
from selenium import webdriver

# Optional argument, if not specified will search path.
driver = webdriver.Chrome('/usr/bin/chromedriver')
driver.get('http://www.google.com/xhtml')
time.sleep(5)  # Let the user actually see something!
search_box = driver.find_element_by_name('q')
search_box.send_keys('ChromeDriver')
search_box.submit()
time.sleep(5)  # Let the user actually see something!
driver.quit()

を走らせた時に自動でブラウザが起動して、検索窓にChromeDriverを打ち込み検索結果を表示その5秒後にブラウザ閉じるという動作をさせますが 今までしたことができるようになるのはやはり楽しいし感動しますね! しばらくSeleniumで遊んでみます。

Reference:

GitHub - SeleniumHQ/selenium: A browser automation framework and ecosystem.

Selenium Client Driver — Selenium 3.14 documentation

Downloads - ChromeDriver - WebDriver for Chrome

system integrity protection disable - Google 検索

「SQL 第2版 ゼロからはじめるデータベース操作」読みました

割と時間に余裕が出てきたから以前から積ん読してたうちの一冊を読みきりました。 SQL 第2版 ゼロからはじめるデータベース操作 この本の良い点は、紹介されたクエリを実際にデータベースを作って試せる点ですね。さらにMySQL, Postgers, Oracle, SQLServerなど多種多様なDBMSに沿った書き方を比べることができるので、それぞれの違いを確認することもできます。

ぼくがこの本読んで新しく発見したことはwindow関数とgroupingの使い方ですね。おそらくweb developerしている限り普段の業務でクエリがっつり書くことがあるのかは知りませんが、まあ知ってるに越したことはないので良い経験になりました。

I just finished reading a book related to SQL. The good points of this book is that you can try queries which you learned with making a database with several DBMS such as MySQL, Postgers, Oracle, SQLServer so that you can find the different styles of writing. What I learned this time is how to use window function and grouping. As long as I work as a web developer, I might not have chances to write complicated qeries. However that was the good chances to expose myself to know these ways of writing queries.

国名しりとり countries' name caterpiller

頭の体操という事でしりとりしました。 問題の条件は以下です。 与えられた国名リストでしりとりをします。最長を求めよ。

const list = [
  "Brazil",
  "Cameroon",
  "Chile",
  "Greece",
  "Uruguay",
  "Italy",
  "France",
  "Bosnia and Herzegovia",
  "Germany",
  "USA",
  "Russia",
  "Croatia",
  "Spain",
  "Australia",
  "Cote D'Ivoire",
  "Costa RIca",
  "Switzerland",
  "Honduras",
  "Iran",
  "Portugal",
  "Belgium",
  "Korea Republic",
  "Mexico",
  "Netherlands",
  "Colombia",
  "Japan",
  "England",
  "Ecuador",
  "Argentina",
  "Nigeria",
  "Ghana",
  "Algeria"
];

function makeLowerCase(countries) {
  return countries.map((elem) => elem.toLowerCase());
}
// make a loop to connect each tale of a word and beginning of a next word as long as possible, if it is not possible to connect from the rest of the list, then finish and push into the empty array.
function findMaximumLength(countries) {
  const result = [];
  const countriesList = makeLowerCase(countries);
  for (let i = 0; i < countriesList.length; i++) {
    const copyList = countriesList.slice();
    copyList.splice(i, 1);
    result.push(search([countriesList[i]], copyList));
  }
  // look for result array and find a maximum
  const sortedlist = result.sort((first, second) => second - first);
  return sortedlist[0];
}

const search = (currentList, candidateList) => {
  for (let i = 0; i < candidateList.length; i++) {
    if (
      currentList.slice(-1)[0][currentList.slice(-1)[0].length - 1] ===
      candidateList[i][0]
    ) {
      currentList.push(candidateList[i]);
      candidateList.splice(i, 1);
      search(currentList, candidateList);
    }
  }
  return currentList.length;
};

console.log(findMaximumLength(list));

答えは8です。 他にもっと簡単に解く方法があるのかもしれませんが、とりあえずこれが思いついたアプローチです。

Exercise time! The restrictions are below. Find the longest length of a caterpillar. I found a recursive way that always iterates through the rest of the countries which have never been selected. However, if there might have other approaches, and in that case please share with me. In addition, the answer is 8.