iT邦幫忙

2025 iThome 鐵人賽

DAY 28
0
Software Development

clojure 30 days系列 第 28

clojure 30 days - day 28

  • 分享至 

  • xImage
  •  

Problem Description

Create a function that returns the name of the winner in a fight between two fighters.

Each fighter takes turns attacking the other and whoever kills the other first is victorious. Death is defined as having health <= 0.

Each fighter will be a Fighter object/instance. See the Fighter class below in your chosen language.

Both health and damagePerAttack (damage_per_attack for python) will be integers larger than 0. You can mutate the Fighter objects.

Your function also receives a third argument, a string, with the name of the fighter that attacks first.

Example:
declare_winner(Fighter("Lew", 10, 2), Fighter("Harry", 5, 4), "Lew") => "Lew"

Lew attacks Harry; Harry now has 3 health.
Harry attacks Lew; Lew now has 6 health.
Lew attacks Harry; Harry now has 1 health.
Harry attacks Lew; Lew now has 2 health.
Lew attacks Harry: Harry now has -1 health and is dead. Lew wins.
Technical note: The second fighter argument (f2) always attacks first.

這次題目實在太長了,先整理一下:

Create a function declare_winner that determines the name of the winner in a fight between two fighters (Fighter).

Rules:

  • Fighters take turns attacking each other.

  • The first to reduce the opponent’s health (hp) to 0 or below wins.

  • Each fighter has:

    • name: the fighter’s name
    • hp: health (an integer > 0)
    • attack: damage dealt per attack (an integer > 0)
  • The third argument specifies the name of the fighter who attacks first.

  • Fighter objects are mutable.

Note

這題在調整測試的寫法(我是用 comment 做 evaluate)就花了不少工夫。
這是我的解法,我不使用 Fighter 物件,而是在測試中直接傳入對應的 map 資料結構:

(comment
  (tester {:name "Harald" :health 20 :damage-per-attack 5} {:name "Harry" :health 5 :damage-per-attack 4} "Harald")
  (tester {:name "Jerry" :health 30 :damage-per-attack 3} {:name "Harald" :health 20 :damage-per-attack 5} "Harald"))
  • keywords:
    • Math/ceil: rounds up to calculate number of attacks needed to win
      • (to avoid underestimating the number of attacks)
    • let: binds the number of attacks each fighter needs
    • if: determines the winner based on who needs fewer attacks

Implementation

; implement
(defn declare-winner [f1 f2]
  (let [attacks-f1-needs (Math/ceil (/ (:health f2) (:damage-per-attack f1)))
        attacks-f2-needs (Math/ceil (/ (:health f1) (:damage-per-attack f2)))]
    (if (<= attacks-f1-needs attacks-f2-needs)
      (:name f1)
      (:name f2))))

; test
; execute implement function
(defn tester [f1 f2 exp]
  (= (declare-winner f1 f2) exp))

; args & exception
(comment
  (tester {:name "Harald" :health 20 :damage-per-attack 5} {:name "Harry" :health 5 :damage-per-attack 4} "Harald")
  (tester {:name "Jerry" :health 30 :damage-per-attack 3} {:name "Harald" :health 20 :damage-per-attack 5} "Harald"))

上一篇
clojure 30 days - day 27
下一篇
clojure 30 days - day 29
系列文
clojure 30 days30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言