Square-free integers: Difference between revisions
Content added Content deleted
(→{{header|Ruby}}: removed unneeded to_a twice) |
(jq) |
||
Line 765: | Line 765: | ||
from 1 to 1000000 = 607926 |
from 1 to 1000000 = 607926 |
||
</pre> |
</pre> |
||
=={{header|jq}}== |
|||
Requires jq 1.5 or higher |
|||
For brevity and in order to highlight some points of interest regarding jq, |
|||
this entry focuses on solving the task in a manner that reflects |
|||
the specification as closely as possible (no prime sieves or calls |
|||
to sqrt), with efficiency concerns playing second fiddle. |
|||
Once a suitable generator for squares and a test for divisibility have been written, the |
|||
test for whether a number is square-free can be written in one line: |
|||
def square_free: . as $n | all( squares; divides($n) | not); |
|||
In words: to verify whether an integer, $n, is square_free, check that no admissible square divides $n. |
|||
'''squares''' |
|||
We could define the required `squares` generator using `while`: |
|||
def squares: . as $n | 2 | while(.*. <= $n; .+1) | .*.; |
|||
(Here `.*.` calculates the square of the input number.) |
|||
However, this entails performing an unnecessary multiplication, so the question becomes whether there |
|||
is a more economical solution that closely reflects the specification of the required generator. Since jq supports tail-recursion optimization for 0-arity filters, the answer is: |
|||
def squares: |
|||
. as $n |
|||
| def s: |
|||
(.*.) as $s |
|||
| select($s <= $n) |
|||
| $s, ((1+.)|s); |
|||
2|s; |
|||
The point of interest here is the def-within-a-def. |
|||
'''divides''' |
|||
def divides($x): ($x % .) == 0; |
|||
'''is_square_free''' |
|||
`is_square_free` as defined here intentionally returns true for all numeric inputs less than 4. |
|||
def is_square_free: . as $n | all( squares; divides($n) | not) ; |
|||
---- |
|||
'''The tasks''' |
|||
The primary task is to examine square-free numbers in an inclusive range, |
|||
so we define `square_free` to emit a stream of such numbers: |
|||
def square_free(from; including): |
|||
range(from;including+1) | select( is_square_free ) ; |
|||
# Compute SIGMA(s) where s is a stream |
|||
def sigma(s): reduce s as $s (null; .+$s); |
|||
# Group items in a stream into arrays of length at most $n. |
|||
# For generality, this function uses `nan` as the eos marker. |
|||
def nwise(stream; $n): |
|||
foreach (stream, nan) as $x ([]; |
|||
if length == $n then [$x] else . + [$x] end; |
|||
if (.[-1] | isnan) and length>1 then .[:-1] |
|||
elif length == $n then . |
|||
else empty |
|||
end); |
|||
def prettify_squares(from; including; width): |
|||
"Square-free integers from \(from) to \(including) (inclusive):", |
|||
(nwise( square_free(from;including); width) | map(tostring) | join(" ")), |
|||
""; |
|||
def prettify_count($from; $including): |
|||
"Count from \($from) to \($including) inclusive: \(sigma( square_free($from ; $including) | 1 ))"; |
|||
'''The specific tasks''' |
|||
prettify_squares(1;145; 20), |
|||
prettify_squares(1E12; 1E12 + 145; 5), |
|||
((1E2, 1E3, 1E4, 1E5, 1E6) | prettify_count(1; .)) |
|||
'''Output''' |
|||
<pre>Square-free integers from 1 to 145 (inclusive): |
|||
1 2 3 5 6 7 10 11 13 14 15 17 19 21 22 23 26 29 30 31 |
|||
33 34 35 37 38 39 41 42 43 46 47 51 53 55 57 58 59 61 62 65 |
|||
66 67 69 70 71 73 74 77 78 79 82 83 85 86 87 89 91 93 94 95 |
|||
97 101 102 103 105 106 107 109 110 111 113 114 115 118 119 122 123 127 129 130 |
|||
131 133 134 137 138 139 141 142 143 145 |
|||
Square-free integers from 1000000000000 to 1000000000145 (inclusive): |
|||
1000000000001 1000000000002 1000000000003 1000000000005 1000000000006 |
|||
1000000000007 1000000000009 1000000000011 1000000000013 1000000000014 |
|||
1000000000015 1000000000018 1000000000019 1000000000021 1000000000022 |
|||
1000000000023 1000000000027 1000000000029 1000000000030 1000000000031 |
|||
1000000000033 1000000000037 1000000000038 1000000000039 1000000000041 |
|||
1000000000042 1000000000043 1000000000045 1000000000046 1000000000047 |
|||
1000000000049 1000000000051 1000000000054 1000000000055 1000000000057 |
|||
1000000000058 1000000000059 1000000000061 1000000000063 1000000000065 |
|||
1000000000066 1000000000067 1000000000069 1000000000070 1000000000073 |
|||
1000000000074 1000000000077 1000000000078 1000000000079 1000000000081 |
|||
1000000000082 1000000000085 1000000000086 1000000000087 1000000000090 |
|||
1000000000091 1000000000093 1000000000094 1000000000095 1000000000097 |
|||
1000000000099 1000000000101 1000000000102 1000000000103 1000000000105 |
|||
1000000000106 1000000000109 1000000000111 1000000000113 1000000000114 |
|||
1000000000115 1000000000117 1000000000118 1000000000119 1000000000121 |
|||
1000000000122 1000000000123 1000000000126 1000000000127 1000000000129 |
|||
1000000000130 1000000000133 1000000000135 1000000000137 1000000000138 |
|||
1000000000139 1000000000141 1000000000142 1000000000145 |
|||
Count from 1 to 100 inclusive: 61 |
|||
Count from 1 to 1000 inclusive: 608 |
|||
Count from 1 to 10000 inclusive: 6083 |
|||
Count from 1 to 100000 inclusive: 60794 |
|||
Count from 1 to 1000000 inclusive: 607926</pre> |
|||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |