Lucky and even lucky numbers: Difference between revisions
J |
m trying to tidy up the task description |
||
Line 1: | Line 1: | ||
{{draft task}} |
{{draft task}} |
||
<small>Note that in the following explanation list indices are assumed to start at ''one''.</small> |
|||
;Definition of lucky numbers |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
* |
#* Note then return the second number from the list (which is '''3'''). |
||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
#* Note then return the third number from the list (which is '''7'''). |
|||
⚫ | |||
⚫ | |||
⚫ | |||
#* Note then return the 4<sup>th</sup> number from the list (which is '''9'''). |
|||
#* Discard every 9<sup>th</sup>, (as noted), number from the list to form the new list<br><math>1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 45, 49, 51, 55, 63, 67, 69, 73 ...</math> |
|||
#* Take the 5<sup>th</sup>, i.e. '''13'''. Remove every 13<sup>th</sup>. |
|||
⚫ | |||
⚫ | |||
#* Take the 7<sup>th</sup>, i.e. '''21'''. Remove every 21<sup>th</sup>. |
|||
#* Take the 8<sup>th</sup>, i.e. '''25'''. Remove every 25<sup>th</sup>. |
|||
# <small>(Rule for the loop)</small> |
|||
⚫ | |||
#* Note the <math>n</math><sup>th</sup>, which is <math>m</math>. |
|||
#* Remove every <math>m</math><sup>th</sup>. |
|||
:* ... |
|||
#* Increment <math>n</math>. |
|||
:* Take the n<sup>th</sup>, which is '''m'''. Remove every m<sup>th</sup>. Increment n |
|||
:* ... |
|||
<br> |
|||
⚫ | |||
⚫ | |||
This follows the same rules as the definition of lucky numbers above ''except for the very first step'': |
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<br><math>2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40 ...</math> |
|||
# Return the first number from the list (which is '''2'''). |
|||
# <small>(Loop begins here)</small> |
|||
#* Note then return the second number from the list (which is '''4'''). |
|||
#* Discard every 4<sup>th</sup>, (as noted), number from the list to form the new list<br><math>2, 4, 6, 10, 12, 14, 18, 20, 22, 26, 28, 30, 34, 36, 38, 42, 44, 46, 50, 52 ...</math> |
|||
# <small>(Expanding the loop a few more times...)</small> |
|||
#* Note then return the third number from the list (which is '''6'''). |
|||
#* Discard every 6<sup>th</sup>, (as noted), number from the list to form the new list<br><math>2, 4, 6, 10, 12, 18, 20, 22, 26, 28, 34, 36, 38, 42, 44, 50, 52, 54, 58, 60 ...</math> |
|||
#* Take the 4<sup>th</sup>, i.e. '''10'''. Remove every 10<sup>th</sup>. |
|||
#* Take the 5<sup>th</sup>, i.e. '''12'''. Remove every 12<sup>th</sup>. |
|||
# <small>(Rule for the loop)</small> |
|||
:* ... |
|||
#* Note the <math>n</math><sup>th</sup>, which is <math>m</math>. |
|||
#* Remove every <math>m</math><sup>th</sup>. |
|||
:* ... |
|||
#* Increment <math>n</math>. |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
* The command line handling should: |
|||
** support mixed case handling of the (non-numeric) arguments |
|||
⚫ | |||
⚫ | |||
⚫ | |||
* The resulting list of numbers should be printed on a single line. |
|||
⚫ | |||
⚫ | |||
⚫ | |||
* which kind of numbers and which number(s) will be specified via the command line or a similar interface. |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
::* mixed case should be supported |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
<pre> |
<pre> |
||
what is displayed (on a single line) |
what is displayed (on a single line) |
||
Line 74: | Line 74: | ||
where |k| is the absolute value of k |
where |k| is the absolute value of k |
||
</pre> |
</pre> |
||
Demonstrate the program by: |
|||
Specifically: |
|||
* |
* 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,000<sup>th</sup> ''lucky'' number (extra credit) |
||
* |
* showing the 10,000<sup>th</sup> ''even lucky'' number (extra credit) |
||
<br> |
|||
;See also: |
;See also: |
||
Line 89: | Line 88: | ||
* 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. |
||
* Wiki entry [http://en.wikipedia.org/wiki/Lucky_number lucky_number]. |
|||
<br> |
|||
=={{header|J}}== |
=={{header|J}}== |
Revision as of 09:28, 26 April 2014
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 verbage 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.
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