# HG changeset patch # User Steve Losh # Date 1502410154 14400 # Node ID 4f58a841ae48f3a69f6518d363b6eb1f838891e7 # Parent 9230e81d302c415e745a47b37bab9869bea80b66 Problem 345 diff -r 9230e81d302c -r 4f58a841ae48 euler.asd --- a/euler.asd Wed Aug 09 14:55:51 2017 -0400 +++ b/euler.asd Thu Aug 10 20:09:14 2017 -0400 @@ -27,6 +27,7 @@ (:module "src" :serial t :components ((:file "primes") (:file "utils") - (:file "euler") + (:file "hungarian") + (:file "problems") (:file "poker"))))) diff -r 9230e81d302c -r 4f58a841ae48 package.lisp --- a/package.lisp Wed Aug 09 14:55:51 2017 -0400 +++ b/package.lisp Thu Aug 10 20:09:14 2017 -0400 @@ -15,3 +15,13 @@ :euler :anaphora-basic :euler.quickutils)) + +(defpackage :euler.hungarian + (:use + :cl + :iterate + :losh + :euler + :euler.quickutils) + (:export + :find-minimal-assignment)) diff -r 9230e81d302c -r 4f58a841ae48 src/euler.lisp --- a/src/euler.lisp Wed Aug 09 14:55:51 2017 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1860 +0,0 @@ -(in-package :euler) - -(defun problem-1 () - ;; If we list all the natural numbers below 10 that are multiples of 3 or 5, - ;; we get 3, 5, 6 and 9. The sum of these multiples is 23. - ;; - ;; Find the sum of all the multiples of 3 or 5 below 1000. - (iterate (for i :from 1 :below 1000) - (when (or (dividesp i 3) - (dividesp i 5)) - (sum i)))) - -(defun problem-2 () - ;; Each new term in the Fibonacci sequence is generated by adding the previous - ;; two terms. By starting with 1 and 2, the first 10 terms will be: - ;; - ;; 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... - ;; - ;; By considering the terms in the Fibonacci sequence whose values do not - ;; exceed four million, find the sum of the even-valued terms. - (iterate (for n :in-fibonacci t) - (while (<= n 4000000)) - (when (evenp n) - (sum n)))) - -(defun problem-3 () - ;; The prime factors of 13195 are 5, 7, 13 and 29. - ;; - ;; What is the largest prime factor of the number 600851475143 ? - (apply #'max (prime-factorization 600851475143))) - -(defun problem-4 () - ;; A palindromic number reads the same both ways. The largest palindrome made - ;; from the product of two 2-digit numbers is 9009 = 91 × 99. - ;; - ;; Find the largest palindrome made from the product of two 3-digit numbers. - (iterate (for-nested ((i :from 0 :to 999) - (j :from 0 :to 999))) - (for product = (* i j)) - (when (palindromep product) - (maximize product)))) - -(defun problem-5 () - ;; 2520 is the smallest number that can be divided by each of the numbers from - ;; 1 to 10 without any remainder. - ;; - ;; What is the smallest positive number that is evenly divisible by all of the - ;; numbers from 1 to 20? - (iterate - ;; all numbers are divisible by 1 and we can skip checking everything <= 10 - ;; because: - ;; - ;; anything divisible by 12 is automatically divisible by 2 - ;; anything divisible by 12 is automatically divisible by 3 - ;; anything divisible by 12 is automatically divisible by 4 - ;; anything divisible by 15 is automatically divisible by 5 - ;; anything divisible by 12 is automatically divisible by 6 - ;; anything divisible by 14 is automatically divisible by 7 - ;; anything divisible by 16 is automatically divisible by 8 - ;; anything divisible by 18 is automatically divisible by 9 - ;; anything divisible by 20 is automatically divisible by 10 - (with divisors = (range 11 20)) - (for i :from 20 :by 20) ; it must be divisible by 20 - (finding i :such-that (every (curry #'dividesp i) divisors)))) - -(defun problem-6 () - ;; The sum of the squares of the first ten natural numbers is, - ;; 1² + 2² + ... + 10² = 385 - ;; - ;; The square of the sum of the first ten natural numbers is, - ;; (1 + 2 + ... + 10)² = 55² = 3025 - ;; - ;; Hence the difference between the sum of the squares of the first ten - ;; natural numbers and the square of the sum is 3025 − 385 = 2640. - ;; - ;; Find the difference between the sum of the squares of the first one hundred - ;; natural numbers and the square of the sum. - (flet ((sum-of-squares (to) - (sum (irange 1 to :key #'square))) - (square-of-sum (to) - (square (sum (irange 1 to))))) - (abs (- (sum-of-squares 100) ; apparently it wants the absolute value - (square-of-sum 100))))) - -(defun problem-7 () - ;; By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see - ;; that the 6th prime is 13. - ;; - ;; What is the 10 001st prime number? - (nth-prime 10001)) - -(defun problem-8 () - ;; The four adjacent digits in the 1000-digit number that have the greatest - ;; product are 9 × 9 × 8 × 9 = 5832. - ;; - ;; Find the thirteen adjacent digits in the 1000-digit number that have the - ;; greatest product. What is the value of this product? - (let ((digits (map 'list #'digit-char-p - "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450"))) - (iterate (for window :in (n-grams 13 digits)) - (maximize (apply #'* window))))) - -(defun problem-9 () - ;; A Pythagorean triplet is a set of three natural numbers, a < b < c, for - ;; which: - ;; - ;; a² + b² = c² - ;; - ;; For example, 3² + 4² = 9 + 16 = 25 = 5². - ;; - ;; There exists exactly one Pythagorean triplet for which a + b + c = 1000. - ;; Find the product abc. - (product (first (pythagorean-triplets-of-perimeter 1000)))) - -(defun problem-10 () - ;; The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17. - ;; Find the sum of all the primes below two million. - (sum (sieve 2000000))) - -(defun problem-11 () - ;; In the 20×20 grid below, four numbers along a diagonal line have been marked - ;; in red. - ;; - ;; The product of these numbers is 26 × 63 × 78 × 14 = 1788696. - ;; - ;; What is the greatest product of four adjacent numbers in the same direction - ;; (up, down, left, right, or diagonally) in the 20×20 grid? - (let ((grid - #2A((08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08) - (49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00) - (81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65) - (52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91) - (22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80) - (24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50) - (32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70) - (67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21) - (24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72) - (21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95) - (78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92) - (16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57) - (86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58) - (19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40) - (04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66) - (88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69) - (04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36) - (20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16) - (20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54) - (01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48)))) - (max - ;; horizontal - (iterate (for-nested ((row :from 0 :below 20) - (col :from 0 :below 16))) - (maximize (* (aref grid row (+ 0 col)) - (aref grid row (+ 1 col)) - (aref grid row (+ 2 col)) - (aref grid row (+ 3 col))))) - ;; vertical - (iterate (for-nested ((row :from 0 :below 16) - (col :from 0 :below 20))) - (maximize (* (aref grid (+ 0 row) col) - (aref grid (+ 1 row) col) - (aref grid (+ 2 row) col) - (aref grid (+ 3 row) col)))) - ;; backslash \ - (iterate (for-nested ((row :from 0 :below 16) - (col :from 0 :below 16))) - (maximize (* (aref grid (+ 0 row) (+ 0 col)) - (aref grid (+ 1 row) (+ 1 col)) - (aref grid (+ 2 row) (+ 2 col)) - (aref grid (+ 3 row) (+ 3 col))))) - ;; slash / - (iterate (for-nested ((row :from 3 :below 20) - (col :from 0 :below 16))) - (maximize (* (aref grid (- row 0) (+ 0 col)) - (aref grid (- row 1) (+ 1 col)) - (aref grid (- row 2) (+ 2 col)) - (aref grid (- row 3) (+ 3 col)))))))) - -(defun problem-12 () - ;; The sequence of triangle numbers is generated by adding the natural - ;; numbers. So the 7th triangle number would be - ;; 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first ten terms would be: - ;; - ;; 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ... - ;; - ;; Let us list the factors of the first seven triangle numbers: - ;; - ;; 1: 1 - ;; 3: 1,3 - ;; 6: 1,2,3,6 - ;; 10: 1,2,5,10 - ;; 15: 1,3,5,15 - ;; 21: 1,3,7,21 - ;; 28: 1,2,4,7,14,28 - ;; - ;; We can see that 28 is the first triangle number to have over five divisors. - ;; - ;; What is the value of the first triangle number to have over five hundred - ;; divisors? - (iterate - (for tri :key #'triangle :from 1) - (finding tri :such-that (> (count-divisors tri) 500)))) - -(defun problem-13 () - ;; Work out the first ten digits of the sum of the following one-hundred - ;; 50-digit numbers. - (-<> (+ 37107287533902102798797998220837590246510135740250 - 46376937677490009712648124896970078050417018260538 - 74324986199524741059474233309513058123726617309629 - 91942213363574161572522430563301811072406154908250 - 23067588207539346171171980310421047513778063246676 - 89261670696623633820136378418383684178734361726757 - 28112879812849979408065481931592621691275889832738 - 44274228917432520321923589422876796487670272189318 - 47451445736001306439091167216856844588711603153276 - 70386486105843025439939619828917593665686757934951 - 62176457141856560629502157223196586755079324193331 - 64906352462741904929101432445813822663347944758178 - 92575867718337217661963751590579239728245598838407 - 58203565325359399008402633568948830189458628227828 - 80181199384826282014278194139940567587151170094390 - 35398664372827112653829987240784473053190104293586 - 86515506006295864861532075273371959191420517255829 - 71693888707715466499115593487603532921714970056938 - 54370070576826684624621495650076471787294438377604 - 53282654108756828443191190634694037855217779295145 - 36123272525000296071075082563815656710885258350721 - 45876576172410976447339110607218265236877223636045 - 17423706905851860660448207621209813287860733969412 - 81142660418086830619328460811191061556940512689692 - 51934325451728388641918047049293215058642563049483 - 62467221648435076201727918039944693004732956340691 - 15732444386908125794514089057706229429197107928209 - 55037687525678773091862540744969844508330393682126 - 18336384825330154686196124348767681297534375946515 - 80386287592878490201521685554828717201219257766954 - 78182833757993103614740356856449095527097864797581 - 16726320100436897842553539920931837441497806860984 - 48403098129077791799088218795327364475675590848030 - 87086987551392711854517078544161852424320693150332 - 59959406895756536782107074926966537676326235447210 - 69793950679652694742597709739166693763042633987085 - 41052684708299085211399427365734116182760315001271 - 65378607361501080857009149939512557028198746004375 - 35829035317434717326932123578154982629742552737307 - 94953759765105305946966067683156574377167401875275 - 88902802571733229619176668713819931811048770190271 - 25267680276078003013678680992525463401061632866526 - 36270218540497705585629946580636237993140746255962 - 24074486908231174977792365466257246923322810917141 - 91430288197103288597806669760892938638285025333403 - 34413065578016127815921815005561868836468420090470 - 23053081172816430487623791969842487255036638784583 - 11487696932154902810424020138335124462181441773470 - 63783299490636259666498587618221225225512486764533 - 67720186971698544312419572409913959008952310058822 - 95548255300263520781532296796249481641953868218774 - 76085327132285723110424803456124867697064507995236 - 37774242535411291684276865538926205024910326572967 - 23701913275725675285653248258265463092207058596522 - 29798860272258331913126375147341994889534765745501 - 18495701454879288984856827726077713721403798879715 - 38298203783031473527721580348144513491373226651381 - 34829543829199918180278916522431027392251122869539 - 40957953066405232632538044100059654939159879593635 - 29746152185502371307642255121183693803580388584903 - 41698116222072977186158236678424689157993532961922 - 62467957194401269043877107275048102390895523597457 - 23189706772547915061505504953922979530901129967519 - 86188088225875314529584099251203829009407770775672 - 11306739708304724483816533873502340845647058077308 - 82959174767140363198008187129011875491310547126581 - 97623331044818386269515456334926366572897563400500 - 42846280183517070527831839425882145521227251250327 - 55121603546981200581762165212827652751691296897789 - 32238195734329339946437501907836945765883352399886 - 75506164965184775180738168837861091527357929701337 - 62177842752192623401942399639168044983993173312731 - 32924185707147349566916674687634660915035914677504 - 99518671430235219628894890102423325116913619626622 - 73267460800591547471830798392868535206946944540724 - 76841822524674417161514036427982273348055556214818 - 97142617910342598647204516893989422179826088076852 - 87783646182799346313767754307809363333018982642090 - 10848802521674670883215120185883543223812876952786 - 71329612474782464538636993009049310363619763878039 - 62184073572399794223406235393808339651327408011116 - 66627891981488087797941876876144230030984490851411 - 60661826293682836764744779239180335110989069790714 - 85786944089552990653640447425576083659976645795096 - 66024396409905389607120198219976047599490197230297 - 64913982680032973156037120041377903785566085089252 - 16730939319872750275468906903707539413042652315011 - 94809377245048795150954100921645863754710598436791 - 78639167021187492431995700641917969777599028300699 - 15368713711936614952811305876380278410754449733078 - 40789923115535562561142322423255033685442488917353 - 44889911501440648020369068063960672322193204149535 - 41503128880339536053299340368006977710650566631954 - 81234880673210146739058568557934581403627822703280 - 82616570773948327592232845941706525094512325230608 - 22918802058777319719839450180888072429661980811197 - 77158542502016545090413245809786882778948721859617 - 72107838435069186155435662884062257473692284509516 - 20849603980134001723930671666823555245252804609722 - 53503534226472524250874054075591789781264330331690) - aesthetic-string - (subseq <> 0 10) - parse-integer - (nth-value 0 <>))) - -(defun problem-14 () - ;; The following iterative sequence is defined for the set of positive - ;; integers: - ;; - ;; n → n/2 (n is even) - ;; n → 3n + 1 (n is odd) - ;; - ;; Using the rule above and starting with 13, we generate the following - ;; sequence: - ;; - ;; 13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1 - ;; - ;; It can be seen that this sequence (starting at 13 and finishing at 1) - ;; contains 10 terms. Although it has not been proved yet (Collatz Problem), - ;; it is thought that all starting numbers finish at 1. - ;; - ;; Which starting number, under one million, produces the longest chain? - ;; - ;; NOTE: Once the chain starts the terms are allowed to go above one million. - (iterate (for i :from 1 :below 1000000) - (finding i :maximizing #'collatz-length))) - -(defun problem-15 () - ;; Starting in the top left corner of a 2×2 grid, and only being able to move - ;; to the right and down, there are exactly 6 routes to the bottom right - ;; corner. - ;; - ;; How many such routes are there through a 20×20 grid? - (binomial-coefficient 40 20)) - -(defun problem-16 () - ;; 2^15 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26. - ;; - ;; What is the sum of the digits of the number 2^1000? - (sum (digits (expt 2 1000)))) - -(defun problem-17 () - ;; If the numbers 1 to 5 are written out in words: one, two, three, four, - ;; five, then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total. - ;; - ;; If all the numbers from 1 to 1000 (one thousand) inclusive were written out - ;; in words, how many letters would be used? - ;; - ;; NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and - ;; forty-two) contains 23 letters and 115 (one hundred and fifteen) contains - ;; 20 letters. The use of "and" when writing out numbers is in compliance with - ;; British usage, which is awful. - (labels ((letters (n) - (-<> n - (format nil "~R" <>) - (count-if #'alpha-char-p <>))) - (has-british-and (n) - (or (< n 100) - (zerop (mod n 100)))) - (silly-british-letters (n) - (+ (letters n) - (if (has-british-and n) 0 3)))) - (sum (irange 1 1000) - :key #'silly-british-letters))) - -(defun problem-18 () - ;; By starting at the top of the triangle below and moving to adjacent numbers - ;; on the row below, the maximum total from top to bottom is 23. - ;; - ;; 3 - ;; 7 4 - ;; 2 4 6 - ;; 8 5 9 3 - ;; - ;; That is, 3 + 7 + 4 + 9 = 23. - ;; - ;; Find the maximum total from top to bottom of the triangle below. - ;; - ;; NOTE: As there are only 16384 routes, it is possible to solve this problem - ;; by trying every route. However, Problem 67, is the same challenge with - ;; a triangle containing one-hundred rows; it cannot be solved by brute force, - ;; and requires a clever method! ;o) - (let ((triangle '((75) - (95 64) - (17 47 82) - (18 35 87 10) - (20 04 82 47 65) - (19 01 23 75 03 34) - (88 02 77 73 07 63 67) - (99 65 04 28 06 16 70 92) - (41 41 26 56 83 40 80 70 33) - (41 48 72 33 47 32 37 16 94 29) - (53 71 44 65 25 43 91 52 97 51 14) - (70 11 33 28 77 73 17 78 39 68 17 57) - (91 71 52 38 17 14 91 43 58 50 27 29 48) - (63 66 04 68 89 53 67 30 73 16 69 87 40 31) - (04 62 98 27 23 09 70 98 73 93 38 53 60 04 23)))) - (car (reduce (lambda (prev last) - (mapcar #'+ - prev - (mapcar #'max last (rest last)))) - triangle - :from-end t)))) - -(defun problem-19 () - ;; You are given the following information, but you may prefer to do some - ;; research for yourself. - ;; - ;; 1 Jan 1900 was a Monday. - ;; Thirty days has September, - ;; April, June and November. - ;; All the rest have thirty-one, - ;; Saving February alone, - ;; Which has twenty-eight, rain or shine. - ;; And on leap years, twenty-nine. - ;; A leap year occurs on any year evenly divisible by 4, but not on a century - ;; unless it is divisible by 400. - ;; - ;; How many Sundays fell on the first of the month during the twentieth - ;; century (1 Jan 1901 to 31 Dec 2000)? - (iterate - (for-nested ((year :from 1901 :to 2000) - (month :from 1 :to 12))) - (counting (-<> (local-time:encode-timestamp 0 0 0 0 1 month year) - local-time:timestamp-day-of-week - zerop)))) - -(defun problem-20 () - ;; n! means n × (n − 1) × ... × 3 × 2 × 1 - ;; - ;; For example, 10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800, - ;; and the sum of the digits in the number 10! is 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27. - ;; - ;; Find the sum of the digits in the number 100! - (sum (digits (factorial 100)))) - -(defun problem-21 () - ;; Let d(n) be defined as the sum of proper divisors of n (numbers less than - ;; n which divide evenly into n). - ;; - ;; If d(a) = b and d(b) = a, where a ≠ b, then a and b are an amicable pair - ;; and each of a and b are called amicable numbers. - ;; - ;; For example, the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, - ;; 55 and 110; therefore d(220) = 284. The proper divisors of 284 are 1, 2, 4, - ;; 71 and 142; so d(284) = 220. - ;; - ;; Evaluate the sum of all the amicable numbers under 10000. - (labels ((sum-of-divisors (n) - (sum (proper-divisors n))) - (amicablep (n) - (let ((other (sum-of-divisors n))) - (and (not= n other) - (= n (sum-of-divisors other)))))) - (sum (remove-if-not #'amicablep (range 1 10000))))) - -(defun problem-22 () - ;; Using names.txt, a 46K text file containing over five-thousand first names, - ;; begin by sorting it into alphabetical order. Then working out the - ;; alphabetical value for each name, multiply this value by its alphabetical - ;; position in the list to obtain a name score. - ;; - ;; For example, when the list is sorted into alphabetical order, COLIN, which - ;; is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list. So, - ;; COLIN would obtain a score of 938 × 53 = 49714. - ;; - ;; What is the total of all the name scores in the file? - (labels ((read-names () - (-<> "data/22-names.txt" - parse-strings-file - (sort <> #'string<))) - (name-score (name) - (sum name :key #'letter-number))) - (iterate (for (position . name) :in - (enumerate (read-names) :start 1)) - (sum (* position (name-score name)))))) - -(defun problem-23 () - ;; A perfect number is a number for which the sum of its proper divisors is - ;; exactly equal to the number. For example, the sum of the proper divisors of - ;; 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect - ;; number. - ;; - ;; A number n is called deficient if the sum of its proper divisors is less - ;; than n and it is called abundant if this sum exceeds n. - ;; - ;; As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest - ;; number that can be written as the sum of two abundant numbers is 24. By - ;; mathematical analysis, it can be shown that all integers greater than 28123 - ;; can be written as the sum of two abundant numbers. However, this upper - ;; limit cannot be reduced any further by analysis even though it is known - ;; that the greatest number that cannot be expressed as the sum of two - ;; abundant numbers is less than this limit. - ;; - ;; Find the sum of all the positive integers which cannot be written as the - ;; sum of two abundant numbers. - (let* ((limit 28123) - (abundant-numbers - (make-hash-set :initial-contents - (remove-if-not #'abundantp (irange 1 limit))))) - (flet ((abundant-sum-p (n) - (iterate (for a :in-hashset abundant-numbers) - (when (hset-contains-p abundant-numbers (- n a)) - (return t))))) - (sum (remove-if #'abundant-sum-p (irange 1 limit)))))) - -(defun problem-24 () - ;; A permutation is an ordered arrangement of objects. For example, 3124 is - ;; one possible permutation of the digits 1, 2, 3 and 4. If all of the - ;; permutations are listed numerically or alphabetically, we call it - ;; lexicographic order. The lexicographic permutations of 0, 1 and 2 are: - ;; - ;; 012 021 102 120 201 210 - ;; - ;; What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, - ;; 4, 5, 6, 7, 8 and 9? - (-<> "0123456789" - (gathering-vector (:size (factorial (length <>))) - (map-permutations (compose #'gather #'parse-integer) <> - :copy nil)) - (sort <> #'<) - (elt <> (1- 1000000)))) - -(defun problem-25 () - ;; The Fibonacci sequence is defined by the recurrence relation: - ;; - ;; Fn = Fn−1 + Fn−2, where F1 = 1 and F2 = 1. - ;; - ;; Hence the first 12 terms will be: - ;; - ;; F1 = 1 - ;; F2 = 1 - ;; F3 = 2 - ;; F4 = 3 - ;; F5 = 5 - ;; F6 = 8 - ;; F7 = 13 - ;; F8 = 21 - ;; F9 = 34 - ;; F10 = 55 - ;; F11 = 89 - ;; F12 = 144 - ;; - ;; The 12th term, F12, is the first term to contain three digits. - ;; - ;; What is the index of the first term in the Fibonacci sequence to contain - ;; 1000 digits? - (iterate (for f :in-fibonacci t) - (for i :from 1) - (finding i :such-that (= 1000 (digits-length f))))) - -(defun problem-26 () - ;; A unit fraction contains 1 in the numerator. The decimal representation of - ;; the unit fractions with denominators 2 to 10 are given: - ;; - ;; 1/2 = 0.5 - ;; 1/3 = 0.(3) - ;; 1/4 = 0.25 - ;; 1/5 = 0.2 - ;; 1/6 = 0.1(6) - ;; 1/7 = 0.(142857) - ;; 1/8 = 0.125 - ;; 1/9 = 0.(1) - ;; 1/10 = 0.1 - ;; - ;; Where 0.1(6) means 0.166666..., and has a 1-digit recurring cycle. It can - ;; be seen that 1/7 has a 6-digit recurring cycle. - ;; - ;; Find the value of d < 1000 for which 1/d contains the longest recurring - ;; cycle in its decimal fraction part. - (iterate - ;; 2 and 5 are the only primes that aren't coprime to 10 - (for i :in (set-difference (primes-below 1000) '(2 5))) - (finding i :maximizing (multiplicative-order 10 i)))) - -(defun problem-27 () - ;; Euler discovered the remarkable quadratic formula: - ;; - ;; n² + n + 41 - ;; - ;; It turns out that the formula will produce 40 primes for the consecutive - ;; integer values 0 ≤ n ≤ 39. However, when n=40, 40² + 40 + 41 = 40(40 + 1) - ;; + 41 is divisible by 41, and certainly when n=41, 41² + 41 + 41 is clearly - ;; divisible by 41. - ;; - ;; The incredible formula n² − 79n + 1601 was discovered, which produces 80 - ;; primes for the consecutive values 0 ≤ n ≤ 79. The product of the - ;; coefficients, −79 and 1601, is −126479. - ;; - ;; Considering quadratics of the form: - ;; - ;; n² + an + b, where |a| < 1000 and |b| ≤ 1000 - ;; - ;; where |n| is the modulus/absolute value of n - ;; e.g. |11| = 11 and |−4| = 4 - ;; - ;; Find the product of the coefficients, a and b, for the quadratic expression - ;; that produces the maximum number of primes for consecutive values of n, - ;; starting with n=0. - (flet ((primes-produced (a b) - (iterate (for n :from 0) - (while (primep (+ (square n) (* a n) b))) - (counting t)))) - (iterate (for-nested ((a :from -999 :to 999) - (b :from -1000 :to 1000))) - (finding (* a b) :maximizing (primes-produced a b))))) - -(defun problem-28 () - ;; Starting with the number 1 and moving to the right in a clockwise direction - ;; a 5 by 5 spiral is formed as follows: - ;; - ;; 21 22 23 24 25 - ;; 20 7 8 9 10 - ;; 19 6 1 2 11 - ;; 18 5 4 3 12 - ;; 17 16 15 14 13 - ;; - ;; It can be verified that the sum of the numbers on the diagonals is 101. - ;; - ;; What is the sum of the numbers on the diagonals in a 1001 by 1001 spiral - ;; formed in the same way? - (iterate (for size :from 1 :to 1001 :by 2) - (summing (apply #'+ (number-spiral-corners size))))) - -(defun problem-29 () - ;; Consider all integer combinations of a^b for 2 ≤ a ≤ 5 and 2 ≤ b ≤ 5: - ;; - ;; 2²=4, 2³=8, 2⁴=16, 2⁵=32 - ;; 3²=9, 3³=27, 3⁴=81, 3⁵=243 - ;; 4²=16, 4³=64, 4⁴=256, 4⁵=1024 - ;; 5²=25, 5³=125, 5⁴=625, 5⁵=3125 - ;; - ;; If they are then placed in numerical order, with any repeats removed, we - ;; get the following sequence of 15 distinct terms: - ;; - ;; 4, 8, 9, 16, 25, 27, 32, 64, 81, 125, 243, 256, 625, 1024, 3125 - ;; - ;; How many distinct terms are in the sequence generated by a^b for - ;; 2 ≤ a ≤ 100 and 2 ≤ b ≤ 100? - (length (iterate (for-nested ((a :from 2 :to 100) - (b :from 2 :to 100))) - (adjoining (expt a b))))) - -(defun problem-30 () - ;; Surprisingly there are only three numbers that can be written as the sum of - ;; fourth powers of their digits: - ;; - ;; 1634 = 1⁴ + 6⁴ + 3⁴ + 4⁴ - ;; 8208 = 8⁴ + 2⁴ + 0⁴ + 8⁴ - ;; 9474 = 9⁴ + 4⁴ + 7⁴ + 4⁴ - ;; - ;; As 1 = 1⁴ is not a sum it is not included. - ;; - ;; The sum of these numbers is 1634 + 8208 + 9474 = 19316. - ;; - ;; Find the sum of all the numbers that can be written as the sum of fifth - ;; powers of their digits. - (flet ((maximum-sum-for-digits (n) - (* (expt 9 5) n)) - (digit-power-sum (n) - (sum (mapcar (rcurry #'expt 5) (digits n))))) - (iterate - ;; We want to find a limit N that's bigger than the maximum possible sum - ;; for its number of digits. - (with limit = (iterate (for digits :from 1) - (for n = (expt 10 digits)) - (while (< n (maximum-sum-for-digits digits))) - (finally (return n)))) - ;; Then just brute-force the thing. - (for i :from 2 :to limit) - (when (= i (digit-power-sum i)) - (summing i))))) - -(defun problem-31 () - ;; In England the currency is made up of pound, £, and pence, p, and there are - ;; eight coins in general circulation: - ;; - ;; 1p, 2p, 5p, 10p, 20p, 50p, £1 (100p) and £2 (200p). - ;; - ;; It is possible to make £2 in the following way: - ;; - ;; 1×£1 + 1×50p + 2×20p + 1×5p + 1×2p + 3×1p - ;; - ;; How many different ways can £2 be made using any number of coins? - (recursively ((amount 200) - (coins '(200 100 50 20 10 5 2 1))) - (cond - ((zerop amount) 1) - ((minusp amount) 0) - ((null coins) 0) - (t (+ (recur (- amount (first coins)) coins) - (recur amount (rest coins))))))) - -(defun problem-32 () - ;; We shall say that an n-digit number is pandigital if it makes use of all - ;; the digits 1 to n exactly once; for example, the 5-digit number, 15234, is - ;; 1 through 5 pandigital. - ;; - ;; The product 7254 is unusual, as the identity, 39 × 186 = 7254, containing - ;; multiplicand, multiplier, and product is 1 through 9 pandigital. - ;; - ;; Find the sum of all products whose multiplicand/multiplier/product identity - ;; can be written as a 1 through 9 pandigital. - ;; - ;; HINT: Some products can be obtained in more than one way so be sure to only - ;; include it once in your sum. - (labels ((split (digits a b) - (values (digits-to-number (subseq digits 0 a)) - (digits-to-number (subseq digits a (+ a b))) - (digits-to-number (subseq digits (+ a b))))) - (check (digits a b) - (multiple-value-bind (a b c) - (split digits a b) - (when (= (* a b) c) - c)))) - (-<> (gathering - (map-permutations (lambda (digits) - (let ((c1 (check digits 3 2)) - (c2 (check digits 4 1))) - (when c1 (gather c1)) - (when c2 (gather c2)))) - #(1 2 3 4 5 6 7 8 9) - :copy nil)) - remove-duplicates - sum))) - -(defun problem-33 () - ;; The fraction 49/98 is a curious fraction, as an inexperienced mathematician - ;; in attempting to simplify it may incorrectly believe that 49/98 = 4/8, - ;; which is correct, is obtained by cancelling the 9s. - ;; - ;; We shall consider fractions like, 30/50 = 3/5, to be trivial examples. - ;; - ;; There are exactly four non-trivial examples of this type of fraction, less - ;; than one in value, and containing two digits in the numerator and - ;; denominator. - ;; - ;; If the product of these four fractions is given in its lowest common terms, - ;; find the value of the denominator. - (labels ((safe/ (a b) - (unless (zerop b) (/ a b))) - (cancel (digit other digits) - (destructuring-bind (x y) digits - (remove nil (list (when (= digit x) (safe/ other y)) - (when (= digit y) (safe/ other x)))))) - (cancellations (numerator denominator) - (let ((nd (digits numerator)) - (dd (digits denominator))) - (append (cancel (first nd) (second nd) dd) - (cancel (second nd) (first nd) dd)))) - (curiousp (numerator denominator) - (member (/ numerator denominator) - (cancellations numerator denominator))) - (trivialp (numerator denominator) - (and (dividesp numerator 10) - (dividesp denominator 10)))) - (iterate - (with result = 1) - (for numerator :from 10 :to 99) - (iterate (for denominator :from (1+ numerator) :to 99) - (when (and (curiousp numerator denominator) - (not (trivialp numerator denominator))) - (mulf result (/ numerator denominator)))) - (finally (return (denominator result)))))) - -(defun problem-34 () - ;; 145 is a curious number, as 1! + 4! + 5! = 1 + 24 + 120 = 145. - ;; - ;; Find the sum of all numbers which are equal to the sum of the factorial of - ;; their digits. - ;; - ;; Note: as 1! = 1 and 2! = 2 are not sums they are not included. - (iterate - (for n :from 3 :to 1000000) - ;; have to use funcall here because `sum` is an iterate keyword. kill me. - (when (= n (funcall #'sum (digits n) :key #'factorial)) - (summing n)))) - -(defun problem-35 () - ;; The number, 197, is called a circular prime because all rotations of the - ;; digits: 197, 971, and 719, are themselves prime. - ;; - ;; There are thirteen such primes below 100: 2, 3, 5, 7, 11, 13, 17, 31, 37, - ;; 71, 73, 79, and 97. - ;; - ;; How many circular primes are there below one million? - (labels ((rotate (n distance) - (multiple-value-bind (hi lo) - (truncate n (expt 10 distance)) - (+ (* (expt 10 (digits-length hi)) lo) - hi))) - (rotations (n) - (mapcar (curry #'rotate n) (range 1 (digits-length n)))) - (circular-prime-p (n) - (every #'primep (rotations n)))) - (iterate (for i :in-vector (sieve 1000000)) - (counting (circular-prime-p i))))) - -(defun problem-36 () - ;; The decimal number, 585 = 1001001001 (binary), is palindromic in both - ;; bases. - ;; - ;; Find the sum of all numbers, less than one million, which are palindromic - ;; in base 10 and base 2. - ;; - ;; (Please note that the palindromic number, in either base, may not include - ;; leading zeros.) - (iterate (for i :from 1 :below 1000000) - (when (and (palindromep i 10) - (palindromep i 2)) - (sum i)))) - -(defun problem-37 () - ;; The number 3797 has an interesting property. Being prime itself, it is - ;; possible to continuously remove digits from left to right, and remain prime - ;; at each stage: 3797, 797, 97, and 7. Similarly we can work from right to - ;; left: 3797, 379, 37, and 3. - ;; - ;; Find the sum of the only eleven primes that are both truncatable from left - ;; to right and right to left. - ;; - ;; NOTE: 2, 3, 5, and 7 are not considered to be truncatable primes. - (labels ((truncations (n) - (iterate (for i :from 0 :below (digits-length n)) - (collect (truncate-number-left n i)) - (collect (truncate-number-right n i)))) - (truncatablep (n) - (every #'primep (truncations n)))) - (iterate - (with count = 0) - (for i :from 11 :by 2) - (when (truncatablep i) - (sum i) - (incf count)) - (while (< count 11))))) - -(defun problem-38 () - ;; Take the number 192 and multiply it by each of 1, 2, and 3: - ;; - ;; 192 × 1 = 192 - ;; 192 × 2 = 384 - ;; 192 × 3 = 576 - ;; - ;; By concatenating each product we get the 1 to 9 pandigital, 192384576. We - ;; will call 192384576 the concatenated product of 192 and (1,2,3) - ;; - ;; The same can be achieved by starting with 9 and multiplying by 1, 2, 3, 4, - ;; and 5, giving the pandigital, 918273645, which is the concatenated product - ;; of 9 and (1,2,3,4,5). - ;; - ;; What is the largest 1 to 9 pandigital 9-digit number that can be formed as - ;; the concatenated product of an integer with (1,2, ... , n) where n > 1? - (labels ((concatenated-product (number i) - (apply #'concatenate-integers - (iterate (for n :from 1 :to i) - (collect (* number n)))))) - (iterate - main - (for base :from 1) - ;; base can't be more than 5 digits long because we have to concatenate at - ;; least two products of it - (while (digits<= base 5)) - (iterate (for n :from 2) - (for result = (concatenated-product base n)) - ;; result is only ever going to grow larger, so once we pass the - ;; nine digit mark we can stop - (while (digits<= result 9)) - (when (pandigitalp result) - (in main (maximizing result))))))) - -(defun problem-39 () - ;; If p is the perimeter of a right angle triangle with integral length sides, - ;; {a,b,c}, there are exactly three solutions for p = 120. - ;; - ;; {20,48,52}, {24,45,51}, {30,40,50} - ;; - ;; For which value of p ≤ 1000, is the number of solutions maximised? - (iterate - (for p :from 1 :to 1000) - (finding p :maximizing (length (pythagorean-triplets-of-perimeter p))))) - -(defun problem-40 () - ;; An irrational decimal fraction is created by concatenating the positive - ;; integers: - ;; - ;; 0.123456789101112131415161718192021... - ;; - ;; It can be seen that the 12th digit of the fractional part is 1. - ;; - ;; If dn represents the nth digit of the fractional part, find the value of - ;; the following expression. - ;; - ;; d1 × d10 × d100 × d1000 × d10000 × d100000 × d1000000 - (iterate - top - (with index = 0) - (for digits :key #'digits :from 1) - (iterate (for d :in digits) - (incf index) - (when (member index '(1 10 100 1000 10000 100000 1000000)) - (in top (multiplying d)) - (when (= index 1000000) - (in top (terminate))))))) - -(defun problem-41 () - ;; We shall say that an n-digit number is pandigital if it makes use of all - ;; the digits 1 to n exactly once. For example, 2143 is a 4-digit pandigital - ;; and is also prime. - ;; - ;; What is the largest n-digit pandigital prime that exists? - (iterate - ;; There's a clever observation which reduces the upper bound from 9 to - ;; 7 from "gamma" in the forum: - ;; - ;; > Note: Nine numbers cannot be done (1+2+3+4+5+6+7+8+9=45 => always dividable by 3) - ;; > Note: Eight numbers cannot be done (1+2+3+4+5+6+7+8=36 => always dividable by 3) - (for n :downfrom 7) - (thereis (apply (nullary #'max) - (remove-if-not #'primep (pandigitals 1 n)))))) - -(defun problem-42 () - ;; The nth term of the sequence of triangle numbers is given by, tn = ½n(n+1); - ;; so the first ten triangle numbers are: - ;; - ;; 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ... - ;; - ;; By converting each letter in a word to a number corresponding to its - ;; alphabetical position and adding these values we form a word value. For - ;; example, the word value for SKY is 19 + 11 + 25 = 55 = t10. If the word - ;; value is a triangle number then we shall call the word a triangle word. - ;; - ;; Using words.txt (right click and 'Save Link/Target As...'), a 16K text file - ;; containing nearly two-thousand common English words, how many are triangle - ;; words? - (labels ((word-value (word) - (sum word :key #'letter-number)) - (triangle-word-p (word) - (trianglep (word-value word)))) - (count-if #'triangle-word-p (parse-strings-file "data/42-words.txt")))) - -(defun problem-43 () - ;; The number, 1406357289, is a 0 to 9 pandigital number because it is made up - ;; of each of the digits 0 to 9 in some order, but it also has a rather - ;; interesting sub-string divisibility property. - ;; - ;; Let d1 be the 1st digit, d2 be the 2nd digit, and so on. In this way, we - ;; note the following: - ;; - ;; d2d3d4=406 is divisible by 2 - ;; d3d4d5=063 is divisible by 3 - ;; d4d5d6=635 is divisible by 5 - ;; d5d6d7=357 is divisible by 7 - ;; d6d7d8=572 is divisible by 11 - ;; d7d8d9=728 is divisible by 13 - ;; d8d9d10=289 is divisible by 17 - ;; - ;; Find the sum of all 0 to 9 pandigital numbers with this property. - (labels ((extract3 (digits start) - (digits-to-number (subseq digits start (+ 3 start)))) - (interestingp (n) - (let ((digits (digits n))) - ;; eat shit mathematicians, indexes start from zero - (and (dividesp (extract3 digits 1) 2) - (dividesp (extract3 digits 2) 3) - (dividesp (extract3 digits 3) 5) - (dividesp (extract3 digits 4) 7) - (dividesp (extract3 digits 5) 11) - (dividesp (extract3 digits 6) 13) - (dividesp (extract3 digits 7) 17))))) - (sum (remove-if-not #'interestingp (pandigitals 0 9))))) - -(defun problem-44 () - ;; Pentagonal numbers are generated by the formula, Pn=n(3n−1)/2. The first - ;; ten pentagonal numbers are: - ;; - ;; 1, 5, 12, 22, 35, 51, 70, 92, 117, 145, ... - ;; - ;; It can be seen that P4 + P7 = 22 + 70 = 92 = P8. However, their difference, - ;; 70 − 22 = 48, is not pentagonal. - ;; - ;; Find the pair of pentagonal numbers, Pj and Pk, for which their sum and - ;; difference are pentagonal and D = |Pk − Pj| is minimised; what is the value - ;; of D? - (flet ((interestingp (px py) - (and (pentagonp (+ py px)) - (pentagonp (- py px))))) - (iterate - (with result = most-positive-fixnum) ; my kingdom for `CL:INFINITY` - (for y :from 2) - (for z :from 3) - (for py = (pentagon y)) - (for pz = (pentagon z)) - (when (>= (- pz py) result) - (return result)) - (iterate - (for x :from (1- y) :downto 1) - (for px = (pentagon x)) - (when (interestingp px py) - (let ((distance (- py px))) - (when (< distance result) - ;; TODO: This isn't quite right, because this is just the FIRST - ;; number we find -- we haven't guaranteed that it's the SMALLEST - ;; one we'll ever see. But it happens to accidentally be the - ;; correct one, and until I get around to rewriting this with - ;; priority queues it'll have to do. - (return-from problem-44 distance))) - (return)))))) - -(defun problem-45 () - ;; Triangle, pentagonal, and hexagonal numbers are generated by the following - ;; formulae: - ;; - ;; Triangle Tn=n(n+1)/2 1, 3, 6, 10, 15, ... - ;; Pentagonal Pn=n(3n−1)/2 1, 5, 12, 22, 35, ... - ;; Hexagonal Hn=n(2n−1) 1, 6, 15, 28, 45, ... - ;; - ;; It can be verified that T285 = P165 = H143 = 40755. - ;; - ;; Find the next triangle number that is also pentagonal and hexagonal. - (iterate - (for n :key #'triangle :from 286) - (finding n :such-that (and (pentagonp n) (hexagonp n))))) - -(defun problem-46 () - ;; It was proposed by Christian Goldbach that every odd composite number can - ;; be written as the sum of a prime and twice a square. - ;; - ;; 9 = 7 + 2×1² - ;; 15 = 7 + 2×2² - ;; 21 = 3 + 2×3² - ;; 25 = 7 + 2×3² - ;; 27 = 19 + 2×2² - ;; 33 = 31 + 2×1² - ;; - ;; It turns out that the conjecture was false. - ;; - ;; What is the smallest odd composite that cannot be written as the sum of - ;; a prime and twice a square? - (flet ((counterexamplep (n) - (iterate - (for prime :in-vector (sieve n)) - (never (squarep (/ (- n prime) 2)))))) - (iterate - (for i :from 1 :by 2) - (finding i :such-that (and (compositep i) - (counterexamplep i)))))) - -(defun problem-47 () - ;; The first two consecutive numbers to have two distinct prime factors are: - ;; - ;; 14 = 2 × 7 - ;; 15 = 3 × 5 - ;; - ;; The first three consecutive numbers to have three distinct prime factors are: - ;; - ;; 644 = 2² × 7 × 23 - ;; 645 = 3 × 5 × 43 - ;; 646 = 2 × 17 × 19 - ;; - ;; Find the first four consecutive integers to have four distinct prime - ;; factors each. What is the first of these numbers? - (flet ((factor-count (n) - (length (remove-duplicates (prime-factorization n))))) - (iterate - (with run = 0) - (for i :from 1) - (if (= 4 (factor-count i)) - (incf run) - (setf run 0)) - (finding (- i 3) :such-that (= run 4))))) - -(defun problem-48 () - ;; The series, 1^1 + 2^2 + 3^3 + ... + 10^10 = 10405071317. - ;; - ;; Find the last ten digits of the series, 1^1 + 2^2 + 3^3 + ... + 1000^1000. - (-<> (irange 1 1000) - (mapcar #'expt <> <>) - sum - (mod <> (expt 10 10)))) - -(defun problem-49 () - ;; The arithmetic sequence, 1487, 4817, 8147, in which each of the terms - ;; increases by 3330, is unusual in two ways: (i) each of the three terms are - ;; prime, and, (ii) each of the 4-digit numbers are permutations of one - ;; another. - ;; - ;; There are no arithmetic sequences made up of three 1-, 2-, or 3-digit - ;; primes, exhibiting this property, but there is one other 4-digit increasing - ;; sequence. - ;; - ;; What 12-digit number do you form by concatenating the three terms in this - ;; sequence? - (labels ((permutation= (a b) - (orderless-equal (digits a) (digits b))) - (length>=3 (list) - (>= (length list) 3)) - (arithmetic-sequence-p (seq) - (apply #'= (mapcar (curry #'apply #'-) - (n-grams 2 seq)))) - (has-arithmetic-sequence-p (seq) - (map-combinations - (lambda (s) - (when (arithmetic-sequence-p s) - (return-from has-arithmetic-sequence-p s))) - (sort seq #'<) - :length 3) - nil)) - (-<> (primes-in 1000 9999) - (equivalence-classes #'permutation= <>) ; find all permutation groups - (remove-if-not #'length>=3 <>) ; make sure they have at leat 3 elements - (mapcar #'has-arithmetic-sequence-p <>) - (remove nil <>) - (remove-if (lambda (s) (= (first s) 1487)) <>) ; remove the example - first - (mapcan #'digits <>) - digits-to-number))) - -(defun problem-50 () - ;; The prime 41, can be written as the sum of six consecutive primes: - ;; - ;; 41 = 2 + 3 + 5 + 7 + 11 + 13 - ;; - ;; This is the longest sum of consecutive primes that adds to a prime below - ;; one-hundred. - ;; - ;; The longest sum of consecutive primes below one-thousand that adds to - ;; a prime, contains 21 terms, and is equal to 953. - ;; - ;; Which prime, below one-million, can be written as the sum of the most - ;; consecutive primes? - (let ((primes (sieve 1000000))) - (flet ((score (start) - (iterate - (with score = 0) - (with winner = 0) - (for run :from 1) - (for prime :in-vector primes :from start) - (summing prime :into sum) - (while (< sum 1000000)) - (when (primep sum) - (setf score run - winner sum)) - (finally (return (values score winner)))))) - (iterate - (for (values score winner) - :key #'score :from 0 :below (length primes)) - (finding winner :maximizing score))))) - -(defun problem-51 () - ;; By replacing the 1st digit of the 2-digit number *3, it turns out that six - ;; of the nine possible values: 13, 23, 43, 53, 73, and 83, are all prime. - ;; - ;; By replacing the 3rd and 4th digits of 56**3 with the same digit, this - ;; 5-digit number is the first example having seven primes among the ten - ;; generated numbers, yielding the family: 56003, 56113, 56333, 56443, 56663, - ;; 56773, and 56993. Consequently 56003, being the first member of this - ;; family, is the smallest prime with this property. - ;; - ;; Find the smallest prime which, by replacing part of the number (not - ;; necessarily adjacent digits) with the same digit, is part of an eight prime - ;; value family. - (labels - ((patterns (prime) - (iterate (with size = (digits-length prime)) - (with indices = (range 0 size)) - (for i :from 1 :below size) - (appending (combinations indices :length i)))) - (apply-pattern-digit (prime pattern new-digit) - (iterate (with result = (digits prime)) - (for index :in pattern) - (when (and (zerop index) (zerop new-digit)) - (leave)) - (setf (nth index result) new-digit) - (finally (return (digits-to-number result))))) - (apply-pattern (prime pattern) - (iterate (for digit in (irange 0 9)) - (for result = (apply-pattern-digit prime pattern digit)) - (when (and result (primep result)) - (collect result)))) - (apply-patterns (prime) - (mapcar (curry #'apply-pattern prime) (patterns prime))) - (winnerp (prime) - (find-if (curry #'length= 8) (apply-patterns prime)))) - (-<> (iterate (for i :from 3 :by 2) - (thereis (and (primep i) (winnerp i)))) - (sort< <>) - first))) - -(defun problem-52 () - ;; It can be seen that the number, 125874, and its double, 251748, contain - ;; exactly the same digits, but in a different order. - ;; - ;; Find the smallest positive integer, x, such that 2x, 3x, 4x, 5x, and 6x, - ;; contain the same digits. - (iterate (for i :from 1) - (for digits = (digits i)) - (finding i :such-that - (every (lambda (n) - (orderless-equal digits (digits (* n i)))) - '(2 3 4 5 6))))) - -(defun problem-53 () - ;; There are exactly ten ways of selecting three from five, 12345: - ;; - ;; 123, 124, 125, 134, 135, 145, 234, 235, 245, and 345 - ;; - ;; In combinatorics, we use the notation, 5C3 = 10. - ;; - ;; In general, - ;; - ;; nCr = n! / r!(n−r)! - ;; - ;; where r ≤ n, n! = n×(n−1)×...×3×2×1, and 0! = 1. - ;; - ;; It is not until n = 23, that a value exceeds one-million: 23C10 = 1144066. - ;; - ;; How many, not necessarily distinct, values of nCr, for 1 ≤ n ≤ 100, are - ;; greater than one-million? - (iterate - main - (for n :from 1 :to 100) - (iterate - (for r :from 1 :to n) - (for nCr = (binomial-coefficient n r)) - (in main (counting (> nCr 1000000)))))) - -(defun problem-54 () - ;; In the card game poker, a hand consists of five cards and are ranked, from - ;; lowest to highest, in the following way: - ;; - ;; High Card: Highest value card. - ;; One Pair: Two cards of the same value. - ;; Two Pairs: Two different pairs. - ;; Three of a Kind: Three cards of the same value. - ;; Straight: All cards are consecutive values. - ;; Flush: All cards of the same suit. - ;; Full House: Three of a kind and a pair. - ;; Four of a Kind: Four cards of the same value. - ;; Straight Flush: All cards are consecutive values of same suit. - ;; Royal Flush: Ten, Jack, Queen, King, Ace, in same suit. - ;; - ;; The cards are valued in the order: - ;; 2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace. - ;; - ;; If two players have the same ranked hands then the rank made up of the - ;; highest value wins; for example, a pair of eights beats a pair of fives - ;; (see example 1 below). But if two ranks tie, for example, both players have - ;; a pair of queens, then highest cards in each hand are compared (see example - ;; 4 below); if the highest cards tie then the next highest cards are - ;; compared, and so on. - ;; - ;; The file, poker.txt, contains one-thousand random hands dealt to two - ;; players. Each line of the file contains ten cards (separated by a single - ;; space): the first five are Player 1's cards and the last five are Player - ;; 2's cards. You can assume that all hands are valid (no invalid characters - ;; or repeated cards), each player's hand is in no specific order, and in each - ;; hand there is a clear winner. - ;; - ;; How many hands does Player 1 win? - (iterate (for line :in-file "data/54-poker.txt" :using #'read-line) - (for cards = (mapcar #'euler.poker::parse-card - (cl-strings:split line #\space))) - (for p1 = (take 5 cards)) - (for p2 = (drop 5 cards)) - (counting (euler.poker::poker-hand-beats-p p1 p2)))) - -(defun problem-55 () - ;; If we take 47, reverse and add, 47 + 74 = 121, which is palindromic. - ;; - ;; Not all numbers produce palindromes so quickly. For example, - ;; - ;; 349 + 943 = 1292, - ;; 1292 + 2921 = 4213 - ;; 4213 + 3124 = 7337 - ;; - ;; That is, 349 took three iterations to arrive at a palindrome. - ;; - ;; Although no one has proved it yet, it is thought that some numbers, like - ;; 196, never produce a palindrome. A number that never forms a palindrome - ;; through the reverse and add process is called a Lychrel number. Due to the - ;; theoretical nature of these numbers, and for the purpose of this problem, - ;; we shall assume that a number is Lychrel until proven otherwise. In - ;; addition you are given that for every number below ten-thousand, it will - ;; either (i) become a palindrome in less than fifty iterations, or, (ii) no - ;; one, with all the computing power that exists, has managed so far to map it - ;; to a palindrome. In fact, 10677 is the first number to be shown to require - ;; over fifty iterations before producing a palindrome: - ;; 4668731596684224866951378664 (53 iterations, 28-digits). - ;; - ;; Surprisingly, there are palindromic numbers that are themselves Lychrel - ;; numbers; the first example is 4994. - ;; - ;; How many Lychrel numbers are there below ten-thousand? - (labels ((lychrel (n) - (+ n (reverse-integer n))) - (lychrelp (n) - (iterate - (repeat 50) - (for i :iterating #'lychrel :seed n) - (never (palindromep i))))) - (iterate (for i :from 0 :below 10000) - (counting (lychrelp i))))) - -(defun problem-56 () - ;; A googol (10^100) is a massive number: one followed by one-hundred zeros; - ;; 100^100 is almost unimaginably large: one followed by two-hundred zeros. - ;; Despite their size, the sum of the digits in each number is only 1. - ;; - ;; Considering natural numbers of the form, a^b, where a, b < 100, what is the - ;; maximum digital sum? - (iterate (for-nested ((a :from 1 :below 100) - (b :from 1 :below 100))) - (maximizing (funcall #'sum (digits (expt a b)))))) - -(defun problem-57 () - ;; It is possible to show that the square root of two can be expressed as an - ;; infinite continued fraction. - ;; - ;; √ 2 = 1 + 1/(2 + 1/(2 + 1/(2 + ... ))) = 1.414213... - ;; - ;; By expanding this for the first four iterations, we get: - ;; - ;; 1 + 1/2 = 3/2 = 1.5 - ;; 1 + 1/(2 + 1/2) = 7/5 = 1.4 - ;; 1 + 1/(2 + 1/(2 + 1/2)) = 17/12 = 1.41666... - ;; 1 + 1/(2 + 1/(2 + 1/(2 + 1/2))) = 41/29 = 1.41379... - ;; - ;; The next three expansions are 99/70, 239/169, and 577/408, but the eighth - ;; expansion, 1393/985, is the first example where the number of digits in the - ;; numerator exceeds the number of digits in the denominator. - ;; - ;; In the first one-thousand expansions, how many fractions contain - ;; a numerator with more digits than denominator? - (iterate - (repeat 1000) - (for i :initially 1/2 :then (/ (+ 2 i))) - (for expansion = (1+ i)) - (counting (> (digits-length (numerator expansion)) - (digits-length (denominator expansion)))))) - -(defun problem-58 () - ;; Starting with 1 and spiralling anticlockwise in the following way, a square - ;; spiral with side length 7 is formed. - ;; - ;; 37 36 35 34 33 32 31 - ;; 38 17 16 15 14 13 30 - ;; 39 18 5 4 3 12 29 - ;; 40 19 6 1 2 11 28 - ;; 41 20 7 8 9 10 27 - ;; 42 21 22 23 24 25 26 - ;; 43 44 45 46 47 48 49 - ;; - ;; It is interesting to note that the odd squares lie along the bottom right - ;; diagonal, but what is more interesting is that 8 out of the 13 numbers - ;; lying along both diagonals are prime; that is, a ratio of 8/13 ≈ 62%. - ;; - ;; If one complete new layer is wrapped around the spiral above, a square - ;; spiral with side length 9 will be formed. If this process is continued, - ;; what is the side length of the square spiral for which the ratio of primes - ;; along both diagonals first falls below 10%? - (labels ((score (value) - (if (primep value) 1 0)) - (primes-in-layer (size) - (sum (number-spiral-corners size) :key #'score))) - (iterate - (for size :from 3 :by 2) - (for count :from 5 :by 4) - (sum (primes-in-layer size) :into primes) - (for ratio = (/ primes count)) - (finding size :such-that (< ratio 1/10))))) - -(defun problem-59 () - ;; Each character on a computer is assigned a unique code and the preferred - ;; standard is ASCII (American Standard Code for Information Interchange). - ;; For example, uppercase A = 65, asterisk (*) = 42, and lowercase k = 107. - ;; - ;; A modern encryption method is to take a text file, convert the bytes to - ;; ASCII, then XOR each byte with a given value, taken from a secret key. The - ;; advantage with the XOR function is that using the same encryption key on - ;; the cipher text, restores the plain text; for example, 65 XOR 42 = 107, - ;; then 107 XOR 42 = 65. - ;; - ;; For unbreakable encryption, the key is the same length as the plain text - ;; message, and the key is made up of random bytes. The user would keep the - ;; encrypted message and the encryption key in different locations, and - ;; without both "halves", it is impossible to decrypt the message. - ;; - ;; Unfortunately, this method is impractical for most users, so the modified - ;; method is to use a password as a key. If the password is shorter than the - ;; message, which is likely, the key is repeated cyclically throughout the - ;; message. The balance for this method is using a sufficiently long password - ;; key for security, but short enough to be memorable. - ;; - ;; Your task has been made easy, as the encryption key consists of three lower - ;; case characters. Using cipher.txt (right click and 'Save Link/Target - ;; As...'), a file containing the encrypted ASCII codes, and the knowledge - ;; that the plain text must contain common English words, decrypt the message - ;; and find the sum of the ASCII values in the original text. - (let* ((data (-<> "data/59-cipher.txt" - read-file-into-string - (substitute #\space #\, <>) - read-all-from-string)) - (raw-words (-<> "/usr/share/dict/words" - read-file-into-string - (cl-strings:split <> #\newline) - (mapcar #'string-downcase <>))) - (words (make-hash-set :test 'equal :initial-contents raw-words))) - (labels - ((stringify (codes) - (map 'string #'code-char codes)) - (apply-cipher (key) - (iterate (for number :in data) - (for k :in-looping key) - (collect (logxor number k)))) - (score-keyword (keyword) - (-<> (apply-cipher keyword) - (stringify <>) - (string-downcase <>) - (cl-strings:split <>) - (remove-if-not (curry #'hset-contains-p words) <>) - length)) - (answer (keyword) - ;; (pr (stringify keyword)) ; keyword is "god", lol - (sum (apply-cipher keyword)))) - (iterate (for-nested ((a :from (char-code #\a) :to (char-code #\z)) - (b :from (char-code #\a) :to (char-code #\z)) - (c :from (char-code #\a) :to (char-code #\z)))) - (for keyword = (list a b c)) - (finding (answer keyword) :maximizing (score-keyword keyword)))))) - -(defun problem-60 () - ;; The primes 3, 7, 109, and 673, are quite remarkable. By taking any two - ;; primes and concatenating them in any order the result will always be prime. - ;; For example, taking 7 and 109, both 7109 and 1097 are prime. The sum of - ;; these four primes, 792, represents the lowest sum for a set of four primes - ;; with this property. - ;; - ;; Find the lowest sum for a set of five primes for which any two primes - ;; concatenate to produce another prime. - (labels-memoized ((concatenates-prime-p (a b) - (and (primep (concatenate-integers a b)) - (primep (concatenate-integers b a))))) - (flet ((satisfiesp (prime primes) - (every (curry #'concatenates-prime-p prime) primes))) - (iterate - main - ;; 2 can never be part of the winning set, because if you concatenate it - ;; in the last position you get an even number. - (with primes = (subseq (sieve 10000) 1)) - (for a :in-vector primes :with-index ai) - (iterate - (for b :in-vector primes :with-index bi :from (1+ ai)) - (when (satisfiesp b (list a)) - (iterate - (for c :in-vector primes :with-index ci :from (1+ bi)) - (when (satisfiesp c (list a b)) - (iterate - (for d :in-vector primes :with-index di :from (1+ ci)) - (when (satisfiesp d (list a b c)) - (iterate - (for e :in-vector primes :from (1+ di)) - (when (satisfiesp e (list a b c d)) - (in main (return-from problem-60 (+ a b c d e))))))))))))))) - -(defun problem-61 () - ;; Triangle, square, pentagonal, hexagonal, heptagonal, and octagonal numbers - ;; are all figurate (polygonal) numbers and are generated by the following - ;; formulae: - ;; - ;; Triangle P3,n=n(n+1)/2 1, 3, 6, 10, 15, ... - ;; Square P4,n=n² 1, 4, 9, 16, 25, ... - ;; Pentagonal P5,n=n(3n−1)/2 1, 5, 12, 22, 35, ... - ;; Hexagonal P6,n=n(2n−1) 1, 6, 15, 28, 45, ... - ;; Heptagonal P7,n=n(5n−3)/2 1, 7, 18, 34, 55, ... - ;; Octagonal P8,n=n(3n−2) 1, 8, 21, 40, 65, ... - ;; - ;; The ordered set of three 4-digit numbers: 8128, 2882, 8281, has three - ;; interesting properties. - ;; - ;; 1. The set is cyclic, in that the last two digits of each number is the - ;; first two digits of the next number (including the last number with the - ;; first). - ;; 2. Each polygonal type: triangle (P3,127=8128), square (P4,91=8281), and - ;; pentagonal (P5,44=2882), is represented by a different number in the - ;; set. - ;; 3. This is the only set of 4-digit numbers with this property. - ;; - ;; Find the sum of the only ordered set of six cyclic 4-digit numbers for - ;; which each polygonal type: triangle, square, pentagonal, hexagonal, - ;; heptagonal, and octagonal, is represented by a different number in the set. - (labels ((numbers (generator) - (iterate (for i :from 1) - (for n = (funcall generator i)) - (while (<= n 9999)) - (when (>= n 1000) - (collect n)))) - (split (number) - (truncate number 100)) - (prefix (number) - (when number - (nth-value 0 (split number)))) - (suffix (number) - (when number - (nth-value 1 (split number)))) - (matches (prefix suffix number) - (multiple-value-bind (p s) - (split number) - (and (or (not prefix) - (= prefix p)) - (or (not suffix) - (= suffix s))))) - (choose (numbers used prefix &optional suffix) - (-<> numbers - (remove-if-not (curry #'matches prefix suffix) <>) - (set-difference <> used))) - (search-sets (sets) - (recursively ((sets sets) - (path nil)) - (destructuring-bind (set . remaining) sets - (if remaining - ;; We're somewhere in the middle, recur on any number whose - ;; prefix matches the suffix of the previous element. - (iterate - (for number :in (choose set path (suffix (car path)))) - (recur remaining (cons number path))) - ;; We're on the last set, we need to find a number that fits - ;; between the penultimate element and first element to - ;; complete the cycle. - (when-let* - ((init (first (last path))) - (prev (car path)) - (final (choose set path (suffix prev) (prefix init)))) - (return-from problem-61 - (sum (reverse (cons (first final) path)))))))))) - (map-permutations #'search-sets - (list (numbers #'triangle) - (numbers #'square) - (numbers #'pentagon) - (numbers #'hexagon) - (numbers #'heptagon) - (numbers #'octagon))))) - -(defun problem-62 () - ;; The cube, 41063625 (345³), can be permuted to produce two other cubes: - ;; 56623104 (384³) and 66430125 (405³). In fact, 41063625 is the smallest cube - ;; which has exactly three permutations of its digits which are also cube. - ;; - ;; Find the smallest cube for which exactly five permutations of its digits - ;; are cube. - (let ((scores (make-hash-table))) ; canonical-repr => (count . first-cube) - ;; Basic strategy from [1] but with some bug fixes. His strategy happens to - ;; work for this specific case, but could be incorrect for others. - ;; - ;; We can't just return as soon as we hit the 5th cubic permutation, because - ;; what if this cube is actually part of a family of 6? Instead we need to - ;; check all other cubes with the same number of digits before making a - ;; final decision to be sure we don't get fooled. - ;; - ;; [1]: http://www.mathblog.dk/project-euler-62-cube-five-permutations/ - (labels ((canonicalize (cube) - (digits-to-number (sort (digits cube) #'>))) - (mark (cube) - (let ((entry (ensure-gethash (canonicalize cube) scores - (cons 0 cube)))) - (incf (car entry)) - entry))) - (iterate - (with i = 1) - (with target = 5) - (with candidates = nil) - (for limit :initially 10 :then (* 10 limit)) - (iterate - (for cube = (cube i)) - (while (< cube limit)) - (incf i) - (for (score . first) = (mark cube)) - (cond ((= score target) (push first candidates)) - ((> score target) (removef candidates first)))) ; tricksy hobbitses - (thereis (apply (nullary #'min) candidates)))))) - -(defun problem-63 () - ;; The 5-digit number, 16807=7^5, is also a fifth power. Similarly, the - ;; 9-digit number, 134217728=8^9, is a ninth power. - ;; - ;; How many n-digit positive integers exist which are also an nth power? - (flet ((score (n) - ;; 10^n will have n+1 digits, so we never need to check beyond that - (iterate (for base :from 1 :below 10) - (for value = (expt base n)) - (counting (= n (digits-length value))))) - (find-bound () - ;; it's 21.something, but I don't really grok why yet - (iterate - (for power :from 1) - (for maximum-possible-digits = (digits-length (expt 9 power))) - (while (>= maximum-possible-digits power)) - (finally (return power))))) - (iterate (for n :from 1 :below (find-bound)) - (sum (score n))))) - -(defun problem-74 () - ;; The number 145 is well known for the property that the sum of the factorial - ;; of its digits is equal to 145: - ;; - ;; 1! + 4! + 5! = 1 + 24 + 120 = 145 - ;; - ;; Perhaps less well known is 169, in that it produces the longest chain of - ;; numbers that link back to 169; it turns out that there are only three such - ;; loops that exist: - ;; - ;; 169 → 363601 → 1454 → 169 - ;; 871 → 45361 → 871 - ;; 872 → 45362 → 872 - ;; - ;; It is not difficult to prove that EVERY starting number will eventually get - ;; stuck in a loop. For example, - ;; - ;; 69 → 363600 → 1454 → 169 → 363601 (→ 1454) - ;; 78 → 45360 → 871 → 45361 (→ 871) - ;; 540 → 145 (→ 145) - ;; - ;; Starting with 69 produces a chain of five non-repeating terms, but the - ;; longest non-repeating chain with a starting number below one million is - ;; sixty terms. - ;; - ;; How many chains, with a starting number below one million, contain exactly - ;; sixty non-repeating terms? - (labels ((digit-factorial (n) - (sum (mapcar #'factorial (digits n)))) - (term-count (n) - (iterate (for i :initially n :then (digit-factorial i)) - (until (member i prev)) - (collect i :into prev) - (counting t)))) - (iterate (for i :from 1 :below 1000000) - (counting (= 60 (term-count i)))))) - -(defun problem-79 () - ;; A common security method used for online banking is to ask the user for - ;; three random characters from a passcode. For example, if the passcode was - ;; 531278, they may ask for the 2nd, 3rd, and 5th characters; the expected - ;; reply would be: 317. - ;; - ;; The text file, keylog.txt, contains fifty successful login attempts. - ;; - ;; Given that the three characters are always asked for in order, analyse - ;; the file so as to determine the shortest possible secret passcode of - ;; unknown length. - (let ((attempts (-<> "data/79-keylog.txt" - read-all-from-file - (mapcar #'digits <>) - (mapcar (rcurry #'coerce 'vector) <>)))) - ;; Everyone in the forum is assuming that there are no duplicate digits in - ;; the passcode, but as someone pointed out this isn't necessarily a safe - ;; assumption. If you have attempts of (12 21) then the shortest passcode - ;; would be 121. So we'll do things the safe way and just brute force it. - (iterate (for passcode :from 1) - (finding passcode :such-that - (every (rcurry #'subsequencep (digits passcode)) - attempts))))) - -(defun problem-92 () - ;; A number chain is created by continuously adding the square of the digits - ;; in a number to form a new number until it has been seen before. - ;; - ;; For example, - ;; 44 → 32 → 13 → 10 → 1 → 1 - ;; 85 → 89 → 145 → 42 → 20 → 4 → 16 → 37 → 58 → 89 - ;; - ;; Therefore any chain that arrives at 1 or 89 will become stuck in an - ;; endless loop. What is most amazing is that EVERY starting number will - ;; eventually arrive at 1 or 89. - ;; - ;; How many starting numbers below ten million will arrive at 89? - (labels ((square-chain-end (i) - (if (or (= 1 i) (= 89 i)) - i - (square-chain-end - (iterate (for d :in-digits-of i) - (summing (square d))))))) - (iterate (for i :from 1 :below 10000000) - (counting (= 89 (square-chain-end i)))))) - -(defun problem-145 () - ;; Some positive integers n have the property that the sum [ n + reverse(n) ] - ;; consists entirely of odd (decimal) digits. For instance, 36 + 63 = 99 and - ;; 409 + 904 = 1313. We will call such numbers reversible; so 36, 63, 409, and - ;; 904 are reversible. Leading zeroes are not allowed in either n or - ;; reverse(n). - ;; - ;; There are 120 reversible numbers below one-thousand. - ;; - ;; How many reversible numbers are there below one-billion (10^9)? - (flet ((reversiblep (n) - (let ((reversed (reverse-integer n))) - (values (unless (zerop (digit 0 n)) - (every #'oddp (digits (+ n reversed)))) - reversed)))) - (iterate - ;; TODO: improve this one - ;; (with limit = 1000000000) there are no 9-digit reversible numbers... - (with limit = 100000000) - (with done = (make-array limit :element-type 'bit :initial-element 0)) - (for i :from 1 :below limit) - (unless (= 1 (aref done i)) - (for (values reversible j) = (reversiblep i)) - (setf (aref done j) 1) - (when reversible - (sum (if (= i j) 1 2))))))) - -(defun problem-357 () - ;; Consider the divisors of 30: 1,2,3,5,6,10,15,30. It can be seen that for - ;; every divisor d of 30, d+30/d is prime. - ;; - ;; Find the sum of all positive integers n not exceeding 100 000 000 such that - ;; for every divisor d of n, d+n/d is prime. - (labels ((check-divisor (n d) - (primep (+ d (truncate n d)))) - (prime-generating-integer-p (n) - (declare (optimize speed) - (type fixnum n) - (inline divisors-up-to-square-root)) - (every (curry #'check-divisor n) - (divisors-up-to-square-root n)))) - ;; Observations about the candidate numbers, from various places around the - ;; web, with my notes for humans: - ;; - ;; * n+1 must be prime. - ;; - ;; Every number has 1 has a factor, which means one of - ;; the tests will be to see if 1+(n/1) is prime. - ;; - ;; * n must be even (except the edge case of 1). - ;; - ;; We know this because n+1 must be prime, and therefore odd, so n itself - ;; must be even. - ;; - ;; * 2+(n/2) must be prime. - ;; - ;; Because all candidates are even, they all have 2 as a divisor (see - ;; above), and so we can do this check before finding all the divisors. - ;; - ;; * n must be squarefree. - ;; - ;; Consider when n is squareful: then there is some prime that occurs more - ;; than once in its factorization. Choosing this prime as the divisor for - ;; the formula gives us d+(n/d). We know that n/d will still be divisible - ;; by d, because we chose a d that occurs multiple times in the - ;; factorization. Obviously d itself is divisible by d. Thus our entire - ;; formula is divisible by d, and so not prime. - ;; - ;; Unfortunately this doesn't really help us much, because there's no - ;; efficient way to tell if a number is squarefree (see - ;; http://mathworld.wolfram.com/Squarefree.html). - ;; - ;; * We only have to check d <= sqrt(n). - ;; - ;; For each divisor d of n we know there's a twin divisor d' such that - ;; d * d' = n (that's what it MEANS for d to be a divisor of n). - ;; - ;; If we plug d into the formula we have d + n/d. - ;; We know that n/d = d', and so we have d + d'. - ;; - ;; If we plug d' into the formula we have d' + n/d'. - ;; We know that n/d' = d, and so we have d' + d. - ;; - ;; This means that plugging d or d' into the formula both result in the - ;; same number, so we only need to bother checking one of them. - (1+ (iterate - ;; edge case: skip 2 (candidiate 1), we'll add it at the end - (for prime :in-vector (sieve (1+ 100000000)) :from 1) - (for candidate = (1- prime)) - (when (and (check-divisor candidate 2) - (prime-generating-integer-p candidate)) - (summing candidate)))))) - -;;;; Tests -------------------------------------------------------------------- -(def-suite :euler) -(in-suite :euler) - -(test p1 (is (= 233168 (problem-1)))) -(test p2 (is (= 4613732 (problem-2)))) -(test p3 (is (= 6857 (problem-3)))) -(test p4 (is (= 906609 (problem-4)))) -(test p5 (is (= 232792560 (problem-5)))) -(test p6 (is (= 25164150 (problem-6)))) -(test p7 (is (= 104743 (problem-7)))) -(test p8 (is (= 23514624000 (problem-8)))) -(test p9 (is (= 31875000 (problem-9)))) -(test p10 (is (= 142913828922 (problem-10)))) -(test p11 (is (= 70600674 (problem-11)))) -(test p12 (is (= 76576500 (problem-12)))) -(test p13 (is (= 5537376230 (problem-13)))) -(test p14 (is (= 837799 (problem-14)))) -(test p15 (is (= 137846528820 (problem-15)))) -(test p16 (is (= 1366 (problem-16)))) -(test p17 (is (= 21124 (problem-17)))) -(test p18 (is (= 1074 (problem-18)))) -(test p19 (is (= 171 (problem-19)))) -(test p20 (is (= 648 (problem-20)))) -(test p21 (is (= 31626 (problem-21)))) -(test p22 (is (= 871198282 (problem-22)))) -(test p23 (is (= 4179871 (problem-23)))) -(test p24 (is (= 2783915460 (problem-24)))) -(test p25 (is (= 4782 (problem-25)))) -(test p26 (is (= 983 (problem-26)))) -(test p27 (is (= -59231 (problem-27)))) -(test p28 (is (= 669171001 (problem-28)))) -(test p29 (is (= 9183 (problem-29)))) -(test p30 (is (= 443839 (problem-30)))) -(test p31 (is (= 73682 (problem-31)))) -(test p32 (is (= 45228 (problem-32)))) -(test p33 (is (= 100 (problem-33)))) -(test p34 (is (= 40730 (problem-34)))) -(test p35 (is (= 55 (problem-35)))) -(test p36 (is (= 872187 (problem-36)))) -(test p37 (is (= 748317 (problem-37)))) -(test p38 (is (= 932718654 (problem-38)))) -(test p39 (is (= 840 (problem-39)))) -(test p40 (is (= 210 (problem-40)))) -(test p41 (is (= 7652413 (problem-41)))) -(test p42 (is (= 162 (problem-42)))) -(test p43 (is (= 16695334890 (problem-43)))) -(test p44 (is (= 5482660 (problem-44)))) -(test p45 (is (= 1533776805 (problem-45)))) -(test p46 (is (= 5777 (problem-46)))) -(test p47 (is (= 134043 (problem-47)))) -(test p48 (is (= 9110846700 (problem-48)))) -(test p49 (is (= 296962999629 (problem-49)))) -(test p50 (is (= 997651 (problem-50)))) -(test p51 (is (= 121313 (problem-51)))) -(test p52 (is (= 142857 (problem-52)))) -(test p53 (is (= 4075 (problem-53)))) -(test p54 (is (= 376 (problem-54)))) -(test p55 (is (= 249 (problem-55)))) -(test p56 (is (= 972 (problem-56)))) -(test p57 (is (= 153 (problem-57)))) -(test p58 (is (= 26241 (problem-58)))) -(test p59 (is (= 107359 (problem-59)))) -(test p60 (is (= 26033 (problem-60)))) -(test p61 (is (= 28684 (problem-61)))) -(test p62 (is (= 127035954683 (problem-62)))) -(test p63 (is (= 49 (problem-63)))) - - -(test p74 (is (= 402 (problem-74)))) -(test p79 (is (= 73162890 (problem-79)))) -(test p92 (is (= 8581146 (problem-92)))) -(test p145 (is (= 608720 (problem-145)))) -(test p357 (is (= 1739023853137 (problem-357)))) - - -(defun run-tests () - (run! :euler)) diff -r 9230e81d302c -r 4f58a841ae48 src/hungarian.lisp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hungarian.lisp Thu Aug 10 20:09:14 2017 -0400 @@ -0,0 +1,375 @@ +(in-package :euler.hungarian) + +;;;; Data +(defstruct (assignment-problem (:conc-name ap-) + (:constructor make-assignment-problem%)) + original-matrix + cost-matrix + rows + cols + starred-rows + starred-cols + covered-rows + covered-cols + primed-rows + primed-cols) + +(define-with-macro (assignment-problem :conc-name ap) + original-matrix + cost-matrix + rows + cols + starred-rows + starred-cols + covered-rows + covered-cols + primed-rows + primed-cols) + +(defun make-assignment-problem (matrix) + (destructuring-bind (rows cols) (array-dimensions matrix) + (make-assignment-problem% + :original-matrix matrix + :cost-matrix (copy-array matrix) + :rows rows + :cols cols + :starred-rows (make-array rows :initial-element nil) + :starred-cols (make-array cols :initial-element nil) + :covered-rows (make-array rows :initial-element nil) + :covered-cols (make-array cols :initial-element nil) + :primed-rows (make-array rows :initial-element nil) + :primed-cols (make-array cols :initial-element nil)))) + + +;;;; Debug +(defun dump (data) + (with-assignment-problem (data) + (format t " ~{ ~A ~^ ~}~%" + (iterate (for col :below cols) + (collect (if (col-covered-p data col) #\X #\space)))) + (dotimes (row rows) + (format t "~A [~{~4D~A~A~^ ~}]~%" + (if (row-covered-p data row) #\X #\space) + (iterate (for col :below cols) + (collect (aref cost-matrix row col)) + (collect + (if (starredp data row col) + #\* + #\space)) + (collect + (if (primedp data row col) + #\' + #\space)))))) + (pr)) + + +;;;; Marking +(defun mark (row col row-vector col-vector) + (setf (aref row-vector row) col + (aref col-vector col) row)) + +(defun unmark (row col row-vector col-vector) + (when (eql (aref row-vector row) col) + (setf (aref row-vector row) nil)) + (when (eql (aref col-vector col) row) + (setf (aref col-vector col) nil))) + + +;;;; Starring +(defun star (data row col) + (with-assignment-problem (data) + (mark row col starred-rows starred-cols))) + +(defun unstar (data row col) + (with-assignment-problem (data) + (unmark row col starred-rows starred-cols))) + +(defun row-starred-p (data row) + (aref (ap-starred-rows data) row)) + +(defun col-starred-p (data col) + (aref (ap-starred-cols data) col)) + +(defun starred-col-for-row (data row) + (aref (ap-starred-rows data) row)) + +(defun starred-row-for-col (data col) + (aref (ap-starred-cols data) col)) + +(defun starred-list (data) + (with-assignment-problem (data) + (gathering + (dotimes (row rows) + (gather (cons row (starred-col-for-row data row))))))) + +(defun starredp (data row col) + (eql (starred-col-for-row data row) col)) + + +;;;; Priming +(defun prime (data row col) + (with-assignment-problem (data) + (mark row col primed-rows primed-cols))) + +(defun unprime (data row col) + (with-assignment-problem (data) + (unmark row col primed-rows primed-cols))) + +(defun unprime-all (data) + (fill (ap-primed-rows data) nil) + (fill (ap-primed-cols data) nil)) + +(defun primed-col-for-row (data row) + (aref (ap-primed-rows data) row)) + +(defun primed-row-for-col (data col) + (aref (ap-primed-cols data) col)) + +(defun primedp (data row col) + (eql (primed-col-for-row data row) col)) + + +;;;; Covering +(defun cover-row (data row) + (setf (aref (ap-covered-rows data) row) t)) + +(defun cover-col (data col) + (setf (aref (ap-covered-cols data) col) t)) + +(defun uncover-row (data row) + (setf (aref (ap-covered-rows data) row) nil)) + +(defun uncover-col (data col) + (setf (aref (ap-covered-cols data) col) nil)) + +(defun row-covered-p (data row) + (aref (ap-covered-rows data) row)) + +(defun col-covered-p (data col) + (aref (ap-covered-cols data) col)) + +(defun uncover-all (data) + (fill (ap-covered-rows data) nil) + (fill (ap-covered-cols data) nil)) + + +(defmacro-driver (FOR var INDEXES-OF element IN vector) + (let ((kwd (if generate 'generate 'for))) + (with-gensyms (vec el) + `(progn + (with ,vec = ,vector) + (with ,el = ,element) + (,kwd ,var :next + (or (position ,el ,vec :start (if-first-time 0 (1+ ,var))) + (terminate))))))) + +(defmacro-driver (FOR var IN-UNCOVERED-ROWS assignment-problem) + (let ((kwd (if generate 'generate 'for))) + `(,kwd ,var :indexes-of nil :in (ap-covered-rows ,assignment-problem)))) + +(defmacro-driver (FOR var IN-UNCOVERED-COLS assignment-problem) + (let ((kwd (if generate 'generate 'for))) + `(,kwd ,var :indexes-of nil :in (ap-covered-cols ,assignment-problem)))) + +(defmacro-driver (FOR var IN-COVERED-ROWS assignment-problem) + (let ((kwd (if generate 'generate 'for))) + `(,kwd ,var :indexes-of t :in (ap-covered-rows ,assignment-problem)))) + +(defmacro-driver (FOR var IN-COVERED-COLS assignment-problem) + (let ((kwd (if generate 'generate 'for))) + `(,kwd ,var :indexes-of t :in (ap-covered-cols ,assignment-problem)))) + + +(defun all-rows-covered-p (data) + (every #'identity (ap-covered-rows data))) + +(defun all-cols-covered-p (data) + (every #'identity (ap-covered-cols data))) + + +;;;; Incrementing +(defun incf-row (data row i) + (with-assignment-problem (data) + (dotimes (col cols) + (incf (aref cost-matrix row col) i)))) + +(defun incf-col (data col i) + (with-assignment-problem (data) + (dotimes (row rows) + (incf (aref cost-matrix row col) i)))) + +(defun decf-row (data row i) + (incf-row data row (- i))) + +(defun decf-col (data col i) + (incf-col data col (- i))) + + +;;;; Step 1: Initialization --------------------------------------------------- +(defun subtract-smallest-element-in-col (data col) + (decf-col data col (iterate + (for row :below (ap-rows data)) + (minimizing (aref (ap-cost-matrix data) row col))))) + + +(defun initial-subtraction (data) + ;; The first step is to subtract the smallest item in each column from all + ;; entries in the column. + (with-assignment-problem (data) + (dotimes (col cols) + (subtract-smallest-element-in-col data col)))) + +(defun initial-zero-starring (data) + ;; Find a zero Z in the distance matrix. + ;; + ;; If there is no starred zero already in its row or column, star this zero. + ;; + ;; Repeat steps 1.1, 1.2 until all zeros have been considered. + (with-assignment-problem (data) + (iterate + ;; This could be faster if we split the iteration and bailed after marking + ;; the first thing in a row, but meh, it's cleaner this way. + (for (value row col) :in-array cost-matrix) + (when (and (zerop value) + (not (row-starred-p data row)) + (not (col-starred-p data col))) + (star data row col))))) + + +(defun step-1 (data) + (initial-subtraction data) + (initial-zero-starring data) + (step-2 data)) + + +;;;; Step 2: Z* Count and Solution Assessment --------------------------------- +(defun cover-all-starred-columns (data) + (with-assignment-problem (data) + (dotimes (col cols) + (when (col-starred-p data col) + (cover-col data col))))) + + +(defun step-2 (data) + ;; Cover every column containing a Z*. + ;; + ;; Terminate the algorithm if all columns are covered. In this case, the + ;; locations of the entries in the matrix provide the solution to the + ;; assignment problem. + (cover-all-starred-columns data) + (if (all-cols-covered-p data) + (report-solution data) + (step-3 data))) + + + +;;;; Step 3: Main Zero Search ------------------------------------------------- +(defun find-uncovered-zero (data) + (iterate (for row :in-uncovered-rows data) + (iterate (for col :in-uncovered-cols data) + (when (zerop (aref (ap-cost-matrix data) row col)) + (return-from find-uncovered-zero (values t row col))))) + (values nil nil nil)) + +(defun step-3 (data) + ;; Find an uncovered Z in the distance matrix and prime it, Z -> Z'. If no + ;; such zero exists, go to Step 5. + (multiple-value-bind (found row col) (find-uncovered-zero data) + (if (not found) + (step-5 data) + (progn + (prime data row col) + (let ((starred-col (starred-col-for-row data row))) + (if (not starred-col) + ;; If No Z* exists in the row of the Z', go to Step 4. + (step-4 data row col) + ;; If a Z* exists, cover this row and uncover the column of the Z*. + ;; Return to Step 3.1 to find a new Z. + (progn (cover-row data row) + (uncover-col data starred-col) + (step-3 data)))))))) + + +;;;; Step 4: Increment Set of Starred Zeros ----------------------------------- +(defun construct-zero-sequence (data initial-row initial-col) + (gathering + (labels + ((find-next-starred (prime-col) + ;; The Z* in the same column as the given Z', if one exists. + (let ((star-row (starred-row-for-col data prime-col))) + (if (null star-row) + (values nil nil) + (values star-row prime-col)))) + (find-next-primed (star-row) + ;; The Z' in the same row as the given Z* (there will always be one). + (values star-row (primed-col-for-row data star-row))) + (mark-starred (row col) + (when row + (gather (cons row col)) + (multiple-value-call #'mark-primed (find-next-primed row)))) + (mark-primed (row col) + (gather (cons row col)) + (multiple-value-call #'mark-starred (find-next-starred col)))) + (mark-primed initial-row initial-col)))) + +(defun process-zero-sequence (data zeros) + ;; Unstar each starred zero of the sequence. + ;; + ;; Star each primed zero of the sequence, thus increasing the number of + ;; starred zeros by one. + (iterate (for (row . col) :in zeros) + (for primed? :first t :then (not primed?)) + (if primed? + (star data row col) + (unstar data row col)))) + +(defun step-4 (data row col) + (process-zero-sequence data (construct-zero-sequence data row col)) + (unprime-all data) + (uncover-all data) + (step-2 data)) + + +;;;; Step 5: New Zero Manufactures -------------------------------------------- +(defun find-smallest-uncovered-entry (data) + (iterate + main + (for row :in-uncovered-rows data) + (iterate (for col :in-uncovered-cols data) + (in main (minimizing (aref (ap-cost-matrix data) row col)))))) + +(defun incf-covered-rows (data i) + (iterate (for row :in-covered-rows data) + (incf-row data row i))) + +(defun decf-uncovered-cols (data i) + (iterate (for col :in-uncovered-cols data) + (decf-col data col i))) + + +(defun step-5 (data) + ;; Let h be the smallest uncovered entry in the (modified) distance matrix. + ;; + ;; Add h to all covered rows. + ;; + ;; Subtract h from all uncovered columns + ;; + ;; Return to Step 3, without altering stars, primes, or covers. + (let ((i (find-smallest-uncovered-entry data))) + (incf-covered-rows data i) + (decf-uncovered-cols data i) + (step-3 data))) + + +;;;; Reporting Solution ------------------------------------------------------- +(defun report-solution (data) + (starred-list data)) + + +;;;; API ---------------------------------------------------------------------- +(defun find-minimal-assignment (matrix) + (step-1 (make-assignment-problem matrix))) + + +;;;; Scratch ------------------------------------------------------------------ +;; (untrace) diff -r 9230e81d302c -r 4f58a841ae48 src/problems.lisp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/problems.lisp Thu Aug 10 20:09:14 2017 -0400 @@ -0,0 +1,1897 @@ +(in-package :euler) + +(defun problem-1 () + ;; If we list all the natural numbers below 10 that are multiples of 3 or 5, + ;; we get 3, 5, 6 and 9. The sum of these multiples is 23. + ;; + ;; Find the sum of all the multiples of 3 or 5 below 1000. + (iterate (for i :from 1 :below 1000) + (when (or (dividesp i 3) + (dividesp i 5)) + (sum i)))) + +(defun problem-2 () + ;; Each new term in the Fibonacci sequence is generated by adding the previous + ;; two terms. By starting with 1 and 2, the first 10 terms will be: + ;; + ;; 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ... + ;; + ;; By considering the terms in the Fibonacci sequence whose values do not + ;; exceed four million, find the sum of the even-valued terms. + (iterate (for n :in-fibonacci t) + (while (<= n 4000000)) + (when (evenp n) + (sum n)))) + +(defun problem-3 () + ;; The prime factors of 13195 are 5, 7, 13 and 29. + ;; + ;; What is the largest prime factor of the number 600851475143 ? + (apply #'max (prime-factorization 600851475143))) + +(defun problem-4 () + ;; A palindromic number reads the same both ways. The largest palindrome made + ;; from the product of two 2-digit numbers is 9009 = 91 × 99. + ;; + ;; Find the largest palindrome made from the product of two 3-digit numbers. + (iterate (for-nested ((i :from 0 :to 999) + (j :from 0 :to 999))) + (for product = (* i j)) + (when (palindromep product) + (maximize product)))) + +(defun problem-5 () + ;; 2520 is the smallest number that can be divided by each of the numbers from + ;; 1 to 10 without any remainder. + ;; + ;; What is the smallest positive number that is evenly divisible by all of the + ;; numbers from 1 to 20? + (iterate + ;; all numbers are divisible by 1 and we can skip checking everything <= 10 + ;; because: + ;; + ;; anything divisible by 12 is automatically divisible by 2 + ;; anything divisible by 12 is automatically divisible by 3 + ;; anything divisible by 12 is automatically divisible by 4 + ;; anything divisible by 15 is automatically divisible by 5 + ;; anything divisible by 12 is automatically divisible by 6 + ;; anything divisible by 14 is automatically divisible by 7 + ;; anything divisible by 16 is automatically divisible by 8 + ;; anything divisible by 18 is automatically divisible by 9 + ;; anything divisible by 20 is automatically divisible by 10 + (with divisors = (range 11 20)) + (for i :from 20 :by 20) ; it must be divisible by 20 + (finding i :such-that (every (curry #'dividesp i) divisors)))) + +(defun problem-6 () + ;; The sum of the squares of the first ten natural numbers is, + ;; 1² + 2² + ... + 10² = 385 + ;; + ;; The square of the sum of the first ten natural numbers is, + ;; (1 + 2 + ... + 10)² = 55² = 3025 + ;; + ;; Hence the difference between the sum of the squares of the first ten + ;; natural numbers and the square of the sum is 3025 − 385 = 2640. + ;; + ;; Find the difference between the sum of the squares of the first one hundred + ;; natural numbers and the square of the sum. + (flet ((sum-of-squares (to) + (sum (irange 1 to :key #'square))) + (square-of-sum (to) + (square (sum (irange 1 to))))) + (abs (- (sum-of-squares 100) ; apparently it wants the absolute value + (square-of-sum 100))))) + +(defun problem-7 () + ;; By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see + ;; that the 6th prime is 13. + ;; + ;; What is the 10 001st prime number? + (nth-prime 10001)) + +(defun problem-8 () + ;; The four adjacent digits in the 1000-digit number that have the greatest + ;; product are 9 × 9 × 8 × 9 = 5832. + ;; + ;; Find the thirteen adjacent digits in the 1000-digit number that have the + ;; greatest product. What is the value of this product? + (let ((digits (map 'list #'digit-char-p + "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450"))) + (iterate (for window :in (n-grams 13 digits)) + (maximize (apply #'* window))))) + +(defun problem-9 () + ;; A Pythagorean triplet is a set of three natural numbers, a < b < c, for + ;; which: + ;; + ;; a² + b² = c² + ;; + ;; For example, 3² + 4² = 9 + 16 = 25 = 5². + ;; + ;; There exists exactly one Pythagorean triplet for which a + b + c = 1000. + ;; Find the product abc. + (product (first (pythagorean-triplets-of-perimeter 1000)))) + +(defun problem-10 () + ;; The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17. + ;; Find the sum of all the primes below two million. + (sum (sieve 2000000))) + +(defun problem-11 () + ;; In the 20×20 grid below, four numbers along a diagonal line have been marked + ;; in red. + ;; + ;; The product of these numbers is 26 × 63 × 78 × 14 = 1788696. + ;; + ;; What is the greatest product of four adjacent numbers in the same direction + ;; (up, down, left, right, or diagonally) in the 20×20 grid? + (let ((grid + #2A((08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08) + (49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00) + (81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65) + (52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91) + (22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80) + (24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50) + (32 98 81 28 64 23 67 10 26 38 40 67 59 54 70 66 18 38 64 70) + (67 26 20 68 02 62 12 20 95 63 94 39 63 08 40 91 66 49 94 21) + (24 55 58 05 66 73 99 26 97 17 78 78 96 83 14 88 34 89 63 72) + (21 36 23 09 75 00 76 44 20 45 35 14 00 61 33 97 34 31 33 95) + (78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92) + (16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57) + (86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58) + (19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40) + (04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66) + (88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69) + (04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36) + (20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16) + (20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54) + (01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48)))) + (max + ;; horizontal + (iterate (for-nested ((row :from 0 :below 20) + (col :from 0 :below 16))) + (maximize (* (aref grid row (+ 0 col)) + (aref grid row (+ 1 col)) + (aref grid row (+ 2 col)) + (aref grid row (+ 3 col))))) + ;; vertical + (iterate (for-nested ((row :from 0 :below 16) + (col :from 0 :below 20))) + (maximize (* (aref grid (+ 0 row) col) + (aref grid (+ 1 row) col) + (aref grid (+ 2 row) col) + (aref grid (+ 3 row) col)))) + ;; backslash \ + (iterate (for-nested ((row :from 0 :below 16) + (col :from 0 :below 16))) + (maximize (* (aref grid (+ 0 row) (+ 0 col)) + (aref grid (+ 1 row) (+ 1 col)) + (aref grid (+ 2 row) (+ 2 col)) + (aref grid (+ 3 row) (+ 3 col))))) + ;; slash / + (iterate (for-nested ((row :from 3 :below 20) + (col :from 0 :below 16))) + (maximize (* (aref grid (- row 0) (+ 0 col)) + (aref grid (- row 1) (+ 1 col)) + (aref grid (- row 2) (+ 2 col)) + (aref grid (- row 3) (+ 3 col)))))))) + +(defun problem-12 () + ;; The sequence of triangle numbers is generated by adding the natural + ;; numbers. So the 7th triangle number would be + ;; 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first ten terms would be: + ;; + ;; 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ... + ;; + ;; Let us list the factors of the first seven triangle numbers: + ;; + ;; 1: 1 + ;; 3: 1,3 + ;; 6: 1,2,3,6 + ;; 10: 1,2,5,10 + ;; 15: 1,3,5,15 + ;; 21: 1,3,7,21 + ;; 28: 1,2,4,7,14,28 + ;; + ;; We can see that 28 is the first triangle number to have over five divisors. + ;; + ;; What is the value of the first triangle number to have over five hundred + ;; divisors? + (iterate + (for tri :key #'triangle :from 1) + (finding tri :such-that (> (count-divisors tri) 500)))) + +(defun problem-13 () + ;; Work out the first ten digits of the sum of the following one-hundred + ;; 50-digit numbers. + (-<> (+ 37107287533902102798797998220837590246510135740250 + 46376937677490009712648124896970078050417018260538 + 74324986199524741059474233309513058123726617309629 + 91942213363574161572522430563301811072406154908250 + 23067588207539346171171980310421047513778063246676 + 89261670696623633820136378418383684178734361726757 + 28112879812849979408065481931592621691275889832738 + 44274228917432520321923589422876796487670272189318 + 47451445736001306439091167216856844588711603153276 + 70386486105843025439939619828917593665686757934951 + 62176457141856560629502157223196586755079324193331 + 64906352462741904929101432445813822663347944758178 + 92575867718337217661963751590579239728245598838407 + 58203565325359399008402633568948830189458628227828 + 80181199384826282014278194139940567587151170094390 + 35398664372827112653829987240784473053190104293586 + 86515506006295864861532075273371959191420517255829 + 71693888707715466499115593487603532921714970056938 + 54370070576826684624621495650076471787294438377604 + 53282654108756828443191190634694037855217779295145 + 36123272525000296071075082563815656710885258350721 + 45876576172410976447339110607218265236877223636045 + 17423706905851860660448207621209813287860733969412 + 81142660418086830619328460811191061556940512689692 + 51934325451728388641918047049293215058642563049483 + 62467221648435076201727918039944693004732956340691 + 15732444386908125794514089057706229429197107928209 + 55037687525678773091862540744969844508330393682126 + 18336384825330154686196124348767681297534375946515 + 80386287592878490201521685554828717201219257766954 + 78182833757993103614740356856449095527097864797581 + 16726320100436897842553539920931837441497806860984 + 48403098129077791799088218795327364475675590848030 + 87086987551392711854517078544161852424320693150332 + 59959406895756536782107074926966537676326235447210 + 69793950679652694742597709739166693763042633987085 + 41052684708299085211399427365734116182760315001271 + 65378607361501080857009149939512557028198746004375 + 35829035317434717326932123578154982629742552737307 + 94953759765105305946966067683156574377167401875275 + 88902802571733229619176668713819931811048770190271 + 25267680276078003013678680992525463401061632866526 + 36270218540497705585629946580636237993140746255962 + 24074486908231174977792365466257246923322810917141 + 91430288197103288597806669760892938638285025333403 + 34413065578016127815921815005561868836468420090470 + 23053081172816430487623791969842487255036638784583 + 11487696932154902810424020138335124462181441773470 + 63783299490636259666498587618221225225512486764533 + 67720186971698544312419572409913959008952310058822 + 95548255300263520781532296796249481641953868218774 + 76085327132285723110424803456124867697064507995236 + 37774242535411291684276865538926205024910326572967 + 23701913275725675285653248258265463092207058596522 + 29798860272258331913126375147341994889534765745501 + 18495701454879288984856827726077713721403798879715 + 38298203783031473527721580348144513491373226651381 + 34829543829199918180278916522431027392251122869539 + 40957953066405232632538044100059654939159879593635 + 29746152185502371307642255121183693803580388584903 + 41698116222072977186158236678424689157993532961922 + 62467957194401269043877107275048102390895523597457 + 23189706772547915061505504953922979530901129967519 + 86188088225875314529584099251203829009407770775672 + 11306739708304724483816533873502340845647058077308 + 82959174767140363198008187129011875491310547126581 + 97623331044818386269515456334926366572897563400500 + 42846280183517070527831839425882145521227251250327 + 55121603546981200581762165212827652751691296897789 + 32238195734329339946437501907836945765883352399886 + 75506164965184775180738168837861091527357929701337 + 62177842752192623401942399639168044983993173312731 + 32924185707147349566916674687634660915035914677504 + 99518671430235219628894890102423325116913619626622 + 73267460800591547471830798392868535206946944540724 + 76841822524674417161514036427982273348055556214818 + 97142617910342598647204516893989422179826088076852 + 87783646182799346313767754307809363333018982642090 + 10848802521674670883215120185883543223812876952786 + 71329612474782464538636993009049310363619763878039 + 62184073572399794223406235393808339651327408011116 + 66627891981488087797941876876144230030984490851411 + 60661826293682836764744779239180335110989069790714 + 85786944089552990653640447425576083659976645795096 + 66024396409905389607120198219976047599490197230297 + 64913982680032973156037120041377903785566085089252 + 16730939319872750275468906903707539413042652315011 + 94809377245048795150954100921645863754710598436791 + 78639167021187492431995700641917969777599028300699 + 15368713711936614952811305876380278410754449733078 + 40789923115535562561142322423255033685442488917353 + 44889911501440648020369068063960672322193204149535 + 41503128880339536053299340368006977710650566631954 + 81234880673210146739058568557934581403627822703280 + 82616570773948327592232845941706525094512325230608 + 22918802058777319719839450180888072429661980811197 + 77158542502016545090413245809786882778948721859617 + 72107838435069186155435662884062257473692284509516 + 20849603980134001723930671666823555245252804609722 + 53503534226472524250874054075591789781264330331690) + aesthetic-string + (subseq <> 0 10) + parse-integer + (nth-value 0 <>))) + +(defun problem-14 () + ;; The following iterative sequence is defined for the set of positive + ;; integers: + ;; + ;; n → n/2 (n is even) + ;; n → 3n + 1 (n is odd) + ;; + ;; Using the rule above and starting with 13, we generate the following + ;; sequence: + ;; + ;; 13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1 + ;; + ;; It can be seen that this sequence (starting at 13 and finishing at 1) + ;; contains 10 terms. Although it has not been proved yet (Collatz Problem), + ;; it is thought that all starting numbers finish at 1. + ;; + ;; Which starting number, under one million, produces the longest chain? + ;; + ;; NOTE: Once the chain starts the terms are allowed to go above one million. + (iterate (for i :from 1 :below 1000000) + (finding i :maximizing #'collatz-length))) + +(defun problem-15 () + ;; Starting in the top left corner of a 2×2 grid, and only being able to move + ;; to the right and down, there are exactly 6 routes to the bottom right + ;; corner. + ;; + ;; How many such routes are there through a 20×20 grid? + (binomial-coefficient 40 20)) + +(defun problem-16 () + ;; 2^15 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26. + ;; + ;; What is the sum of the digits of the number 2^1000? + (sum (digits (expt 2 1000)))) + +(defun problem-17 () + ;; If the numbers 1 to 5 are written out in words: one, two, three, four, + ;; five, then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total. + ;; + ;; If all the numbers from 1 to 1000 (one thousand) inclusive were written out + ;; in words, how many letters would be used? + ;; + ;; NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and + ;; forty-two) contains 23 letters and 115 (one hundred and fifteen) contains + ;; 20 letters. The use of "and" when writing out numbers is in compliance with + ;; British usage, which is awful. + (labels ((letters (n) + (-<> n + (format nil "~R" <>) + (count-if #'alpha-char-p <>))) + (has-british-and (n) + (or (< n 100) + (zerop (mod n 100)))) + (silly-british-letters (n) + (+ (letters n) + (if (has-british-and n) 0 3)))) + (sum (irange 1 1000) + :key #'silly-british-letters))) + +(defun problem-18 () + ;; By starting at the top of the triangle below and moving to adjacent numbers + ;; on the row below, the maximum total from top to bottom is 23. + ;; + ;; 3 + ;; 7 4 + ;; 2 4 6 + ;; 8 5 9 3 + ;; + ;; That is, 3 + 7 + 4 + 9 = 23. + ;; + ;; Find the maximum total from top to bottom of the triangle below. + ;; + ;; NOTE: As there are only 16384 routes, it is possible to solve this problem + ;; by trying every route. However, Problem 67, is the same challenge with + ;; a triangle containing one-hundred rows; it cannot be solved by brute force, + ;; and requires a clever method! ;o) + (let ((triangle '((75) + (95 64) + (17 47 82) + (18 35 87 10) + (20 04 82 47 65) + (19 01 23 75 03 34) + (88 02 77 73 07 63 67) + (99 65 04 28 06 16 70 92) + (41 41 26 56 83 40 80 70 33) + (41 48 72 33 47 32 37 16 94 29) + (53 71 44 65 25 43 91 52 97 51 14) + (70 11 33 28 77 73 17 78 39 68 17 57) + (91 71 52 38 17 14 91 43 58 50 27 29 48) + (63 66 04 68 89 53 67 30 73 16 69 87 40 31) + (04 62 98 27 23 09 70 98 73 93 38 53 60 04 23)))) + (car (reduce (lambda (prev last) + (mapcar #'+ + prev + (mapcar #'max last (rest last)))) + triangle + :from-end t)))) + +(defun problem-19 () + ;; You are given the following information, but you may prefer to do some + ;; research for yourself. + ;; + ;; 1 Jan 1900 was a Monday. + ;; Thirty days has September, + ;; April, June and November. + ;; All the rest have thirty-one, + ;; Saving February alone, + ;; Which has twenty-eight, rain or shine. + ;; And on leap years, twenty-nine. + ;; A leap year occurs on any year evenly divisible by 4, but not on a century + ;; unless it is divisible by 400. + ;; + ;; How many Sundays fell on the first of the month during the twentieth + ;; century (1 Jan 1901 to 31 Dec 2000)? + (iterate + (for-nested ((year :from 1901 :to 2000) + (month :from 1 :to 12))) + (counting (-<> (local-time:encode-timestamp 0 0 0 0 1 month year) + local-time:timestamp-day-of-week + zerop)))) + +(defun problem-20 () + ;; n! means n × (n − 1) × ... × 3 × 2 × 1 + ;; + ;; For example, 10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800, + ;; and the sum of the digits in the number 10! is 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27. + ;; + ;; Find the sum of the digits in the number 100! + (sum (digits (factorial 100)))) + +(defun problem-21 () + ;; Let d(n) be defined as the sum of proper divisors of n (numbers less than + ;; n which divide evenly into n). + ;; + ;; If d(a) = b and d(b) = a, where a ≠ b, then a and b are an amicable pair + ;; and each of a and b are called amicable numbers. + ;; + ;; For example, the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, + ;; 55 and 110; therefore d(220) = 284. The proper divisors of 284 are 1, 2, 4, + ;; 71 and 142; so d(284) = 220. + ;; + ;; Evaluate the sum of all the amicable numbers under 10000. + (labels ((sum-of-divisors (n) + (sum (proper-divisors n))) + (amicablep (n) + (let ((other (sum-of-divisors n))) + (and (not= n other) + (= n (sum-of-divisors other)))))) + (sum (remove-if-not #'amicablep (range 1 10000))))) + +(defun problem-22 () + ;; Using names.txt, a 46K text file containing over five-thousand first names, + ;; begin by sorting it into alphabetical order. Then working out the + ;; alphabetical value for each name, multiply this value by its alphabetical + ;; position in the list to obtain a name score. + ;; + ;; For example, when the list is sorted into alphabetical order, COLIN, which + ;; is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list. So, + ;; COLIN would obtain a score of 938 × 53 = 49714. + ;; + ;; What is the total of all the name scores in the file? + (labels ((read-names () + (-<> "data/22-names.txt" + parse-strings-file + (sort <> #'string<))) + (name-score (name) + (sum name :key #'letter-number))) + (iterate (for (position . name) :in + (enumerate (read-names) :start 1)) + (sum (* position (name-score name)))))) + +(defun problem-23 () + ;; A perfect number is a number for which the sum of its proper divisors is + ;; exactly equal to the number. For example, the sum of the proper divisors of + ;; 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect + ;; number. + ;; + ;; A number n is called deficient if the sum of its proper divisors is less + ;; than n and it is called abundant if this sum exceeds n. + ;; + ;; As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest + ;; number that can be written as the sum of two abundant numbers is 24. By + ;; mathematical analysis, it can be shown that all integers greater than 28123 + ;; can be written as the sum of two abundant numbers. However, this upper + ;; limit cannot be reduced any further by analysis even though it is known + ;; that the greatest number that cannot be expressed as the sum of two + ;; abundant numbers is less than this limit. + ;; + ;; Find the sum of all the positive integers which cannot be written as the + ;; sum of two abundant numbers. + (let* ((limit 28123) + (abundant-numbers + (make-hash-set :initial-contents + (remove-if-not #'abundantp (irange 1 limit))))) + (flet ((abundant-sum-p (n) + (iterate (for a :in-hashset abundant-numbers) + (when (hset-contains-p abundant-numbers (- n a)) + (return t))))) + (sum (remove-if #'abundant-sum-p (irange 1 limit)))))) + +(defun problem-24 () + ;; A permutation is an ordered arrangement of objects. For example, 3124 is + ;; one possible permutation of the digits 1, 2, 3 and 4. If all of the + ;; permutations are listed numerically or alphabetically, we call it + ;; lexicographic order. The lexicographic permutations of 0, 1 and 2 are: + ;; + ;; 012 021 102 120 201 210 + ;; + ;; What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, + ;; 4, 5, 6, 7, 8 and 9? + (-<> "0123456789" + (gathering-vector (:size (factorial (length <>))) + (map-permutations (compose #'gather #'parse-integer) <> + :copy nil)) + (sort <> #'<) + (elt <> (1- 1000000)))) + +(defun problem-25 () + ;; The Fibonacci sequence is defined by the recurrence relation: + ;; + ;; Fn = Fn−1 + Fn−2, where F1 = 1 and F2 = 1. + ;; + ;; Hence the first 12 terms will be: + ;; + ;; F1 = 1 + ;; F2 = 1 + ;; F3 = 2 + ;; F4 = 3 + ;; F5 = 5 + ;; F6 = 8 + ;; F7 = 13 + ;; F8 = 21 + ;; F9 = 34 + ;; F10 = 55 + ;; F11 = 89 + ;; F12 = 144 + ;; + ;; The 12th term, F12, is the first term to contain three digits. + ;; + ;; What is the index of the first term in the Fibonacci sequence to contain + ;; 1000 digits? + (iterate (for f :in-fibonacci t) + (for i :from 1) + (finding i :such-that (= 1000 (digits-length f))))) + +(defun problem-26 () + ;; A unit fraction contains 1 in the numerator. The decimal representation of + ;; the unit fractions with denominators 2 to 10 are given: + ;; + ;; 1/2 = 0.5 + ;; 1/3 = 0.(3) + ;; 1/4 = 0.25 + ;; 1/5 = 0.2 + ;; 1/6 = 0.1(6) + ;; 1/7 = 0.(142857) + ;; 1/8 = 0.125 + ;; 1/9 = 0.(1) + ;; 1/10 = 0.1 + ;; + ;; Where 0.1(6) means 0.166666..., and has a 1-digit recurring cycle. It can + ;; be seen that 1/7 has a 6-digit recurring cycle. + ;; + ;; Find the value of d < 1000 for which 1/d contains the longest recurring + ;; cycle in its decimal fraction part. + (iterate + ;; 2 and 5 are the only primes that aren't coprime to 10 + (for i :in (set-difference (primes-below 1000) '(2 5))) + (finding i :maximizing (multiplicative-order 10 i)))) + +(defun problem-27 () + ;; Euler discovered the remarkable quadratic formula: + ;; + ;; n² + n + 41 + ;; + ;; It turns out that the formula will produce 40 primes for the consecutive + ;; integer values 0 ≤ n ≤ 39. However, when n=40, 40² + 40 + 41 = 40(40 + 1) + ;; + 41 is divisible by 41, and certainly when n=41, 41² + 41 + 41 is clearly + ;; divisible by 41. + ;; + ;; The incredible formula n² − 79n + 1601 was discovered, which produces 80 + ;; primes for the consecutive values 0 ≤ n ≤ 79. The product of the + ;; coefficients, −79 and 1601, is −126479. + ;; + ;; Considering quadratics of the form: + ;; + ;; n² + an + b, where |a| < 1000 and |b| ≤ 1000 + ;; + ;; where |n| is the modulus/absolute value of n + ;; e.g. |11| = 11 and |−4| = 4 + ;; + ;; Find the product of the coefficients, a and b, for the quadratic expression + ;; that produces the maximum number of primes for consecutive values of n, + ;; starting with n=0. + (flet ((primes-produced (a b) + (iterate (for n :from 0) + (while (primep (+ (square n) (* a n) b))) + (counting t)))) + (iterate (for-nested ((a :from -999 :to 999) + (b :from -1000 :to 1000))) + (finding (* a b) :maximizing (primes-produced a b))))) + +(defun problem-28 () + ;; Starting with the number 1 and moving to the right in a clockwise direction + ;; a 5 by 5 spiral is formed as follows: + ;; + ;; 21 22 23 24 25 + ;; 20 7 8 9 10 + ;; 19 6 1 2 11 + ;; 18 5 4 3 12 + ;; 17 16 15 14 13 + ;; + ;; It can be verified that the sum of the numbers on the diagonals is 101. + ;; + ;; What is the sum of the numbers on the diagonals in a 1001 by 1001 spiral + ;; formed in the same way? + (iterate (for size :from 1 :to 1001 :by 2) + (summing (apply #'+ (number-spiral-corners size))))) + +(defun problem-29 () + ;; Consider all integer combinations of a^b for 2 ≤ a ≤ 5 and 2 ≤ b ≤ 5: + ;; + ;; 2²=4, 2³=8, 2⁴=16, 2⁵=32 + ;; 3²=9, 3³=27, 3⁴=81, 3⁵=243 + ;; 4²=16, 4³=64, 4⁴=256, 4⁵=1024 + ;; 5²=25, 5³=125, 5⁴=625, 5⁵=3125 + ;; + ;; If they are then placed in numerical order, with any repeats removed, we + ;; get the following sequence of 15 distinct terms: + ;; + ;; 4, 8, 9, 16, 25, 27, 32, 64, 81, 125, 243, 256, 625, 1024, 3125 + ;; + ;; How many distinct terms are in the sequence generated by a^b for + ;; 2 ≤ a ≤ 100 and 2 ≤ b ≤ 100? + (length (iterate (for-nested ((a :from 2 :to 100) + (b :from 2 :to 100))) + (adjoining (expt a b))))) + +(defun problem-30 () + ;; Surprisingly there are only three numbers that can be written as the sum of + ;; fourth powers of their digits: + ;; + ;; 1634 = 1⁴ + 6⁴ + 3⁴ + 4⁴ + ;; 8208 = 8⁴ + 2⁴ + 0⁴ + 8⁴ + ;; 9474 = 9⁴ + 4⁴ + 7⁴ + 4⁴ + ;; + ;; As 1 = 1⁴ is not a sum it is not included. + ;; + ;; The sum of these numbers is 1634 + 8208 + 9474 = 19316. + ;; + ;; Find the sum of all the numbers that can be written as the sum of fifth + ;; powers of their digits. + (flet ((maximum-sum-for-digits (n) + (* (expt 9 5) n)) + (digit-power-sum (n) + (sum (mapcar (rcurry #'expt 5) (digits n))))) + (iterate + ;; We want to find a limit N that's bigger than the maximum possible sum + ;; for its number of digits. + (with limit = (iterate (for digits :from 1) + (for n = (expt 10 digits)) + (while (< n (maximum-sum-for-digits digits))) + (finally (return n)))) + ;; Then just brute-force the thing. + (for i :from 2 :to limit) + (when (= i (digit-power-sum i)) + (summing i))))) + +(defun problem-31 () + ;; In England the currency is made up of pound, £, and pence, p, and there are + ;; eight coins in general circulation: + ;; + ;; 1p, 2p, 5p, 10p, 20p, 50p, £1 (100p) and £2 (200p). + ;; + ;; It is possible to make £2 in the following way: + ;; + ;; 1×£1 + 1×50p + 2×20p + 1×5p + 1×2p + 3×1p + ;; + ;; How many different ways can £2 be made using any number of coins? + (recursively ((amount 200) + (coins '(200 100 50 20 10 5 2 1))) + (cond + ((zerop amount) 1) + ((minusp amount) 0) + ((null coins) 0) + (t (+ (recur (- amount (first coins)) coins) + (recur amount (rest coins))))))) + +(defun problem-32 () + ;; We shall say that an n-digit number is pandigital if it makes use of all + ;; the digits 1 to n exactly once; for example, the 5-digit number, 15234, is + ;; 1 through 5 pandigital. + ;; + ;; The product 7254 is unusual, as the identity, 39 × 186 = 7254, containing + ;; multiplicand, multiplier, and product is 1 through 9 pandigital. + ;; + ;; Find the sum of all products whose multiplicand/multiplier/product identity + ;; can be written as a 1 through 9 pandigital. + ;; + ;; HINT: Some products can be obtained in more than one way so be sure to only + ;; include it once in your sum. + (labels ((split (digits a b) + (values (digits-to-number (subseq digits 0 a)) + (digits-to-number (subseq digits a (+ a b))) + (digits-to-number (subseq digits (+ a b))))) + (check (digits a b) + (multiple-value-bind (a b c) + (split digits a b) + (when (= (* a b) c) + c)))) + (-<> (gathering + (map-permutations (lambda (digits) + (let ((c1 (check digits 3 2)) + (c2 (check digits 4 1))) + (when c1 (gather c1)) + (when c2 (gather c2)))) + #(1 2 3 4 5 6 7 8 9) + :copy nil)) + remove-duplicates + sum))) + +(defun problem-33 () + ;; The fraction 49/98 is a curious fraction, as an inexperienced mathematician + ;; in attempting to simplify it may incorrectly believe that 49/98 = 4/8, + ;; which is correct, is obtained by cancelling the 9s. + ;; + ;; We shall consider fractions like, 30/50 = 3/5, to be trivial examples. + ;; + ;; There are exactly four non-trivial examples of this type of fraction, less + ;; than one in value, and containing two digits in the numerator and + ;; denominator. + ;; + ;; If the product of these four fractions is given in its lowest common terms, + ;; find the value of the denominator. + (labels ((safe/ (a b) + (unless (zerop b) (/ a b))) + (cancel (digit other digits) + (destructuring-bind (x y) digits + (remove nil (list (when (= digit x) (safe/ other y)) + (when (= digit y) (safe/ other x)))))) + (cancellations (numerator denominator) + (let ((nd (digits numerator)) + (dd (digits denominator))) + (append (cancel (first nd) (second nd) dd) + (cancel (second nd) (first nd) dd)))) + (curiousp (numerator denominator) + (member (/ numerator denominator) + (cancellations numerator denominator))) + (trivialp (numerator denominator) + (and (dividesp numerator 10) + (dividesp denominator 10)))) + (iterate + (with result = 1) + (for numerator :from 10 :to 99) + (iterate (for denominator :from (1+ numerator) :to 99) + (when (and (curiousp numerator denominator) + (not (trivialp numerator denominator))) + (mulf result (/ numerator denominator)))) + (finally (return (denominator result)))))) + +(defun problem-34 () + ;; 145 is a curious number, as 1! + 4! + 5! = 1 + 24 + 120 = 145. + ;; + ;; Find the sum of all numbers which are equal to the sum of the factorial of + ;; their digits. + ;; + ;; Note: as 1! = 1 and 2! = 2 are not sums they are not included. + (iterate + (for n :from 3 :to 1000000) + ;; have to use funcall here because `sum` is an iterate keyword. kill me. + (when (= n (funcall #'sum (digits n) :key #'factorial)) + (summing n)))) + +(defun problem-35 () + ;; The number, 197, is called a circular prime because all rotations of the + ;; digits: 197, 971, and 719, are themselves prime. + ;; + ;; There are thirteen such primes below 100: 2, 3, 5, 7, 11, 13, 17, 31, 37, + ;; 71, 73, 79, and 97. + ;; + ;; How many circular primes are there below one million? + (labels ((rotate (n distance) + (multiple-value-bind (hi lo) + (truncate n (expt 10 distance)) + (+ (* (expt 10 (digits-length hi)) lo) + hi))) + (rotations (n) + (mapcar (curry #'rotate n) (range 1 (digits-length n)))) + (circular-prime-p (n) + (every #'primep (rotations n)))) + (iterate (for i :in-vector (sieve 1000000)) + (counting (circular-prime-p i))))) + +(defun problem-36 () + ;; The decimal number, 585 = 1001001001 (binary), is palindromic in both + ;; bases. + ;; + ;; Find the sum of all numbers, less than one million, which are palindromic + ;; in base 10 and base 2. + ;; + ;; (Please note that the palindromic number, in either base, may not include + ;; leading zeros.) + (iterate (for i :from 1 :below 1000000) + (when (and (palindromep i 10) + (palindromep i 2)) + (sum i)))) + +(defun problem-37 () + ;; The number 3797 has an interesting property. Being prime itself, it is + ;; possible to continuously remove digits from left to right, and remain prime + ;; at each stage: 3797, 797, 97, and 7. Similarly we can work from right to + ;; left: 3797, 379, 37, and 3. + ;; + ;; Find the sum of the only eleven primes that are both truncatable from left + ;; to right and right to left. + ;; + ;; NOTE: 2, 3, 5, and 7 are not considered to be truncatable primes. + (labels ((truncations (n) + (iterate (for i :from 0 :below (digits-length n)) + (collect (truncate-number-left n i)) + (collect (truncate-number-right n i)))) + (truncatablep (n) + (every #'primep (truncations n)))) + (iterate + (with count = 0) + (for i :from 11 :by 2) + (when (truncatablep i) + (sum i) + (incf count)) + (while (< count 11))))) + +(defun problem-38 () + ;; Take the number 192 and multiply it by each of 1, 2, and 3: + ;; + ;; 192 × 1 = 192 + ;; 192 × 2 = 384 + ;; 192 × 3 = 576 + ;; + ;; By concatenating each product we get the 1 to 9 pandigital, 192384576. We + ;; will call 192384576 the concatenated product of 192 and (1,2,3) + ;; + ;; The same can be achieved by starting with 9 and multiplying by 1, 2, 3, 4, + ;; and 5, giving the pandigital, 918273645, which is the concatenated product + ;; of 9 and (1,2,3,4,5). + ;; + ;; What is the largest 1 to 9 pandigital 9-digit number that can be formed as + ;; the concatenated product of an integer with (1,2, ... , n) where n > 1? + (labels ((concatenated-product (number i) + (apply #'concatenate-integers + (iterate (for n :from 1 :to i) + (collect (* number n)))))) + (iterate + main + (for base :from 1) + ;; base can't be more than 5 digits long because we have to concatenate at + ;; least two products of it + (while (digits<= base 5)) + (iterate (for n :from 2) + (for result = (concatenated-product base n)) + ;; result is only ever going to grow larger, so once we pass the + ;; nine digit mark we can stop + (while (digits<= result 9)) + (when (pandigitalp result) + (in main (maximizing result))))))) + +(defun problem-39 () + ;; If p is the perimeter of a right angle triangle with integral length sides, + ;; {a,b,c}, there are exactly three solutions for p = 120. + ;; + ;; {20,48,52}, {24,45,51}, {30,40,50} + ;; + ;; For which value of p ≤ 1000, is the number of solutions maximised? + (iterate + (for p :from 1 :to 1000) + (finding p :maximizing (length (pythagorean-triplets-of-perimeter p))))) + +(defun problem-40 () + ;; An irrational decimal fraction is created by concatenating the positive + ;; integers: + ;; + ;; 0.123456789101112131415161718192021... + ;; + ;; It can be seen that the 12th digit of the fractional part is 1. + ;; + ;; If dn represents the nth digit of the fractional part, find the value of + ;; the following expression. + ;; + ;; d1 × d10 × d100 × d1000 × d10000 × d100000 × d1000000 + (iterate + top + (with index = 0) + (for digits :key #'digits :from 1) + (iterate (for d :in digits) + (incf index) + (when (member index '(1 10 100 1000 10000 100000 1000000)) + (in top (multiplying d)) + (when (= index 1000000) + (in top (terminate))))))) + +(defun problem-41 () + ;; We shall say that an n-digit number is pandigital if it makes use of all + ;; the digits 1 to n exactly once. For example, 2143 is a 4-digit pandigital + ;; and is also prime. + ;; + ;; What is the largest n-digit pandigital prime that exists? + (iterate + ;; There's a clever observation which reduces the upper bound from 9 to + ;; 7 from "gamma" in the forum: + ;; + ;; > Note: Nine numbers cannot be done (1+2+3+4+5+6+7+8+9=45 => always dividable by 3) + ;; > Note: Eight numbers cannot be done (1+2+3+4+5+6+7+8=36 => always dividable by 3) + (for n :downfrom 7) + (thereis (apply (nullary #'max) + (remove-if-not #'primep (pandigitals 1 n)))))) + +(defun problem-42 () + ;; The nth term of the sequence of triangle numbers is given by, tn = ½n(n+1); + ;; so the first ten triangle numbers are: + ;; + ;; 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ... + ;; + ;; By converting each letter in a word to a number corresponding to its + ;; alphabetical position and adding these values we form a word value. For + ;; example, the word value for SKY is 19 + 11 + 25 = 55 = t10. If the word + ;; value is a triangle number then we shall call the word a triangle word. + ;; + ;; Using words.txt (right click and 'Save Link/Target As...'), a 16K text file + ;; containing nearly two-thousand common English words, how many are triangle + ;; words? + (labels ((word-value (word) + (sum word :key #'letter-number)) + (triangle-word-p (word) + (trianglep (word-value word)))) + (count-if #'triangle-word-p (parse-strings-file "data/42-words.txt")))) + +(defun problem-43 () + ;; The number, 1406357289, is a 0 to 9 pandigital number because it is made up + ;; of each of the digits 0 to 9 in some order, but it also has a rather + ;; interesting sub-string divisibility property. + ;; + ;; Let d1 be the 1st digit, d2 be the 2nd digit, and so on. In this way, we + ;; note the following: + ;; + ;; d2d3d4=406 is divisible by 2 + ;; d3d4d5=063 is divisible by 3 + ;; d4d5d6=635 is divisible by 5 + ;; d5d6d7=357 is divisible by 7 + ;; d6d7d8=572 is divisible by 11 + ;; d7d8d9=728 is divisible by 13 + ;; d8d9d10=289 is divisible by 17 + ;; + ;; Find the sum of all 0 to 9 pandigital numbers with this property. + (labels ((extract3 (digits start) + (digits-to-number (subseq digits start (+ 3 start)))) + (interestingp (n) + (let ((digits (digits n))) + ;; eat shit mathematicians, indexes start from zero + (and (dividesp (extract3 digits 1) 2) + (dividesp (extract3 digits 2) 3) + (dividesp (extract3 digits 3) 5) + (dividesp (extract3 digits 4) 7) + (dividesp (extract3 digits 5) 11) + (dividesp (extract3 digits 6) 13) + (dividesp (extract3 digits 7) 17))))) + (sum (remove-if-not #'interestingp (pandigitals 0 9))))) + +(defun problem-44 () + ;; Pentagonal numbers are generated by the formula, Pn=n(3n−1)/2. The first + ;; ten pentagonal numbers are: + ;; + ;; 1, 5, 12, 22, 35, 51, 70, 92, 117, 145, ... + ;; + ;; It can be seen that P4 + P7 = 22 + 70 = 92 = P8. However, their difference, + ;; 70 − 22 = 48, is not pentagonal. + ;; + ;; Find the pair of pentagonal numbers, Pj and Pk, for which their sum and + ;; difference are pentagonal and D = |Pk − Pj| is minimised; what is the value + ;; of D? + (flet ((interestingp (px py) + (and (pentagonp (+ py px)) + (pentagonp (- py px))))) + (iterate + (with result = most-positive-fixnum) ; my kingdom for `CL:INFINITY` + (for y :from 2) + (for z :from 3) + (for py = (pentagon y)) + (for pz = (pentagon z)) + (when (>= (- pz py) result) + (return result)) + (iterate + (for x :from (1- y) :downto 1) + (for px = (pentagon x)) + (when (interestingp px py) + (let ((distance (- py px))) + (when (< distance result) + ;; TODO: This isn't quite right, because this is just the FIRST + ;; number we find -- we haven't guaranteed that it's the SMALLEST + ;; one we'll ever see. But it happens to accidentally be the + ;; correct one, and until I get around to rewriting this with + ;; priority queues it'll have to do. + (return-from problem-44 distance))) + (return)))))) + +(defun problem-45 () + ;; Triangle, pentagonal, and hexagonal numbers are generated by the following + ;; formulae: + ;; + ;; Triangle Tn=n(n+1)/2 1, 3, 6, 10, 15, ... + ;; Pentagonal Pn=n(3n−1)/2 1, 5, 12, 22, 35, ... + ;; Hexagonal Hn=n(2n−1) 1, 6, 15, 28, 45, ... + ;; + ;; It can be verified that T285 = P165 = H143 = 40755. + ;; + ;; Find the next triangle number that is also pentagonal and hexagonal. + (iterate + (for n :key #'triangle :from 286) + (finding n :such-that (and (pentagonp n) (hexagonp n))))) + +(defun problem-46 () + ;; It was proposed by Christian Goldbach that every odd composite number can + ;; be written as the sum of a prime and twice a square. + ;; + ;; 9 = 7 + 2×1² + ;; 15 = 7 + 2×2² + ;; 21 = 3 + 2×3² + ;; 25 = 7 + 2×3² + ;; 27 = 19 + 2×2² + ;; 33 = 31 + 2×1² + ;; + ;; It turns out that the conjecture was false. + ;; + ;; What is the smallest odd composite that cannot be written as the sum of + ;; a prime and twice a square? + (flet ((counterexamplep (n) + (iterate + (for prime :in-vector (sieve n)) + (never (squarep (/ (- n prime) 2)))))) + (iterate + (for i :from 1 :by 2) + (finding i :such-that (and (compositep i) + (counterexamplep i)))))) + +(defun problem-47 () + ;; The first two consecutive numbers to have two distinct prime factors are: + ;; + ;; 14 = 2 × 7 + ;; 15 = 3 × 5 + ;; + ;; The first three consecutive numbers to have three distinct prime factors are: + ;; + ;; 644 = 2² × 7 × 23 + ;; 645 = 3 × 5 × 43 + ;; 646 = 2 × 17 × 19 + ;; + ;; Find the first four consecutive integers to have four distinct prime + ;; factors each. What is the first of these numbers? + (flet ((factor-count (n) + (length (remove-duplicates (prime-factorization n))))) + (iterate + (with run = 0) + (for i :from 1) + (if (= 4 (factor-count i)) + (incf run) + (setf run 0)) + (finding (- i 3) :such-that (= run 4))))) + +(defun problem-48 () + ;; The series, 1^1 + 2^2 + 3^3 + ... + 10^10 = 10405071317. + ;; + ;; Find the last ten digits of the series, 1^1 + 2^2 + 3^3 + ... + 1000^1000. + (-<> (irange 1 1000) + (mapcar #'expt <> <>) + sum + (mod <> (expt 10 10)))) + +(defun problem-49 () + ;; The arithmetic sequence, 1487, 4817, 8147, in which each of the terms + ;; increases by 3330, is unusual in two ways: (i) each of the three terms are + ;; prime, and, (ii) each of the 4-digit numbers are permutations of one + ;; another. + ;; + ;; There are no arithmetic sequences made up of three 1-, 2-, or 3-digit + ;; primes, exhibiting this property, but there is one other 4-digit increasing + ;; sequence. + ;; + ;; What 12-digit number do you form by concatenating the three terms in this + ;; sequence? + (labels ((permutation= (a b) + (orderless-equal (digits a) (digits b))) + (length>=3 (list) + (>= (length list) 3)) + (arithmetic-sequence-p (seq) + (apply #'= (mapcar (curry #'apply #'-) + (n-grams 2 seq)))) + (has-arithmetic-sequence-p (seq) + (map-combinations + (lambda (s) + (when (arithmetic-sequence-p s) + (return-from has-arithmetic-sequence-p s))) + (sort seq #'<) + :length 3) + nil)) + (-<> (primes-in 1000 9999) + (equivalence-classes #'permutation= <>) ; find all permutation groups + (remove-if-not #'length>=3 <>) ; make sure they have at leat 3 elements + (mapcar #'has-arithmetic-sequence-p <>) + (remove nil <>) + (remove-if (lambda (s) (= (first s) 1487)) <>) ; remove the example + first + (mapcan #'digits <>) + digits-to-number))) + +(defun problem-50 () + ;; The prime 41, can be written as the sum of six consecutive primes: + ;; + ;; 41 = 2 + 3 + 5 + 7 + 11 + 13 + ;; + ;; This is the longest sum of consecutive primes that adds to a prime below + ;; one-hundred. + ;; + ;; The longest sum of consecutive primes below one-thousand that adds to + ;; a prime, contains 21 terms, and is equal to 953. + ;; + ;; Which prime, below one-million, can be written as the sum of the most + ;; consecutive primes? + (let ((primes (sieve 1000000))) + (flet ((score (start) + (iterate + (with score = 0) + (with winner = 0) + (for run :from 1) + (for prime :in-vector primes :from start) + (summing prime :into sum) + (while (< sum 1000000)) + (when (primep sum) + (setf score run + winner sum)) + (finally (return (values score winner)))))) + (iterate + (for (values score winner) + :key #'score :from 0 :below (length primes)) + (finding winner :maximizing score))))) + +(defun problem-51 () + ;; By replacing the 1st digit of the 2-digit number *3, it turns out that six + ;; of the nine possible values: 13, 23, 43, 53, 73, and 83, are all prime. + ;; + ;; By replacing the 3rd and 4th digits of 56**3 with the same digit, this + ;; 5-digit number is the first example having seven primes among the ten + ;; generated numbers, yielding the family: 56003, 56113, 56333, 56443, 56663, + ;; 56773, and 56993. Consequently 56003, being the first member of this + ;; family, is the smallest prime with this property. + ;; + ;; Find the smallest prime which, by replacing part of the number (not + ;; necessarily adjacent digits) with the same digit, is part of an eight prime + ;; value family. + (labels + ((patterns (prime) + (iterate (with size = (digits-length prime)) + (with indices = (range 0 size)) + (for i :from 1 :below size) + (appending (combinations indices :length i)))) + (apply-pattern-digit (prime pattern new-digit) + (iterate (with result = (digits prime)) + (for index :in pattern) + (when (and (zerop index) (zerop new-digit)) + (leave)) + (setf (nth index result) new-digit) + (finally (return (digits-to-number result))))) + (apply-pattern (prime pattern) + (iterate (for digit in (irange 0 9)) + (for result = (apply-pattern-digit prime pattern digit)) + (when (and result (primep result)) + (collect result)))) + (apply-patterns (prime) + (mapcar (curry #'apply-pattern prime) (patterns prime))) + (winnerp (prime) + (find-if (curry #'length= 8) (apply-patterns prime)))) + (-<> (iterate (for i :from 3 :by 2) + (thereis (and (primep i) (winnerp i)))) + (sort< <>) + first))) + +(defun problem-52 () + ;; It can be seen that the number, 125874, and its double, 251748, contain + ;; exactly the same digits, but in a different order. + ;; + ;; Find the smallest positive integer, x, such that 2x, 3x, 4x, 5x, and 6x, + ;; contain the same digits. + (iterate (for i :from 1) + (for digits = (digits i)) + (finding i :such-that + (every (lambda (n) + (orderless-equal digits (digits (* n i)))) + '(2 3 4 5 6))))) + +(defun problem-53 () + ;; There are exactly ten ways of selecting three from five, 12345: + ;; + ;; 123, 124, 125, 134, 135, 145, 234, 235, 245, and 345 + ;; + ;; In combinatorics, we use the notation, 5C3 = 10. + ;; + ;; In general, + ;; + ;; nCr = n! / r!(n−r)! + ;; + ;; where r ≤ n, n! = n×(n−1)×...×3×2×1, and 0! = 1. + ;; + ;; It is not until n = 23, that a value exceeds one-million: 23C10 = 1144066. + ;; + ;; How many, not necessarily distinct, values of nCr, for 1 ≤ n ≤ 100, are + ;; greater than one-million? + (iterate + main + (for n :from 1 :to 100) + (iterate + (for r :from 1 :to n) + (for nCr = (binomial-coefficient n r)) + (in main (counting (> nCr 1000000)))))) + +(defun problem-54 () + ;; In the card game poker, a hand consists of five cards and are ranked, from + ;; lowest to highest, in the following way: + ;; + ;; High Card: Highest value card. + ;; One Pair: Two cards of the same value. + ;; Two Pairs: Two different pairs. + ;; Three of a Kind: Three cards of the same value. + ;; Straight: All cards are consecutive values. + ;; Flush: All cards of the same suit. + ;; Full House: Three of a kind and a pair. + ;; Four of a Kind: Four cards of the same value. + ;; Straight Flush: All cards are consecutive values of same suit. + ;; Royal Flush: Ten, Jack, Queen, King, Ace, in same suit. + ;; + ;; The cards are valued in the order: + ;; 2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace. + ;; + ;; If two players have the same ranked hands then the rank made up of the + ;; highest value wins; for example, a pair of eights beats a pair of fives + ;; (see example 1 below). But if two ranks tie, for example, both players have + ;; a pair of queens, then highest cards in each hand are compared (see example + ;; 4 below); if the highest cards tie then the next highest cards are + ;; compared, and so on. + ;; + ;; The file, poker.txt, contains one-thousand random hands dealt to two + ;; players. Each line of the file contains ten cards (separated by a single + ;; space): the first five are Player 1's cards and the last five are Player + ;; 2's cards. You can assume that all hands are valid (no invalid characters + ;; or repeated cards), each player's hand is in no specific order, and in each + ;; hand there is a clear winner. + ;; + ;; How many hands does Player 1 win? + (iterate (for line :in-file "data/54-poker.txt" :using #'read-line) + (for cards = (mapcar #'euler.poker::parse-card + (cl-strings:split line #\space))) + (for p1 = (take 5 cards)) + (for p2 = (drop 5 cards)) + (counting (euler.poker::poker-hand-beats-p p1 p2)))) + +(defun problem-55 () + ;; If we take 47, reverse and add, 47 + 74 = 121, which is palindromic. + ;; + ;; Not all numbers produce palindromes so quickly. For example, + ;; + ;; 349 + 943 = 1292, + ;; 1292 + 2921 = 4213 + ;; 4213 + 3124 = 7337 + ;; + ;; That is, 349 took three iterations to arrive at a palindrome. + ;; + ;; Although no one has proved it yet, it is thought that some numbers, like + ;; 196, never produce a palindrome. A number that never forms a palindrome + ;; through the reverse and add process is called a Lychrel number. Due to the + ;; theoretical nature of these numbers, and for the purpose of this problem, + ;; we shall assume that a number is Lychrel until proven otherwise. In + ;; addition you are given that for every number below ten-thousand, it will + ;; either (i) become a palindrome in less than fifty iterations, or, (ii) no + ;; one, with all the computing power that exists, has managed so far to map it + ;; to a palindrome. In fact, 10677 is the first number to be shown to require + ;; over fifty iterations before producing a palindrome: + ;; 4668731596684224866951378664 (53 iterations, 28-digits). + ;; + ;; Surprisingly, there are palindromic numbers that are themselves Lychrel + ;; numbers; the first example is 4994. + ;; + ;; How many Lychrel numbers are there below ten-thousand? + (labels ((lychrel (n) + (+ n (reverse-integer n))) + (lychrelp (n) + (iterate + (repeat 50) + (for i :iterating #'lychrel :seed n) + (never (palindromep i))))) + (iterate (for i :from 0 :below 10000) + (counting (lychrelp i))))) + +(defun problem-56 () + ;; A googol (10^100) is a massive number: one followed by one-hundred zeros; + ;; 100^100 is almost unimaginably large: one followed by two-hundred zeros. + ;; Despite their size, the sum of the digits in each number is only 1. + ;; + ;; Considering natural numbers of the form, a^b, where a, b < 100, what is the + ;; maximum digital sum? + (iterate (for-nested ((a :from 1 :below 100) + (b :from 1 :below 100))) + (maximizing (funcall #'sum (digits (expt a b)))))) + +(defun problem-57 () + ;; It is possible to show that the square root of two can be expressed as an + ;; infinite continued fraction. + ;; + ;; √ 2 = 1 + 1/(2 + 1/(2 + 1/(2 + ... ))) = 1.414213... + ;; + ;; By expanding this for the first four iterations, we get: + ;; + ;; 1 + 1/2 = 3/2 = 1.5 + ;; 1 + 1/(2 + 1/2) = 7/5 = 1.4 + ;; 1 + 1/(2 + 1/(2 + 1/2)) = 17/12 = 1.41666... + ;; 1 + 1/(2 + 1/(2 + 1/(2 + 1/2))) = 41/29 = 1.41379... + ;; + ;; The next three expansions are 99/70, 239/169, and 577/408, but the eighth + ;; expansion, 1393/985, is the first example where the number of digits in the + ;; numerator exceeds the number of digits in the denominator. + ;; + ;; In the first one-thousand expansions, how many fractions contain + ;; a numerator with more digits than denominator? + (iterate + (repeat 1000) + (for i :initially 1/2 :then (/ (+ 2 i))) + (for expansion = (1+ i)) + (counting (> (digits-length (numerator expansion)) + (digits-length (denominator expansion)))))) + +(defun problem-58 () + ;; Starting with 1 and spiralling anticlockwise in the following way, a square + ;; spiral with side length 7 is formed. + ;; + ;; 37 36 35 34 33 32 31 + ;; 38 17 16 15 14 13 30 + ;; 39 18 5 4 3 12 29 + ;; 40 19 6 1 2 11 28 + ;; 41 20 7 8 9 10 27 + ;; 42 21 22 23 24 25 26 + ;; 43 44 45 46 47 48 49 + ;; + ;; It is interesting to note that the odd squares lie along the bottom right + ;; diagonal, but what is more interesting is that 8 out of the 13 numbers + ;; lying along both diagonals are prime; that is, a ratio of 8/13 ≈ 62%. + ;; + ;; If one complete new layer is wrapped around the spiral above, a square + ;; spiral with side length 9 will be formed. If this process is continued, + ;; what is the side length of the square spiral for which the ratio of primes + ;; along both diagonals first falls below 10%? + (labels ((score (value) + (if (primep value) 1 0)) + (primes-in-layer (size) + (sum (number-spiral-corners size) :key #'score))) + (iterate + (for size :from 3 :by 2) + (for count :from 5 :by 4) + (sum (primes-in-layer size) :into primes) + (for ratio = (/ primes count)) + (finding size :such-that (< ratio 1/10))))) + +(defun problem-59 () + ;; Each character on a computer is assigned a unique code and the preferred + ;; standard is ASCII (American Standard Code for Information Interchange). + ;; For example, uppercase A = 65, asterisk (*) = 42, and lowercase k = 107. + ;; + ;; A modern encryption method is to take a text file, convert the bytes to + ;; ASCII, then XOR each byte with a given value, taken from a secret key. The + ;; advantage with the XOR function is that using the same encryption key on + ;; the cipher text, restores the plain text; for example, 65 XOR 42 = 107, + ;; then 107 XOR 42 = 65. + ;; + ;; For unbreakable encryption, the key is the same length as the plain text + ;; message, and the key is made up of random bytes. The user would keep the + ;; encrypted message and the encryption key in different locations, and + ;; without both "halves", it is impossible to decrypt the message. + ;; + ;; Unfortunately, this method is impractical for most users, so the modified + ;; method is to use a password as a key. If the password is shorter than the + ;; message, which is likely, the key is repeated cyclically throughout the + ;; message. The balance for this method is using a sufficiently long password + ;; key for security, but short enough to be memorable. + ;; + ;; Your task has been made easy, as the encryption key consists of three lower + ;; case characters. Using cipher.txt (right click and 'Save Link/Target + ;; As...'), a file containing the encrypted ASCII codes, and the knowledge + ;; that the plain text must contain common English words, decrypt the message + ;; and find the sum of the ASCII values in the original text. + (let* ((data (-<> "data/59-cipher.txt" + read-file-into-string + (substitute #\space #\, <>) + read-all-from-string)) + (raw-words (-<> "/usr/share/dict/words" + read-file-into-string + (cl-strings:split <> #\newline) + (mapcar #'string-downcase <>))) + (words (make-hash-set :test 'equal :initial-contents raw-words))) + (labels + ((stringify (codes) + (map 'string #'code-char codes)) + (apply-cipher (key) + (iterate (for number :in data) + (for k :in-looping key) + (collect (logxor number k)))) + (score-keyword (keyword) + (-<> (apply-cipher keyword) + (stringify <>) + (string-downcase <>) + (cl-strings:split <>) + (remove-if-not (curry #'hset-contains-p words) <>) + length)) + (answer (keyword) + ;; (pr (stringify keyword)) ; keyword is "god", lol + (sum (apply-cipher keyword)))) + (iterate (for-nested ((a :from (char-code #\a) :to (char-code #\z)) + (b :from (char-code #\a) :to (char-code #\z)) + (c :from (char-code #\a) :to (char-code #\z)))) + (for keyword = (list a b c)) + (finding (answer keyword) :maximizing (score-keyword keyword)))))) + +(defun problem-60 () + ;; The primes 3, 7, 109, and 673, are quite remarkable. By taking any two + ;; primes and concatenating them in any order the result will always be prime. + ;; For example, taking 7 and 109, both 7109 and 1097 are prime. The sum of + ;; these four primes, 792, represents the lowest sum for a set of four primes + ;; with this property. + ;; + ;; Find the lowest sum for a set of five primes for which any two primes + ;; concatenate to produce another prime. + (labels-memoized ((concatenates-prime-p (a b) + (and (primep (concatenate-integers a b)) + (primep (concatenate-integers b a))))) + (flet ((satisfiesp (prime primes) + (every (curry #'concatenates-prime-p prime) primes))) + (iterate + main + ;; 2 can never be part of the winning set, because if you concatenate it + ;; in the last position you get an even number. + (with primes = (subseq (sieve 10000) 1)) + (for a :in-vector primes :with-index ai) + (iterate + (for b :in-vector primes :with-index bi :from (1+ ai)) + (when (satisfiesp b (list a)) + (iterate + (for c :in-vector primes :with-index ci :from (1+ bi)) + (when (satisfiesp c (list a b)) + (iterate + (for d :in-vector primes :with-index di :from (1+ ci)) + (when (satisfiesp d (list a b c)) + (iterate + (for e :in-vector primes :from (1+ di)) + (when (satisfiesp e (list a b c d)) + (in main (return-from problem-60 (+ a b c d e))))))))))))))) + +(defun problem-61 () + ;; Triangle, square, pentagonal, hexagonal, heptagonal, and octagonal numbers + ;; are all figurate (polygonal) numbers and are generated by the following + ;; formulae: + ;; + ;; Triangle P3,n=n(n+1)/2 1, 3, 6, 10, 15, ... + ;; Square P4,n=n² 1, 4, 9, 16, 25, ... + ;; Pentagonal P5,n=n(3n−1)/2 1, 5, 12, 22, 35, ... + ;; Hexagonal P6,n=n(2n−1) 1, 6, 15, 28, 45, ... + ;; Heptagonal P7,n=n(5n−3)/2 1, 7, 18, 34, 55, ... + ;; Octagonal P8,n=n(3n−2) 1, 8, 21, 40, 65, ... + ;; + ;; The ordered set of three 4-digit numbers: 8128, 2882, 8281, has three + ;; interesting properties. + ;; + ;; 1. The set is cyclic, in that the last two digits of each number is the + ;; first two digits of the next number (including the last number with the + ;; first). + ;; 2. Each polygonal type: triangle (P3,127=8128), square (P4,91=8281), and + ;; pentagonal (P5,44=2882), is represented by a different number in the + ;; set. + ;; 3. This is the only set of 4-digit numbers with this property. + ;; + ;; Find the sum of the only ordered set of six cyclic 4-digit numbers for + ;; which each polygonal type: triangle, square, pentagonal, hexagonal, + ;; heptagonal, and octagonal, is represented by a different number in the set. + (labels ((numbers (generator) + (iterate (for i :from 1) + (for n = (funcall generator i)) + (while (<= n 9999)) + (when (>= n 1000) + (collect n)))) + (split (number) + (truncate number 100)) + (prefix (number) + (when number + (nth-value 0 (split number)))) + (suffix (number) + (when number + (nth-value 1 (split number)))) + (matches (prefix suffix number) + (multiple-value-bind (p s) + (split number) + (and (or (not prefix) + (= prefix p)) + (or (not suffix) + (= suffix s))))) + (choose (numbers used prefix &optional suffix) + (-<> numbers + (remove-if-not (curry #'matches prefix suffix) <>) + (set-difference <> used))) + (search-sets (sets) + (recursively ((sets sets) + (path nil)) + (destructuring-bind (set . remaining) sets + (if remaining + ;; We're somewhere in the middle, recur on any number whose + ;; prefix matches the suffix of the previous element. + (iterate + (for number :in (choose set path (suffix (car path)))) + (recur remaining (cons number path))) + ;; We're on the last set, we need to find a number that fits + ;; between the penultimate element and first element to + ;; complete the cycle. + (when-let* + ((init (first (last path))) + (prev (car path)) + (final (choose set path (suffix prev) (prefix init)))) + (return-from problem-61 + (sum (reverse (cons (first final) path)))))))))) + (map-permutations #'search-sets + (list (numbers #'triangle) + (numbers #'square) + (numbers #'pentagon) + (numbers #'hexagon) + (numbers #'heptagon) + (numbers #'octagon))))) + +(defun problem-62 () + ;; The cube, 41063625 (345³), can be permuted to produce two other cubes: + ;; 56623104 (384³) and 66430125 (405³). In fact, 41063625 is the smallest cube + ;; which has exactly three permutations of its digits which are also cube. + ;; + ;; Find the smallest cube for which exactly five permutations of its digits + ;; are cube. + (let ((scores (make-hash-table))) ; canonical-repr => (count . first-cube) + ;; Basic strategy from [1] but with some bug fixes. His strategy happens to + ;; work for this specific case, but could be incorrect for others. + ;; + ;; We can't just return as soon as we hit the 5th cubic permutation, because + ;; what if this cube is actually part of a family of 6? Instead we need to + ;; check all other cubes with the same number of digits before making a + ;; final decision to be sure we don't get fooled. + ;; + ;; [1]: http://www.mathblog.dk/project-euler-62-cube-five-permutations/ + (labels ((canonicalize (cube) + (digits-to-number (sort (digits cube) #'>))) + (mark (cube) + (let ((entry (ensure-gethash (canonicalize cube) scores + (cons 0 cube)))) + (incf (car entry)) + entry))) + (iterate + (with i = 1) + (with target = 5) + (with candidates = nil) + (for limit :initially 10 :then (* 10 limit)) + (iterate + (for cube = (cube i)) + (while (< cube limit)) + (incf i) + (for (score . first) = (mark cube)) + (cond ((= score target) (push first candidates)) + ((> score target) (removef candidates first)))) ; tricksy hobbitses + (thereis (apply (nullary #'min) candidates)))))) + +(defun problem-63 () + ;; The 5-digit number, 16807=7^5, is also a fifth power. Similarly, the + ;; 9-digit number, 134217728=8^9, is a ninth power. + ;; + ;; How many n-digit positive integers exist which are also an nth power? + (flet ((score (n) + ;; 10^n will have n+1 digits, so we never need to check beyond that + (iterate (for base :from 1 :below 10) + (for value = (expt base n)) + (counting (= n (digits-length value))))) + (find-bound () + ;; it's 21.something, but I don't really grok why yet + (iterate + (for power :from 1) + (for maximum-possible-digits = (digits-length (expt 9 power))) + (while (>= maximum-possible-digits power)) + (finally (return power))))) + (iterate (for n :from 1 :below (find-bound)) + (sum (score n))))) + +(defun problem-74 () + ;; The number 145 is well known for the property that the sum of the factorial + ;; of its digits is equal to 145: + ;; + ;; 1! + 4! + 5! = 1 + 24 + 120 = 145 + ;; + ;; Perhaps less well known is 169, in that it produces the longest chain of + ;; numbers that link back to 169; it turns out that there are only three such + ;; loops that exist: + ;; + ;; 169 → 363601 → 1454 → 169 + ;; 871 → 45361 → 871 + ;; 872 → 45362 → 872 + ;; + ;; It is not difficult to prove that EVERY starting number will eventually get + ;; stuck in a loop. For example, + ;; + ;; 69 → 363600 → 1454 → 169 → 363601 (→ 1454) + ;; 78 → 45360 → 871 → 45361 (→ 871) + ;; 540 → 145 (→ 145) + ;; + ;; Starting with 69 produces a chain of five non-repeating terms, but the + ;; longest non-repeating chain with a starting number below one million is + ;; sixty terms. + ;; + ;; How many chains, with a starting number below one million, contain exactly + ;; sixty non-repeating terms? + (labels ((digit-factorial (n) + (sum (mapcar #'factorial (digits n)))) + (term-count (n) + (iterate (for i :initially n :then (digit-factorial i)) + (until (member i prev)) + (collect i :into prev) + (counting t)))) + (iterate (for i :from 1 :below 1000000) + (counting (= 60 (term-count i)))))) + +(defun problem-79 () + ;; A common security method used for online banking is to ask the user for + ;; three random characters from a passcode. For example, if the passcode was + ;; 531278, they may ask for the 2nd, 3rd, and 5th characters; the expected + ;; reply would be: 317. + ;; + ;; The text file, keylog.txt, contains fifty successful login attempts. + ;; + ;; Given that the three characters are always asked for in order, analyse + ;; the file so as to determine the shortest possible secret passcode of + ;; unknown length. + (let ((attempts (-<> "data/79-keylog.txt" + read-all-from-file + (mapcar #'digits <>) + (mapcar (rcurry #'coerce 'vector) <>)))) + ;; Everyone in the forum is assuming that there are no duplicate digits in + ;; the passcode, but as someone pointed out this isn't necessarily a safe + ;; assumption. If you have attempts of (12 21) then the shortest passcode + ;; would be 121. So we'll do things the safe way and just brute force it. + (iterate (for passcode :from 1) + (finding passcode :such-that + (every (rcurry #'subsequencep (digits passcode)) + attempts))))) + +(defun problem-92 () + ;; A number chain is created by continuously adding the square of the digits + ;; in a number to form a new number until it has been seen before. + ;; + ;; For example, + ;; 44 → 32 → 13 → 10 → 1 → 1 + ;; 85 → 89 → 145 → 42 → 20 → 4 → 16 → 37 → 58 → 89 + ;; + ;; Therefore any chain that arrives at 1 or 89 will become stuck in an + ;; endless loop. What is most amazing is that EVERY starting number will + ;; eventually arrive at 1 or 89. + ;; + ;; How many starting numbers below ten million will arrive at 89? + (labels ((square-chain-end (i) + (if (or (= 1 i) (= 89 i)) + i + (square-chain-end + (iterate (for d :in-digits-of i) + (summing (square d))))))) + (iterate (for i :from 1 :below 10000000) + (counting (= 89 (square-chain-end i)))))) + +(defun problem-145 () + ;; Some positive integers n have the property that the sum [ n + reverse(n) ] + ;; consists entirely of odd (decimal) digits. For instance, 36 + 63 = 99 and + ;; 409 + 904 = 1313. We will call such numbers reversible; so 36, 63, 409, and + ;; 904 are reversible. Leading zeroes are not allowed in either n or + ;; reverse(n). + ;; + ;; There are 120 reversible numbers below one-thousand. + ;; + ;; How many reversible numbers are there below one-billion (10^9)? + (flet ((reversiblep (n) + (let ((reversed (reverse-integer n))) + (values (unless (zerop (digit 0 n)) + (every #'oddp (digits (+ n reversed)))) + reversed)))) + (iterate + ;; TODO: improve this one + ;; (with limit = 1000000000) there are no 9-digit reversible numbers... + (with limit = 100000000) + (with done = (make-array limit :element-type 'bit :initial-element 0)) + (for i :from 1 :below limit) + (unless (= 1 (aref done i)) + (for (values reversible j) = (reversiblep i)) + (setf (aref done j) 1) + (when reversible + (sum (if (= i j) 1 2))))))) + +(defun problem-345 () + ;; We define the Matrix Sum of a matrix as the maximum sum of matrix elements + ;; with each element being the only one in his row and column. For example, + ;; the Matrix Sum of the matrix below equals 3315 ( = 863 + 383 + 343 + 959 + ;; + 767): + ;; + ;; 7 53 183 439 863 + ;; 497 383 563 79 973 + ;; 287 63 343 169 583 + ;; 627 343 773 959 943 + ;; 767 473 103 699 303 + ;; + ;; Find the Matrix Sum of: ... + (let ((matrix + (copy-array + #2a(( 7 53 183 439 863 497 383 563 79 973 287 63 343 169 583) + (627 343 773 959 943 767 473 103 699 303 957 703 583 639 913) + (447 283 463 29 23 487 463 993 119 883 327 493 423 159 743) + (217 623 3 399 853 407 103 983 89 463 290 516 212 462 350) + (960 376 682 962 300 780 486 502 912 800 250 346 172 812 350) + (870 456 192 162 593 473 915 45 989 873 823 965 425 329 803) + (973 965 905 919 133 673 665 235 509 613 673 815 165 992 326) + (322 148 972 962 286 255 941 541 265 323 925 281 601 95 973) + (445 721 11 525 473 65 511 164 138 672 18 428 154 448 848) + (414 456 310 312 798 104 566 520 302 248 694 976 430 392 198) + (184 829 373 181 631 101 969 613 840 740 778 458 284 760 390) + (821 461 843 513 17 901 711 993 293 157 274 94 192 156 574) + ( 34 124 4 878 450 476 712 914 838 669 875 299 823 329 699) + (815 559 813 459 522 788 168 586 966 232 308 833 251 631 107) + (813 883 451 509 615 77 281 613 459 205 380 274 302 35 805))))) + (do-array (val matrix) + (negatef val)) + (iterate + (for (row . col) :in (euler.hungarian:find-minimal-assignment matrix)) + (summing (- (aref matrix row col)))))) + +(defun problem-357 () + ;; Consider the divisors of 30: 1,2,3,5,6,10,15,30. It can be seen that for + ;; every divisor d of 30, d+30/d is prime. + ;; + ;; Find the sum of all positive integers n not exceeding 100 000 000 such that + ;; for every divisor d of n, d+n/d is prime. + (labels ((check-divisor (n d) + (primep (+ d (truncate n d)))) + (prime-generating-integer-p (n) + (declare (optimize speed) + (type fixnum n) + (inline divisors-up-to-square-root)) + (every (curry #'check-divisor n) + (divisors-up-to-square-root n)))) + ;; Observations about the candidate numbers, from various places around the + ;; web, with my notes for humans: + ;; + ;; * n+1 must be prime. + ;; + ;; Every number has 1 has a factor, which means one of + ;; the tests will be to see if 1+(n/1) is prime. + ;; + ;; * n must be even (except the edge case of 1). + ;; + ;; We know this because n+1 must be prime, and therefore odd, so n itself + ;; must be even. + ;; + ;; * 2+(n/2) must be prime. + ;; + ;; Because all candidates are even, they all have 2 as a divisor (see + ;; above), and so we can do this check before finding all the divisors. + ;; + ;; * n must be squarefree. + ;; + ;; Consider when n is squareful: then there is some prime that occurs more + ;; than once in its factorization. Choosing this prime as the divisor for + ;; the formula gives us d+(n/d). We know that n/d will still be divisible + ;; by d, because we chose a d that occurs multiple times in the + ;; factorization. Obviously d itself is divisible by d. Thus our entire + ;; formula is divisible by d, and so not prime. + ;; + ;; Unfortunately this doesn't really help us much, because there's no + ;; efficient way to tell if a number is squarefree (see + ;; http://mathworld.wolfram.com/Squarefree.html). + ;; + ;; * We only have to check d <= sqrt(n). + ;; + ;; For each divisor d of n we know there's a twin divisor d' such that + ;; d * d' = n (that's what it MEANS for d to be a divisor of n). + ;; + ;; If we plug d into the formula we have d + n/d. + ;; We know that n/d = d', and so we have d + d'. + ;; + ;; If we plug d' into the formula we have d' + n/d'. + ;; We know that n/d' = d, and so we have d' + d. + ;; + ;; This means that plugging d or d' into the formula both result in the + ;; same number, so we only need to bother checking one of them. + (1+ (iterate + ;; edge case: skip 2 (candidiate 1), we'll add it at the end + (for prime :in-vector (sieve (1+ 100000000)) :from 1) + (for candidate = (1- prime)) + (when (and (check-divisor candidate 2) + (prime-generating-integer-p candidate)) + (summing candidate)))))) + + +;;;; Tests -------------------------------------------------------------------- +(def-suite :euler) +(in-suite :euler) + +(test p1 (is (= 233168 (problem-1)))) +(test p2 (is (= 4613732 (problem-2)))) +(test p3 (is (= 6857 (problem-3)))) +(test p4 (is (= 906609 (problem-4)))) +(test p5 (is (= 232792560 (problem-5)))) +(test p6 (is (= 25164150 (problem-6)))) +(test p7 (is (= 104743 (problem-7)))) +(test p8 (is (= 23514624000 (problem-8)))) +(test p9 (is (= 31875000 (problem-9)))) +(test p10 (is (= 142913828922 (problem-10)))) +(test p11 (is (= 70600674 (problem-11)))) +(test p12 (is (= 76576500 (problem-12)))) +(test p13 (is (= 5537376230 (problem-13)))) +(test p14 (is (= 837799 (problem-14)))) +(test p15 (is (= 137846528820 (problem-15)))) +(test p16 (is (= 1366 (problem-16)))) +(test p17 (is (= 21124 (problem-17)))) +(test p18 (is (= 1074 (problem-18)))) +(test p19 (is (= 171 (problem-19)))) +(test p20 (is (= 648 (problem-20)))) +(test p21 (is (= 31626 (problem-21)))) +(test p22 (is (= 871198282 (problem-22)))) +(test p23 (is (= 4179871 (problem-23)))) +(test p24 (is (= 2783915460 (problem-24)))) +(test p25 (is (= 4782 (problem-25)))) +(test p26 (is (= 983 (problem-26)))) +(test p27 (is (= -59231 (problem-27)))) +(test p28 (is (= 669171001 (problem-28)))) +(test p29 (is (= 9183 (problem-29)))) +(test p30 (is (= 443839 (problem-30)))) +(test p31 (is (= 73682 (problem-31)))) +(test p32 (is (= 45228 (problem-32)))) +(test p33 (is (= 100 (problem-33)))) +(test p34 (is (= 40730 (problem-34)))) +(test p35 (is (= 55 (problem-35)))) +(test p36 (is (= 872187 (problem-36)))) +(test p37 (is (= 748317 (problem-37)))) +(test p38 (is (= 932718654 (problem-38)))) +(test p39 (is (= 840 (problem-39)))) +(test p40 (is (= 210 (problem-40)))) +(test p41 (is (= 7652413 (problem-41)))) +(test p42 (is (= 162 (problem-42)))) +(test p43 (is (= 16695334890 (problem-43)))) +(test p44 (is (= 5482660 (problem-44)))) +(test p45 (is (= 1533776805 (problem-45)))) +(test p46 (is (= 5777 (problem-46)))) +(test p47 (is (= 134043 (problem-47)))) +(test p48 (is (= 9110846700 (problem-48)))) +(test p49 (is (= 296962999629 (problem-49)))) +(test p50 (is (= 997651 (problem-50)))) +(test p51 (is (= 121313 (problem-51)))) +(test p52 (is (= 142857 (problem-52)))) +(test p53 (is (= 4075 (problem-53)))) +(test p54 (is (= 376 (problem-54)))) +(test p55 (is (= 249 (problem-55)))) +(test p56 (is (= 972 (problem-56)))) +(test p57 (is (= 153 (problem-57)))) +(test p58 (is (= 26241 (problem-58)))) +(test p59 (is (= 107359 (problem-59)))) +(test p60 (is (= 26033 (problem-60)))) +(test p61 (is (= 28684 (problem-61)))) +(test p62 (is (= 127035954683 (problem-62)))) +(test p63 (is (= 49 (problem-63)))) + + +(test p74 (is (= 402 (problem-74)))) +(test p79 (is (= 73162890 (problem-79)))) +(test p92 (is (= 8581146 (problem-92)))) +(test p145 (is (= 608720 (problem-145)))) +(test p357 (is (= 1739023853137 (problem-357)))) + + +(defun run-tests () + (run! :euler)) diff -r 9230e81d302c -r 4f58a841ae48 src/utils.lisp --- a/src/utils.lisp Wed Aug 09 14:55:51 2017 -0400 +++ b/src/utils.lisp Thu Aug 10 20:09:14 2017 -0400 @@ -470,3 +470,42 @@ (every (lambda (el) (setf p (position el haystack :start p :key key :test test))) needles))))) + + +(deftype matrix (&optional (element-type '*)) + `(array ,element-type (* *))) + +(defun transpose-matrix (matrix) + (check-type matrix matrix) + (iterate (with (rows cols) = (array-dimensions matrix)) + (with result = (make-array (list cols rows))) + (for-nested ((i :from 0 :below rows) + (j :from 0 :below cols))) + (setf (aref result j i) + (aref matrix i j)) + (finally (return result)))) + +(defun rotate-matrix-clockwise (matrix) + (check-type matrix matrix) + (iterate (with (rows cols) = (array-dimensions matrix)) + (with result = (make-array (list cols rows))) + (for source-row :from 0 :below rows) + (for target-col = (- rows source-row 1)) + (dotimes (source-col cols) + (for target-row = source-col) + (setf (aref result target-row target-col) + (aref matrix source-row source-col))) + (finally (return result)))) + +(defun rotate-matrix-counterclockwise (matrix) + (check-type matrix matrix) + (iterate (with (rows cols) = (array-dimensions matrix)) + (with result = (make-array (list cols rows))) + (for source-row :from 0 :below rows) + (for target-col = source-row) + (dotimes (source-col cols) + (for target-row = (- cols source-col 1)) + (setf (aref result target-row target-col) + (aref matrix source-row source-col))) + (finally (return result)))) + diff -r 9230e81d302c -r 4f58a841ae48 vendor/make-quickutils.lisp --- a/vendor/make-quickutils.lisp Wed Aug 09 14:55:51 2017 -0400 +++ b/vendor/make-quickutils.lisp Thu Aug 10 20:09:14 2017 -0400 @@ -5,6 +5,7 @@ :utilities '( :compose + :copy-array :curry :define-constant :emptyp diff -r 9230e81d302c -r 4f58a841ae48 vendor/quickutils.lisp --- a/vendor/quickutils.lisp Wed Aug 09 14:55:51 2017 -0400 +++ b/vendor/quickutils.lisp Thu Aug 10 20:09:14 2017 -0400 @@ -2,7 +2,7 @@ ;;;; See http://quickutil.org for details. ;;;; To regenerate: -;;;; (qtlc:save-utils-as "quickutils.lisp" :utilities '(:COMPOSE :CURRY :DEFINE-CONSTANT :EMPTYP :ENSURE-BOOLEAN :ENSURE-FUNCTION :ENSURE-GETHASH :EQUIVALENCE-CLASSES :MAP-COMBINATIONS :MAP-PERMUTATIONS :MAXF :MINF :N-GRAMS :RANGE :RCURRY :READ-FILE-INTO-STRING :REMOVEF :SWITCH :WITH-GENSYMS) :ensure-package T :package "EULER.QUICKUTILS") +;;;; (qtlc:save-utils-as "quickutils.lisp" :utilities '(:COMPOSE :COPY-ARRAY :CURRY :DEFINE-CONSTANT :EMPTYP :ENSURE-BOOLEAN :ENSURE-FUNCTION :ENSURE-GETHASH :EQUIVALENCE-CLASSES :MAP-COMBINATIONS :MAP-PERMUTATIONS :MAXF :MINF :N-GRAMS :RANGE :RCURRY :READ-FILE-INTO-STRING :REMOVEF :SWITCH :WITH-GENSYMS) :ensure-package T :package "EULER.QUICKUTILS") (eval-when (:compile-toplevel :load-toplevel :execute) (unless (find-package "EULER.QUICKUTILS") @@ -14,13 +14,13 @@ (when (boundp '*utilities*) (setf *utilities* (union *utilities* '(:MAKE-GENSYM-LIST :ENSURE-FUNCTION - :COMPOSE :CURRY :DEFINE-CONSTANT - :NON-ZERO-P :EMPTYP :ENSURE-BOOLEAN - :ENSURE-GETHASH :EQUIVALENCE-CLASSES - :MAP-COMBINATIONS :MAP-PERMUTATIONS - :MAXF :MINF :TAKE :N-GRAMS :RANGE - :RCURRY :ONCE-ONLY :WITH-OPEN-FILE* - :WITH-INPUT-FROM-FILE + :COMPOSE :COPY-ARRAY :CURRY + :DEFINE-CONSTANT :NON-ZERO-P :EMPTYP + :ENSURE-BOOLEAN :ENSURE-GETHASH + :EQUIVALENCE-CLASSES :MAP-COMBINATIONS + :MAP-PERMUTATIONS :MAXF :MINF :TAKE + :N-GRAMS :RANGE :RCURRY :ONCE-ONLY + :WITH-OPEN-FILE* :WITH-INPUT-FROM-FILE :READ-FILE-INTO-STRING :REMOVEF :STRING-DESIGNATOR :WITH-GENSYMS :EXTRACT-FUNCTION-NAME :SWITCH)))) @@ -77,6 +77,24 @@ ,(compose-1 funs)))))) + (defun copy-array (array &key (element-type (array-element-type array)) + (fill-pointer (and (array-has-fill-pointer-p array) + (fill-pointer array))) + (adjustable (adjustable-array-p array))) + "Returns an undisplaced copy of `array`, with same `fill-pointer` and +adjustability (if any) as the original, unless overridden by the keyword +arguments." + (let* ((dimensions (array-dimensions array)) + (new-array (make-array dimensions + :element-type element-type + :adjustable adjustable + :fill-pointer fill-pointer))) + (dotimes (i (array-total-size array)) + (setf (row-major-aref new-array i) + (row-major-aref array i))) + new-array)) + + (defun curry (function &rest arguments) "Returns a function that applies `arguments` and the arguments it is called with to `function`." @@ -526,8 +544,8 @@ (generate-switch-body whole object clauses test key '(cerror "Return NIL from CSWITCH."))) (eval-when (:compile-toplevel :load-toplevel :execute) - (export '(compose curry define-constant emptyp ensure-boolean ensure-function - ensure-gethash equivalence-classes map-combinations + (export '(compose copy-array curry define-constant emptyp ensure-boolean + ensure-function ensure-gethash equivalence-classes map-combinations map-permutations maxf minf n-grams range rcurry read-file-into-string removef switch eswitch cswitch with-gensyms with-unique-names)))