exit('IN');

本を読んで得た学びとか

【CodeWars】11/8~11/14に解いた問題たち

記事の概要

僕が1週間に解いたCodeWarsのまとめです。
PHP 7.0を使用しています。

Form The Largest

レベル

7kyu

概要

与えられた数字の最も大きい組み合わせを返す。

書いたコード

ソート系の戻り値がbooleanではなく、ソート後の配列だったら一行で書けるのに。

function maxNumber($n) {
  $num_array = [];
  
  $num_array = str_split($n);
  rsort($num_array);
  return (int)implode('', $num_array);
}

Tidy Number (Special Numbers Series #9)

レベル

7kyu

概要

与えられた数字の並びが小→大になっているか調べる。

書いたコード

function tidyNumber($n) {
  $num_array = [];
  $sorted_num = 0;
  
  $num_array = str_split($n);
  sort($num_array);
  $sorted_num = implode('', $num_array);
  return $n == $sorted_num ? true : false;
}

Remove anchor from URL

レベル

7kyu

概要

与えられた文字列(URL)の#以下を除去して返す。

書いたコード

explodeやstrtokで解いている人もいた。

function replaceAll($string) {
  return preg_replace('/#\w*/', '', $string);
}

Row Weights

レベル

7kyu

概要

与えられた配列の数値を交互に別々の変数に足し合わせる。

書いたコード

function rowWeights($arr) {
  $row1 = 0;
  $row2 = 0;
  
  foreach ($arr as $key => $value) {
    $key % 2 == 0 ? $row1+= $value : $row2+= $value;
  }
  return [$row1, $row2];
}

Get the mean of an array

レベル

8kyu

概要

配列の要素の平均値を少数切り捨てで返却する。

書いたコード

function get_average($a) {
  return floor(array_sum($a)/count($a));
}

Maximum Product

レベル

7kyu

概要

配列の隣接する要素同士の掛け算の結果が最も大きいものを返却する。

書いたコード

function adjacentElementsProduct($array) {
  for  ($i = 0; $i < count($array) -1; $i++) {
    if ($max < $array[$i] * $array[$i + 1]) {
      $max = $array[$i] * $array[$i + 1];
    }
  }
  return $max;
}

Is n divisible by x and y?

レベル

8kyu

概要

nをxとyで割り切れるかどうかを調べる。

書いたコード

// return $n % $x == 0 && $n % $y == 0 ? true : false;

if ($n % $x == 0 && $n % $y == 0) {return true;}
  return false;

【CodeWars】11/1~11/7に解いた問題たち

記事の概要

僕が1週間に解いたCodeWarsのまとめです。
PHP 7.0を使用しています。

Reverse words(11/1)

レベル

7kyu

概要

与えられた文字列の単語を逆にして返す。

書いたコード

1回目

function reverseWords($str) {
  $words = [];
  $words = explode(' ', $str);
  foreach($words as &$word) {
    $word = strrev($word);
  }
  return implode(' ', $words);
}

2回目

function reverseWords($str) {
  implode(' ', array_map('strrev', explode(' ', $str)));
}

Substituting Variables Into Strings: Padded Numbers(11/2)

レベル

7kyu

概要

与えられた数字が5桁になるように0で埋める。

書いたコード

sprintfを使って終わり。
最初はprintfを使おうとしていたけど、printfは返り値がintになるから使えなかった。

function solution($value){
  return sprintf("Value is %05d",$value);
};

Cryptanalysis Word Patterns(11/3)

レベル

7kyu

概要

与えられた文字列に番号を割り当てる。同じ文字には同じ番号。

書いたコード

やはりforeachのネストは読み辛い。
foreachの箇所をstr_replaceで書ければだいぶ短くできそう。

function wordPattern($word) {
  $chars = [];
  $alphabet_orders = [];
  $pattern = [];
  
  $chars = str_split(strtolower($word));
  $alphabet_orders = array_flip(array_values(array_unique($chars)));
  foreach($chars as $char) {
    foreach($alphabet_orders as $alphabet => $order) {
      if ($char == $alphabet) {
        $pattern[] = $order;        
      }
    }
  } 
  return implode('.', $pattern); 
}

Fix string case(11/4)

レベル

7kyu

概要

文字列中に含まれる大文字と小文字の数に応じて文字列を変換する。

書いたコード

相変わらずforeachのなかにifを入れてしまっている。
大文字小文字の判定を正規表現でやればもっと簡潔にできた。

function solve($s) {
  $char_array = [];
  $count_upper = 0;
  $count_lower = 0;
  
  $char_array = str_split($s);
  foreach($char_array as $char) {
    if (ctype_upper($char)) {
      $count_upper++;
    } else {
      $count_lower++;    
    }
  }
  return $count_upper > $count_lower ? strtoupper($s) : strtolower($s);
}

String repeat(11/5)

レベル

8kyu

概要

与えられた文字列を指定の数だけ繰り返す。

書いたコード

function repeatStr($n, $str)
{
  return str_repeat($str, $n);
}

Calculate average(11/6)

レベル

8kyu

概要

int型配列の要素の平均を出す。

書いたコード

一発で配列の平均を計算する関数はない?

function find_average($array) {
  return array_sum($array) / count($array);
}

Nth power rules them all!(11/7)

レベル

7kyu

概要

int型の配列の各要素を利用して計算する。

書いたコード

function modified_sum(array $array, int $n): int {
  $answer = 0;
  foreach($array as $num) {
    $answer += $num ** $n;
  }
  return $answer - array_sum($array);
}

【CodeWars】10/25~10/31に解いた問題たち

Persistent Bugger.(10/25)

レベル

6kyu

概要

与えられた数字の1桁ずつを乗算する。
乗算の結果が一桁になるまで繰り返す。
繰り返した回数を返す。

書いたコード

答えを見てしまった…
はじめに自分で書いたコードはサンプルテストは合格したが、ランダムではうまくいかなかった。
array_productの存在に気づければもっと楽に解けたのに。

unction persistence(int $num): int {
  $count = 0;
  while ($num > 9) {
    $num = array_product(str_split($num));
    $count++;
  }
  return $count;
}

Convert boolean values to strings 'Yes' or 'No'.(10/26)

レベル

8kyu

概要

問題タイトルそのまま。
trueであれば"Yes", falseであれば"No"を返す。

書いたコード

「== true」は別になくてもいいことにあとで気づいた。
簡単な問題ではあるものの、他の人の解答を見ると様々なやり方があるので勉強になる。
ただ、やはりもうちょっと難しい問題を解いた方がいいかも。

function boolToWord($bool){
    return $bool == true ? 'Yes' : 'No';
}

Sum of odd numbers(10/27)

レベル

7kyu

概要

奇数から成るピラミッドのn段目の数の合計を求める。

書いたコード

各段がnの3乗でできているとわかればすぐできた。

function rowSumOddNumbers($n) {
  return pow($n, 3);
}

Pyramid Array(10/28)

レベル

6kyu

概要

n個の1から成る配列をn個作る。

書いたコード

1回目

function pyramid($n) {
  $array = [];
  for ($i = 1; $i <= $n; $i++) {
    $array[] = [];
    for ($j = 0; $j < $i; $j++) {
      array_push($array[$i - 1], 1);
    }
  }
  return $array;
}

2回目
array_fillを使ってもう一度。

function pyramid($n) {
  $array = [];
  for ($i = 1; $i <= $n; $i++) {
    $array[] = array_fill(0, $i, 1);
  }
  return $array;
}

Odd or Even?(10/29)

レベル

7kyu

概要

配列の値の合計が奇数か偶数か判定する。

書いたコード

function odd_or_even(array $a): string {
  if (empty($a)) {
    return "even";
  }
  return abs(array_sum($a)) % 2 == 1 ? "odd" : "even";
}

Valid Spacing(10/30)

レベル

7kyu

概要

文字列の中に不適切な空白(行頭・行末の空白, 連続した空白)が含まれていないかを調べて結果を返す。

書いたコード

行末の^は先に書くのに対し、行末の$は後に書かないといけない。

function valid_spacing($s) {
  return preg_match('/^\s|\s{2,}|\s$/', $s) ? false : true;
}

Dashatize it(10/31)

レベル

6kyu

概要

与えられた数字を「-」で区切る。
ただし、偶数が続く場合は区切らない。

書いたコード

昨日と今日に引き続き正規表現を利用する問題だったため、正規表現への抵抗が無くなった気がする。

function dashatize(int $num): string {
  $array = [];
  preg_match_all('/[02468]{2,}|\d/', $num, $array);
  return implode('-', $array[0]);
}

【CodeWars】10/18 ~ 10/24に解いた問題たち

内容

10/18 ~ 10/24に解いたCodeWarsの問題です。

Complementary DNA(10/18)

レベル

7kyu

概要

与えられた塩基配列の塩基対を返す。(この言葉が生物学的にあってるか不明)
AならT, CならGというふうな感じ。

書いたコード

1回目
長い, 文字列を置換するときはとりあえず配列にする, という固定観念が招いた結果。

function DNA_strand($dna) {
  $complementary_chars = [];

  foreach (str_split($dna) as $char) {
    switch ($char) {
      case "A":
        $complementary_chars[] = "T";
        break;
      case "T":
        $complementary_chars[] = "A";
        break;
      case "C":
        $complementary_chars[] = "G";
        break;
      case "G":
        $complementary_chars[] = "C";
        break;
    }
  }
  return implode($complementary_chars);
}

2回目 一番評価が高かった解答のまね。
strtrって便利なものがあるとは。
文字列置換の関数があることは知っていたけど、文字列の各文字に対して置換ができるのはわかっていなかった。

function DNA_strand($dna) { 
  return strtr($dna, "ACGT", "TGCA");
}

Simple Fun #176: Reverse Letter (10/19)

レベル

7kyu

概要

与えられた文字列からアルファベットを抜き出して逆順にして返す。

書いたコード

1回目
正規表現の否定形を知らず、一度アルファベットを抜き出して連結した。

function reverseLetter($str){
  $alphabets = [];
  preg_match_all("/[a-zA-Z]*/", $str, $alphabets);
  return strrev(implode('', $alphabets[0]));
}

2回目
^ キャレットを用いてアルファベット以外を除去したことでコード量が減った。

function reverseLetter($str){
  return strrev(preg_replace("/[^a-zA-Z]/", '', $str));
}

A Needle in the Haystack(10/20)

レベル

8kyu

概要

配列の中から"needle"の位置を見つける。 found the needle at position [needleの位置]という形で返却する。

書いたコード

array_searchの結果を文字列連結すれば一行でかけた。

function findNeedle($haystack) {
    $key = array_search('needle', $haystack);
    return "found the needle at position $key";
}

String Task(10/21)

レベル

7kyu

概要

与えられた文字列を以下の条件で加工して返す。 - 母音の削除 - 全て小文字にする - それぞれの文字の前に '.' をつける

書いたコード

他の人は、prg_replace一行で書いていた。

function string_task(string $string): string {
  $vowels = ['a', 'o', 'y', 'e', 'u', 'i'];
  
  $string = str_replace($vowels, '', strtolower($string));
  if ($string) {
    return '.' . implode('.', str_split($string));
  }
  return "";
  
}

Two to One(10/22)

レベル

7kyu

概要

2つの文字列から重複を無くし、アルファベット順に並べ替えて一つの文字列にして返す。

書いたコード

count_chars(, 3)を使えば一発でいけるようです。
なんでソート系の関数って戻り値がbooleanなんでしょうか?
戻り値をbooleanと配列で選べたら、もっと使いやすいような気がするんですが。

function longest($a, $b) {
  $array = str_split($a . $b);
  sort($array);
  return implode('', array_unique($array));
}

Numbers in strings(10/23)

レベル

7kyu

概要

文字列に含まれる最も大きい数字を返す。

書いたコード

1回目
ユニークにする必要なかった。

function solve($s) {
  $numbers_array = [];
  
  preg_match_all('/[0-9]*/', $s, $numbers_array);  
  return max(array_unique($numbers_array[0]));
}

2回目
array_uniqueを省略。
また、正規表現も[0-9]* から \d+に変更した。 +にしてしまったけど、数字が全部一桁なら動かなくなるか…?

function solve($s) {
  preg_match_all('/\d+/', $s, $numbers_array);
  return max($numbers_array[0]);
}

Growth of a Population(10/24)

レベル

7kyu

概要

何年で人口が基準を超えるかを返す。

書いたコード

function nbYear($p0, $percent, $aug, $p) {
    $year = 0;
    while($p0 < $p) {
      $p0 = $p0 + $p0 * ($percent * 0.01) + $aug;
      $year ++;
    }
    return $year;
}

【CodeWars】10/11~10/17に解いた問題たち

記事の内容

10/11~10/17にCodeWarsで解いた問題と僕の解答を載せています。
使用言語はPHPです。(たまに違う言語も使うかも?)

Invert values (10/11)

レベル

8kyu

概要

配列の正の数を負に, 負の数を正にして返却する

書いたコード

1回目

function invert(array $a): array {
  
  $array = [];
  
  foreach ($a as $num) {
    $array[] = -$num;
  }
  
  return $array;
}

2回目

function invert(array $a): array {
  return array_map(function ($n) {return -$n;}, $a);
}

コードの解説

1回目は関数を使わずに解いた。 2回目は、array_mapを使った。
どちらのほうが読みやすいだろうか?


Shortest Word (10/12)

レベル

7kyu

概要

文字列中の最も短い単語の文字数を見つける。

書いたコード

1回目
正直かなり悪いコードだと書いてて感じた。 特に$shortest_lengthが…

function findShort($str){
  $array = [];
  $length = 0;
  $shortest_length = 999;
  
  $array = str_word_count($str, 1);
  foreach ($array as $word) {   
     $length = strlen($word);
    
    if ($shortest_length > $length) {
      $shortest_length = $length;
    }
  }
  
  return $shortest_length;
}

2回目 他の方の解答を見て真似をした。
array_map関数は便利。

function findShort($str){
  $length = array_map('strlen', str_word_count($str, 1));
  return min($length);
}

Two Oldest Ages (10/13)

7kyu

概要

配列の1番目と2番目に大きい値を返す

書いたコード

rsortの第2引数のSORT_NUMERICは必要なかったみたい。
returnの箇所はarray_sliceでやってる人もいた。
個人的には今回のように直接指定した方が1番目と2番目をreturnしているとわかる気がする。
array_sliceに慣れてないだけだろうか。

// Return the two oldest/oldest ages within the array of ages passed in.
function twoOldestAges($ages) {
  rsort($ages, SORT_NUMERIC);
  return [0 => $ages[1], 1 => $ages[0]];
}

Ones and Zeros (10/14)

レベル

7kyu

概要

0, 1から構成される配列から2進数の値を返す

書いたコード

1回目

function binaryArrayToNumber($arr) {
  $sum = 0;
  $array_length = count($arr);
  
  foreach ($arr as $binary) {
    if ($binary == 1) {
      $sum  += pow(2, $array_length - 1);
    }
    $array_length -= 1;
  }
  
  return $sum;
}

2回目
他の人の解答を真似しました。
こんなに短くかけるんですね。
bindecという関数があると知れて非常に勉強になりました。

function binaryArrayToNumber($arr) {
  return bindec(implode('', $arr));
}

Descending Order (10/15)

レベル

7kyu

概要

数字を大きい順に並べ替える

書いたコード

特に難しいということもなく。
戻り値がintになっているから、returnするときにキャストした方が確実だと思う。

function descendingOrder(int $n): int {
  $numbers = [];
  
  $numbers = str_split("$n");
  rsort($numbers);
  return implode('', $numbers);
}

The iccanobiF Sequence (10/16)

レベル

7kyu

概要

与えられた数だけフィボナッチ数列の配列を作る。
作った配列を逆順にして返す。

書いたコード

forとswitchを使ったので縦に長くなってしまった。
ただ、個人的には短く書くよりもこのぐらいの方が理解しやすいんじゃないかと思う。

function iccanobif($n) {
  $fib = [];
  
  for ($i = 0; $i < $n; $i++) {
    switch ($i) {
      case 0:
        $fib[] += 1;
        break;
      case 1:
        $fib[] += 1;
        break;
      default:
        $fib[] = $fib[$i - 1] + $fib[$i - 2 ];
        break;
    }
  }
  return array_reverse($fib);
}

Pairs of integers from m to n (10/17)

レベル

7kyu

概要

与えられた2つの数 (m, n)が与えられたとき、mからnまでの数のペアを過不足なく作る
(上手く言語化出来ない…)

書いたコード

正直すごく見辛い。
変数の名前の付け方・ループのネストが原因。
再帰処理を行うのが良いのかもしれない。

function generatePairs($m,$n){
  $pairs = [];

  for ($i = $m; $i <= $n; $i++) {
    for ($j = $m; $j <= $n; $j++) {
      $pairs[] = [$i, $j];
    }
    $m++;
  }
  return $pairs; 
}

1週間の振り返り

ほぼ7kyu。
6kyuや5kyuは朝の時間でちょこっと特にはまだ厳しいかも。

改善点 - 一行空ける箇所を統一する - 変数名は$arr, $strではなく適切な名前をつける(ただ問題文が元々そういう名前をつけている場合もある)

「マンガでわかるデータベース」を読んだ

www.ohmsha.co.jp

なぜ読んだか

業務でMySQLを使ってはいるものの、体系的に学んだことがなかったため読んでみました。 結論から言うと、読んでよかったと思います。

学んだこと


2章 リレーショナルデータベースって何だろう?

演算

射影, 選択, 結合などはもちろん知っていたが、直積や商などの演算は聞いたことはあったが理解はしていなかった。

  • 直積:2つの表のレコードの組み合わせ これはすぐ理解できた。
  • 商:割られる方の表から、割る表のすべての行を取り出し、割る方の行を除く らしい。   

3章 データベースを設計しよう

正規化

正規化はなんとなく理解した気にはなっているものの、自分の言葉で説明するとなると難しい。

  • 非正規形:繰り返しが排除されていない表 1つの項目に複数の値が入っている。
  • 第一正規形:繰り返しが排除されるように別の表に分割するした状態
  • 第二正規形:主キーによって他の列の値が決まる(関数従属)ように表を分割した状態
  • 第三正規形:間接的に値が決まる(推移従属)部分がなくなるように表を分割した状態

4章 データベースを利用しようーSQLの基本操作

相関副問い合わせ correlated subquery

副問い合わせ外で指定された表を副問い合わせ内で用いる。
これは初めて知った。
ややこしく感じるが、上の言葉のとおり副問い合わせに副問い合わせ外の情報を使うというもの。

5章 データベースを運用しよう

ACID属性

基本情報の午前問題でちょろっと出てくるやつ。という印象だった。

その他、時刻印制御や楽観的制御といった同時実行制御の方法, ダーティーリードやノンリピータブルリート, ファントムなどの独立性のレベルなど知らないことも多かった。

6章 データベースの普及と活躍

分散データベース

  • 水平分散:複数の対等なデータベースサーバーを用いる。どれかのDBサーバーに障害が起きても、DBを稼働させることが可能。
  • 垂直分散:中心的な役割を持つサーバーと、処理を依頼するサーバーに分ける。主サーバーへの負担が大きいが、主サーバーの管理がしやすい。

2相コミット

調停者が各参加者にコミット可能かを尋ねる。参加者が全員コミット可能でなければロールバックする。
↓の解説がわかりやすかった。
平成21年秋期問31 2相コミットプロトコル|応用情報技術者試験.com

分散データベースの結合処理

その他分散データベースの結合について。

  • ネステッドループ
  • ソートマージ
  • セミジョイン
  • ハッシュセミジョイン

読んでどうだったか?

読んでみてよかったです。
マンガでわかるというタイトルのため正直なめてかかっていましたが、知らない・理解できていないことも多くあり、非常に勉強になりました。 (特に後半)

この本はデータベースを全然知らない人がデータベースの雰囲気を知るのにもよいですし、僕のようなデータベース触ってなんとなく理解した気になっている人間が知識を整理する・知識の隙間を埋めるのにも活用できます。

ルルナ姫がかわいいです。