]> gitweb.factorcode.org Git - factor.git/blob - extra/project-euler/061/061.factor
assocs.extras: Move some often-used words to core
[factor.git] / extra / project-euler / 061 / 061.factor
1 ! Copyright (C) 2023 Giftpflanze.
2 ! See https://factorcode.org/license.txt for BSD license
3 USING: arrays assocs assocs.extras grouping kernel math
4 project-euler.common ranges sequences sequences.extras ;
5 IN: project-euler.061
6
7 ! https://projecteuler.net/problem=61
8
9 ! DESCRIPTION
10 ! -----------
11
12 ! Triangle, square, pentagonal, hexagonal, heptagonal, and
13 ! octagonal numbers are all figurate (polygonal) numbers and are
14 ! generated by the following formulae:
15
16 ! Triangle   P(3,n) = n(n+1)/2  1, 3, 6, 10, 15, ...
17 ! Square     P(4,n) = n²        1, 4, 9, 16, 25, ...
18 ! Pentagonal P(5,n) = n(3n-1)/2 1, 5, 12, 22, 35, ...
19 ! Hexagonal  P(6,n) = n(2n-1)   1, 6, 15, 28, 45, ...
20 ! Heptagonal P(7,n) = n(5n-3)/2 1, 7, 18, 34, 55, ...
21 ! Octagonal  P(8,n) = n(3n-2)   1, 8, 21, 40, 65, ...
22
23 ! The ordered set of three 4-digit numbers: 8128, 2882, 8281,
24 ! has three interesting properties.
25
26 ! 1. The set is cyclic, in that the last two digits of each
27 ! number is the first two digits of the next number (including
28 ! the last number with the first).
29
30 ! 2. Each polygonal type: triangle (P(3,127) = 8128), square
31 ! (P(4,91) = 8281), and pentagonal (P(5,44) = 2882), is
32 ! represented by a different number in the set.
33
34 ! 3. This is the only set of 4-digit numbers with this property.
35 !
36 ! Find the sum of the only ordered set of six cyclic 4-digit
37 ! numbers for which each polygonal type: triangle, square,
38 ! pentagonal, hexagonal, heptagonal, and octagonal, is
39 ! represented by a different number in the set.
40
41
42 ! SOLUTION
43 ! --------
44
45 ! https://en.wikipedia.org/wiki/Polygonal_number#Formula
46 ! nth s-gonal number P(s,n) = [(s-2)n²-(s-4)n]/2
47 : nth-polygon ( n s -- p )
48     [ [ sq ] dip 2 - * ] [ 4 - * ] 2bi - 2 / ;
49
50 : (4-digit-polygons) ( s -- seq )
51     [ V{ } clone 1 ] dip
52     [ 2dup nth-polygon dup 9999 > ] [
53         dup 1000 >= [ dupd 2array reach push ] [ drop ] if
54         [ 1 + ] dip
55     ] until 3drop ;
56
57 : 4-digit-polygons ( -- seq )
58     3 8 [a..b] [ (4-digit-polygons) ] map-concat ;
59
60 : cycle? ( chain -- ? )
61     2 circular-clump [
62         values first2 [ 100 mod ] [ 100 /i ] bi* =
63     ] all? ;
64
65 : links ( polygons chain -- chains )
66     [ keys '[ _ member? ] reject-keys ] keep
67     tuck values last 100 mod '[ 100 /i _ = ] filter-values
68     [ suffix ] with map ;
69
70 : find-cycle ( polygons chain length -- chain )
71     2dup [ length ] dip = [
72         drop nip [ cycle? ] keep and
73     ] [
74         [ dupd links ] dip '[ _ find-cycle ] with map-find drop
75     ] if ;
76
77 : euler061 ( -- n )
78     4-digit-polygons dup [ 8 = ] filter-keys [
79         1array 6 find-cycle
80     ] with map-find drop sum-values ;
81
82 SOLUTION: euler061