Accumulator Pattern

"Patterns" are programming tehniques that are not necessarily part of the programming language, but are implemented using the programming language. One typical pattern is the Accumulator Pattern. The idea is that you have one (or, more) variables dedicated to holding a value. As the program runs, those variables may have their values changed based on the existing value already stored in that variable(s).

For example, a counter that count from 1 to 1000 is simple accumulator.

In [1]:
def main():
    # Accumulator variable, starts at 1 because we are multiplying 
    # the existing value in fact with a new value.
    fact = 1
    
    for factor in [6, 5, 4, 3, 2, 1]:
        print("fact = ", fact, " * ", factor, end= " ")
        fact = fact * factor
        print(" = ", fact )
In [2]:
main()
fact =  1  *  6  =  6
fact =  6  *  5  =  30
fact =  30  *  4  =  120
fact =  120  *  3  =  360
fact =  360  *  2  =  720
fact =  720  *  1  =  720

Interlude: Augmented assignment statements

It's very common to take an accumulator variable and add/multiply/subtract/etc. a value from it. Python makes this very easy with "augmented assignment statements".

Note, the literal 10 given in the examples can be any arbitrary expression that results in a numeric value that can be used mathematically with the value in variable a.

In [3]:
a = 5

# Basic expression for "add 10 to variable 'a'"
a = a + 10

# Augmented assignment statement that does this more compactly.
a += 10
In [4]:
a = a * 10
a *= 10
In [5]:
a = a / 10
a /= 10
In [6]:
a = a % 10
a %= 10
In [7]:
a = a ** 10
a **= 10
In [9]:
def fact():
    # Accumulator variable
    fact = 1
    for factor in [2, 3, 4, 5, 6]:
        print("fact = ", fact, " * ", factor, end= " ")
        fact = fact * factor
        print(" = ", fact )

Interlude 2: range()

When we need to make a loop run for a specific number of reptitions (iterations), range() is your function. The simplest use of range is when it is given one integer parameter:

In [16]:
# Range of numbers between 0..99
range(100)
Out[16]:
range(0, 100)

The range() functions produces a "range object". It is a proxy to your range of numbers you wish to generate. Therefore, you can create a range and store it in a variable for later use.

In [8]:
my_range = range(0, 100)
my_range
Out[8]:
range(0, 100)

Range objects are not immediate clear about all the values it produces. When evaluating a range object (see above), it describes how it was created when range() was called. That might be enough for you. If not, and you wish to see the entire list of numbers, use list():

In [22]:
print(list(range(0, 100)))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
In [23]:
print(list(my_range))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]

range() has three total parameters possible, though one is required. A start, stop and step values are the full set of parameters given to range. The step parameter allows you to skip to every n number (to say, produce a list of even, or odd numbers, for example).

In [24]:
odd = range(5, 30, 2)
In [25]:
print(list(odd))
[5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29]
In [31]:
even = range(6, 31, 2)
In [32]:
print(list(even))
[6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30]
In [33]:
n = 50
print(list(range(0, n+1)))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50]
In [36]:
print(list(range(n, 1, -1)))
[50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2]

Better Factorial

Let's use range() to make factorial much more useful.

In [40]:
def fact2():
    n = eval(input("Please enter a whole number: "))
    
    # Accumulator variable
    fact = 1
    
    for factor in range(n, 1, -1):
        #print("fact = ", fact, " * ", factor, end= " ")
        fact = fact * factor
        #print(" = ", fact )
        
    print("The factorial of", n, "is", fact)
In [41]:
fact2()
Please enter a whole number: 50
The factorial of 50 is 30414093201713378043612608166064768844377641568960512000000000000

Big Integers!

Python has "expanding ints" which is a technique to surpass the usual architectural and programmatic limitations of numerical storage. It's a super convenience, but it comes with necessary tradeoffs of speed and memory use.

In [42]:
num = 30414093201713378043612608166064768844377641568960512000000000000
In [43]:
num.bit_length()
Out[43]:
215
In [45]:
fact2()
Please enter a whole number: 100
The factorial of 100 is 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
In [46]:
fact2()
Please enter a whole number: 1000
The factorial of 1000 is 402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
In [47]:
vbn = 402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
In [49]:
vbn.bit_length()
Out[49]:
8530
In [50]:
vbn * 476433
Out[50]:
191710569480310017810746781701238557928238924680503404526740222725866895277616020167729398382072294437307082413522080709802060943301535626143034416141140711322675948755716812659404897428947709400596109358750532388096827184523853974154514487466714167436870908973694572821485702783205915580696108097985279637603213898899318554423449502438477043096535386344556682702922670374434826723717087116057800805267643659184588620835308024840306616675006853565627771978463165358974206121419821547893787037588486995163732179968401064519621924929920704414090343234840745861064691279801056958797255795680838188674488693409549128901823658420579915918921552615653957337837324254423518189707449912764038108134233667642647750742814181950233861190878923853853589250325697373416908567488230437560795226165742899417957778919620328427183770520878138425439679591363457898627104772297555446630420388573620800998094465983724281919169822465848641758068499869958813206330169443550028480049780534937931514918576913786453324272697267275311004654026591666183990487987598759261366546290714851197329711972199388855307981193172768041244382262121485855279281168629621912461318728512861733111291362262031224275055829272777432433867754782496042164609229709142207157842426825155968872082374452101446379380579591818065861242487187739636096009548591710773373280293535755867167742933670492364974970482449720839784441108456540321930993178736096803401002309556212367070853583009889617413912250689010301391961159543506402351558021102012419955508478213946979639256490485065673101077279988899772265630511895112397743165941081579695133487397052722750045877001764119581796122685449253084318766192018024158944693825043782595102372475261483705912857448417592668526937910112824131059694170674749672549172456965380611795209627051050253448217951474574141544045238166915902485617106663824648317911266441124485487751409580056537231571798586501388914443142827546445694983510549740694403131434989578719233244074715276402300983428113256972117529223372482244862754947675773032442323335567686613866154927533118033733136300351365304475534780002889914514767811261839709239028711187666162070832392550359051469409833904366996571588525304259423409040069577986384085971016903763045929529352601079057005322932272750836738800260767799523421314848207575955038240445720831191007386683232669925376000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
In [52]:
n = 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
In [54]:
_100_factorial = float(n)
In [55]:
_100_factorial
Out[55]:
9.332621544394415e+157
In [56]:
big = 93326215443944152681
In [57]:
big = 93_326_215_443_944_152_6_8_1
In [58]:
big
Out[58]:
93326215443944152681