Lucky and even lucky numbers

From Rosetta Code
Task
Lucky and even lucky numbers
You are encouraged to solve this task according to the task description, using any language you may know.

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:

  1. Form a list of all the positive odd integers > 0
  2. Return the first number from the list (which is 1).
  3. (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
  4. (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.
  5. (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:

  1. Form a list of all the positive even integers > 0
  2. Return the first number from the list (which is 2).
  3. (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
  4. (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.
  5. (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

11l

Translation of: Nim
-V NoValue = 0

F initLuckyNumbers(nelems, evenlucky, limit = -1)
   [Int] result
   L(i) 0 .< nelems
      V k = i
      L(j) (result.len - 1 .< 0).step(-1)
         k = k * result[j] I/ (result[j] - 1)
      V n = 2 * k + 1 + evenlucky
      I limit != -1 & n > limit
         L.break
      result.append(n)
   R result

F name(evenlucky)
   R [‘Lucky’, ‘Even lucky’][evenlucky]

F printSingle(j, evenlucky)
   V luckySeq = initLuckyNumbers(j, evenlucky)
   print(name(evenlucky)‘ number at index ’j‘ is ’luckySeq[j - 1])

F printRange(j, k, evenlucky)
   V luckySeq = initLuckyNumbers(k, evenlucky)
   print(name(evenlucky)‘ numbers at indexes ’j‘ to ’k‘ are: ’, end' ‘’)
   L(idx) j - 1 .< k
      I idx != j - 1
         print(‘, ’, end' ‘’)
      print(luckySeq[idx], end' ‘’)
   print()

F printInRange(j, k, evenlucky)
   V luckySeq = initLuckyNumbers(k, evenlucky, k)
   print(name(evenlucky)‘ numbers between ’j‘ to ’k‘ are: ’, end' ‘’)
   V first = 1B
   L(val) luckySeq
      I val > j
         I first
            first = 0B
         E
            print(‘, ’, end' ‘’)
         print(val, end' ‘’)
   print()

F process_args(args)
   assert(args.len C 1..3, ‘Wrong number of arguments’)

   // First argument: "j" value.
   V j = Int(args[0])

   V k = NoValue
   // Second argument: "k" value or a comma.
   I args.len > 1
      I args[1] == ‘,’
         // Must be followed by the kind of lucky number.
         assert(args.len == 3, ‘Missing kind argument’)
      E
         k = Int(args[1])
         assert(k != 0, ‘Expected a non null number’)

   V evenlucky = 0
   // Third argument: number kind.
   I args.len == 3
      V kind = args[2].lowercase()
      assert(kind C (‘lucky’, ‘evenlucky’), ‘Wrong kind’)
      I kind == ‘evenlucky’
         evenlucky = 1

   I k == NoValue
      // Print jth value.
      printSingle(j, evenlucky)
   E I k > 0
      // Print jth to kth values.
      printRange(j, k, evenlucky)
   E
      // Print values in range j..(-k).
      printInRange(j, -k, evenlucky)

:start:
I 1B
   L(args) [‘1 20’, ‘1 20 evenlucky’, ‘6000 -6100’, ‘6000 -6100 evenlucky’, ‘10000’, ‘10000 , lucky’, ‘10000 , evenlucky’]
      print(‘Command line arguments: ’args)
      process_args(args.split(‘ ’))
      print()
E
   process_args(:argv[1..])
Output:
Command line arguments: 1 20
Lucky numbers at indexes 1 to 20 are: 1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79

Command line arguments: 1 20 evenlucky
Even lucky numbers at indexes 1 to 20 are: 2, 4, 6, 10, 12, 18, 20, 22, 26, 34, 36, 42, 44, 50, 52, 54, 58, 68, 70, 76

Command line arguments: 6000 -6100
Lucky numbers between 6000 to 6100 are: 6009, 6019, 6031, 6049, 6055, 6061, 6079, 6093

Command line arguments: 6000 -6100 evenlucky
Even lucky numbers between 6000 to 6100 are: 6018, 6020, 6022, 6026, 6036, 6038, 6050, 6058, 6074, 6090, 6092

Command line arguments: 10000
Lucky number at index 10000 is 115591

Command line arguments: 10000 , lucky
Lucky number at index 10000 is 115591

Command line arguments: 10000 , evenlucky
Even lucky number at index 10000 is 111842

C

Translation of: C++
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

#define LUCKY_SIZE 60000
int luckyOdd[LUCKY_SIZE];
int luckyEven[LUCKY_SIZE];

void compactLucky(int luckyArray[]) {
    int i, j, k;

    for (i = 0; i < LUCKY_SIZE; i++) {
        if (luckyArray[i] == 0) {
            j = i;
            break;
        }
    }

    for (j = i + 1; j < LUCKY_SIZE; j++) {
        if (luckyArray[j] > 0) {
            luckyArray[i++] = luckyArray[j];
        }
    }

    for (; i < LUCKY_SIZE; i++) {
        luckyArray[i] = 0;
    }
}

void initialize() {
    int i, j;

    // unfiltered
    for (i = 0; i < LUCKY_SIZE; i++) {
        luckyEven[i] = 2 * i + 2;
        luckyOdd[i] = 2 * i + 1;
    }

    // odd filter
    for (i = 1; i < LUCKY_SIZE; i++) {
        if (luckyOdd[i] > 0) {
            for (j = luckyOdd[i] - 1; j < LUCKY_SIZE; j += luckyOdd[i]) {
                luckyOdd[j] = 0;
            }
            compactLucky(luckyOdd);
        }
    }

    // even filter
    for (i = 1; i < LUCKY_SIZE; i++) {
        if (luckyEven[i] > 0) {
            for (j = luckyEven[i] - 1; j < LUCKY_SIZE; j += luckyEven[i]) {
                luckyEven[j] = 0;
            }
            compactLucky(luckyEven);
        }
    }
}

void printBetween(size_t j, size_t k, bool even) {
    int i;

    if (even) {
        if (luckyEven[j] == 0 || luckyEven[k] == 0) {
            fprintf(stderr, "At least one argument is too large\n");
            exit(EXIT_FAILURE);
        }
        printf("Lucky even numbers between %d and %d are:", j, k);
        for (i = 0; luckyEven[i] != 0; i++) {
            if (luckyEven[i] > k) {
                break;
            }
            if (luckyEven[i] > j) {
                printf(" %d", luckyEven[i]);
            }
        }
    } else {
        if (luckyOdd[j] == 0 || luckyOdd[k] == 0) {
            fprintf(stderr, "At least one argument is too large\n");
            exit(EXIT_FAILURE);
        }
        printf("Lucky numbers between %d and %d are:", j, k);
        for (i = 0; luckyOdd[i] != 0; i++) {
            if (luckyOdd[i] > k) {
                break;
            }
            if (luckyOdd[i] > j) {
                printf(" %d", luckyOdd[i]);
            }
        }
    }
    printf("\n");
}

void printRange(size_t j, size_t k, bool even) {
    int i;

    if (even) {
        if (luckyEven[k] == 0) {
            fprintf(stderr, "The argument is too large\n");
            exit(EXIT_FAILURE);
        }
        printf("Lucky even numbers %d to %d are:", j, k);
        for (i = j - 1; i < k; i++) {
            printf(" %d", luckyEven[i]);
        }
    } else {
        if (luckyOdd[k] == 0) {
            fprintf(stderr, "The argument is too large\n");
            exit(EXIT_FAILURE);
        }
        printf("Lucky numbers %d to %d are:", j, k);
        for (i = j - 1; i < k; i++) {
            printf(" %d", luckyOdd[i]);
        }
    }
    printf("\n");
}

void printSingle(size_t j, bool even) {
    if (even) {
        if (luckyEven[j] == 0) {
            fprintf(stderr, "The argument is too large\n");
            exit(EXIT_FAILURE);
        }
        printf("Lucky even number %d=%d\n", j, luckyEven[j - 1]);
    } else {
        if (luckyOdd[j] == 0) {
            fprintf(stderr, "The argument is too large\n");
            exit(EXIT_FAILURE);
        }
        printf("Lucky number %d=%d\n", j, luckyOdd[j - 1]);
    }
}

void help() {
    printf("./lucky j [k] [--lucky|--evenLucky]\n");
    printf("\n");
    printf("       argument(s)        |  what is displayed\n");
    printf("==============================================\n");
    printf("-j=m                      |  mth lucky number\n");
    printf("-j=m  --lucky             |  mth lucky number\n");
    printf("-j=m  --evenLucky         |  mth even lucky number\n");
    printf("-j=m  -k=n                |  mth through nth (inclusive) lucky numbers\n");
    printf("-j=m  -k=n  --lucky       |  mth through nth (inclusive) lucky numbers\n");
    printf("-j=m  -k=n  --evenLucky   |  mth through nth (inclusive) even lucky numbers\n");
    printf("-j=m  -k=-n               |  all lucky numbers in the range [m, n]\n");
    printf("-j=m  -k=-n  --lucky      |  all lucky numbers in the range [m, n]\n");
    printf("-j=m  -k=-n  --evenLucky  |  all even lucky numbers in the range [m, n]\n");
}

void process(int argc, char *argv[]) {
    bool evenLucky = false;
    int j = 0;
    int k = 0;

    bool good = false;
    int i;

    for (i = 1; i < argc; ++i) {
        if ('-' == argv[i][0]) {
            if ('-' == argv[i][1]) {
                // long args
                if (0 == strcmp("--lucky", argv[i])) {
                    evenLucky = false;
                } else if (0 == strcmp("--evenLucky", argv[i])) {
                    evenLucky = true;
                } else {
                    fprintf(stderr, "Unknown long argument: [%s]\n", argv[i]);
                    exit(EXIT_FAILURE);
                }
            } else {
                // short args
                if ('j' == argv[i][1] && '=' == argv[i][2] && argv[i][3] != 0) {
                    good = true;
                    j = atoi(&argv[i][3]);
                } else if ('k' == argv[i][1] && '=' == argv[i][2]) {
                    k = atoi(&argv[i][3]);
                } else {
                    fprintf(stderr, "Unknown short argument: [%s]\n", argv[i]);
                    exit(EXIT_FAILURE);
                }
            }
        } else {
            fprintf(stderr, "Unknown argument: [%s]\n", argv[i]);
            exit(EXIT_FAILURE);
        }
    }

    if (!good) {
        help();
        exit(EXIT_FAILURE);
    }

    if (k > 0) {
        printRange(j, k, evenLucky);
    } else if (k < 0) {
        printBetween(j, -k, evenLucky);
    } else {
        printSingle(j, evenLucky);
    }
}

void test() {
    printRange(1, 20, false);
    printRange(1, 20, true);

    printBetween(6000, 6100, false);
    printBetween(6000, 6100, true);

    printSingle(10000, false);
    printSingle(10000, true);
}

int main(int argc, char *argv[]) {
    initialize();

    //test();

    if (argc < 2) {
        help();
        return 1;
    }
    process(argc, argv);

    return 0;
}
Output:
LuckyNumbers.exe -j=1 -k=20
Lucky numbers 1 to 20 are: 1 3 7 9 13 15 21 25 31 33 37 43 49 51 63 67 69 73 75 79

LuckyNumbers.exe -j=1 -k=20 --evenLucky
Lucky even numbers 1 to 20 are: 2 4 6 10 12 18 20 22 26 34 36 42 44 50 52 54 58 68 70 76

LuckyNumbers.exe -j=6000 -k=-6100
Lucky numbers between 6000 and 6100 are: 6009 6019 6031 6049 6055 6061 6079 6093

LuckyNumbers.exe -j=6000 -k=-6100 --evenLucky
Lucky even numbers between 6000 and 6100 are: 6018 6020 6022 6026 6036 6038 6050 6058 6074 6090 6092

LuckyNumbers.exe -j=10000
Lucky number 10000=115591

LuckyNumbers.exe -j=10000 --evenLucky
Lucky even number 10000=111842

C++

Translation of: Go
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

const int luckySize = 60000;
std::vector<int> luckyEven(luckySize);
std::vector<int> luckyOdd(luckySize);

void init() {
    for (int i = 0; i < luckySize; ++i) {
        luckyEven[i] = i * 2 + 2;
        luckyOdd[i] = i * 2 + 1;
    }
}

void filterLuckyEven() {
    for (size_t n = 2; n < luckyEven.size(); ++n) {
        int m = luckyEven[n - 1];
        int end = (luckyEven.size() / m) * m - 1;
        for (int j = end; j >= m - 1; j -= m) {
            std::copy(luckyEven.begin() + j + 1, luckyEven.end(), luckyEven.begin() + j);
            luckyEven.pop_back();
        }
    }
}

void filterLuckyOdd() {
    for (size_t n = 2; n < luckyOdd.size(); ++n) {
        int m = luckyOdd[n - 1];
        int end = (luckyOdd.size() / m) * m - 1;
        for (int j = end; j >= m - 1; j -= m) {
            std::copy(luckyOdd.begin() + j + 1, luckyOdd.end(), luckyOdd.begin() + j);
            luckyOdd.pop_back();
        }
    }
}

void printBetween(size_t j, size_t k, bool even) {
    std::ostream_iterator<int> out_it{ std::cout, ", " };

    if (even) {
        size_t max = luckyEven.back();
        if (j > max || k > max) {
            std::cerr << "At least one are is too big\n";
            exit(EXIT_FAILURE);
        }

        std::cout << "Lucky even numbers between " << j << " and " << k << " are: ";
        std::copy_if(luckyEven.begin(), luckyEven.end(), out_it, [j, k](size_t n) {
            return j <= n && n <= k;
        });
    } else {
        size_t max = luckyOdd.back();
        if (j > max || k > max) {
            std::cerr << "At least one are is too big\n";
            exit(EXIT_FAILURE);
        }

        std::cout << "Lucky numbers between " << j << " and " << k << " are: ";
        std::copy_if(luckyOdd.begin(), luckyOdd.end(), out_it, [j, k](size_t n) {
            return j <= n && n <= k;
        });
    }
    std::cout << '\n';
}

void printRange(size_t j, size_t k, bool even) {
    std::ostream_iterator<int> out_it{ std::cout, ", " };
    if (even) {
        if (k >= luckyEven.size()) {
            std::cerr << "The argument is too large\n";
            exit(EXIT_FAILURE);
        }
        std::cout << "Lucky even numbers " << j << " to " << k << " are: ";
        std::copy(luckyEven.begin() + j - 1, luckyEven.begin() + k, out_it);
    } else {
        if (k >= luckyOdd.size()) {
            std::cerr << "The argument is too large\n";
            exit(EXIT_FAILURE);
        }
        std::cout << "Lucky numbers " << j << " to " << k << " are: ";
        std::copy(luckyOdd.begin() + j - 1, luckyOdd.begin() + k, out_it);
    }
}

void printSingle(size_t j, bool even) {
    if (even) {
        if (j >= luckyEven.size()) {
            std::cerr << "The argument is too large\n";
            exit(EXIT_FAILURE);
        }
        std::cout << "Lucky even number " << j << "=" << luckyEven[j - 1] << '\n';
    } else {
        if (j >= luckyOdd.size()) {
            std::cerr << "The argument is too large\n";
            exit(EXIT_FAILURE);
        }
        std::cout << "Lucky number " << j << "=" << luckyOdd[j - 1] << '\n';
    }
}

void help() {
    std::cout << "./lucky j [k] [--lucky|--evenLucky]\n";
    std::cout << "\n";
    std::cout << "       argument(s)        |  what is displayed\n";
    std::cout << "==============================================\n";
    std::cout << "-j=m                      |  mth lucky number\n";
    std::cout << "-j=m  --lucky             |  mth lucky number\n";
    std::cout << "-j=m  --evenLucky         |  mth even lucky number\n";
    std::cout << "-j=m  -k=n                |  mth through nth (inclusive) lucky numbers\n";
    std::cout << "-j=m  -k=n  --lucky       |  mth through nth (inclusive) lucky numbers\n";
    std::cout << "-j=m  -k=n  --evenLucky   |  mth through nth (inclusive) even lucky numbers\n";
    std::cout << "-j=m  -k=-n               |  all lucky numbers in the range [m, n]\n";
    std::cout << "-j=m  -k=-n  --lucky      |  all lucky numbers in the range [m, n]\n";
    std::cout << "-j=m  -k=-n  --evenLucky  |  all even lucky numbers in the range [m, n]\n";
}

int main(int argc, char **argv) {
    bool evenLucky = false;
    int j = 0;
    int k = 0;

    // skip arg 0, because that is just the executable name
    if (argc < 2) {
        help();
        exit(EXIT_FAILURE);
    }

    bool good = false;
    for (int i = 1; i < argc; ++i) {
        if ('-' == argv[i][0]) {
            if ('-' == argv[i][1]) {
                // long args
                if (0 == strcmp("--lucky", argv[i])) {
                    evenLucky = false;
                } else if (0 == strcmp("--evenLucky", argv[i])) {
                    evenLucky = true;
                } else {
                    std::cerr << "Unknown long argument: [" << argv[i] << "]\n";
                    exit(EXIT_FAILURE);
                }
            } else {
                // short args
                if ('j' == argv[i][1] && '=' == argv[i][2] && argv[i][3] != 0) {
                    good = true;
                    j = atoi(&argv[i][3]);
                } else if ('k' == argv[i][1] && '=' == argv[i][2]) {
                    k = atoi(&argv[i][3]);
                } else {
                    std::cerr << "Unknown short argument: " << argv[i] << '\n';
                    exit(EXIT_FAILURE);
                }
            }
        } else {
            std::cerr << "Unknown argument: " << argv[i] << '\n';
            exit(EXIT_FAILURE);
        }
    }
    if (!good) {
        help();
        exit(EXIT_FAILURE);
    }

    init();
    filterLuckyEven();
    filterLuckyOdd();
    if (k > 0) {
        printRange(j, k, evenLucky);
    } else if (k < 0) {
        printBetween(j, -k, evenLucky);
    } else {
        printSingle(j, evenLucky);
    }

    return 0;
}
Output:
>LuckyNumbers.exe -j=1 -k=20
Lucky numbers 1 to 20 are: 1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79,

>LuckyNumbers.exe -j=1 -k=20 --evenLucky
Lucky even numbers 1 to 20 are: 2, 4, 6, 10, 12, 18, 20, 22, 26, 34, 36, 42, 44, 50, 52, 54, 58, 68, 70, 76,

>LuckyNumbers.exe -j=6000 -k=-6100
Lucky numbers between 6000 and 6100 are: 6009, 6019, 6031, 6049, 6055, 6061, 6079, 6093,

>LuckyNumbers.exe -j=6000 -k=-6100 --evenLucky
Lucky even numbers between 6000 and 6100 are: 6018, 6020, 6022, 6026, 6036, 6038, 6050, 6058, 6074, 6090, 6092,

>LuckyNumbers.exe -j=10000
Lucky number 10000=115591

>LuckyNumbers.exe -j=10000 --evenLucky
Lucky even number 10000=111842

D

import std.algorithm;
import std.concurrency;
import std.conv;
import std.getopt;
import std.range;
import std.stdio;

auto lucky(bool even, int nmax=200_000) {
    import std.container.array;

    int start = even ? 2 : 1;

    return new Generator!int({
        auto ln = make!(Array!int)(iota(start,nmax,2));

        // yield the first number
        yield(ln[0]);

        int n=1;
        for(; n<ln.length/2+1; n++) {
            yield(ln[n]);

            int step = ln[n]-1;

            // remove the non-lucky numbers related to the current lucky number
            for (int i=step; i<ln.length; i+=step) {
                ln.linearRemove(ln[].drop(i).take(1));
            }
        }

        // yield all remaining values
        foreach(val; ln[n..$]) {
            yield(val);
        }
    });
}

void help(Option[] opt) {
    defaultGetoptPrinter("./lucky j [k] [--lucky|--evenLucky]", opt);

    writeln;
    writeln("       argument(s)        |  what is displayed");
    writeln("==============================================");
    writeln("-j=m                      |  mth lucky number");
    writeln("-j=m  --lucky             |  mth lucky number");
    writeln("-j=m  --evenLucky         |  mth even lucky number");
    writeln("-j=m  -k=n                |  mth through nth (inclusive) lucky numbers");
    writeln("-j=m  -k=n  --lucky       |  mth through nth (inclusive) lucky numbers");
    writeln("-j=m  -k=n  --evenLucky   |  mth through nth (inclusive) even lucky numbers");
    writeln("-j=m  -k=-n               |  all lucky numbers in the range [m, n]");
    writeln("-j=m  -k=-n  --lucky      |  all lucky numbers in the range [m, n]");
    writeln("-j=m  -k=-n  --evenLucky  |  all even lucky numbers in the range [m, n]");
}

void main(string[] args) {
    int j;
    int k;
    bool evenLucky = false;

    void luckyOpt() {
        evenLucky = false;
    }
    auto helpInformation = getopt(
        args,
        std.getopt.config.passThrough,
        std.getopt.config.required,
        "j", "The starting point to generate lucky numbers", &j,
        "k", "The ending point for generating lucky numbers", &k,
        "lucky", "Specify to generate a list of lucky numbers", &luckyOpt,
        "evenLucky", "Specify to generate a list of even lucky numbers", &evenLucky
    );

    if (helpInformation.helpWanted) {
        help(helpInformation.options);
        return;
    }

    if (k>0) {
        lucky(evenLucky).drop(j-1).take(k-j+1).writeln;
    } else if (k<0) {
        auto f = (int a) => j<=a && a<=-k;
        lucky(evenLucky, -k).filter!f.writeln;
    } else {
        lucky(evenLucky).drop(j-1).take(1).writeln;
    }
}
Output:
.\lucky_and_even_lucky_numbers.exe -j=1 -k=20
[1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79]

.\lucky_and_even_lucky_numbers.exe -j=1 -k=20 --evenLucky
[2, 4, 6, 10, 12, 18, 20, 22, 26, 34, 36, 42, 44, 50, 52, 54, 58, 68, 70, 76]

.\lucky_and_even_lucky_numbers.exe -j=6000 -k=-6100
[6009, 6019, 6031, 6049, 6055, 6061, 6079, 6093]

.\lucky_and_even_lucky_numbers.exe -j=6000 -k=-6100 --evenLucky
[6018, 6020, 6022, 6026, 6036, 6038, 6050, 6058, 6074, 6090, 6092]

.\lucky_and_even_lucky_numbers.exe -j=10000
[115591]

.\lucky_and_even_lucky_numbers.exe -j=10000 --evenLucky
[111842]

F#

The functions

// Odd and Even Lucky Numbers. Nigel Galloway: October 3rd., 2020
let rec fN i g e l=seq{yield! i|>Seq.skip g|>Seq.take(e-g-1)
                       let n=Seq.chunkBySize e i|>Seq.collect(Seq.take(e-1)) in yield! fN n (e-1) (Seq.item l n) (l+1)}
let oLuck,eLuck=let rec fG g=seq{yield g; yield! fG(g+2)} in (fN(fG 1) 0 3 2,fN(fG 2) 0 4 2)

The task

Using a fsi console:

Output:
> oLuck|>Seq.take 20|>Seq.iter(printf "%d "); printfn "";;
1 3 7 9 13 15 21 25 31 33 37 43 49 51 63 67 69 73 75 79

> eLuck|>Seq.take 20|>Seq.iter(printf "%d "); printfn "";;
2 4 6 10 12 18 20 22 26 34 36 42 44 50 52 54 58 68 70 76

> oLuck|>Seq.skipWhile(fun n->n<6000)|>Seq.takeWhile(fun n->n<6100)|>Seq.iter(printf "%d "); printfn "";;
6009 6019 6031 6049 6055 6061 6079 6093

> eLuck|>Seq.skipWhile(fun n->n<6000)|>Seq.takeWhile(fun n->n<6100)|>Seq.iter(printf "%d "); printfn "";;
6018 6020 6022 6026 6036 6038 6050 6058 6074 6090 6092

FreeBASIC

Translation of: Go
Translation of: Phix
Const luckyMax = 120000

Dim Shared As Integer lucky(luckyMax - 1)

Sub RemoveElement(arr() As Integer, index As Integer)
    If index < Lbound(arr) Or index > Ubound(arr) Then
        Print "Index out of bounds"
        Exit Sub
    End If
    For i As Integer = index To Ubound(arr) - 1
        arr(i) = arr(i + 1)
    Next i
    Redim Preserve arr(Lbound(arr) To Ubound(arr) - 1)
End Sub

Sub filterLucky(lucky() As Integer)
    Dim As Integer n, m, p
    Dim As Integer dellucky()

For n = 2 To Ubound(lucky)
        Redim dellucky(1 To 1)
        For m = lucky(n) To Ubound(lucky) Step lucky(n)
            dellucky(Ubound(dellucky)) = m
            Redim Preserve dellucky(1 To Ubound(dellucky) + 1)
        Next m
        For p = Ubound(dellucky) - 1 To 1 Step -1
            RemoveElement (lucky(), dellucky(p))
        Next p
    Next n
End Sub

Const helptxt = _
"   argument(s)   |  what is displayed  "   & Chr(10) & _
"======================================="   & Chr(10) & _
" j               |  jth lucky number   "   & Chr(10) & _
" j [,] lucky     |  jth lucky number   "   & Chr(10) & _
" j [,] evenLucky |  jth even lucky number" & Chr(10) & _
" j k             |  jth through kth (inclusive) lucky numbers" & Chr(10) & _
" j k lucky       |  jth through kth (inclusive) lucky numbers" & Chr(10) & _
" j k evenLucky   |  jth through kth (inclusive) even lucky numbers" & Chr(10) & _
" j -k            |  all lucky numbers in the range j to k" & Chr(10) & _
" j -k lucky      |  all lucky numbers in the range j to k" & Chr(10) & _
" j -k evenLucky  |  all even lucky numbers in the range j to k "

Sub fatal(msg As String)
    Print msg; Chr(10)
    Print helptxt
    Sleep
    End
End Sub

Sub process(cl() As String)
    If Ubound(cl) = 2 And cl(2) = "," Then cl(2) = ""
    
    Dim As Integer i, j
    Dim As Integer k, m, n
    Dim As Boolean single_ = true, range = true, oddluck = true
    
    For i = 1 To Ubound(cl)
        Dim As String cli = cl(i)
        If Val(cli) <> 0 Or cli = "0" Then
            n = Valint(cli)
            If i > 2 Then fatal("too many numbers")
            If i = 1 Then
                If n < 1 Then fatal("first argument must be a positive integer")
                j = n
            Else
                single_ = False
                If n < 0 Then
                    range = False
                    n = -n
                End If
                If n < j Then fatal("second argument cannot be less than first")
                k = n
            End If
        Else
            Select Case Lcase(cli)
            Case "lucky"
                oddluck = true
            Case "evenlucky"
                oddluck = False
            Case Else
                fatal("unrecognised " & cli)
            End Select
            If i <> Ubound(cl) Then fatal(cli & " must be last parameter")
        End If
    Next
    
    If oddluck Then
        For i = 1 To luckyMax
            lucky(i) = 2 * i - 1
        Next
    Else
        For i = 1 To luckyMax
            lucky(i) = 2 * i
        Next
    End If
    
    filterLucky(lucky())
    
    Dim As String evenstr = Iif(oddluck, "", "even ")
    
    If single_ Then
        If j > Ubound(lucky) Then fatal("the argument, " & j & ", is too big")
        Print "Lucky " & evenstr & "number " & j & " = " & lucky(j)
    Elseif range Then
        If k > Ubound(lucky) Then fatal("the argument, " & k & ", is too big")
        Print "Lucky " & evenstr & "numbers " & j & " to " & k & !" are: \n";
        For i = j To k '- 1
            Print lucky(i);
        Next
        Print
    Else
        If j > lucky(Ubound(lucky) - 1) Then
            fatal("start of range is too big")
        Elseif k > lucky(Ubound(lucky) - 1) Then
            fatal("end of range is too big")
        End If
        m = 0
        While lucky(m) < j
            m += 1
        Wend
        n = m
        While lucky(n) <= k
            n += 1
        Wend
        Print "Lucky " & evenstr & "numbers between " & j & " and " & k & !" are: \n";
        For i = m To n - 1
            Print lucky(i);
        Next
        Print
    End If
End Sub

Sub main()
    Dim As String nargs = Command(-1)
    If Len(nargs) < 1 Then
        Dim As String tests(1 To 8) = {"1 20", "1 20 evenLucky", "20 lucky", "20 evenLucky", "6000 -6100", "6000 -6100 evenLucky", "10000 lucky", "10000 evenLucky"}
        Dim As String testArgs()
        For t As Integer = 1 To Ubound(tests)
            Dim As Integer numArgs = 0
            Dim As String test = tests(t)
            Dim As Integer posic = 1
            While posic <= Len(test)
                Dim As Integer nextPos = Instr(posic, test, " ")
                If nextPos = 0 Then nextPos = Len(test) + 1
                numArgs += 1
                Redim Preserve testArgs(1 To numArgs)
                testArgs(numArgs) = Mid(test, posic, nextPos - posic)
                posic = nextPos + 1
            Wend
            Print
            process(testArgs())
        Next
        Print "tests complete"
        Exit Sub
    Else
        Dim As String testArgs()
        Dim As Integer numArgs = 1
        Do
            Dim As String arg = Command(numArgs)
            If Len(arg) = 0 Then Exit Do
            Redim Preserve testArgs(numArgs)
            testArgs(numArgs) = Command(numArgs)
            numArgs += 1
        Loop
        
        process(testArgs())
    End If
End Sub

main()

Sleep
Output:
Lucky numbers 1 to 20 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 are:
 2 4 6 10 12 18 20 22 26 34 36 42 44 50 52 54 58 68 70 76

Lucky number 20 = 79

Lucky even number 20 = 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 10000 = 115591

Lucky even number 10000 = 111842
tests complete

Go

Translation of: Kotlin
package main

import (
    "fmt"
    "log"
    "os"
    "strconv"
    "strings"
)

const luckySize = 60000

var luckyOdd = make([]int, luckySize)
var luckyEven = make([]int, luckySize)

func init() {
    for i := 0; i < luckySize; i++ {
        luckyOdd[i] = i*2 + 1
        luckyEven[i] = i*2 + 2
    }
}

func filterLuckyOdd() {
    for n := 2; n < len(luckyOdd); n++ {
        m := luckyOdd[n-1]
        end := (len(luckyOdd)/m)*m - 1
        for j := end; j >= m-1; j -= m {
            copy(luckyOdd[j:], luckyOdd[j+1:])
            luckyOdd = luckyOdd[:len(luckyOdd)-1]
        }
    }
}

func filterLuckyEven() {
    for n := 2; n < len(luckyEven); n++ {
        m := luckyEven[n-1]
        end := (len(luckyEven)/m)*m - 1
        for j := end; j >= m-1; j -= m {
            copy(luckyEven[j:], luckyEven[j+1:])
            luckyEven = luckyEven[:len(luckyEven)-1]
        }
    }
}

func printSingle(j int, odd bool) error {
    if odd {
        if j >= len(luckyOdd) {
            return fmt.Errorf("the argument, %d, is too big", j)
        }
        fmt.Println("Lucky number", j, "=", luckyOdd[j-1])
    } else {
        if j >= len(luckyEven) {
            return fmt.Errorf("the argument, %d, is too big", j)
        }
        fmt.Println("Lucky even number", j, "=", luckyEven[j-1])
    }
    return nil
}

func printRange(j, k int, odd bool) error {
    if odd {
        if k >= len(luckyOdd) {
            return fmt.Errorf("the argument, %d, is too big", k)
        }
        fmt.Println("Lucky numbers", j, "to", k, "are:")
        fmt.Println(luckyOdd[j-1 : k])
    } else {
        if k >= len(luckyEven) {
            return fmt.Errorf("the argument, %d, is too big", k)
        }
        fmt.Println("Lucky even numbers", j, "to", k, "are:")
        fmt.Println(luckyEven[j-1 : k])
    }
    return nil
}

func printBetween(j, k int, odd bool) error {
    var r []int
    if odd {
        max := luckyOdd[len(luckyOdd)-1]
        if j > max || k > max {
            return fmt.Errorf("at least one argument, %d or %d, is too big", j, k)
        }
        for _, num := range luckyOdd {
            if num < j {
                continue
            }
            if num > k {
                break
            }
            r = append(r, num)
        }
        fmt.Println("Lucky numbers between", j, "and", k, "are:")
        fmt.Println(r)
    } else {
        max := luckyEven[len(luckyEven)-1]
        if j > max || k > max {
            return fmt.Errorf("at least one argument, %d or %d, is too big", j, k)
        }
        for _, num := range luckyEven {
            if num < j {
                continue
            }
            if num > k {
                break
            }
            r = append(r, num)
        }
        fmt.Println("Lucky even numbers between", j, "and", k, "are:")
        fmt.Println(r)
    }
    return nil
}

func main() {
    nargs := len(os.Args)
    if nargs < 2 || nargs > 4 {
        log.Fatal("there must be between 1 and 3 command line arguments")
    }
    filterLuckyOdd()
    filterLuckyEven()
    j, err := strconv.Atoi(os.Args[1])
    if err != nil || j < 1 {
        log.Fatalf("first argument, %s, must be a positive integer", os.Args[1])
    }
    if nargs == 2 {
        if err := printSingle(j, true); err != nil {
            log.Fatal(err)
        }
        return
    }

    if nargs == 3 {
        k, err := strconv.Atoi(os.Args[2])
        if err != nil {
            log.Fatalf("second argument, %s, must be an integer", os.Args[2])
        }
        if k >= 0 {
            if j > k {
                log.Fatalf("second argument, %d, can't be less than first, %d", k, j)
            }
            if err := printRange(j, k, true); err != nil {
                log.Fatal(err)
            }
        } else {
            l := -k
            if j > l {
                log.Fatalf("second argument, %d, can't be less in absolute value than first, %d", k, j)
            }
            if err := printBetween(j, l, true); err != nil {
                log.Fatal(err)
            }
        }
        return
    }

    var odd bool
    switch lucky := strings.ToLower(os.Args[3]); lucky {
    case "lucky":
        odd = true
    case "evenlucky":
        odd = false
    default:
        log.Fatalf("third argument, %s, is invalid", os.Args[3])
    }
    if os.Args[2] == "," {
        if err := printSingle(j, odd); err != nil {
            log.Fatal(err)
        }
        return
    }

    k, err := strconv.Atoi(os.Args[2])
    if err != nil {
        log.Fatal("second argument must be an integer or a comma")
    }
    if k >= 0 {
        if j > k {
            log.Fatalf("second argument, %d, can't be less than first, %d", k, j)
        }
        if err := printRange(j, k, odd); err != nil {
            log.Fatal(err)
        }
    } else {
        l := -k
        if j > l {
            log.Fatalf("second argument, %d, can't be less in absolute value than first, %d", k, j)
        }
        if err := printBetween(j, l, odd); err != nil {
            log.Fatal(err)
        }
    }
}
Output:
$ ./lucky 1 20
Lucky numbers 1 to 20 are:
[1 3 7 9 13 15 21 25 31 33 37 43 49 51 63 67 69 73 75 79]

$ ./lucky 1 20 evenLucky
Lucky even numbers 1 to 20 are:
[2 4 6 10 12 18 20 22 26 34 36 42 44 50 52 54 58 68 70 76]

$ ./lucky 6000 -6100
Lucky numbers between 6000 and 6100 are:
[6009 6019 6031 6049 6055 6061 6079 6093]

$ ./lucky 6000 -6100 evenLucky
Lucky even numbers between 6000 and 6100 are:
[6018 6020 6022 6026 6036 6038 6050 6058 6074 6090 6092]

$ ./lucky 10000 , lucky
Lucky number 10000 = 115591

$ ./lucky 10000 , evenLucky
Lucky even number 10000 = 111842

Haskell

Haskell is a very nice language for this problem because it is a lazy language. Here regular expressions and data types are used.

import System.Environment
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 Lucky     = luckyNumbers oddNumbers !! (j-1)
nth j EvenLucky = luckyNumbers evenNumbers !! (j-1)

range :: Int -> Int -> Lucky -> [Int]
range x x2 Lucky     = drop (x-1) (take x2 (luckyNumbers oddNumbers))
range x x2 EvenLucky = drop (x-1) (take x2 (luckyNumbers evenNumbers))

interval :: Int -> Int -> Lucky -> [Int]
interval x x2 Lucky     = dropWhile (<x) (takeWhile (<=x2) (luckyNumbers oddNumbers))
interval x x2 EvenLucky = dropWhile (<x) (takeWhile (<=x2) (luckyNumbers evenNumbers))

lucky :: [String] -> Lucky
lucky xs = 
  if "evenLucky" `elem` xs
   then EvenLucky
   else Lucky

readn :: String -> Int
readn s = read s :: Int

isInt :: String -> Bool
isInt s = not (null (s =~ "-?[0-9]{0,10}" :: String))

main :: IO ()
main = do
  args <- getArgs
  if head args == "--help" || null args
    then
      helpMessage
    else
      let l = lucky args in
      case map readn (filter isInt args) of
        [] -> do
          putStrLn "Invalid input, missing arguments"
          putStrLn "Type --help"
        [x] -> print (nth x l)
        [x, x2] -> if x2 > 0
          then print (range x x2 l)
          else print (interval x (-x2) l)
        _ -> do 
          putStrLn "Invalid input, wrong number of arguments"
          putStrLn "Type --help"
Output:
$ luckyNumbers 1 20
[1,3,7,9,13,15,21,25,31,33,37,43,49,51,63,67,69,73,75,79]
$ luckyNumbers 1 20 evenLucky
[2,4,6,10,12,18,20,22,26,34,36,42,44,50,52,54,58,68,70,76]
$ luckyNumbers 6000 -6100 lucky
[6009,6019,6031,6049,6055,6061,6079,6093]
$ luckyNumbers 6000 -6100 evenLucky
[6018,6020,6022,6026,6036,6038,6050,6058,6074,6090,6092]
$ luckyNumbers 10000
115591
$ luckyNumbers 10000 evenLucky
111842

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:

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.@(+*)@-~

Task:

   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

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.

Java

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class LuckyNumbers {

    private static int MAX = 200000;
    private static List<Integer> luckyEven = luckyNumbers(MAX, true);
    private static List<Integer> luckyOdd = luckyNumbers(MAX, false);
    
    public static void main(String[] args) {
        //  Case 1 and 2
        if ( args.length == 1 || ( args.length == 2 && args[1].compareTo("lucky") == 0 ) ) {
            int n = Integer.parseInt(args[0]);
            System.out.printf("LuckyNumber(%d) = %d%n", n, luckyOdd.get(n-1));
        }
        //  Case 3
        else if ( args.length == 2 && args[1].compareTo("evenLucky") == 0 ) {
            int n = Integer.parseInt(args[0]);
            System.out.printf("EvenLuckyNumber(%d) = %d%n", n, luckyEven.get(n-1));            
        }
        //  Case 4 through 9
        else if ( args.length == 2 || args.length == 3 ) {
            int j = Integer.parseInt(args[0]);
            int k = Integer.parseInt(args[1]);
            //  Case 4 and 5
            if ( ( args.length == 2 && k > 0 ) || (args.length == 3 && k > 0 && args[2].compareTo("lucky") == 0 ) ) {
                System.out.printf("LuckyNumber(%d) through LuckyNumber(%d) = %s%n", j, k, luckyOdd.subList(j-1, k));
            }
            //  Case 6
            else if ( args.length == 3 && k > 0 && args[2].compareTo("evenLucky") == 0 ) {
                System.out.printf("EvenLuckyNumber(%d) through EvenLuckyNumber(%d) = %s%n", j, k, luckyEven.subList(j-1, k));
            }
            //  Case 7 and 8
            else if ( ( args.length == 2 && k < 0 ) || (args.length == 3 && k < 0 && args[2].compareTo("lucky") == 0 ) ) {
                int n = Collections.binarySearch(luckyOdd, j);
                int m = Collections.binarySearch(luckyOdd, -k);
                System.out.printf("Lucky Numbers in the range %d to %d inclusive = %s%n", j, -k, luckyOdd.subList(n < 0 ? -n-1 : n, m < 0 ? -m-1 : m+1));
            }
            //  Case 9
            else if ( args.length == 3 && k < 0 && args[2].compareTo("evenLucky") == 0 ) {
                int n = Collections.binarySearch(luckyEven, j);
                int m = Collections.binarySearch(luckyEven, -k);
                System.out.printf("Even Lucky Numbers in the range %d to %d inclusive = %s%n", j, -k, luckyEven.subList(n < 0 ? -n-1 : n, m < 0 ? -m-1 : m+1));
            }
        }
    }
    
    private static List<Integer> luckyNumbers(int max, boolean even) {
        List<Integer> luckyList = new ArrayList<>();
        for ( int i = even ? 2 : 1 ; i <= max ; i += 2 ) {
            luckyList.add(i);
        }
        int start = 1;
        boolean removed = true;
        while ( removed ) {
            removed = false;
            int increment = luckyList.get(start);
            List<Integer> remove = new ArrayList<>();
            for ( int i = increment-1 ; i < luckyList.size() ; i += increment ) {
                remove.add(0, i);
                removed = true;
            }
            for ( int i : remove ) {
                luckyList.remove(i);
            }
            start++;
        }
        return luckyList;
    }

}
Output:
C:\My_Data\software\EclipseOxygenProjects\Rosetta Code\bin>java LuckyNumbers 1 20
LuckyNumber(1) through LuckyNumber(20) = [1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79]

C:\My_Data\software\EclipseOxygenProjects\Rosetta Code\bin>java LuckyNumbers 1 20 evenLucky
EvenLuckyNumber(1) through EvenLuckyNumber(20) = [2, 4, 6, 10, 12, 18, 20, 22, 26, 34, 36, 42, 44, 50, 52, 54, 58, 68, 70, 76]

C:\My_Data\software\EclipseOxygenProjects\Rosetta Code\bin>java LuckyNumbers 6000 -6100
Lucky Numbers in the range 6000 to 6100 inclusive = [6009, 6019, 6031, 6049, 6055, 6061, 6079, 6093]

C:\My_Data\software\EclipseOxygenProjects\Rosetta Code\bin>java LuckyNumbers 6000 -6100 evenLucky
Even Lucky Numbers in the range 6000 to 6100 inclusive = [6018, 6020, 6022, 6026, 6036, 6038, 6050, 6058, 6074, 6090, 6092]

C:\My_Data\software\EclipseOxygenProjects\Rosetta Code\bin>java LuckyNumbers 10000
LuckyNumber(10000) = 115591

C:\My_Data\software\EclipseOxygenProjects\Rosetta Code\bin>java LuckyNumbers 10000 evenLucky
EvenLuckyNumber(10000) = 111842

JavaScript

First: the function.

function luckyNumbers(opts={}) {
  /**************************************************************************\
  | OPTIONS                                                                  |
  |**************************************************************************|
  |   even ...... boolean ............. return even/uneven numbers           |
  |                                     (default: false)                     |
  |                                                                          |
  |   nth ....... number ............... return nth number                   |
  |                                                                          |
  |   through ... number ............... return numbers from #1 to number    |
  |               OR array[from, to] ... return numbers on index             |
  |                                      from array[from] to array[to]       |
  |                                                                          |
  |   range ..... array[from, to] ...... return numbers between from and to  |
  \**************************************************************************/

  opts.even =  opts.even || false;
  if (typeof opts.through == 'number') opts.through = [0, opts.through];
  let out = [],
      x = opts.even ? 2 : 1,
      max = opts.range ? opts.range[1] * 3
        : opts.through ? opts.through[1] * 12
        : opts.nth ? opts.nth * 15
        : 2000;

  for (x; x <= max; x = x+2) out.push(x);            // fill
  for (x = 1; x < Math.floor(out.length / 2); x++) { // sieve
    let i = out.length;
    while (i--)
      (i+1) % out[x] == 0 && out.splice(i, 1);
  }

  if (opts.nth) return out[opts.nth-1];
  if (opts.through) return out.slice(opts.through[0], opts.through[1]);
  if (opts.range) return out.filter(function(val) {
      return val >= opts.range[0] && val <= opts.range[1];
    });
  return out;
}

/* TESTING */
// blank
console.log( luckyNumbers() );
// showing the first twenty lucky numbers
console.log( luckyNumbers({through: 20}) );
// showing the first twenty even lucky numbers
console.log( luckyNumbers({even: true, through: 20}) );
// showing all lucky numbers between 6,000 and 6,100 (inclusive)
console.log( luckyNumbers({range: [6000, 6100]}) );
// showing all even lucky numbers in the same range as above
console.log( luckyNumbers({even: true, range: [6000, 6100]}) );
// showing the 10,000th lucky number (extra credit)
console.log( luckyNumbers({nth: 10000}) );
// showing the 10,000th even lucky number (extra credit)
console.log( luckyNumbers({even: true, nth: 10000}) );
Output:

> Array(276) [ 1, 3, 7, 9, 13, 15, 21, 25, 31, 33, … ] > Array(20) [ 1, 3, 7, 9, 13, 15, 21, 25, 31, 33, … ] > Array(20) [ 2, 4, 6, 10, 12, 18, 20, 22, 26, 34, … ] > Array(8) [ 6009, 6019, 6031, 6049, 6055, 6061, 6079, 6093 ] > Array(11) [ 6018, 6020, 6022, 6026, 6036, 6038, 6050, 6058, 6074, 6090, … ] > 115591 > 111842

And that's just pretty much it.

But now: our line interpreter!

We'll use an HTML-prompt here, because JavaScript actually doesn't have a command interface on it's own.

(function() {
  document.write(`
    <table>
      <tr><th>argument(s)<br>space separated</th><th>gives</th></tr>
      <tr><td>$j</td><td><i>j</i><sup>th</sup> lucky number</tr>
      <tr><td>$j lucky</td><td><i>j</i><sup>th</sup> lucky number</tr>
      <tr><td>$j evenLucky</td><td><i>j</i><sup>th</sup> even lucky number</tr>
      <tr><td>&nbsp;</td><td>&nbsp;</td></tr>
      <tr><td>$j $k</td><td><i>J</i><sup>th</sup> through <i>k</i><sup>th</sup> (inclusive) lucky numbers</td></tr>
      <tr><td>$j $k lucky</td><td><i>J</i><sup>th</sup> through <i>k</i><sup>th</sup> (inclusive) lucky numbers</td></tr>
      <tr><td>$j $k evenLucky</td><td><i>J</i><sup>th</sup> through <i>k</i><sup>th</sup> (inclusive) even lucky numbers</td></tr>
      <tr><td>&nbsp;</td><td>&nbsp;</td></tr>
      <tr><td>-$j</td><td>all lucky numbers in the range 1 .. |<i>j</i>|*</tr>
      <tr><td>$j -$k</td><td>all lucky numbers in the range <i>j</i> .. |<i>k</i>|*</tr>
      <tr><td>$j -$k lucky</td><td>all lucky numbers in the range <i>j</i> .. |<i>k</i>|*</tr>
      <tr><td>$j -$k evenLucky</td><td>all even lucky numbers in the range <i>j</i> .. |<i>k</i>|*</tr>
    </table>
    <p>* where |<i>x</i>| is the absolute value of <i>x</i></p>
  `);
  let args = prompt('Enter a luckyNumbers argument string:').split(' '),
      numbers = [],
      strings = [],
      obj = {},      // object to pass to our luckyNumbers function
      msg = '';
  for (let x = 0; x < args.length; x++) {
    if (isNaN(parseInt(args[x]))) strings.push(args[x].toUpperCase());
    else numbers.push(parseInt(args[x]));
  }
  // check strings
  switch (true) {
    case (strings.length > 1):
      msg += 'Too many arguments.';
      break;
    case (strings.length == 0): break;
    case (strings[0] != 'LUCKY' && strings[0] != 'EVENLUCKY'):
      msg += `Unknown argument: ${strings[0]}.`;
      break;
    case (strings[0] == 'EVENLUCKY'): obj.even = true;
  }
  // check numbers
  switch (true) {
    case (numbers.length == 0):
      msg += 'Missing number argument.';
      break;
    case (numbers.length > 2):
      msg += 'Too many number arguments.';
      break;
    case (numbers.length == 1):
      if (numbers[0] > 0) obj.nth = numbers[0];
      else obj.through = Math.abs(numbers[0]);
      break;
    case (numbers.length == 2):
      // both negative
      if (numbers[0] < 0 && numbers[1] < 0) {
        msg += 'Missing positive argument';
        break;
      }
      // negative + positive
      numbers.sort();
      if (numbers[0] < 0 && numbers[1] > 0) {
        obj.range = [numbers[1], Math.abs(numbers[0])];
        break;
      }
      // both positive
      if (numbers[0] > 0 && numbers[1] > 0) {
        obj.through = [numbers[0]-1, numbers[1]];
      }
  }
  if (msg.length > 0)
    document.write(`<p>${msg}<br>Reload to try again</p>`);
  else {
    let res;
    try { res = luckyNumbers(obj); }
    catch (err) {
      document.write(`<p>${err}<br>Reload to try again</p>`);
    }
    finally {
      if (typeof res == 'object' ) res = res.join(', ');
      document.write(`
        <p>
          <b>Input: </b>${args.join(' ')}<br>
          <b>Result: </b>${res}
        </p>
        <p>Reload to continue</p>
      `)
    }
  }
})();

Using the task demonstrations again, the I/O part looks like:

Output:

Input: 1 20 Result: 1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79

Input: -20 evenLucky Result: 2, 4, 6, 10, 12, 18, 20, 22, 26, 34, 36, 42, 44, 50, 52, 54, 58, 68, 70, 76

Input: 6000 -6100 Result: 6009, 6019, 6031, 6049, 6055, 6061, 6079, 6093

Input: -6100 evenlucky 6000 Result: 6018, 6020, 6022, 6026, 6036, 6038, 6050, 6058, 6074, 6090, 6092

Input: 10000 Result: 115591

Input: Evenlucky 10000 Result: 111842

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:

JQ -Rrcf program.jq <<< '1 20'

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.

# 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)
  | 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
Output:
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

Julia

This iterator for lucky numbers is semi-lazy: it completes one pass of the filter each iteration.

using Base, StringDistances

struct Lucky
    start::Int
    nmax::Int
    Lucky(iseven, nmax) = new(iseven ? 2 : 1, nmax)
end

struct LuckyState
    nextindex::Int
    sequence::Vector{Int}
end

Base.eltype(iter::Lucky) = Int

function Base.iterate(iter::Lucky, state = LuckyState(1, collect(iter.start:2:iter.nmax)))
    if length(state.sequence) < state.nextindex
        return nothing
    elseif state.nextindex == 1
        return (iter.start, LuckyState(2, state.sequence))
    end
    result = state.sequence[state.nextindex]
    newsequence = Vector{Int}()
    for (i, el) in enumerate(state.sequence)
        if i % result != 0
            push!(newsequence, el)
        end
    end
    (result, LuckyState(state.nextindex + 1, newsequence))
end

function luckyindex(j, wanteven, k=0)
    topindex = max(j, k) + 4
    luck = Lucky(wanteven, topindex * 20)
    iter_result = iterate(luck)
    while iter_result != nothing
        (elem, state) = iter_result
        iter_result = iterate(luck, state)
        if iter_result != nothing && iter_result[2].nextindex > topindex
            return iter_result[2].sequence[k > j ? (j:k) : j]
        end
    end
    throw("Index $j out of range for nmax of $(luck.nmax).")
end
    
function luckyrange(j, k, wanteven)
    topvalue = max(j, k)
    luck = Lucky(wanteven, topvalue + 1)
    iter_result = iterate(luck)
    (elem, state) = iter_result # save next to last result
    while iter_result != nothing
        (elem, state) = iter_result
        iter_result = iterate(luck, state)
    end
    filter(x -> (j <= x <= k), state.sequence)
end

function helpdisplay(exitlevel=1)
    println("\n", PROGRAM_FILE, " j [-][k] [lucky|evenLucky]")
    println("\tj: index wanted or a starting point (index or value)", 
            "\n\tk: optional ending point (index), \n\t-k: optional ending point (value)\n")
    helpstring =
""" | Argument(s)        |    What is printed                                  |
 |--------------------------------------------------------------------------|
 | j                  |  jth lucky number (required argument)               |
 | 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 value range [m, |k|]      |
 | j  -k  lucky       |  all lucky numbers in the value range [m, |k|]      |
 | j  -k  evenLucky   |  all even lucky numbers in the value range [m, |k|] |
 |--------------------------------------------------------------------------|\n\n"""

    println(helpstring)
    exit(exitlevel)
end

function parsecommandline()
    comma = false
    evenLucky = false
    range = false
    j = k = 0
    if length(ARGS) < 1
        helpdisplay()
    end
    for (pos, arg) in enumerate(ARGS)
        if pos == 1
            j = tryparse(Int, arg)
            if j == nothing
                println("The first argument must be a positive integer.\n")
                helpdisplay()
            end
        elseif pos == 2 || (pos == 3 && comma)
            k = tryparse(Int, arg)
            if k == nothing
                k = 0
                if arg == ","
                    comma = true
                    continue
                elseif arg == "lucky"
                    continue
                elseif arg == "evenLucky"
                    evenLucky = true
                elseif compare(Hamming(), arg, "lucky") > 0.4 || compare(Hamming(), arg, "evenLucky") > 0.4
                    println("Did you misspell \"lucky\" or \"evenLucky\"? Check capitalization.\n")
                    helpdisplay()
                else
                    helpdisplay()
                end
            elseif k < 0
                k = -k
                range = true
            end
        elseif pos == 3 || pos == 4 && comma
            if arg == ","
                comma = true
                continue
            elseif arg == "lucky"
                continue
            elseif arg == "evenLucky"
                evenLucky = true
            elseif compare(Hamming(), arg, "lucky") > 0.1 || compare(Hamming(), arg, "evenLucky") > 0.1
                println("Did you misspell "\lucky\" or "\evenLucky\"?\n\n")
                helpdisplay()
            else
                helpdisplay()
            end
        elseif arg == "lucky"
                continue
        elseif arg == "evenLucky"
                evenLucky = true
        else
            println("Too many arguments.\n")
            helpdisplay()
        end
    end
    (j, k, evenLucky, range)
end

function runopts()
    (j, k, evenLucky, range) = parsecommandline()
    if j < 1 || (k != 0 && j >= k)
        throw("Lucky number integer parameters out of range: $(typeof(j)), $j, $(typeof(k)), $k")
    end
    if range
        println(luckyrange(j, k, evenLucky))
    else
        println(luckyindex(j, evenLucky, k))
    end
end

runopts()
Output:

> julia luckymath.jl 1 20 [1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79] > julia luckymath.jl 1 20 evenLucky [2, 4, 6, 10, 12, 18, 20, 22, 26, 34, 36, 42, 44, 50, 52, 54, 58, 68, 70, 76] > julia luckymath.jl 6000 -6100 [6009, 6019, 6031, 6049, 6055, 6061, 6079, 6093] > julia luckymath.jl 6000 -6100 evenLucky [6018, 6020, 6022, 6026, 6036, 6038, 6050, 6058, 6074, 6090, 6092] > julia luckymath.jl 10000 115591 > julia luckymath.jl 10000 evenLucky 111842

Kotlin

// version 1.1.51

typealias IAE = IllegalArgumentException

val luckyOdd  = MutableList(100000) { it * 2 + 1 }
val luckyEven = MutableList(100000) { it * 2 + 2 }

fun filterLuckyOdd() {
    var n = 2
    while (n < luckyOdd.size) {
        val m = luckyOdd[n - 1]
        val end = (luckyOdd.size / m) * m - 1
        for (j in end downTo m - 1 step m) luckyOdd.removeAt(j)
        n++
    }
}

fun filterLuckyEven() {
    var n = 2
    while (n < luckyEven.size) {
        val m = luckyEven[n - 1]
        val end = (luckyEven.size / m) * m - 1
        for (j in end downTo m - 1 step m) luckyEven.removeAt(j)
        n++
    }
}

fun printSingle(j: Int, odd: Boolean) {
    if (odd) {
        if (j >= luckyOdd.size) throw IAE("Argument is too big")
        println("Lucky number $j = ${luckyOdd[j - 1]}")
    }
    else {
        if (j >= luckyEven.size) throw IAE("Argument is too big")
        println("Lucky even number $j = ${luckyEven[j - 1]}")
    }
}

fun printRange(j: Int, k: Int, odd: Boolean) {
    if (odd) {
        if (k >= luckyOdd.size) throw IAE("Argument is too big")
        println("Lucky numbers $j to $k are:\n${luckyOdd.drop(j - 1).take(k - j + 1)}")
    }
    else {
        if (k >= luckyEven.size) throw IAE("Argument is too big")
        println("Lucky even numbers $j to $k are:\n${luckyEven.drop(j - 1).take(k - j + 1)}")
    }
}

fun printBetween(j: Int, k: Int, odd: Boolean) {
    val range = mutableListOf<Int>()
    if (odd) {
        val max = luckyOdd[luckyOdd.lastIndex]
        if (j > max || k > max) {
            throw IAE("At least one argument is too big")
        }
        for (num in luckyOdd) {
            if (num < j) continue
            if (num > k) break
            range.add(num)
        }
        println("Lucky numbers between $j and $k are:\n$range")
    }
    else {
        val max = luckyEven[luckyEven.lastIndex]
        if (j > max || k > max) {
            throw IAE("At least one argument is too big")
        }
        for (num in luckyEven) {
            if (num < j) continue
            if (num > k) break
            range.add(num)
        }
        println("Lucky even numbers between $j and $k are:\n$range")
    }
}

fun main(args: Array<String>) {
    if (args.size !in 1..3) throw IAE("There must be between 1 and 3 command line arguments")
    filterLuckyOdd()
    filterLuckyEven()
    val j = args[0].toIntOrNull()
    if (j == null || j < 1) throw IAE("First argument must be a positive integer")
    if (args.size == 1) { printSingle(j, true); return }

    if (args.size == 2) {
        val k = args[1].toIntOrNull()
        if (k == null) throw IAE("Second argument must be an integer")
        if (k >= 0) {
            if (j > k) throw IAE("Second argument can't be less than first")
            printRange(j, k, true)
        }
        else {
           val l = -k
            if (j > l) throw IAE("The second argument can't be less in absolute value than first")
            printBetween(j, l, true)
        }
        return
    }

    var odd =
        if (args[2].toLowerCase() == "lucky") true
        else if (args[2].toLowerCase() == "evenlucky") false
        else throw IAE("Third argument is invalid")

    if (args[1] == ",") {
        printSingle(j, odd)
        return
    }

    val k = args[1].toIntOrNull()
    if (k == null) throw IAE("Second argument must be an integer or a comma")

    if (k >= 0) {
        if (j > k) throw IAE("Second argument can't be less than first")
        printRange(j, k, odd)
    }
    else {
        val l = -k
        if (j > l) throw IAE("The second argument can't be less in absolute value than first")
        printBetween(j, l, odd)
    }
}
Output:
$ java -jar lucky.jar 1 20
Lucky numbers 1 to 20 are:
[1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79]

$ java -jar lucky.jar 1 20 evenLucky
Lucky even numbers 1 to 20 are:
[2, 4, 6, 10, 12, 18, 20, 22, 26, 34, 36, 42, 44, 50, 52, 54, 58, 68, 70, 76]

$ java -jar lucky.jar 6000 -6100
Lucky numbers between 6000 and 6100 are:
[6009, 6019, 6031, 6049, 6055, 6061, 6079, 6093]

$ java -jar lucky.jar 6000 -6100 evenLucky
Lucky even numbers between 6000 and 6100 are:
[6018, 6020, 6022, 6026, 6036, 6038, 6050, 6058, 6074, 6090, 6092]

$ java -jar lucky.jar 10000 , lucky
Lucky number 10000 = 115591

$ java -jar lucky.jar 10000 , evenLucky
Lucky even number 10000 = 111842

Mathematica /Wolfram Language

Save the following code in the file script.wls and execute the wolframscript from the command line:

ClearAll[GetLuckies, GetEvenLuckies]
GetLuckies[max_] := Module[{luckies, f, i},
  luckies = Range[1, max, 2];
  f[n_] := Block[{k = luckies[[n]]}, luckies = Delete[luckies, Table[{k}, {k, k, Length@luckies, k}]]];
  i = 2;
  While[i < Length[luckies],
   f[i];
   i++
   ];
  luckies
  ]
GetEvenLuckies[max_] := Module[{lst, i, len},
  lst = Range[2, max, 2];
  i = 2;
  While[i <= (len = Length@lst) && (k = lst[[i]]) <= len,
   lst = Drop[lst, {k, len, k}];
   i++
   ];
  lst
  ]
GiveLucky[s_String] := GiveLucky[StringSplit[s, " "]]
GiveLucky[args_List] := Module[{argc = Length[args], j, k, type},
  If[argc > 3,
   Print["Too many arguments"]
   ,
   If[argc == 0,
    Print["Too few arguments"]
    ,
    Switch[argc, 1,
     j = Interpreter["Integer"][args[[1]]];
     If[! FailureQ[j],
      If[j > 0,
       Print@GetLuckies[20 j][[j]]
       ,
       Print["j should be positive"]
       ]
      ,
      Print["one argument that is not an integer"]
      ]
     , 2,
     j = Interpreter["Integer"][args[[1]]];
     k = Interpreter["Integer"][args[[2]]];
     If[! FailureQ[j] \[And] ! FailureQ[k],
      If[j > 0,
       If[k > 0,
        Print@GetLuckies[20 k][[j ;; k]]
        ,
        Print@Select[GetLuckies[-k], GreaterEqualThan[j]]
        ]
       ,
       Print["j should be positive"]
       ]
      ,
      Print["one of the two arguments is not an integer\[Ellipsis]"]
      ]
     , 3,
     If[args[[2]] === ",",
      j = Interpreter["Integer"][args[[1]]];
      If[! FailureQ[j],
       If[j > 0,
        type = args[[3]];
        If[MatchQ[type, "evenLucky" | "lucky"],
         If[type === "evenLucky",
          Print@GetEvenLuckies[20 j][[j]]
          ,
          Print@GetLuckies[20 j][[j]]
          ]
         ,
         Print["unknown type ", type]
         ]
        ,
        Print["j should be positive"]
        ]
       ,
       Print["j should be an integer"]
       ]
      ,
      j = Interpreter["Integer"][args[[1]]];
      k = Interpreter["Integer"][args[[2]]];
      If[! FailureQ[j] \[And] ! FailureQ[k],
       If[j > 0,
        type = args[[3]];
        If[k > 0,
         If[MatchQ[type, "evenLucky" | "lucky"],
          If[type === "evenLucky",
           Print@GetEvenLuckies[20 k][[j ;; k]]
           ,
           Print@GetLuckies[20 k][[j ;; k]]
           ]
          ,
          Print["unknown type ", type]
          ]
         ,
         If[MatchQ[type, "evenLucky" | "lucky"],
          If[type === "evenLucky",
           Print@Select[GetEvenLuckies[-k], GreaterEqualThan[j]]
           ,
           Print@Select[GetLuckies[-k], GreaterEqualThan[j]]
           ]
          ,
          Print["unknown type ", type]
          ]
         ]
        ,
        Print["j should be positive"]
        ]
       ,
       Print["one of the two arguments is not an integer\[Ellipsis]"]
       ]
      ]
     ]
    ]
   ]
  ]
GiveLucky[Last@$ScriptCommandLine]
Output:
wolframscript -file script.wls -args "1 20 lucky"
{1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79}
wolframscript -file script.wls -args "1 20 evenLucky"
{2, 4, 6, 10, 12, 18, 20, 22, 26, 34, 36, 42, 44, 50, 52, 54, 58, 68, 70, 76}
wolframscript -file script.wls -args "6000 -6100"
{6009, 6019, 6031, 6049, 6055, 6061, 6079, 6093}
wolframscript -file script.wls -args "6000 -6100 evenLucky"
{6018, 6020, 6022, 6026, 6036, 6038, 6050, 6058, 6074, 6090, 6092}
wolframscript -file script.wls -args "10000 , lucky"
115591
wolframscript -file script.wls -args "10000 , evenLucky"
111842

Nim

For the generation of lucky numbers, we use the second Python algorithm, modified to return a sequence.

import os, strformat, strutils

type LuckyKind {.pure.} = enum Lucky = "lucky", EvenLucky = "evenlucky"

const NoValue = 0   # Indicates that no value have been specified.


####################################################################################################
# Lucky numbers generation.

func initLuckyNumbers(nelems: int; kind: LuckyKind): seq[int] =
  ## Initialize a list of lucky numbers.
  result = newSeqOfCap[int](nelems)
  for i in 0..<nelems:
    var k = i
    for j in countdown(result.high, 1):
      k = k * result[j] div (result[j] - 1)
    result.add 2 * k + 1 + ord(kind)


####################################################################################################
# Printing.

template name(kind: LuckyKind): string =
  if kind == Lucky: "Lucky" else: "Even lucky"

proc printSingle(j: int; kind: LuckyKind) =
  ## Print the lucky number at a given index.
  let luckySeq = initLuckyNumbers(j, kind)
  echo &"{name(kind)} number at index {j} is {luckySeq[j - 1]}"

proc printRange(j, k: int; kind: LuckyKind) =
  ## print the luck numbers in a range of indexes.
  let luckySeq = initLuckyNumbers(k, kind)
  var list = &"{name(kind)} numbers at indexes {j} to {k} are: "
  let start = list.len
  for idx in (j - 1)..(k - 1):
    list.addSep(", ", start)
    list.add $luckySeq[idx]
  echo list

proc printInRange(j, k: int; kind: LuckyKind) =
  ## Print the lucky numbers in a range of values.
  let luckySeq = initLuckyNumbers(k, kind)  # "k" is greater than needed.
  var list = &"{name(kind)} numbers between {j} to {k} are: "
  let start = list.len
  for val in luckySeq:
    if val > k: break
    if val > j:
      list.addSep(", ", start)
      list.add $val
  echo list


####################################################################################################
# Command line parsing.

proc parseCommandLine(): tuple[j, k: int; kind: LuckyKind] =
  ## Parse the command line.

  # Internal exception to catch invalid argument value.
  type InvalidArgumentError = object of ValueError

  template raiseError(message, value = "") =
    ## Raise an InvalidArgumentError.
    raise newException(InvalidArgumentError, message & value & '.')


  result = (Novalue, Novalue, Lucky)

  try:

    if paramCount() notin 1..3: raiseError "Wrong number of arguments"

    # First argument: "j" value.
    let p1 = paramStr(1)
    try:
      result.j = parseInt(p1)
      if result.j <= 0: raiseError "Expected a positive number, got: ", p1
    except ValueError:
      raiseError "Expected an integer, got: ", p1

    # Second argument: "k" value or a comma.
    if paramCount() > 1:
      let p2 = paramStr(2)
      if p2 == ",":
        # Must be followed by the kind of lucky number.
        if paramCount() != 3: raiseError "Missing kind argument"
      else:
        try:
          result.k = parseInt(p2)
          if result.k == 0: raiseError "Expected a non null number, got: ", p2
        except ValueError:
          raiseError "Expected an integer, got: ", p2

    # Third argument: number kind.
    if paramCount() == 3:
      let p3 = paramStr(3)
      try:
        result.kind = parseEnum[LuckyKind](p3.toLowerAscii())
      except ValueError:
        raiseError "Wrong kind: ", p3

  except InvalidArgumentError:
    quit getCurrentExceptionMsg()


#———————————————————————————————————————————————————————————————————————————————————————————————————
# Main program.

let (j, k, kind) = parseCommandLine()

if k == NoValue:
  # Print jth value.
  printSingle(j, kind)

elif k > 0:
  # Print jth to kth values.
  printRange(j, k, kind)

else:
  # Print values in range j..(-k).
  printInRange(j, -k, kind)
Output:
./lucky_numbers 1 20
Lucky numbers at indexes 1 to 20 are: 1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79

./lucky_numbers 1 20 evenlucky
Even lucky numbers at indexes 1 to 20 are: 2, 4, 6, 10, 12, 18, 20, 22, 26, 34, 36, 42, 44, 50, 52, 54, 58, 68, 70, 76

./lucky_numbers 6000 -6100
Lucky numbers between 6000 to 6100 are: 6009, 6019, 6031, 6049, 6055, 6061, 6079, 6093

./lucky_numbers 6000 -6100 evenlucky
Even lucky numbers between 6000 to 6100 are: 6018, 6020, 6022, 6026, 6036, 6038, 6050, 6058, 6074, 6090, 6092

./lucky_numbers 10000 , lucky
Lucky number at index 10000 is 115591

./lucky_numbers 10000 , evenlucky
Even lucky number at index 10000 is 111842

Perl

The module Perl6::GatherTake emulates the Raku gather/take syntax, and allows us to access values from what acts (mostly) like a lazy list.

Translation of: Raku
use Perl6::GatherTake;

sub luck {
my($a,$b) = @_;

gather {
    my $i = $b;
    my(@taken,@rotor,$j);

    take 0; # 0th index is a placeholder
    push @taken, take $a;

    while () {
        for ($j = 0; $j < @rotor; $j++) {
            --$rotor[$j] or last;
        }
        if ($j < @rotor) {
            $rotor[$j] = $taken[$j+1];
        }
        else {
            take $i;
            push @taken, $i;
            push @rotor, $i - @taken;
        }
        $i += 2;
    }
}
}

# fiddle with user input
$j = shift || usage();
$k = shift || ',';
$l = shift || 'lucky';
usage() unless $k =~ /,|-?\d+/;
usage() unless $l =~ /^(even)?lucky$/i;
sub usage { print "Args must be:  j [,|k|-k] [lucky|evenlucky]\n" and exit }

# seed the iterator
my $lucky = $l =~ /^l/i ? luck(1,3) : luck(2,4);

# access values from 'lazy' list
if ($k eq ',') {
    print $lucky->[$j]
} elsif ($k > $j) {
    print $lucky->[$_] . ' ' for $j..$k
} elsif ($k < 0) {
    while () { last if abs($k) < $lucky->[$i++] } # must first extend the array
    print join ' ', grep { $_ >= $j and $_ <= abs($k) } @$lucky
}

print "\n"
Output:
$ ./lucky
Args must be:  j [,|k|-k] [lucky|evenlucky]
$ ./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

Phix

with javascript_semantics
constant luckyMax = 120000
 
sequence lucky
 
procedure filterLucky()
    integer n = 2
    while n<=length(lucky) do
        integer m = lucky[n], 
                l = m-1
        for k=m+1 to length(lucky) do
            if mod(k,m)!=0 then
                l += 1
                lucky[l] = lucky[k]
            end if
        end for
        if l>=length(lucky) then exit end if
        lucky = lucky[1..l]
        n += 1
    end while
end procedure
 
constant helptxt = """
   argument(s)   |  what is displayed
=======================================
 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 to k
 j -k lucky      |  all lucky numbers in the range j to k
 j -k evenLucky  |  all even lucky numbers in the range j to k
"""
 
procedure fatal(string msg)
    puts(1,msg)
    puts(1,helptxt)
    {} = wait_key()
    abort(0)
end procedure

procedure process(sequence cl)
    --
    -- Allow eg "lucky j , evenLucky" to be == "lucky j evenLucky"
    --
    if length(cl)=3 and cl[2]="," then cl[2..2] = {} end if
    integer j, k
    bool single = true, range = true, oddluck = true
    for i=1 to length(cl) do
        string cli = cl[i]
        if cli[1]<='9' then     -- (includes '-')
            sequence d = scanf(cl[i],"%d")
            if length(d)!=1 then
                fatal("unrecognised "&cli)
            end if
            if i>2 then
                fatal("too many numbers")
            end if
            integer n = d[1][1]
            if i=1 then
                if n<1 then
                    fatal("first argument must be a positive integer")
                end if
                j = n
            else 
                single = false
                if n<0 then
                    range = false
                    n = -n
                end if
                if n<j then
                    fatal("second argument cannot be less than first")
                end if
                k = n
            end if
        else
            integer l = find(cli,{"lucky","evenLucky"})
            if l=0 then
                fatal("unrecognised "&cli)
            end if
            if i!=length(cl) then
                fatal(cli&" must be last parameter")
            end if
            oddluck = (l=1)
        end if
    end for

    lucky = tagset(luckyMax,2-oddluck,2)
    filterLucky()
    printf(1,"Output when args are %s\n",{join(cl)})
    string evenstr = iff(oddluck?"":"even ")
    if single then
        if j>length(lucky) then
            fatal(sprintf("the argument, %d, is too big", j))
        end if
        printf(1,"Lucky %snumber %d = %d\n",{evenstr,j, lucky[j]})
    elsif range then
        if k>length(lucky) then
            fatal(sprintf("the argument, %d, is too big", k))
        end if
        printf(1,"Lucky %snumbers %d to %d are: %v\n",{evenstr,j,k,lucky[j..k]})
    else
        if j>lucky[$] then
            fatal("start of range is too big")
        elsif k>lucky[$] then
            fatal("end of range is too big")
        end if
        integer m = abs(binary_search(j,lucky)),
                n = binary_search(k,lucky)
        if n<0 then n = -n-1 end if
        printf(1,"Lucky %snumbers between %d and %d are: %v\n", {evenstr,j,k,lucky[m..n]})
    end if
end procedure
 
procedure main()
    sequence cl = command_line()
    if length(cl)=2 then
--      fatal("at least one argument must be supplied") -- (if preferred)
        sequence tests = {"1 20",
                          "1 20 evenLucky",
                          "20 lucky",
                          "20 evenLucky",
                          "6000 -6100",
                          "6000 -6100 evenLucky",
                          "10000 lucky",
                          "10000 evenLucky"}
        -- (done this way to exercise the real command line handling...)
        if cl[1]=cl[2] then                     -- (compiled)
            cl = cl[1..1]
        elsif platform()=WINDOWS then           -- (and interpreted)
            cl[1] = substitute(cl[1],"pw","p")  -- (pw.exe -> p.exe)
        end if
        for i=1 to length(cl) do
            if find(' ',cl[i]) then cl[i] = sprintf("\"%s\"",{cl[i]}) end if
        end for
        for t=1 to length(tests) do
            if platform()=JS then
                -- (...except when we can't do that, of course)
                process(split(tests[t]))
            else
                string cmd = join(append(deep_copy(cl),tests[t]))
--              printf(1,"running %s\n",{cmd})
                {} = system_exec(cmd)
            end if
        end for
        puts(1, "tests complete\n") 
        {} = wait_key()
    else
        cl = cl[3..$] -- ({1,2} are {interperter,source} or {exe,exe})
        process(cl)
    end if
end procedure
main()
Output:

You may need to run this from a [windows] console to get them all on the same screen, and use p.exe rather than pw.exe

Output when args are 1 20
Lucky numbers 1 to 20 are: {1,3,7,9,13,15,21,25,31,33,37,43,49,51,63,67,69,73,75,79}
Output when args are 1 20 evenLucky
Lucky even numbers 1 to 20 are: {2,4,6,10,12,18,20,22,26,34,36,42,44,50,52,54,58,68,70,76}
Output when args are 20 lucky
Lucky number 20 = 79
Output when args are 20 evenLucky
Lucky even number 20 = 76
Output when args are 6000 -6100
Lucky numbers between 6000 and 6100 are: {6009,6019,6031,6049,6055,6061,6079,6093}
Output when args are 6000 -6100 evenLucky
Lucky even numbers between 6000 and 6100 are: {6018,6020,6022,6026,6036,6038,6050,6058,6074,6090,6092}
Output when args are 10000 lucky
Lucky number 10000 = 115591
Output when args are 10000 evenLucky
Lucky even number 10000 = 111842
tests complete

PicoLisp

(off *Even)

(de nn (Lst N)
   (seek
      '((L)
         (when (car L) (=0 (dec 'N))) )
      Lst ) )

(de lucky (B)
   (let Lst (range (if *Even 2 1) B 2)
      (for A (cdr Lst)
         (for (L (nn Lst A) L (nn (cdr L) A))
            (set L) ) )
      (filter bool Lst) ) )

(argv . *Argv) # without validations
(when (= "evenLucky" (last *Argv)) (on *Even))
(setq *Lst (lucky 7000))
(let (A (format (car *Argv))  B (format (cadr *Argv)))
   (println
      (if (lt0 B)
         (filter '((N) (<= A N (abs B))) *Lst)
         (head B (nth *Lst A)) ) ) )
Output:
$ pil ./lucky.l 1 20
(1 3 7 9 13 15 21 25 31 33 37 43 49 51 63 67 69 73 75 79)
$ pil ./lucky.l 1 20 evenLucky
(2 4 6 10 12 18 20 22 26 34 36 42 44 50 52 54 58 68 70 76)
$ pil ./lucky.l 6000 -6100
(6009 6019 6031 6049 6055 6061 6079 6093)
$ pil ./lucky.l 6000 -6100 evenLucky
(6018 6020 6022 6026 6036 6038 6050 6058 6074 6090 6092)

Python

The generator

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

The argument handler

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:]))
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

Python: streaming lazy generator

The following streaming version of function lgen returns odd or even lucky numbers until reaching system limits. Instead of creating a bounded table and deleting elements, it uses the insight that after each iteration the remaining numbers are shuffled left, modifying their indices in a regular way. Reversing this process tracks the k'th lucky number in the final list back to its position in the initial list of integers, and hence determines its value without any need to build the table. The only storage requirement is for the list of numbers found so far.
Based on the algorithm at https://oeis.org/A000959/a000959.txt.

from itertools import count
def lgen(even=False):
    lucky = []
    if not even:
        yield 1
    for k in count(1):
        for l in reversed(lucky):
            k = (k*l)//(l-1)
        lucky.append(2*k+1 + even)
        yield 2*k+1 + even

Raku

(formerly Perl 6)

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);
}
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

REXX

This REXX version does extra error checking for the arguments.

/*REXX program displays  lucky  or  evenLucky  integers   (numbers  or  a number range).*/
parse arg bot top func _ .                       /*obtain required & optional arguments.*/
if func==''  then func= 'lucky'                  /*Not specified?  Then use the default.*/
s= left('s', bot\==top  &  top\==",")            /*plural results (or maybe not plural).*/
say func  'number's":"   bot  top   '───►'   $lucky(bot, top, func, _)
exit 0                                           /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
$lucky: arg x,y,f,?;   if y=='' | y==","  then y= x      /*obtain some arguments; set Y.*/
        #= 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 argument is less than 1st arg."
        ay=abs(y); yL=ay; if y>0  then yL= y*10  + y + y /*adjust the upper  Y  limit.  */
                                                         /* [↓]  build LUCKY | EVENLUCKY*/
            do j=1  until j>=yL                          /*construct list 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-THEN  logic.*/
                      else if  j   //8==0  then iterate  /*prune next  if  mod 8 ≡ zero.*/
            #= # + 1                                     /*bump the counter of numbers. */
            $= $ j                                       /*append integer to the $ list.*/
            end   /*j*/
        q=0
            do p=3  until  q=='';       q= word($, p)    /*start to prune  integer list.*/
            if q>#  then leave                           /*if integer is too large, stop*/
                                do j=#%q*q  by -q  to q  /*elide every  Qth  integer.   */
                                $= delword($, j, 1)      /*delete a particular number.  */
                                #= # -1                  /*decrease the integer count.  */
                                end   /*j*/              /*delete from the right side.  */
            end   /*p*/
        @.=
                  do k=1;  parse var $ q $;       if q==''  then leave;       @.k= q
                  end   /*k*/
        @.0=k-1
                  do m=1  for #                          /*restrict the found integers. */
                  if (\ny  &  (m<x  |  m>ay))  |  (ny  &  (@.m<x | @.m>ay))  then @.m=
                  end   /*m*/                            /* [↑]  a list of #s or a range*/
        _=
                  do b=1  for @.0;     _= _ @.b          /*construct a list of integers.*/
                  end   /*b*/
        return space(_)                                  /*remove superfluous blanks.   */
output   when using the input of:     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 using the input of:     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 using the input of:     6000   -6100   lucky
lucky numbers: 6000 -6100 ───► 6009 6019 6031 6049 6055 6061 6079 6093
output   when using the input of:     6000   -6100   evenLucky
evenLucky numbers: 6000 -6100 ───► 6018 6020 6022 6026 6036 6038 6050 6058 6074 6090 6092
output   when using the input of:     10000
lucky number: 10000 ───► 115591
output   when using the input of:     10000   ,   evenLucky
evenLucky number: 10000 ───► 111842

Ring

# Project : Lucky and even lucky numbers

lucky = list(50)
dellucky = []
for n = 1 to 50  
     lucky[n] = 2*n-1
next
see "the first 20 lucky numbers:" + nl
luckynumbers(lucky)
showarray(lucky)
see nl

lucky = list(50)
dellucky = []
for n = 1 to 50  
     lucky[n] = 2*n
next
see "the first 20 even lucky numbers:" + nl
luckynumbers(lucky)
showarray(lucky)
see nl

lucky = list(20000)
dellucky = []
for n = 1 to 10000 
     lucky[n] = 2*n-1
next
see "lucky numbers between 6,000 and 6,100:" + nl
luckynumbers2(lucky)
showarray2(lucky)
see nl

lucky = list(20000)
dellucky = []
for n = 1 to 10000 
     lucky[n] = 2*n
next
see "even lucky numbers between 6,000 and 6,100:" + nl
luckynumbers2(lucky)
showarray2(lucky)
see nl

func luckynumbers(lucky)
      for n = 2 to len(lucky) 
          dellucky = [] 
          for m = lucky[n] to len(lucky) step lucky[n]
              add(dellucky, m)
          next
          for p = len(dellucky)  to 1 step -1
              del(lucky, dellucky[p])
          next
      next

func luckynumbers2(lucky)
      for n = 2 to len(lucky) 
          dellucky = [] 
          for m = lucky[n] to len(lucky) step lucky[n]
              add(dellucky, m)
          next
          for p = len(dellucky)  to 1 step -1
              del(lucky, dellucky[p])
          next
          if lucky[n] >= 6100
             exit
          ok
next

func showarray(vect)
      see "["
      svect = ""
      for n = 1 to 20
          svect = svect + vect[n] + ", "
      next
      svect = left(svect, len(svect) - 2)
      see svect
      see "]" + nl

func showarray2(vect)
      see "["
      svect = ""
      for n = 1 to len(vect)
          if vect[n] >= 6000 and vect[n] <= 6100
             svect = svect + vect[n] + ", "
          ok
      next
      svect = left(svect, len(svect) - 2)
      see svect
      see "]" + nl

Output:

the first 20 lucky numbers:
[1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79]

the first 20 even lucky numbers:
[2, 4, 6, 10, 12, 18, 20, 22, 26, 34, 36, 42, 44, 50, 52, 54, 58, 68, 70, 76]

lucky numbers between 6,000 and 6,100:
[6009, 6019, 6031, 6049, 6055, 6061, 6079, 6093]

even lucky numbers between 6,000 and 6,100:
[6018, 6020, 6022, 6026, 6036, 6038, 6050, 6058, 6074, 6090, 6092]

RPL

Works with: HP version 48

The program returns even lucky numbers when one of the 2 arguments is negative, which is more idiomatic.

RPL code Comment
≪ 
   1 CF DUP2 * 0 < ≪ 1 SF ≫ IFT
   ABS SWAP ABS DUP2 ≤ ≪ #202h DOERR ≫ IFT
   2 → b a n
   ≪ { } 1 1 FS? + b FOR j j + 2 STEP
      DO
        DUP n GET → m
        ≪ { } 1 3 PICK SIZE FOR j
              OVER j DUP m + 2 - SUB + m STEP 
        ≫ SWAP DROP 'n' INCR
      UNTIL OVER SIZE > END 
      { } 1 3 PICK SIZE FOR j
         IF OVER j GET DUP a < THEN DROP ELSE + END 
      NEXT SWAP DROP
≫ ≫ 'LUCKY' STO 
LUCKY ( a (-)b → { (even)lucky } ) 
Set flag 1 if a xor b is negative
abort if b ≤ a with an error message 
n = 2
generate list of odd/even numbers according to flag 1
loop
  m = nth number of the list
  for j = 1 to size(list) step m
     keep numbers from j to j+m-2
  clean stack ; n++
until n > size(list)
for j = 1 to size(list)
  keep jth number only if ≥ a
clean stack
return list
1 80 LUCKY
1 -80 LUCKY
6000 6100 LUCKY
6000 -6100 LUCKY
Output:
4: { 1 3 7 9 13 15 21 25 31 33 37 43 49 51 63 67 69 73 75 79 }
3: { 2 4 6 10 12 18 20 22 26 34 36 42 44 50 52 54 58 68 70 76 }
2: { 6009 6019 6031 6049 6055 6061 6079 6093 } 
1: { 6018 6020 6022 6026 6036 6038 6050 6058 6074 6090 6092 } 

A 6000-number sieve requiring more than 30 KB RAM, the last 2 demonstrations have been run on an emulator instead of a genuine calculator.


Ruby

Translation of: Python
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
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

Swift

Translation of: Python

The lucky numbers sequence:

struct LuckyNumbers : Sequence, IteratorProtocol {
  let even: Bool
  let through: Int
  
  private var drainI = 0
  private var n = 0
  private var lst: [Int]
  
  init(even: Bool = false, through: Int = 1_000_000) {
    self.even = even
    self.through = through
    self.lst = Array(stride(from: even ? 2 : 1, through: through, by: 2))
  }
  
  mutating func next() -> Int? {
    guard n != 0 else {
      defer { n += 1 }
      
      return lst[0]
    }
    
    while n < lst.count && lst[n] < lst.count {
      let retVal = lst[n]
      
      lst = lst.enumerated().filter({ ($0.offset + 1) % lst[n] != 0  }).map({ $0.element })
      n += 1
      
      return retVal
    }
    
    if drainI == 0 {
      lst = Array(lst.dropFirst(n))
    }

    while drainI < lst.count {
      defer { drainI += 1 }
      
      return lst[drainI]
    }
    
    return nil
  }
}

The main file:

let args = Array(CommandLine.arguments.dropFirst())

guard let sj = args.first, let j = Int(sj), j > 0, j <= 10_000 else {
  fatalError("Incorrect j")
}

func evenString(_ even: Bool) -> String {
  return even ? "even" : ""
}

func jLuckyNumber(_ j: Int, even: Bool) {
  print("The \(j)th \(evenString(even)) lucky number is \(Array(LuckyNumbers(even: even))[j-1..<j].first!)")
}

func luckyNumbersKth(j: Int, k: Int, even: Bool) {
  print("List of \(j) ... \(k) \(evenString(even)) lucky numbers: ", terminator: "")
  
  for (offset, luck) in LuckyNumbers(even: even).lazy.enumerated() {
    guard offset + 1 <= k else { break }
    
    if offset + 1 >= j {
      print(luck, terminator: ", ")
    }
  }
  
  print()
}

func luckyNumbersRange(j: Int, k: Int, even: Bool) {
  print("List of \(evenString(even)) lucky numbers in the range \(j) ... \(-k): ", terminator: "")
  
  for lucky in LuckyNumbers(even: even).lazy {
    guard lucky <= -k else { break }
    
    if lucky >= j {
      print(lucky, terminator: ", ")
    }
  }
  
  print()
}

switch args.count {
case 1:
  jLuckyNumber(j, even: false)
case 2:  
  switch Int(args.last!) {
  case let k? where k > 0 && k <= 10_000 && k > j:
    luckyNumbersKth(j: j, k: k, even: false)
  case let k? where k < 0 && -k > j:
    luckyNumbersRange(j: j, k: k, even: false)
  case _:
    fatalError("Bad args")
  }
case 3:
  switch (Int(args[1]), args.last!) {
  case (nil, "lucky"):
    jLuckyNumber(j, even: false)
  case (nil, "evenLucky"):
    jLuckyNumber(j, even: true)
  case let (k?, "lucky") where k > 0 && k <= 10_000 && k > j:
    luckyNumbersKth(j: j, k: k, even: false)
  case let (k?, "evenLucky") where k > 0 && k <= 10_000 && k > j:
    luckyNumbersKth(j: j, k: k, even: true)
  case let (k?, "lucky") where k < 0 && -k > j:
    luckyNumbersRange(j: j, k: k, even: false)
  case let (k?, "evenLucky") where k < 0 && -k > j:
    luckyNumbersRange(j: j, k: k, even: true)
  case _:
    fatalError("Bad args")
  }
case _:
  fatalError()
}
Output:
$ ./main 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, 
$ ./main 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, 
$ ./main 6000 -6100 lucky
List of  lucky numbers in the range 6000 ... 6100: 6009, 6019, 6031, 6049, 6055, 6061, 6079, 6093, 
$ ./main 6000 -6100 evenLucky
List of even lucky numbers in the range 6000 ... 6100: 6018, 6020, 6022, 6026, 6036, 6038, 6050, 6058, 6074, 6090, 6092, 
$ ./main 10000
The 10000th  lucky number is 115591
$ ./main 10000 , evenLucky
The 10000th even lucky number is 111842

Tcl

Works with: Tcl version 8.6
Translation of: Python
#!/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]] ,]"
}
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

Wren

Translation of: Kotlin
Library: Wren-iterate
Library: Wren-str
import "os" for Process
import "./iterate" for Stepped
import "./str" for Str

var luckyOdd  = List.filled(1e5, 0)
var luckyEven = List.filled(1e5, 0)

var init = Fn.new {
    for (i in 0...1e5) {
        luckyOdd[i]  = i*2 + 1
        luckyEven[i] = i*2 + 2
    }
}

var filterLuckyOdd = Fn.new {
    var n = 2
    while (n < luckyOdd.count) {
        var m = luckyOdd[n-1]
        var end = (luckyOdd.count/m).floor * m - 1
        for (j in Stepped.descend(end..m-1, m)) luckyOdd.removeAt(j)
        n = n + 1
    }
}

var filterLuckyEven = Fn.new {
    var n = 2
    while (n < luckyEven.count) {
        var m = luckyEven[n-1]
        var end = (luckyEven.count/m).floor * m - 1
        for (j in Stepped.descend(end..m-1, m)) luckyEven.removeAt(j)
        n = n + 1
    }
}

var printSingle = Fn.new { |j, odd|
    if (odd) {
        if (j >= luckyOdd.count) Fiber.abort("Argument is too big")
        System.print("Lucky number %(j) = %(luckyOdd[j-1])")
    } else {
        if (j >= luckyEven.count) Fiber.abort("Argument is too big")
        System.print("Lucky even number %(j) = %(luckyEven[j-1])")
    }
}

var printRange = Fn.new { |j, k, odd|
    if (odd) {
        if (k >= luckyOdd.count) Fiber.abort("Argument is too big")
        var rng = luckyOdd.skip(j-1).take(k-j+1).toList
        System.print("Lucky numbers %(j) to %(k) are:\n %(rng)")
    } else {
        if (k >= luckyEven.count) Fiber.abort("Argument is too big")
        var rng = luckyEven.skip(j-1).take(k-j+1).toList
        System.print("Lucky even numbers %(j) to %(k) are:\n %(rng)")
    }
}

var printBetween = Fn.new { |j, k, odd|
    var rng = []
    if (odd) {
        var max = luckyOdd[-1]
        if (j > max || k > max) {
            Fiber.abort("At least one argument is too big")
        }
        for (num in luckyOdd) {
            if (num >= j) {
                if (num > k) break
                rng.add(num)
            }
        }
        System.print("Lucky numbers between %(j) and %(k) are:\n%(rng)")
    } else {
        var max = luckyEven[-1]
        if (j > max || k > max) {
            Fiber.abort("At least one argument is too big")
        }
        for (num in luckyEven) {
            if (num >= j) {
                if (num > k) break
                rng.add(num)
            }
        }
        System.print("Lucky even numbers between %(j) and %(k) are:\n%(rng)")
    }
}

var args = Process.arguments
var argsSize = args.count
if (argsSize < 1 || argsSize > 3) Fiber.abort("There must be between 1 and 3 command line arguments")
init.call()
filterLuckyOdd.call()
filterLuckyEven.call()
var j = Num.fromString(args[0])
if (j.type != Num || !j.isInteger || j < 1) Fiber.abort("First argument must be a positive integer")
if (argsSize == 1) {
    printSingle.call(j, true)
    return
}

if (argsSize == 2) {
    var k = Num.fromString(args[1])
    if (k.type != Num || !k.isInteger) Fiber.abort("Second argument must be an integer")
    if (k >= 0) {
        if (j > k) Fiber.abort("Second argument can't be less than first")
        printRange.call(j, k, true)
    } else {
        var l = -k
        if (j > l) Fiber.abort("The second argument can't be less in absolute value than first")
        printBetween.call(j, l, true)
    }
    return
}

args[2] = Str.lower(args[2])
var odd = (args[2] == "lucky") ? true :
          (args[2] == "evenlucky") ? false : Fiber.abort("Third argument is invalid")

if (args[1] == ",") {
    printSingle.call(j, odd)
    return
}

var k = Num.fromString(args[1])
if (!((k.type == Num && k.isInteger) || (k.type == String && k == ","))) {
    Fiber.abort("Second argument must be an integer or a comma")
}
if (k >= 0) {
    if (j > k) Fiber.abort("Second argument can't be less than first")
    printRange.call(j, k, odd)
} else {
    var l = -k
    if (j > l) Fiber.abort("The second argument can't be less in absolute value than first")
    printBetween.call(j, l, odd)
}
Output:
$ wren Lucky_and_even_lucky_numbers.wren 1 20
Lucky numbers 1 to 20 are:
 [1, 3, 7, 9, 13, 15, 21, 25, 31, 33, 37, 43, 49, 51, 63, 67, 69, 73, 75, 79]

$ wren Lucky_and_even_lucky_numbers.wren 1 20 evenLucky
Lucky even numbers 1 to 20 are:
 [2, 4, 6, 10, 12, 18, 20, 22, 26, 34, 36, 42, 44, 50, 52, 54, 58, 68, 70, 76]

$ wren Lucky_and_even_lucky_numbers.wren 6000 -6100
Lucky numbers between 6000 and 6100 are:
[6009, 6019, 6031, 6049, 6055, 6061, 6079, 6093]

$ wren Lucky_and_even_lucky_numbers.wren 6000 -6100 evenLucky
Lucky even numbers between 6000 and 6100 are:
[6018, 6020, 6022, 6026, 6036, 6038, 6050, 6058, 6074, 6090, 6092]

$ wren Lucky_and_even_lucky_numbers.wren 10000 , lucky
Lucky number 10000 = 115591

$ wren Lucky_and_even_lucky_numbers.wren 10000 , evenLucky
Lucky even number 10000 = 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.

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  }

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.

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() }
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