0

I was generating (19 digit) sequential numbers like this:

seq 1234496713247997000 1234496713247998000 > seq_numbers.txt

and then validating them online using a luhn checker. Instead of doing a two step approach, How can i do this in a like a bash script for example all in one go, and output only valid numbers to a file?

Hopelessone
  • 337
  • 1
  • 12
  • 1
    How do you invoke the `luhn` checker in command line? – Inian Jan 03 '17 at 05:40
  • not sure, i will re-write the question above so it says bash file – Hopelessone Jan 03 '17 at 05:45
  • What have you tried? Most of us here are happy to help you improve your code, but are less happy acting as short order unpaid programming staff. Show us your work so far in an [MCVE](http://stackoverflow.com/help/mcve), the result you were expecting and the results you got, and we'll help you figure it out. – ghoti Jan 03 '17 at 06:06
  • Hi, i was unsure the direction to go, thats when i posted here asking for advice, the code below works for me. – Hopelessone Jan 03 '17 at 06:16
  • Ah, alas, recommendations for tools are off-topic for SO. We really do try to encourage people to write code rather than just ask for handouts. The best way to build expertise is to practice. – ghoti Jan 03 '17 at 06:21

2 Answers2

1

I do not claim the truthfulness of the luhn checker algorithm from below. It is a reference from this Rosetta Code page.

You can use it as

#!/bin/bash

function luhn_validate
{
    num=$1
    shift 1

    len=${#num}
    is_odd=1
    sum=0
    for((t = len - 1; t >= 0; --t)) {
        digit=${num:$t:1}

        if [[ $is_odd -eq 1 ]]; then
            sum=$(( sum + $digit ))
        else
            sum=$(( $sum + ( $digit != 9 ? ( ( 2 * $digit ) % 9 ) : 9 ) ))
        fi

        is_odd=$(( ! $is_odd ))
    }

    # NOTE: returning exit status of 0 on success
    return $(( 0 != ( $sum % 10 ) ))
}


for i in $(seq 1234496713247997000 1234496713247998000)
do
    if luhn_validate "$i"; then
        echo "$i is valid"
    else
        echo "$i is not valid"
    fi
done

You can put it up in a script as script.sh and set execute permissions chmod +x script.sh and run as

$ ./script.sh

I was able to make it work on GNU bash, version 4.3.46(2)-release (x86_64-pc-msys) and have not tested it on other systems.

P.S.: Use it at your own risk!

Inian
  • 80,270
  • 14
  • 142
  • 161
  • Did you actually test this code? It doesn't work for me. It appears that you simply copied and pasted it from a likely looking hit from a Google search. :-P – ghoti Jan 03 '17 at 06:03
  • @ghoti: Yup, it worked fine for me, I can post the test results, it was seemingly long. – Inian Jan 03 '17 at 06:04
  • @ghoti: That's why added a big disclaimer in the beginning! – Inian Jan 03 '17 at 06:05
  • @ghoti: Was it a case of empty output or any syntax violations? – Inian Jan 03 '17 at 06:06
  • Hi, i verified the code and it works perfect for me, thanks a bunch. – Hopelessone Jan 03 '17 at 06:16
  • @Hopelessone: Appreciate it, do cross-verify the algorithm once for its logic before adopting it, I haven't explored much on it. – Inian Jan 03 '17 at 06:18
1

Why check them all? Just generate the last digit! It is 3 times faster!

#!/bin/bash
# https://stackoverflow.com/questions/41437080
# answer corrected By Zibri

function luhn_generate_last_digit
{
    num=$1
    shift 1

    len=${#num}

    is_odd=$((1-len%2))
    sum=0
    for((t = len - 1; t >= 0; --t)) {
        digit=${num:$t:1}

        if [[ $is_odd -eq 1 ]]; then
            sum=$(( sum + $digit ))
        else
            sum=$(( $sum + ( $digit != 9 ? ( ( 2 * $digit ) % 9 ) : 9 ) ))
        fi

        is_odd=$(( ! $is_odd ))
    }
    if [ $(( $sum % 10 )) -eq 0 ]; then sum=10;else sum=$(( $sum % 10 ));fi

    # NOTE: returning exit status of 0 on success
    echo -n $(( 10 - $sum  ))
}


for i in $(seq 123449671324799700 123449671324799800)
do
        echo "$i"$(luhn_generate_last_digit "$i")
done
Zibri
  • 9,096
  • 3
  • 52
  • 44