Lucky and even lucky numbers: Difference between revisions
m (added whitespace before TOC.) |
|||
Line 87: | Line 87: | ||
* Sequence [https://oeis.org/A000959 A000959 lucky numbers] on The On-Line Encyclopedia of Integer Sequences. |
* Sequence [https://oeis.org/A000959 A000959 lucky numbers] on The On-Line Encyclopedia of Integer Sequences. |
||
* Sequence [https://oeis.org/A045954 A045954 even lucky numbers or ELN] on The On-Line Encyclopedia of Integer Sequences. |
* Sequence [https://oeis.org/A045954 A045954 even lucky numbers or ELN] on The On-Line Encyclopedia of Integer Sequences. |
||
* Entry [http://mathworld.wolfram.com/LuckyNumber.html lucky numbers] on The Eric Weisstein's World of Mathematics. |
* Entry [http://mathworld.wolfram.com/LuckyNumber.html lucky numbers] on The Eric Weisstein's World of Mathematics.<br><br> |
||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
Revision as of 05:42, 28 March 2016
Note that in the following explanation list indices are assumed to start at one.
- Definition of lucky numbers
Lucky numbers are positive integers that are formed by:
- Form a list of all the positive odd integers > 0
- Return the first number from the list (which is 1).
- (Loop begins here)
- Note then return the second number from the list (which is 3).
- Discard every third, (as noted), number from the list to form the new list
- (Expanding the loop a few more times...)
- Note then return the third number from the list (which is 7).
- Discard every 7th, (as noted), number from the list to form the new list
- Note then return the 4th number from the list (which is 9).
- Discard every 9th, (as noted), number from the list to form the new list
- Take the 5th, i.e. 13. Remove every 13th.
- Take the 6th, i.e. 15. Remove every 15th.
- Take the 7th, i.e. 21. Remove every 21th.
- Take the 8th, i.e. 25. Remove every 25th.
- (Rule for the loop)
- Note the th, which is .
- Remove every th.
- Increment .
- Definition of even lucky numbers
This follows the same rules as the definition of lucky numbers above except for the very first step:
- Form a list of all the positive even integers > 0
- Return the first number from the list (which is 2).
- (Loop begins here)
- Note then return the second number from the list (which is 4).
- Discard every 4th, (as noted), number from the list to form the new list
- (Expanding the loop a few more times...)
- Note then return the third number from the list (which is 6).
- Discard every 6th, (as noted), number from the list to form the new list
- Take the 4th, i.e. 10. Remove every 10th.
- Take the 5th, i.e. 12. Remove every 12th.
- (Rule for the loop)
- Note the th, which is .
- Remove every th.
- Increment .
- Task requirements
- Write one or two subroutines (functions) to generate lucky numbers and even lucky numbers
- Write a command-line interface to allow selection of which kind of numbers and which number(s). Since input is from the command line, tests should be made for the common errors:
- missing arguments
- too many arguments
- number (or numbers) aren't legal
- misspelled argument (lucky or evenLucky)
- The command line handling should:
- support mixed case handling of the (non-numeric) arguments
- support printing a particular number
- support printing a range of numbers by their index
- support printing a range of numbers by their values
- The resulting list of numbers should be printed on a single line.
The program should support the arguments:
what is displayed (on a single line) argument(s) (optional verbiage is encouraged) ╔═══════════════════╦════════════════════════════════════════════════════╗ ║ j ║ Jth lucky number ║ ║ j , lucky ║ Jth lucky number ║ ║ j , evenLucky ║ Jth even lucky number ║ ║ ║ ║ ║ j k ║ Jth through Kth (inclusive) lucky numbers ║ ║ j k lucky ║ Jth through Kth (inclusive) lucky numbers ║ ║ j k evenLucky ║ Jth through Kth (inclusive) even lucky numbers ║ ║ ║ ║ ║ j -k ║ all lucky numbers in the range j ──► |k| ║ ║ j -k lucky ║ all lucky numbers in the range j ──► |k| ║ ║ j -k evenLucky ║ all even lucky numbers in the range j ──► |k| ║ ╚═══════════════════╩════════════════════════════════════════════════════╝ where |k| is the absolute value of k
Demonstrate the program by:
- showing the first twenty lucky numbers
- showing the first twenty even lucky numbers
- showing all lucky numbers between 6,000 and 6,100 (inclusive)
- showing all even lucky numbers in the same range as above
- showing the 10,000th lucky number (extra credit)
- showing the 10,000th even lucky number (extra credit)
- See also
- This task is related to the Sieve of Eratosthenes task.
- OEIS Wiki Lucky numbers.
- Sequence A000959 lucky numbers on The On-Line Encyclopedia of Integer Sequences.
- Sequence A045954 even lucky numbers or ELN on The On-Line Encyclopedia of Integer Sequences.
- Entry lucky numbers on The Eric Weisstein's World of Mathematics.
Haskell
Haskell is a very nice language for this problem because it is a lazy language. Here regular expressions and data types are used.
<lang Haskell> import System.Environment import System.Exit import Data.Char import Text.Regex.Posix
data Lucky = Lucky | EvenLucky
helpMessage :: IO () helpMessage = do
putStrLn " what is displayed (on a single line)" putStrLn " argument(s) (optional verbiage is encouraged)" putStrLn "======================|===================================================" putStrLn " j | Jth lucky number " putStrLn " j , lucky | Jth lucky number " putStrLn " j , evenLucky | Jth even lucky number " putStrLn " " putStrLn " j k | Jth through Kth (inclusive) lucky numbers " putStrLn " j k lucky | Jth through Kth (inclusive) lucky numbers " putStrLn " j k evenlucky | Jth through Kth (inclusive) even lucky numbers " putStrLn " " putStrLn " j -k | all lucky numbers in the range j -> |k| " putStrLn " j -k lucky | all lucky numbers in the range j -> |k| " putStrLn " j -k evenlucky | all even lucky numbers in the range j -> |k| " putStrLn "======================|==================================================="
oddNumbers :: [Int] oddNumbers = filter odd [1..]
evenNumbers :: [Int] evenNumbers = filter even [1..]
luckyNumbers :: [Int] -> [Int] luckyNumbers xs =
let i = 3 in sieve i xs where sieve i (ln:s:xs) = ln : sieve (i + 1) (s : [x | (n, x) <- zip [i..] xs, rem n s /= 0])
nth :: Int -> Lucky -> Int nth j l = case l of
Lucky -> last (take j (luckyNumbers oddNumbers)) EvenLucky -> last (take j (luckyNumbers evenNumbers))
range :: Int -> Int -> Lucky -> [Int] range x x2 l = case l of
Lucky -> let n = length (take x (luckyNumbers oddNumbers)) in drop (n-1) (take x2 (luckyNumbers oddNumbers)) EvenLucky -> let n = length (take x (luckyNumbers evenNumbers)) in drop (n-1) (take x2 (luckyNumbers evenNumbers))
interval :: Int -> Int -> Lucky -> [Int] interval x x2 l = let x = (-1 * x2) in
case l of Lucky -> let n = length (takeWhile (<x) (luckyNumbers oddNumbers)) in drop (n-1) (takeWhile (<x) (luckyNumbers oddNumbers)) EvenLucky -> let n = length (takeWhile (<x) (luckyNumbers evenNumbers)) in drop (n-1) (takeWhile (<x) (luckyNumbers evenNumbers))
lucky :: [String] -> Lucky lucky xs =
if (not (null (filter (== "evenLucky") xs))) then EvenLucky else Lucky
readn :: String -> Int readn s = read s :: Int
isInt :: String -> Bool isInt s = length (s =~ "-?[0-9]{0,10}" :: String) > 0
main :: IO () main = do
args <- getArgs if head args == "--help" || null args then helpMessage else let numArgs = map readn (filter isInt args) in if null numArgs then do print "Invalid input, missing arguments" print "Type --help" exitWith ExitSuccess else let l = lucky args in case length numArgs of 1 -> do print (nth (head numArgs) l) exitWith ExitSuccess 2 -> if last numArgs > 0 then do print (range (head numArgs) (last numArgs) l) exitWith ExitSuccess else do print (interval (head numArgs) (last numArgs) l) exitWith ExitSuccess otherwise -> do print "Invalid input, wrong number of arguments" print "Type --help" exitWith ExitSuccess</lang>
- Output:
$ luckyNumbers 12 43 $ luckyNumbers 122 lucky 745 $ luckyNumbers 1231 evenLucky 10658 $ luckyNumbers 2 12 [3,7,9,13,15,21,25,31,33,37,43] $ luckyNumbers 22 31 lucky [93,99,105,111,115,127,129,133,135,141] $ luckyNumbers 219 231 evenLucky [1458,1462,1466,1476,1478,1482,1484,1492,1498,1508,1514,1524,1538] $ luckyNumbers 100 -200 [99,105,111,115,127,129,133,135,141,151,159,163,169,171,189,193,195] $ luckyNumbers 1 -100 lucky [1,3,7,9,13,15,21,25,31,33,37,43,49,51,63,67,69,73,75,79,87,93,99] $ luckyNumbers 1 -100 evenLucky [2,4,6,10,12,18,20,22,26,34,36,42,44,50,52,54,58,68,70,76,84,90,98]
J
Not going for extra credit because I want to encourage functional reactive "types" in J. (Note that FRP, along with an ML typed compiler, would probably remove the motivation for the while loop in this implementation.)
Implementation:
<lang J>luckySeq=:3 :0
1 luckySeq y
len=.0 nth=.0 seq=.x+2*i.4*y while. len~:#seq do. len=. #seq nth=. nth+1 seq=. nth exclude seq end.
)
exclude=: ] #~ 1 - #@] $ -@{ {. 1:
lucky=: evenLucky=:0 program=:3 :0
range=: |y-.0 seq=. (1+0 e.y) luckySeq >./range if. 0><./y do. (#~ e.&(thru/range)) seq else. (<:thru/range) { seq end.
)
thru=: <./ + i.@(+*)@-~</lang>
Task:
<lang J> program 1 20 1 3 7 9 13 15 21 25 31 33 37 43 49 51 63 67 69 73 75 79
program 1 20,evenLucky
2 4 6 10 12 18 20 22 26 34 36 42 44 50 52 54 58 68 70 76
program 6000,-6100
6009 6019 6031 6049 6055 6061 6079 6093
program 6000,-6100,evenLucky
6018 6020 6022 6026 6036 6038 6050 6058 6074 6090 6092</lang>
Note that I've used the J command line rather than a unix or windows command line. This is because J is portable to a wide variety of environments (including phones) and there's no reliably common command line that exists across all these environments. Therefore, J must provide its own, and J's command line requires some slight syntax changes from the suggestions implicit in this task.
Perl 6
<lang perl6>sub luck(\a,\b) {
gather {
my @taken = take a; my @rotor; my $i = b;
loop { loop (my $j = 0; $j < @rotor; $j++) { --@rotor[$j] or last; } if $j < @rotor { @rotor[$j] = @taken[$j+1]; } else { push @taken, take $i; push @rotor, $i - @taken; } $i += 2; }
}
}
constant @lucky = luck(1,3); constant @evenlucky = luck(2,4);
subset Luck where m:i/^ 'even'? 'lucky' $/;
multi MAIN (Int $num where * > 0) {
say @lucky[$num-1];
}
multi MAIN (Int $num where * > 0, ',', Luck $howlucky = 'lucky') {
say @::(lc $howlucky)[$num-1];
}
multi MAIN (Int $first where * > 0, Int $last where * > 0, Luck $howlucky = 'lucky') {
say @::(lc $howlucky)[$first-1 .. $last - 1];
}
multi MAIN (Int $min where * > 0, Int $neg-max where * < 0, Luck $howlucky = 'lucky') {
say grep * >= $min, (@::(lc $howlucky) ...^ * > abs $neg-max);
}</lang>
- Output:
$ ./lucky Usage: ./lucky <num> ./lucky <num> , [<howlucky>] ./lucky <first> <last> [<howlucky>] ./lucky <min> <neg-max> [<howlucky>] $ ./lucky 20 , lucky 79 $ ./lucky 20 , evenlucky 76 $ ./lucky 1 20 1 3 7 9 13 15 21 25 31 33 37 43 49 51 63 67 69 73 75 79 $ ./lucky 1 20 evenlucky 2 4 6 10 12 18 20 22 26 34 36 42 44 50 52 54 58 68 70 76 $ ./lucky 6000 -6100 6009 6019 6031 6049 6055 6061 6079 6093 $ ./lucky 6000 -6100 evenLucky 6018 6020 6022 6026 6036 6038 6050 6058 6074 6090 6092 $ ./lucky 10000 115591 $ ./lucky 10000 EVENLUCKY 111842
Python
The generator <lang python>from __future__ import print_function
def lgen(even=False, nmax=1000000):
start = 2 if even else 1 n, lst = 1, list(range(start, nmax + 1, 2)) lenlst = len(lst) yield lst[0] while n < lenlst and lst[n] < lenlst: yield lst[n] n, lst = n + 1, [j for i,j in enumerate(lst, 1) if i % lst[n]] lenlst = len(lst) # drain for i in lst[n:]: yield i</lang>
The argument handler <lang python>from itertools import islice import sys, re
class ArgumentError(Exception):
pass
def arghandler(argstring):
match_obj = re.match( r"""(?mx) (?: (?P<SINGLE> (?: ^ (?P<SINGLEL> \d+ ) (?: | \s , \s lucky ) \s* $ ) |(?: ^ (?P<SINGLEE> \d+ ) (?: | \s , \s evenLucky ) \s* $ ) ) |(?P<KTH> (?: ^ (?P<KTHL> \d+ \s \d+ ) (?: | \s lucky ) \s* $ ) |(?: ^ (?P<KTHE> \d+ \s \d+ ) (?: | \s evenLucky ) \s* $ ) ) |(?P<RANGE> (?: ^ (?P<RANGEL> \d+ \s -\d+ ) (?: | \s lucky ) \s* $ ) |(?: ^ (?P<RANGEE> \d+ \s -\d+ ) (?: | \s evenLucky ) \s* $ ) ) )""", argstring) if match_obj: # Retrieve group(s) by name SINGLEL = match_obj.group('SINGLEL') SINGLEE = match_obj.group('SINGLEE') KTHL = match_obj.group('KTHL') KTHE = match_obj.group('KTHE') RANGEL = match_obj.group('RANGEL') RANGEE = match_obj.group('RANGEE') if SINGLEL: j = int(SINGLEL) assert 0 < j < 10001, "Argument out of range" print("Single %i'th lucky number:" % j, end=' ') print( list(islice(lgen(), j-1, j))[0] ) elif SINGLEE: j = int(SINGLEE) assert 0 < j < 10001, "Argument out of range" print("Single %i'th even lucky number:" % j, end=' ') print( list(islice(lgen(even=True), j-1, j))[0] ) elif KTHL: j, k = [int(num) for num in KTHL.split()] assert 0 < j < 10001, "first argument out of range" assert 0 < k < 10001 and k > j, "second argument out of range" print("List of %i ... %i lucky numbers:" % (j, k), end=' ') for n, luck in enumerate(lgen(), 1): if n > k: break if n >=j: print(luck, end = ', ') print() elif KTHE: j, k = [int(num) for num in KTHE.split()] assert 0 < j < 10001, "first argument out of range" assert 0 < k < 10001 and k > j, "second argument out of range" print("List of %i ... %i even lucky numbers:" % (j, k), end=' ') for n, luck in enumerate(lgen(even=True), 1): if n > k: break if n >=j: print(luck, end = ', ') print() elif RANGEL: j, k = [int(num) for num in RANGEL.split()] assert 0 < j < 10001, "first argument out of range" assert 0 < -k < 10001 and -k > j, "second argument out of range" k = -k print("List of lucky numbers in the range %i ... %i :" % (j, k), end=' ') for n in lgen(): if n > k: break if n >=j: print(n, end = ', ') print() elif RANGEE: j, k = [int(num) for num in RANGEE.split()] assert 0 < j < 10001, "first argument out of range" assert 0 < -k < 10001 and -k > j, "second argument out of range" k = -k print("List of even lucky numbers in the range %i ... %i :" % (j, k), end=' ') for n in lgen(even=True): if n > k: break if n >=j: print(n, end = ', ') print() else: raise ArgumentError( Error Parsing Arguments! Expected Arguments of the form (where j and k are integers): j # Jth lucky number j , lucky # Jth lucky number j , evenLucky # Jth even lucky number # j k # Jth through Kth (inclusive) lucky numbers j k lucky # Jth through Kth (inclusive) lucky numbers j k evenLucky # Jth through Kth (inclusive) even lucky numbers # j -k # all lucky numbers in the range j --? |k| j -k lucky # all lucky numbers in the range j --? |k| j -k evenLucky # all even lucky numbers in the range j --? |k| )
if __name__ == '__main__':
arghandler(' '.join(sys.argv[1:]))</lang>
- Output:
# Output when arguments are: 1 20 lucky List of 1 ... 20 lucky numbers: 1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79, # Output when arguments are: 1 20 evenLucky List of 1 ... 20 even lucky numbers: 2, 4, 6, 10, 12, 18, 20, 22, 26, 34, 36, 42, 44, 50, 52, 54, 58, 68, 70, 76, # Output when arguments are: 6000 -6100 lucky List of lucky numbers in the range 6000 ... 6100 : 6009, 6019, 6031, 6049, 6055, 6061, 6079, 6093, # Output when arguments are: 6000 -6100 evenLucky List of even lucky numbers in the range 6000 ... 6100 : 6018, 6020, 6022, 6026, 6036, 6038, 6050, 6058, 6074, 6090, 6092, # Output when arguments are: 10000 Single 10000'th lucky number: 115591 # Output when arguments are: 10000 , evenLucky Single 10000'th even lucky number: 111842
REXX
<lang REXX>/*REXX program displays lucky or evenLucky integers (#'s or a # range).*/ parse arg bot top func _ . /*get what we need from the C.L. */ if func== then func='lucky' /*Not defined? Use the default. */ s=left('s',bot\==top & top\==",") /*plural results (or not plural).*/ say func 'number's":" bot top '───►' $lucky(bot, top, func, _) exit /*stick a fork in it, we're done.*/ /*────────────────────────────────$LUCKY subroutine─────────────────────*/ $lucky: arg x,y,f,?; if y== | y==',' then y=x /*get some vars.*/
- =0; $=; ny=y<0 /*set variable: NOY: value range*/
if f== then f='LUCKY'; lucky=f=='LUCKY' /*assume LUCKY if omitted*/ if f\=='LUCKY' & f\=='EVENLUCKY' then return 'function not valid: ' f if arg()>3 & ?\= then return "too many arguments entered: " ? if x= then return "1st argument is missing." if x<1 then return "1st argument isn't a positive integer: " x if \datatype(x,'W') then return "1st argument isn't an integer: " x if \datatype(y,'W') then return "2nd argument isn't an integer: " y if x>ay then return "2nd arg is less than 1st arg." ay=abs(y); yL=ay; if y>0 then yL=y*10+y+y /*adjust the upper Y limit. */ if f== then f='LUCKY'; lucky=f=='LUCKY'
/* [↓] build for LUCKY|EVENLUCKY*/ do j=1 until j>=yL /*construct list of pos integers.*/ if j//2==(\lucky) then iterate /*EVENLUCKY? Use only even ints.*/
if lucky then if (j+1)//6==0 then iterate /*prune if mod 6≡zero.*/ else nop /*balance the IF logic. */ else if j //8==0 then iterate /*prune next if mod 8≡0.*/ #=#+1 /*bump the counter of #'s found. */ $=$ j /*append integer to the $ list.*/ end /*j*/
z=0
do p=3 until z==; z=word($,p) /*start to prune the integer list*/ if z># then leave /*if integer is too large, stop. */ do j=#%z*z by -z to z /*elide every Zth int.*/ $=delword($,j,1) /*delete a particular #.*/ #=#-1 /*decrease integer count*/ end /*j*/ /*delete from right end.*/ end /*p*/
@.=
do k=1; parse var $ q $; if q== then leave; @.k=q; end /*k*/
@.0=k-1
do j=1 for # /*restrict the found integers. */ if (\ny & (j<x | j>ay)) | (ny & (@.j<x | @.j>ay)) then @.j= end /*j*/ /* [↑] a list of #s or a range. */
_=
do b=1 for @.0; _=_ @.b; end /*build a list. */
return space(_) /*remove superfluous list blanks.*/</lang> output when the input is: 1 20 lucky
lucky numbers: 1 20 ───► 1 3 7 9 13 15 21 25 31 33 37 43 49 51 63 67 69 73 75 79
output when the input is: 1 20 evenLucky
evenLucky numbers: 1 20 ───► 2 4 6 10 12 18 20 22 26 34 36 42 44 50 52 54 58 68 70 76
output when the input is: 6000 -6100 lucky
lucky numbers: 6000 -6100 ───► 6009 6019 6031 6049 6055 6061 6079 6093
output when the input is: 6000 -6100 evenLucky
evenLucky numbers: 6000 -6100 ───► 6018 6020 6022 6026 6036 6038 6050 6058 6074 6090 6092
output when the input is: 10000
lucky number: 10000 ───► 115591
output when the input is: 10000 , evenLucky
evenLucky number: 10000 ───► 111842
Ruby
<lang ruby>def generator(even=false, nmax=1000000)
start = even ? 2 : 1 Enumerator.new do |y| n = 1 ary = [0] + (start..nmax).step(2).to_a # adds [0] to revise the 0 beginnings. y << ary[n] while (m = ary[n+=1]) < ary.size y << m (m...ary.size).step(m){|i| ary[i]=nil} ary.compact! # remove nil end # drain ary[n..-1].each{|i| y << i} raise StopIteration end
end
def lucky(argv)
j, k = argv[0].to_i, argv[1].to_i mode = /even/i=~argv[2] ? :'even lucky' : :lucky seq = generator(mode == :'even lucky') ord = ->(n){"#{n}#{(n%100).between?(11,19) ? 'th' : %w[th st nd rd th th th th th th][n%10]}"} if k.zero? puts "#{ord[j]} #{mode} number: #{seq.take(j).last}" elsif 0 < k puts "#{ord[j]} through #{ord[k]} (inclusive) #{mode} numbers", " #{seq.take(k)[j-1..-1]}" else k = -k ary = [] loop do case num=seq.next when 1...j when j..k then ary << num else break end end puts "all #{mode} numbers in the range #{j}..#{k}", " #{ary}" end
end
if __FILE__ == $0
lucky(ARGV)
end</lang>
- Output:
C:\>ruby lucky.rb 1 20 1st through 20th (inclusive) lucky numbers [1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79] C:\>ruby lucky.rb 1 20 evenLucky 1st through 20th (inclusive) even lucky numbers [2, 4, 6, 10, 12, 18, 20, 22, 26, 34, 36, 42, 44, 50, 52, 54, 58, 68, 70, 76] C:\>ruby lucky.rb 6000 -6100 Lucky all lucky numbers in the range 6000..6100 [6009, 6019, 6031, 6049, 6055, 6061, 6079, 6093] C:\>ruby lucky.rb 6000 -6100 evenLucky all even lucky numbers in the range 6000..6100 [6018, 6020, 6022, 6026, 6036, 6038, 6050, 6058, 6074, 6090, 6092] C:\>ruby lucky.rb 10000 10000th lucky number: 115591 C:\>ruby lucky.rb 10000 , EVENLUCKY 10000th even lucky number: 111842
Tcl
<lang tcl>#!/usr/bin/env tclsh8.6 package require Tcl 8.6
proc lgen {{even false} {nmax 200000}} {
coroutine lgen.[incr ::lgen] apply {{start nmax} {
set n 1 for {set i $start} {$i <= $nmax+1} {incr i 2} {lappend lst $i} yield [info coroutine] yield [lindex $lst 0] while {$n < [llength $lst] && [lindex $lst $n] < [llength $lst]} { yield [lindex $lst $n] set lst [set i 0;lmap j $lst { if {[incr i] % [lindex $lst $n]} {set j} else continue }] incr n } foreach i [lrange $lst $n end] { yield $i }
}} [expr {$even ? 2 : 1}] $nmax
}
proc collectIndices {generator from to} {
set result {} for {set i 0} {$i <= $to} {incr i} {
set n [$generator] if {$i >= $from} {lappend result $n}
} rename $generator {} return $result
} proc collectValues {generator from to} {
set result {} while 1 {
set n [$generator] if {$n > $to} break if {$n >= $from} {lappend result $n}
} rename $generator {} return $result
}
if {$argc<1||$argc>3} {
puts stderr "wrong # args: should be \"$argv0 from ?to? ?evenOdd?\"" exit 1
} lassign $argv from to evenOdd if {$argc < 3} {set evenOdd lucky} if {$argc < 2} {set to ,} if {![string is integer -strict $from] || $from < 1} {
puts stderr "\"from\" must be positive integer" exit 1
} elseif {$to ne "," && (![string is integer -strict $to] || $to == 0)} {
puts stderr "\"to\" must be positive integer or comma" exit 1
} elseif {[set evenOdd [string tolower $evenOdd]] ni {lucky evenlucky}} {
puts stderr "\"evenOdd\" must be \"lucky\" or \"evenLucky\"" exit 1
} set l [lgen [expr {$evenOdd eq "evenlucky"}]] set evenOdd [lindex {"lucky" "even lucky"} [expr {$evenOdd eq "evenlucky"}]] if {$to eq ","} {
puts "$from'th $evenOdd number = [collectIndices $l [incr from -1] $from]"
} elseif {$to < 0} {
set to [expr {-$to}] puts "all $evenOdd numbers from $from to $to: [join [collectValues $l $from $to] ,]"
} else {
puts "$from'th to $to'th $evenOdd numbers: [join [collectIndices $l [incr from -1] [incr to -1]] ,]"
}</lang>
- Output:
bash$ lucky.tcl 1 20 1'th to 20'th lucky numbers: 1,3,7,9,13,15,21,25,31,33,37,43,49,51,63,67,69,73,75,79 bash$ lucky.tcl 1 20 evenLucky 1'th to 20'th even lucky numbers: 2,4,6,10,12,18,20,22,26,34,36,42,44,50,52,54,58,68,70,76 bash$ lucky.tcl 6000 -6100 all lucky numbers from 6000 to 6100: 6009,6019,6031,6049,6055,6061,6079,6093 bash$ lucky.tcl 6000 -6100 evenLucky all even lucky numbers from 6000 to 6100: 6018,6020,6022,6026,6036,6038,6050,6058,6074,6090,6092 bash$ lucky.tcl 10000 10000'th lucky number = 115591 bash$ lucky.tcl 10000 , evenLucky 10000'th even lucky number = 111842
zkl
The lucky number generator works by chaining filters to a even or odd infinite sequence. So it acts like a sieve as each starting number percolates through the filters. It also means there are lots and lots of filters, which doesn't scale well but works for the examples. <lang zkl>fcn lgen(a){
ns,idx:=[a..*,2],2; vm.yield(ns.next()); while(1){ n:=ns.next(); vm.yield(n); ns=ns.tweak(skipper.fp1(n,Ref(idx+=1))); // tack on another filter }
} fcn skipper(n,skp,cnt){ z:=cnt.inc(); if(z%skp==0) Void.Skip else n }</lang> The command line is a bit funky (by Unix standards) so we just hard code it and use exceptions (such as trying to convert "foo" to int) to show the options. <lang zkl>cmdLineArgs,j,k,start:=vm.arglist,Void,Void,1; try{
j=cmdLineArgs[0].toInt(); na:=cmdLineArgs.len(); if(na>1){ if(cmdLineArgs[1]==",") start=cmdLineArgs[2][0].toLower()=="e" and 2 or 1; else{
k=cmdLineArgs[1].toInt(); if(na>2) start=cmdLineArgs[2][0].toLower()=="e" and 2 or 1;
} }
}catch{
fcn options{ "args: j | j , [even]lucky | j k [even]lucky | j -k [even]lucky" .println(); System.exit(1); }()
} luckies:=Utils.Generator(lgen,start); try{
if(Void==k) luckies.drop(j-1).next().println(); else{ if(k>0) luckies.drop(j-1).walk(k-j+1).println(); else{ k=-k;
while((n:=luckies.next())<j){} luckies.push(n); luckies.pump(List,'wrap(n){ n<=k and n or Void.Stop }).println();
} }
}catch(TheEnd){ options() }</lang>
- Output:
$ zkl lucky args: j | j , [even]lucky | j k [even]lucky | j -k [even]lucky $ zkl lucky 1 20 L(1,3,7,9,13,15,21,25,31,33,37,43,49,51,63,67,69,73,75,79) $ zkl lucky 1 20 evenLucky L(2,4,6,10,12,18,20,22,26,34,36,42,44,50,52,54,58,68,70,76) $ zkl lucky 6000 -6100 L(6009,6019,6031,6049,6055,6061,6079,6093) $ zkl lucky 6000 -6100 Even L(6018,6020,6022,6026,6036,6038,6050,6058,6074,6090,6092) $ zkl lucky 10000 115591 $ zkl lucky 10000 , evenLucky 111842 $ zkl lucky 6000 -5000 L() $ zkl lucky 4 2 args: j | j , [even]lucky | j k [even]lucky | j -k [even]lucky