【问题标题】:Little lisp challenge [closed]小口齿挑战[关闭]
【发布时间】:2014-10-07 15:57:53
【问题描述】:

我有一个类似“2d 6:36”的字符串,我想将这个小时数乘以一个常数。

这意味着我想要计算这个:

(2*24 + 6 + 36/60) * constant

或者,一般来说

(d*24 + h + m/60)

有什么帮助吗?

编辑:我只有 string 而不是 d、h 和 m。

【问题讨论】:

  • 你确定你想要那个 *100 吗?
  • 你试过(* constant (+ (* d 24) h (/ m 60)))吗?你在寻求什么帮助?编写 LISP 表达式?解析?
  • NeilForrester,你是对的。 @RayToal,解析是困难的部分,但现在你已经告诉我如何编写公式,我也需要。
  • * 实际上并不是 Lisp 挑战的站点。如果您能付出一些努力来实际解决问题,那就太好了。

标签: lisp


【解决方案1】:

你需要用有用的东西解析你的字符串,例如整数列表,你可以使用cl-ppcre

(defun parse-day-and-time (string)
  "Get string like 3d 23:40 and return list (3 23 40)"
  (multiple-value-bind (str matches)
    (cl-ppcre:scan-to-strings "(\\d+)d ([0-9]|0[0-9]|1[0-9]|2[0-3]):([0-5][0-9])" string)
    (declare (ignore str))
    (when (< (length matches) 3)
      (error "Wrong day and time string: ~A" string))
    (map 'list #'parse-integer matches)))

然后你就可以自己计算了:

(defun mult-time (string-time coeff)
  (destructuring-bind (days hours minutes)
    (parse-day-and-time string-time)
    (* coeff (+ (* 24 days) hours (/ minutes 60)))))

CL-USER> (mult-time "2d 6:36" 300)
16380

当然,如果你想用你的时间做更多的计算,最好将它表示为秒数,用它进行计算,然后以你想要的任何字符串返回它。

【讨论】:

  • 您的mult-time 不使用字符串时间,而是使用常量"2d 6:36"
【解决方案2】:

所以我理解数据是人类可读的时间量......例如“2d 1:35”表示 2 天 1 小时 35 秒或 595/12 小时。我很想像这样放开字符串的规范:

(defparameter *units* '(("w" . 168) ("d" . 24) (":" . 1)
                        ("h" . 1) ("m" . 1/60) ("s" . 1/3600)))
(defun str-to-hours (str &optional (acc 0))
  (or
   (cl-ppcre:register-groups-bind (num unit rest)
                                  ("(\\d+)\\s*(\\D{0,1})\\D*(.*)" str :sharedp t)
     (str-to-hours rest
                   (+ acc
                      (* (parse-integer num)
                         (or (cdr (assoc (string-downcase unit) 
                                         *units* 
                                         :test #'equal)) 
                              1/60)))))
   acc))

(str-to-hours  "2d 6:36")  ; ==> 273/5 ~54.6
(str-to-hours  "2D6H36M")  ; ==> 273/5 ~54.6
(str-to-hours  "2 weeks, 1 day, 3 hours, 7 minutes and 10 seconds") ; ==> 130723/360 ~363.11945

(* 10 (str-to-hours "2d6:36")) ; ==> 546

【讨论】: