Lucky and even lucky numbers

From Rosetta Code
Revision as of 07:59, 9 March 2014 by rosettacode>Paddy3118 (→‎{{header|Python}}: Remove alternative use of islice().)
Lucky and even lucky numbers is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

definition of lucky numbers

Lucky numbers are positive integers that are formed by:

  • take a list of all the positive integers
  • remove every 2nd number
  • take the 2nd number   (which is   3 )
  • remove every 3rd number
  • take the 3rd number   (which is   7 )
  • remove every 7th number
  • take the 4th number   (which is   9 )
  • remove every 9th number
  • take the 5th number   (which is   13 )
  • remove every 13th number
  • take the 6th number ···


definition of even lucky numbers

Even lucky numbers are positive even integers that are formed by:

  • take a list of all the positive even integers
  • remove every 2nd number
  • take the 2nd number   (which is   4 )
  • remove every 4th number
  • take the 3rd number   (which is   6 )
  • remove every 6th number
  • take the 4th number   (which is   10 )
  • remove every 10th number
  • take the 5th number   (which is   12 )
  • remove every 12th number
  • take the 6th number ···

task requirements

  • write one or two subroutines (functions) to generate lucky numbers and even lucky numbers
  • which kind of numbers and which number(s) will be specified via the command line or a similar interface.
  • 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)
  • mixed case should be supported
  • support for a particular number
  • support for a range of particular numbers
  • support for a range of values


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

Specifically:

  • show the first twenty lucky numbers
  • show the first twenty even lucky numbers
  • show all lucky numbers between 6,000 and 6,100 (inclusive)
  • show all even lucky numbers in the same range as above
  • show the 10,000th lucky number (extra credit)
  • show the 10,000th even lucky number (extra credit)


see also


Perl 6

This example is incorrect. Please fix the code and remove this message.

Details: command-line argument handling modified

<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, 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> [<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 from itertools import islice import sys, re

class ArgumentError(Exception):

   pass

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>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.*/

  1. =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