Code:for patterns

From Predictive Chemistry
Revision as of 16:05, 25 January 2016 by David M. Rogers (talk | contribs) (Solutions)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Here are some example codes that write essentially the same instruction over and over. Let's see how to abstract these patterns out using variables. Try and work the problems before flipping over to the solutions section.

Problems

<source lang="python">

  1. Replace text in a formula.
  2. A B C

vals = ["1", "", "2", # 1

       "",  "", "3", # 2
       "",  "", "" ] # 3

out = "A1 + C1 * C2" out = out.replace("A1", vals[0]) out = out.replace("A2", vals[3]) out = out.replace("A3", vals[6])

out = out.replace("B1", vals[1]) out = out.replace("B2", vals[4]) out = out.replace("B3", vals[7])

out = out.replace("C1", vals[2]) out = out.replace("C2", vals[5]) out = out.replace("C3", vals[8])

  1. Increment items in a list.

fed[5] = fed[5] + 1 fed[4] = fed[4] + 1 fed[3] = fed[3] + 1

  1. Append a line to a string.

if n >= 1:

   out = out + "%f %f %f\n"%(a[0][0], a[0][1], a[0][2])

if n >= 2:

   out = out + "%f %f %f\n"%(a[1][0], a[1][1], a[1][2])

if n >= 3:

   out = out + "%f %f %f\n"%(a[2][0], a[2][1], a[2][2])

if n >= 4:

   out = out + "%f %f %f\n"%(a[3][0], a[3][1], a[3][2])
  1. Iterate the linear congruential random number generator.

i = len(x)-1 x.append(x[i]*61 % 900) i = len(x)-1 x.append(x[i]*61 % 900) i = len(x)-1 x.append(x[i]*61 % 900) i = len(x)-1 x.append(x[i]*61 % 900) i = len(x)-1 x.append(x[i]*61 % 900) </source>

First, assume the loop control variable is "i", and try and write each one of these as a loop body that uses the variable "i" to make the pattern. Next, add the "for i in (...):" syntax on top by figuring out how many times / what values of "i" the loop should run.

Solutions

<source lang="python">

  1. Replace text in a formula.
  2. A B C

def substitute_str(fmt, vals): # substitute_str : str -> [str] -> str

   out = fmt
   n = 0
   for i in ["A1", "B1", "C1", "A2", "B2", "C2", "A3", "B3", "C3"]:
       out = out.replace(i, vals[n])
       n = n + 1
   return out

print substitute_str("A1 + C1*C2", vals)

  1. Increment items in a list.

def sow_list_6(fed, n): # sow_list : [int] -> int -> [int]

   out = fed[:] # copy all elements of fed by slicing all of them
   for i in range(n):
       out[5-i] = out[5-i] + 1
   return out
  1. Increment items in a list (advanced).

def sow_list(ABC, fed, start, n): # [int] -> [int] -> int -> int -> ([int], [int], int)

   ABC = ABC[:] # copy ABC
   fed = fed[:] # copy fed
   for i in range(n):
       pos = (start + i) % 12 # use mod to get an index in the circular
                                       # range 0, 1, 2, 3, ..., 10, 11, 0, 1, 2
       if pos < 6: # positions 0, 1, ..., 5 are ABC
           ABC[pos] = ABC[pos] + 1
       else: # positions 6, 7, ..., 11 map to fed 5, 4, ..., 0
           fed[5-(pos-6)] = fed[5-(pos-6)] + 1
   return ABC, fed, pos
  1. Append a line to a string.

def print_atoms(a): # print_atoms : float -> str

   out = "Atomic coordinates (in Angstrom)\n"
   for i in range(len(a)): # loop over all items in a
       if len(a) > i: # This test is no longer needed.  Do you see why?
           out = out + "%f %f %f\n"%(a[i][0], a[i][1], a[i][2])
   return out
  1. Iterate the linear congruential "random" number generator.

x = [1] # start with a `seed' value for i in range(5): # generate 5 numbers

   x.append(x[i]*62 % 900)

</source>