Matrix Rotation (CODEEVAL)

行列回転の問題。今回は面白かったです。

CHALLENGE DESCRIPTION:

You are given a 2D N×N matrix. Each element of the matrix is a letter: from ‘a’ to ‘z’. Your task is to rotate the matrix 90° clockwise:

a b c        g d a
d e f  =>    h e b
g h i        i f c

INPUT SAMPLE:

a b c d
a b c d e f g h i j k l m n o p
a b c d e f g h i

OUTPUT SAMPLE:

c a d b
m i e a n j f b o k g c p l h d
g d a h e b i f c

CONSTRAINTS:

  1. The N size of the matrix can be from 1 to 10
  2. The number of test cases is 100

My Code

とりあえず書いて見たコード。

#!/usr/bin/env ruby -w
def generate_matrix(numbers)
  n = Math.sqrt(numbers.size).to_i
  numbers.each_slice(n).to_a
end

def rotate(matrix)
  matrix_size = matrix.size
  result = Array.new(matrix_size) { [] }
  matrix.each_with_index do |line, i|
    line.each_with_index do |elm, j|
      result[j][matrix_size - i - 1] = elm
    end
  end
  result
end

ARGF.each_line do |line|
  matrix = generate_matrix(line.chomp.split)
  puts rotate(matrix).join(" ")
end

他のやり方

rotate メソッドがダサいので他の方法を調べてみました。
 
すると、Ruby Quiz というサイトで同様の問題が出題されていたようで Ruby-Forum でエレガントな解き方が紹介されていました。
Matrix Rotator (#209) - Ruby Forum
 
それがこれ。

    def rotate(n=1)
      (n%4).times {self.replace(self.reverse.transpose)}
    end

self.reverse.transpose 。これすごい。これは思いつかない。

>>  [["a", "b"], ["c", "d"]].reverse
=> [["c", "d"], ["a", "b"]]

>>  [["a", "b"], ["c", "d"]].reverse.transpose
=> [["c", "a"], ["d", "b"]]

別解

def generate_matrix(numbers)
  n = Math.sqrt(numbers.size).to_i
  numbers.each_slice(n).to_a
end

class Array
  def rotate(n = 1)
    (n % 4).times { self.replace(self.reverse.transpose) }
    self
  end
end

ARGF.each_line do |line|
  matrix = generate_matrix(line.chomp.split)
  puts matrix.rotate.join(" ")
end

Reactのチュートリアルをやってみた

(少し古いですが)WEB+DB Press Vol.92 を読んでいたら naoyaさんがreduxについて書いていたので、 これを読む前に忘れ気味だったReactを復習しようと、以前から気になっていた以下のチュートリアルをやってみました。
いずれも、1〜2時間程度でできます。
 

React.js Introduction For People Who Know Just Enough jQuery To Get By | Shu Uesugi

Hacker News でも話題になった2015年の記事。
一部古い箇所(twitterの画像uploadのロジック)もありますが、今でも良い記事だと思います。 Reactの良いところをjQueryとの比較で際立たせる内容は分かりやすくてとても良いです。 なぜclassNameが使われているとか、function呼び出しに() が必要となるケースがあるのかなど結構細かい話も書いています。
React分かんない人は、最初にこれ読むと良いですね。
対象者は、エンジニアはもちろんですが、JS書けるデザイナも含まれています。

 

入門 React ―コンポーネントベースのWebフロントエンド開発

入門 React ―コンポーネントベースのWebフロントエンド開発


昔こちらを読んだときは、viewを小さく分割していくスタイルに違和感を持ちましたが(当時感じた記憶も曖昧ですが)、肝のところは states であり、上記のチュートリアルはここを中心に説明しているのがとても良いです。
 
本筋ではないですが、以下も良いと思いました。

  • chapter毎に所要時間が記載されている(全体でmax2時間くらいと最初に書いている)
  • JS Bin - Collaborative JavaScript Debugging というjsxを実行できるサイトを利用している
    (環境構築不要。chapter毎に丁寧にembedされていて迷子にならなくて良い)

 

2016年8月時点での国別アクセス数

Shuさんの別記事です。日本は10位だそうです。世界中で読まれてるなぁ。
Traffic by Country: React.js Introduction For People Who Know Just Enough jQuery To Get By
 

Reactで学ぶ!いまどきのWeb開発 // Speaker Deck

もう一つ。jsbin だと環境構築不要でしたが、こちらはcloneして実行していくstyle。なのでより実践的。
最低限必要なものは何か、どう進めれば良いのかというのが理解できます。
fand/react-hands-on: FRONTEND CONFERENCE 2017 - Reactハンズオン用レポジトリ
 
Layout使ってページの共通化したり、Next.jsを使ってCSSをどう扱うのかを学べたり(Next.js個人的には少し違和感がありましたが)します。
 

余談

Hatena Frontend | Free Listening on SoundCloud
podcastを運用されているようで、JSer.info の内容を読んだりする内容で、割と良いなと思いました。
JSer.info frontendの人に解説してもらいながら聞けるのは嬉しい。

感想

この1年ほどFrontEndは積極的に勉強しないスタイルでしたが、 特にShuさんの記事を読んでいて、Reactいいやんって思いました。
全てがReactになる必要はないけど、使えるところは使ってみたい印象。
既存のjQuery Plugin(アニメーション含む)どうする?、既存のテンプレートエンジン無しでいける?外部公開サイトだとサーバーサイドレンダリング必要ですよね?などというのは気になるところ。

Prefix Expressions(CODEEVAL)

ポーランド記法の問題。
何度かtryしましたが、scoreが100にならないです(85-95)。なんかケース漏れがありそうだけど、どういうケースでNGになっているのかcodeeval上ではわからないのが残念。
些細なミスのような気がしますが、一旦諦めました。

CHALLENGE DESCRIPTION:

You are given a prefix expression. Write a program which evaluates it.

INPUT SAMPLE:

Your program should accept a file as its first argument. The file contains one prefix expression per line.
For example:

* + 2 3 4

Your program should read this file and insert it into any data structure you like. Traverse this data structure and evaluate the prefix expression. Each token is delimited by a whitespace. You may assume that sum ‘+’, multiplication ‘*’ and division ‘/’ are the only valid operators appearing in the test data.

OUTPUT SAMPLE:

Print to stdout the output of the prefix expression, one per line.

20

CONSTRAINTS:

  1. The evaluation result will always be an integer ≥ 0.
  2. The number of the test cases is ≤ 40.

My Code

stackを使った解き方。

def prefix_expression(exps)
  stack = []
  exps.reverse.each do |exp|
    if exp.match(/\d+/)
      stack << exp
    else
      x = stack.pop
      y = stack.pop
      stack << (x.to_i.send(exp, y.to_i))
    end
  end
  stack[0]
end

ARGF.each_line do |line|
  puts prefix_expression(line.chomp.split)
end

もう1個。正規表現を使った計算例。

CALC_PATTERN = %r{([+*/]) (\d+) (\d+)}
def prefix_expression(str)
  match = str.match(CALC_PATTERN)
  return str unless match
  ope, x, y = match.captures
  result = eval("#{x} #{ope} #{y}")
  str = match.pre_match + result.to_s + match.post_match
  prefix_expression(str)
end

ARGF.each_line do |line|
  puts prefix_expression(line.chomp)
end