src/4d/polydivisible-numbers.lisp @ 4b54adfbaf3d
default tip
More refactoring
author |
Steve Losh <steve@stevelosh.com> |
date |
Tue, 24 Dec 2019 13:50:19 -0500 |
parents |
(none) |
children |
(none) |
(defpackage :euler/4d/polydivisible-numbers #.euler:*use*)
(in-package :euler/4d/polydivisible-numbers)
(setf lparallel:*kernel* (lparallel:make-kernel 30))
(deftype radix ()
'(integer 2 64))
(deftype digit ()
'(integer 1 63))
(deftype digit-set ()
'(unsigned-byte 63))
(defun make-digits (radix)
(1- (expt 2 (1- radix))))
(defun-inline remove-digit (d digits)
(declare (optimize speed)
(type digit d)
(type digit-set digits))
(dpb 0 (byte 1 (1- d)) digits))
(defun new-candidates (radix candidate remaining)
(declare (optimize speed)
(type radix radix)
(type digit-set remaining)
(type (integer 0) candidate))
(iterate
(declare (iterate:declare-variables)
(type (or (integer 0) digit) d)
(type digit-set n more))
(for d :from 1)
(for n :first remaining :then more)
(for (values more d?) = (truncate n 2))
(unless (zerop d?)
(collect (cons (+ (* radix candidate) d)
(remove-digit d remaining))))
(until (zerop more))))
(defun find-polydivisible-numbers (radix)
(labels ((recur (n candidate remaining)
(when (or (zerop n) (dividesp candidate n))
(if (= n (1- radix))
(list candidate)
(funcall (if (< n 2)
#'lparallel:pmapcan
;; #'mapcan
#'mapcan
)
(lambda (next)
(recur (1+ n) (car next) (cdr next)))
(new-candidates radix candidate remaining))))))
(cons radix (recur 0 0 (make-digits radix)))))