iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 23
0
自我挑戰組

Codewars Ruby Challenge in 30 Days系列 第 23

Codewars Ruby Challenge - Day 23/30

  • 分享至 

  • xImage
  •  

學習

  1. 寫測試為何用 expect(XXX).to "xxx" 會錯:今天開始是直接在 Codewars 上找題目,在處理測試時拉到本地 vscode 改寫成 Rspec 時,發現當我寫「expect(XXX).to "xxx"」會噴錯,後來才發現原因,下面詳細說明:

測試沒過,想說 expect 跟 got 不是長一樣嗎?

expected #<String:1960> => "should return false"
     got #<String:1980> => "should return false"
     
     Compared using equal?, which compares object identity,
     but expected and actual are not the same object. Use
     `expect(actual).to eq(expected)` if you don't care about
     object identity in this example.

# expect(XXX).to "xxx" 要寫成 expect(XXX).to eq("xxx") 才行

雖然我們看起來 "should return false" 兩個是一樣的,但在測試時,是在比對 object_id 是否一樣,下面舉個例子

a = "a"
b = "a"
a == b # true
a.object_id == b.object_id # false

總結:
1.在測試中如果不寫 eq() 會用最後一行的判斷
2.在測試中如果寫 eq() 會用倒數第二行的判斷


題目:

# You live in the city of Cartesia where all roads are laid out in a perfect grid. You arrived ten minutes too early to an appointment, so you decided to take the opportunity to go for a short walk. The city provides its citizens with a Walk Generating App on their phones -- everytime you press the button it sends you an array of one-letter strings representing directions to walk (eg. ['n', 's', 'w', 'e']). You always walk only a single block for each letter (direction) and you know it takes you one minute to traverse one city block, so create a function that will return true if the walk the app gives you will take you exactly ten minutes (you don't want to be early or late!) and will, of course, return you to your starting point. Return false otherwise.

# 翻譯:總之最多只能走10個街區,且相鄰不能是同樣的街區名稱

def is_valid_walk(walk)

end

答案需要過以下測試:

RSpec.describe do
  it "計算不重複元素的總合" do
    expect(is_valid_walk(['n','s','n','s','n','s','n','s','n','s'])).to eq('should return true')
    expect(!is_valid_walk(['w','e','w','e','w','e','w','e','w','e','w','e'])).to eq('should return false')
    expect(!is_valid_walk(['w'])).to eq('should return false')
    expect(!is_valid_walk(['n','n','n','s','n','s','n','s','n','s'])).to eq('should return false')
  end
end

我的答案

def is_valid_walk(walk)
  count = 0
  return "should return false" if walk.length != 10
  walk.each.with_index do |w, i|
    count += 1 if w == walk[i+1]
  end
  return "should return false" if count > 0
  "should return true"
end

思路:

  1. 先用 if 判斷排除 arry 長度不到 10 的
  2. 再用 each 判斷相鄰是否有相同時
  3. 若有相鄰回傳 false 不然就是回傳 true

Best Practice Voted in Codewars

def is_valid_walk(walk)
  walk.count('n') == walk.count('s') && walk.count('e') == walk.count('w') && walk.length == 10 ? true : false
end

上一篇
Codewars Ruby Challenge - Day 22/30
下一篇
Codewars Ruby Challenge - Day 24/30
系列文
Codewars Ruby Challenge in 30 Days30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言