Lucky and even lucky numbers: Difference between revisions

m (→‎{{header|Wren}}: Wren-trait -> Wren-iterate)
Line 1,430:
Result: 111842
</pre>
 
=={{header|jq}}==
'''Works with jq and jaq, the C and Rust implementions of jq'''
 
Also works with gojq, the Go implementation, but gojq requires
a very large amount of memory to complete the last task (finding the 10,000th even lucky number).
 
The following program has been written to run using the C, Go and Rust
implementations of jq and is therefore not as succinct as it would
otherwise have been. Also, the mechanisms for passing in command-line
parameters differ amongst the three implementations, so the program presented here expects the
parameters to be presented on a single line as input. Thus a possible
invocation would be:
 
<pre>
JQ -Rrcf program.jq <<< '1 20'
</pre>
 
The disadvantage of the sieve-based approach used below is the
difficulty of choosing a sieve size that is on the one hand sufficient
but on the other frugal. No claim is made for the algorithm used to
determine the sieve size here other than it is reasonable for problems
sufficiently similar to the ones solved here. However, if the sieve size
turns out to be insufficient, an error condition will be raised.
<syntaxhighlight lang=jq>
# Preliminaries:
# This def can be omitted if using jq or gojq:
def range($a;$b;$c): $a | while(. < $b; .+$c);
 
# jaq does not support string interpolation so, for brevity:
def tos: tostring;
 
# The following def should be modified if an alternative mechanism for
# reading the parameter arguments is used:
def args: {args: [splits(" *")]};
 
def argsSize: .args|length;
 
# Input: an array
# Emit the items in the array until the condition on the items is met.
# The item for which the condition is first met is NOT emitted.
def emit_until(cond):
length as $length
| if $length == 0 or (.[0]|cond) then empty
else . as $in
| {i:0, ok: true}
| while(.ok;
.i+=1
| .ok = .i < $length and ($in[.i] | cond | not) )
| $in[.i]
end;
 
# input: a number or a string
# If the input is or can be converted to a number using tonumber, then return the number
# else return false.
def isnumber:
if type == "number" then .
elif type == "string" then tonumber? // false
else false
end;
 
# input: anything
# output: a boolean
def isinteger:
if type == "number" then . == floor
else isnumber as $x
| if $x then $x | (. == floor) else false end
end;
 
# mark and collapse
def removeEvery($n):
reduce range($n-1; length; $n) as $i (.; .[$i]=null)
| map(select(.));
 
# Input: {lucky}
def filterLucky:
(.lucky|length) as $length
| .n = 2
| until( .n >= $length;
.lucky[.n-1] as $m
| if $m then .lucky |= removeEvery($m) | .n += 1
else .n = $length
end )
| del(.n);
 
def printSingle($j):
if $j >= 1 + (.lucky|length) then "Argument is too big" | error
else
(if .odd then "Lucky number #" else "Lucky even number #" end)
+ ($j|tos) + " = " + (.lucky[$j-1]|tos)
end;
 
# like jq's range($j-1; $k)
def printRange($j; $k):
if $k >= (.lucky|length) then "Argument " + ($k|tos) + " is too big" | error
elif .odd
then "Lucky numbers " + ($j|tos) + " to " + ($k|tos) + " inclusive are:",
.lucky[$j-1:$k]
else "Lucky even numbers " + ($j|tos) + " to " + ($k|tos) + " inclusive are:",
.lucky[$j-1:$k]
end;
 
def printBetween($j; $k):
.lucky[-1] as $max
| if $j > $max or $k > $max
then "At least one argument is too big" | error
else
(if .odd
then "Lucky numbers between " + ($j|tos) + " and " + ($k|tos) + " are:"
else "Lucky even numbers between " + ($j|tos) + " and " + ($k|tos) + " are:"
end),
[.lucky | emit_until(. > $k) | select(. >= $j)]
end;
 
def odd:
if argsSize < 3 then true
else (.args[2] | tostring | ascii_downcase)
| if . == "lucky" or . == "odd" then true
elif . == "evenlucky" or . == "even" then false
else "Third argument " + (.args[2]|tos) + " is invalid" | error
end
end;
 
# Input: {odd}
def init($n):
if .odd
then .lucky = reduce range(0;$n) as $i (null; . + [$i*2 + 1])
else .lucky = reduce range(0;$n) as $i (null; . + [$i*2 + 2])
end;
 
# Emit {args, j, k, odd, single} or raise an error
def gatherArgs:
args
| if argsSize | (. < 1 or . > 3)
then "There must be between 1 and 3 command line arguments" | error
else .j = (.args[0] | isnumber )
| .k = (.args[1] | isnumber )
| .single = (argsSize == 1 or .args[1] == ",")
| .odd = odd
| if (.j | isinteger | not) or (.j < 1)
then "First argument " + (.args[0]|tos) + " must be a positive integer" | error
elif argsSize >= 2 and .args[1] != "," and (.k | isinteger | not)
then "Second argument " + (.args[1]|tos) + " must be an integer or ," | error
else .
end
| if .k and .k >= 0 and .j > .k
then "Second argument cannot be less than first" | error
else .
end
end ;
def start:
gatherArgs
| (if .k then (if .k > 0 then .k else null end) else .j end) as $size
| (if $size then ($size | . * (tostring|length|.*.)) else -.k end) as $size
| init($size|debug)
| filterLucky
| if .single then printSingle(.j)
elif .k > 0 then printRange(.j; .k)
else .k |= - .
| if (.j > .k)
then "The second argument cannot be less in absolute value than first" | error
else printBetween(.j; .k)
end
end;
 
start
</syntaxhighlight>
{{output}}
<pre>
Lucky numbers 1 to 20 inclusive are:
[1,3,7,9,13,15,21,25,31,33,37,43,49,51,63,67,69,73,75,79]
 
Lucky even numbers 1 to 20 inclusive are:
[2,4,6,10,12,18,20,22,26,34,36,42,44,50,52,54,58,68,70,76]
 
Lucky numbers between 6000 and 6100 are:
[6009,6019,6031,6049,6055,6061,6079,6093]
 
Lucky even numbers between 6000 and 6100 are:
[6018,6020,6022,6026,6036,6038,6050,6058,6074,6090,6092]
 
Lucky number #1000 = 8809
 
Lucky even number #10000 = 111842
</pre>
 
 
=={{header|Julia}}==
2,471

edits