73 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Factor
		
	
	
			
		
		
	
	
			73 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Factor
		
	
	
! Copyright (c) 2012 Anonymous
 | 
						|
! See http://factorcode.org/license.txt for BSD license.
 | 
						|
USING: kernel math math.parser math.order math.ranges sequences ;
 | 
						|
IN: rosetta-code.luhn-test
 | 
						|
 | 
						|
! http://rosettacode.org/wiki/Luhn_test_of_credit_card_numbers
 | 
						|
 | 
						|
! The Luhn test is used by some credit card companies to
 | 
						|
! distinguish valid credit card numbers from what could be a
 | 
						|
! random selection of digits.
 | 
						|
 | 
						|
! Those companies using credit card numbers that can be
 | 
						|
! validated by the Luhn test have numbers that pass the following
 | 
						|
! test:
 | 
						|
 | 
						|
! 1. Reverse the order of the digits in the number.
 | 
						|
 | 
						|
! 2. Take the first, third, ... and every other odd digit in the
 | 
						|
!    reversed digits and sum them to form the partial sum s1
 | 
						|
 | 
						|
! 3. Taking the second, fourth ... and every other even digit in
 | 
						|
!    the reversed digits:
 | 
						|
!    a. Multiply each digit by two and sum the digits if the
 | 
						|
!       answer is greater than nine to form partial sums for the
 | 
						|
!       even digits
 | 
						|
!    b. Sum the partial sums of the even digits to form s2
 | 
						|
 | 
						|
! 4. If s1 + s2 ends in zero then the original number is in the
 | 
						|
!    form of a valid credit card number as verified by the Luhn test.
 | 
						|
 | 
						|
! For example, if the trial number is 49927398716:
 | 
						|
 | 
						|
! Reverse the digits:
 | 
						|
!   61789372994
 | 
						|
! Sum the odd digits:
 | 
						|
!   6 + 7 + 9 + 7 + 9 + 4 = 42 = s1
 | 
						|
! The even digits:
 | 
						|
!     1,  8,  3,  2,  9
 | 
						|
!   Two times each even digit:
 | 
						|
!     2, 16,  6,  4, 18
 | 
						|
!   Sum the digits of each multiplication:
 | 
						|
!     2,  7,  6,  4,  9
 | 
						|
!   Sum the last:
 | 
						|
!     2 + 7 + 6 + 4 + 9 = 28 = s2
 | 
						|
 | 
						|
! s1 + s2 = 70 which ends in zero which means that 49927398716
 | 
						|
! passes the Luhn test
 | 
						|
 | 
						|
! The task is to write a function/method/procedure/subroutine
 | 
						|
! that will validate a number with the Luhn test, and use it to
 | 
						|
! validate the following numbers:
 | 
						|
!   49927398716
 | 
						|
!   49927398717
 | 
						|
!   1234567812345678
 | 
						|
!   1234567812345670
 | 
						|
 | 
						|
: reversed-digits ( n -- list )
 | 
						|
    { } swap
 | 
						|
    [ dup 0 > ]
 | 
						|
        [ 10 /mod  swapd suffix  swap ]
 | 
						|
    while drop ;
 | 
						|
 | 
						|
: luhn-digit  ( n -- n )
 | 
						|
    reversed-digits dup length iota [
 | 
						|
        2dup swap nth
 | 
						|
        swap odd? [ 2 *  10 /mod + ] when
 | 
						|
    ] map sum 10 mod
 | 
						|
    nip ;
 | 
						|
 | 
						|
: luhn? ( n -- ? )
 | 
						|
    luhn-digit 0 = ;
 | 
						|
 |