--- a/src/problems/iev.lisp Fri Feb 22 19:32:24 2019 -0500
+++ b/src/problems/iev.lisp Sat Feb 23 12:42:07 2019 -0500
@@ -9,14 +9,13 @@
(hh (read data))
(hr (read data))
(rr (read data)))
- (format nil "~,4F"
- ;; It's just a weighted average…
- (* 2 (+ (* dd 1)
- (* dh 1)
- (* dr 1)
- (* hh 3/4)
- (* hr 1/2)
- (* rr 0))))))
+ (float-string
+ ;; It's just a weighted average…
+ (* 2 (+ (* dd 1)
+ (* dh 1)
+ (* dr 1)
+ (* hh 3/4)
+ (* hr 1/2)
+ (* rr 0)))
+ 4)))
-;; (problem-iev)
-;; (solve iev)
--- a/src/problems/iprb.lisp Fri Feb 22 19:32:24 2019 -0500
+++ b/src/problems/iprb.lisp Sat Feb 23 12:42:07 2019 -0500
@@ -24,13 +24,14 @@
;; = 2XY/N²-N
(/ (* 2 x y)
(- (* n n) n))))
- (format nil "~,5F"
- (+ (* (p-same d d) 1) ;; AA AA
- (* (p-diff d h) 1) ;; AA Aa
- (* (p-diff d r) 1) ;; AA aa
- (* (p-same h h) 3/4) ;; Aa Aa
- (* (p-diff h r) 1/2) ;; Aa aa
- (* (p-same r r) 0)))))) ;; aa aa
+ (float-string
+ (+ (* (p-same d d) 1) ;; AA AA
+ (* (p-diff d h) 1) ;; AA Aa
+ (* (p-diff d r) 1) ;; AA aa
+ (* (p-same h h) 3/4) ;; Aa Aa
+ (* (p-diff h r) 1/2) ;; Aa aa
+ (* (p-same r r) 0))
+ 5)))) ;; aa aa
;; (problem-iprb)
;; (solve iprb)
--- a/src/problems/lia.lisp Fri Feb 22 19:32:24 2019 -0500
+++ b/src/problems/lia.lisp Sat Feb 23 12:42:07 2019 -0500
@@ -51,4 +51,4 @@
(let* ((generations (read data))
(target (read data))
(population (expt 2 generations)))
- (format nil "~,3F" (bernoulli-at-least target population 1/4))))
+ (float-string (bernoulli-at-least target population 1/4))))
--- a/src/problems/prob.lisp Fri Feb 22 19:32:24 2019 -0500
+++ b/src/problems/prob.lisp Sat Feb 23 12:42:07 2019 -0500
@@ -18,4 +18,4 @@
(iterate
(for base :in-string dna)
(summing (log (base-probability gc-content base) 10)))))
- (format nil "~{~,3F~^ ~}" (mapcar #'prob gc-contents)))))
+ (float-string (mapcar #'prob gc-contents)))))
--- a/src/problems/prtm.lisp Fri Feb 22 19:32:24 2019 -0500
+++ b/src/problems/prtm.lisp Sat Feb 23 12:42:07 2019 -0500
@@ -36,6 +36,6 @@
(-<> data
(delete #\newline <>)
(summation <> :key #'monoisotopic-mass)
- (format nil "~,3F" <>)))
+ float-string))
--- a/src/problems/rstr.lisp Fri Feb 22 19:32:24 2019 -0500
+++ b/src/problems/rstr.lisp Sat Feb 23 12:42:07 2019 -0500
@@ -12,5 +12,5 @@
(let* ((n (read data))
(gc (coerce (read data) 'double-float))
(dna (read-line data))
- (prob (product dna :key (curry #'base-probability gc))))
- (format nil "~,3F" (- 1 (expt (- 1 prob) n)))))
+ (prob (sequence-probability gc dna)))
+ (float-string (- 1 (expt (- 1 prob) n)))))
--- a/src/utils.lisp Fri Feb 22 19:32:24 2019 -0500
+++ b/src/utils.lisp Sat Feb 23 12:42:07 2019 -0500
@@ -95,6 +95,10 @@
(/ gc-content 2)
(/ (- 1 gc-content) 2)))
+(defun sequence-probability (gc-content sequence)
+ "Return the probability of seeing `sequence` when generating a random sequence with the given `gc-content`."
+ (product sequence :key (curry #'base-probability gc-content)))
+
(defun mapcount (predicate sequence &rest more-sequences)
"Map `predicate` across sequences, counting satisfactory applications."
@@ -107,6 +111,12 @@
result))
+(defun ensure-list (value)
+ (if (listp value)
+ value
+ (list value)))
+
+
;;;; Math ---------------------------------------------------------------------
(defmacro do-sum ((var from to) &body body)
"Sum `body` with `var` iterating over `[from, to]`.
@@ -354,6 +364,13 @@
first)))
+;;;; Output -------------------------------------------------------------------
+(defun float-string (float-or-floats &optional (precision 3))
+ (with-output-to-string (s)
+ (loop :for (float . more) :on (ensure-list float-or-floats)
+ :do (format s "~,VF~:[~; ~]" precision float more))))
+
+
;;;; Testing ------------------------------------------------------------------
(defmacro define-test (problem input output &optional (test 'string=))
`(test ,(symb 'test- problem)