
# gaussian.py
# gaussian elimination

def gaussian(arr):
  n = len(arr)
  xs = [0]*n

  for z in range(n-1):  # looking at row z
    # partial pivot
    maxVal = 0
    # look down column z for largest value, and save row value
    for r in range(z, n):
      if abs(arr[r][z]) > maxVal:
        maxRow = r 
        maxVal = abs(arr[r][z])
    if maxRow != z:
      # exchange z and maxRow rows
      arr[maxRow], arr[z] = arr[z], arr[maxRow]

    # reduce all later rows
    for r in range(z+1, n):
      pivot = arr[r][z]/arr[z][z]
      for s in range(z+1, n+1): 
        arr[r][s] -= pivot*arr[z][s]
        # subtract from all values on row
  
  # back substitution; work up the rows
  for r in range(n-1, -1, -1):
    pivot = arr[r][n]
    if r != n-1:
      for s in range(r+1, n):
        pivot -= arr[r][s]*xs[s]
    xs[r] = pivot/arr[r][r]

  return xs


if __name__ == "__main__":
  from reader import *

  fnm = input("fnm? ")
  arr = readFloat2D(readVals(fnm))
  for row in arr:
    print(*row)
  print()
  
  xs = gaussian(arr)
  for r in range(len(xs)):
    print(f"xs[{r}] = {xs[r]:.4f}")
