2025-07-22

[EN] A Curio about the Digits of Pi

;;;; pi-digits.cl -*- mode: lisp; -*-
;;; Illustrate a curio about the first 40 (decimal) digits of π.
;;; Time-stamp: <2025-07-22 16:52:39>

#|
Output:
                                 1588419
3.14159265358979323846264338327950288419
--------------------^20------------^35--
|#

;; Four magic numbers.
(defconstant n-groups 3
  "The magic number of groups of digits of pi.")
(defconstant group-length 6
  "The magic length of groups of digits of pi.")
(defconstant magic-prefix-length 2
  "The length of the distance to the next occurrence.")
(defconstant fractional-part-start (+ (position #\. (prin1-to-string pi)) 1)
  "The start of pi's fractional part in the string of its digits.")

#-clisp (error "We require Clisp so we can obtain enough digits for pi.")
(setf (ext:long-float-digits) 1000)

;;; All digits are decimal; digit sequences are strings.
;;; (In a perfect world, they would be of type `(vector (integer 0 9))'.)

(defun sum-digit-groups (digits &key (start fractional-part-start)
                                     (count n-groups)
                                     (length group-length))
  "Sum COUNT LENGTH-digit groups from START in DIGITS.
Return (1) the sum as a string and (2) the position where the groups end."
  (loop for i from 0 below count
        for group-start = (+ start (* length i))
        sum (parse-integer (subseq digits group-start (+ group-start length)))
        into result
        finally (return (values (prin1-to-string result)
                                (+ start (* count length))))))

(defun make-ruler (length &rest ps)
  "Return \"---...---^pp-...---^pp-...\" of the given LENGTH.
The carets are at positions PS and 'pp' are the positions as numbers."
  (loop with ruler = (make-string length :initial-element #\-)
        for p in ps
        do (setf (aref ruler p) #\^)
           (replace ruler (prin1-to-string p) :start1 (+ p 1))
        finally (return ruler)))

(defun main ()
  "Demonstrate a curio about the digits of pi."
  (let ((pi-digits (prin1-to-string pi)))
    (multiple-value-bind (magic-sum group-end)
                         (sum-digit-groups pi-digits)
      (let* ((magic-distance (parse-integer magic-sum
                                            :end magic-prefix-length))
             (magic-start (+ group-end magic-distance))
             (magic-end (+ magic-start (- (length magic-sum)
                                          magic-prefix-length)))
             (ruler (make-ruler magic-end group-end magic-start)))
        (format *trace-output*
                "~v@A~%~A~%~A~%"
                magic-end magic-sum
                (subseq pi-digits 0 magic-end)
                ruler)
        (assert (string= magic-sum pi-digits
                         :start1 magic-prefix-length
                         :start2 magic-start :end2 magic-end))))))

;;; A poor programmer's unit test.
(assert (equal (multiple-value-list (sum-digit-groups "90102034" :start 1 :length 2))
               '("6" 7)))


2025-06-15

[bg] Епикур V


„Най-голямото зло, което може да ни се случи, е да не можем да се наслаждаваме на малките радости в животът.“

2025-06-14

[EN] No Kings

Photograph:
A sign saying
NO KINGS
SOLIDARITY
at the monument to Ronald Reagan in South Park, Sofia, Bulgaria.

Who, if not Us!
When, if not Now!

(Solidarnosć won in Poland in 1989.)

2025-06-12

[bg] Епикур IV

„Не изисквай всичко да бъде, както ти го искаш, а се научи да се радваш на онова, което имаш.“

2025-06-11

[bg] Епикур III

„Приятелството е най-голямото богатство, което можем да притежаваме.“

2025-06-09

[bg] Епикур II

„Богатството не се заключава в притежания, а в свободата от желания.“

2025-06-08

[bg] Епикур I

„Не се страхувай от смъртта, защото тя не съществува, когато ние съществуваме, и ние не съществуваме, когато тя идва.“

[EN] A Curio about the Digits of Pi

;;;; pi-digits.cl -*- mode: lisp; -*- ;;; Illustrate a curio about the first 40 (decimal) digits of π. ;;; Time-stamp: <2025-07-22 16:52...