ruby-on-rails - It costs 5 mins to read

Mấy bữa nay, khi rãnh thì mình hay vào Codewars để chiến, tìm vài bài trình độ 5 kyu, 6 kyu làm để giải trí (Độ khó của những bài này không cao, nói chung là vừa sức với Beginner). Công nhận, khi bắt tay vào làm thì học được thêm nhiều thứ, nâng Skill Problem Solving, Skills về Ruby nữa, khi đụng đến những thứ liên quan là phải google tìm hiểu về Array, String, Enumerable, Regular Expression… Có những bài tưởng đơn giản nhưng làm hoài không ra, phải nói với Codewars là Tui bó tay để xem bài giải gợi ý, hic hic. Những bài mình giải được thì cũng có những người đã đi trước, cách làm của họ hay hơn, thông minh hơn, ngắn gọn hơn nữa… Đọc Code của họ, mình biết thêm nhiều thứ mới: như những methods mình không biết chẳng hạn. Và sau đây là một ví dụ – Bài Convert một Chuỗi Int32 thành Chuỗi IPv4.

Description

Take the following IPv4 address: 128.32.10.1

This address has 4 octets where each octet is a single byte (or 8 bits).

1st octet 128 has the binary representation: 10000000 2nd octet 32 has the binary representation: 00100000 3rd octet 10 has the binary representation: 00001010 4th octet 1 has the binary representation: 00000001 So 128.32.10.1 == 10000000.00100000.00001010.00000001

Because the above IP address has 32 bits, we can represent it as the 32 bit number: 2149583361

Write a function int32_to_ip(int32) that takes a 32 bit number and returns a string representation of its IPv4 address.

int32_to_ip(2149583361) => “128.32.10.1”

Đây là bài mình làm (sau khi Google những method cần thiết)

def int32_to_ip(int32)
  str_binary = int32.to_s(2)
  str_binary.rjust(32,'0')
  str_array = []
  4.times do
    str_array.push str_binary.slice!(0..7).to_i(2)
  end
  str_array.join(".")
end

Nhận xét là nó dùng các lệnh khá cơ bản, dễ hiểu nhưng chưa catch trường hợp lớn hơn 255.

Và cùng một hướng ấy, lại có nhiều cách giải khác nhau, có những cách mà mình khi đọc solutions của những người khác cũng phải há hốc vì những kiến thức (methods) này lạ quá, người mới học Ruby được 1~2 tháng như mình, chưa hề biết tới, hic >.<.

def int32_to_ip(int32)
  [24, 16, 8, 0].collect {|b| (int32 >> b) & 255}.join('.')
end
def int32_to_ip(int32)
  [int32].pack('N').unpack('C*') * '.'
end
def int32_to_ip(int32)
  int32.to_s(2).rjust(32, '0').scan(/w{8}/).collect { |oct| oct.to_i(2) }.join('.')
end
def int32_to_ip(int32)
  first = (int32 & 0xFF000000) >> 24 second = (int32 & 0x00FF0000) >> 16 third = (int32 & 0x0000FF00) >> 8 fourth = (int32 & 0xFF)
  return "#{first}.#{second}.#{third}.#{fourth}"
end
def int32_to_ip int32
  int32 == 0 ? "0.0.0.0" : int32.to_s(2).scan(/.{1,8}/).map { |i| i.to_i(2) }.join('.')
end
def int32_to_ip(int32)
  4.times.collect do |i| int32.to_s(2).rjust(32, '0')[i*8..-1].chars.take(8).join.to_i(2).to_s end.join('.')
end
def int32_to_ip(int32)
  # your solution
  str = []
  4.times do
      str.unshift((int32.to_i & 255)) int32 = int32.to_i() >> 8
  end
  str.join('.')
end

Và còn nhiều nhiều nữa - Xem thêm

Mình Post bài này để lưu lại những đoạn Code này là chủ yếu, và cũng cho các bạn thấy, Ruby thiên biến vạn hóa như thế nào, nó có quá nhiều methods viết sẵn, mà bản thân người lập trình viên, muốn nắm rõ và tường tận những methods của nó thật không đơn giản.

Làm bài Int32 to Ipv4 này trong lúc ngồi chờ Data của bạn Xuân Trang, hỗ trợ bạn ấy cắt dán bằng Macro của VBA – Haizz, nói đến chuyện này thì tội Xuân Trang quá, Công việc thì chồng chất và khó khăn, Sếp thì thiếu trách nhiệm nên bỏ mặc, hậu quả là cháy gần đến đít… đến cả người ở bộ phận không liên quan như mình phải nhảy vào giúp sức – Cũng là vì cái tình đồng nghiệp. (Bạn Xuân Trang tính tình khá dễ thương, hay giúp đỡ người khác nên bây giờ khi bạn ấy cần, nhiều người sẵn sàng giúp lại)