Skip to content

Instantly share code, notes, and snippets.

@mikerourke
Last active October 27, 2020 20:54
Show Gist options
  • Save mikerourke/bd63da404055fe2f28aa07f9fcdbb4d8 to your computer and use it in GitHub Desktop.
Save mikerourke/bd63da404055fe2f28aa07f9fcdbb4d8 to your computer and use it in GitHub Desktop.
Fortran Blog Post
program debt_prioritizer
implicit none
type debtor
character(len=:), allocatable :: name
integer :: debt
end type debtor
! Ugh! Global variables!?
! Originally, I was passing the "debtors" and "debtor_count"
! variables as parameters to all the subroutines and functions.
type(debtor), dimension(:), allocatable :: debtors
integer :: debtor_count = 0
call assign_values_to_globals()
call prioritize_debt()
contains
! Assigns values to the global variables declared at the start of the
! program.
subroutine assign_values_to_globals()
call assign_debtor_count(debtor_count)
allocate(debtors(debtor_count))
call assign_debtors()
end subroutine assign_values_to_globals
! Loops through the file to determine how many people owe money.
! I know this seems stupid to open the file twice, but I
! couldn't find a way to dynamically allocate items to an array
! that I could actually understand.
subroutine assign_debtor_count(debtor_count)
integer :: debtor_count, read_status, sum_of_lines = 0
! Open the input data file for reading:
open(10, file = "input.txt", status = "old", action = "read")
! Loop through each line in the file to get a running count:
do
! The "iostat" is used for error handling. If there's nothing to
! read, it throws an error (which is just a number other than 0).
! We don't want it to throw an error though, because it just hit
! the end of the file.
read(10, *, iostat = read_status)
if (read_status /= 0) exit
sum_of_lines = (sum_of_lines + 1)
end do
! If you don't do this, you end up with a crazy big number:
close(10)
debtor_count = sum_of_lines
end subroutine assign_debtor_count
! Opens the input file, loops through the records, and populates the
! debtors array with the name and debt of the corresponding debtor.
subroutine assign_debtors()
character(50) :: line, name
integer :: read_status, debt, line_number = 1
! Open the input data file for reading:
open(10, file = "input.txt", status = "old", action = "read")
! Loop through each line in the file to get the name and debt:
do
read(10, "(A)", iostat = read_status) line
! Exit the loop at the end of the file:
if (read_status /= 0) exit
! Populate the name and debt variables with the value
! from the input file:
call get_name_and_debt(line, name, debt)
debtors(line_number)%name = name
debtors(line_number)%debt = debt
! There needs to be an iterator to assign to each debtor:
line_number = (line_number + 1)
end do
close(10)
end subroutine assign_debtors
! Once the debtors are loaded into the array and their debt is calculated,
! this reorders them descending by debt (so whoever owes the
! most money is right at the top of the list). Once that's done, the
! debtors are written to a CSV file for easy parsing!
subroutine prioritize_debt()
call sort_descending_by_debt()
call write_debtors_to_file()
print *, "Done!"
end subroutine prioritize_debt
! Splits the value of the line into the person's name and their
! corresponding debt.
subroutine get_name_and_debt(line, name, debt)
! The name and debt in the input file are separated by a pipe:
character(1) :: DELIM = "|"
character(50) :: line, name, debt_string
integer :: debt, index
! Get rid of any whitespace at the end of the line:
line = trim(line)
! Get the position of the pipe character:
index = scan(line, DELIM)
! Pull the name from the line, essentially this grabs the line value
! from the first character of the line to where the pipe character was
! found in the "scan" function above:
name = line(1 : index - 1)
! Pull the debt from the line, this just grabs the line value from the
! first character after the pipe until the end of the line:
debt_string = line(index + 1 : )
! Convert the debt to a number. Character strings are
! considered to be "internal files" in Fortran.
! See https://www.eng-tips.com/viewthread.cfm?qid=37205
read(debt_string, '(I5)') debt
end subroutine get_name_and_debt
! This is a ridiculously inefficient bubble sort. It loops through each
! record, and within that loop it does another loop The higher debt
! amount is moved before the lower debt amount. This has to be done for
! each record, which is why there are 2 loops.
subroutine sort_descending_by_debt()
integer :: base_index, compare_index
! This loop starts at the beginning of the list and iterates by 1:
do base_index = 1, debtor_count
! This loops through each record in the file (starting from the
! bottom of the list), looks at the value of the debt, and either
! leaves it in it's current position (if lower than the parent
! value) or moves it after the parent value:
do compare_index = debtor_count, (base_index + 1), -1
call swap(debtors(compare_index - 1), debtors(compare_index))
end do
end do
end subroutine sort_descending_by_debt
! Given two debtors, this reorders them descending by debt level. If the
! larger debt value is on the left side, it doesn't do anything.
subroutine swap(left_debtor, right_debtor)
type(debtor) :: left_debtor, right_debtor, temp
if (left_debtor%debt < right_debtor%debt) then
temp = right_debtor
right_debtor = left_debtor
left_debtor = temp
end if
end subroutine swap
! If the CSV file "output.csv" doesn't already exist, it creates it in the
! same directory where you compiled the program. Once the file exists, it
! writes each debtor to the file.
subroutine write_debtors_to_file()
character(len=:), allocatable :: name_trimmed
integer :: debtor_number
print *, "Creating the output file..."
open(20, file = "output.csv", action = "write")
! This just writes the first line headers so when you copy it into
! your spreadsheet software, you know what the columns represent:
write (20, "(A)") "Name,Debt"
do i = 1, debtor_count
! Get rid of any extra whitespace in the name:
name_trimmed = trim(debtors(i)%name)
print *, debtors(i)%debt
! Write the name and debt (separated by a comma) to the output file:
write (20, 2000) name_trimmed, ",", debtors(i)%debt
2000 format (A, A1, I5)
end do
close(20)
end subroutine write_debtors_to_file
end program debt_prioritizer
Vivian Larson|5458
Geraldine Gibson|9207
Violet Price|9745
Hilda Cohen|6835
Aurora Cooke|6463
Xyla Buck|6613
Cynthia Boone|5324
Gavin Russell|7419
Macey Guerra|6840
Chava Riley|7560
Cullen Sweeney|8156
Juliet Tate|8165
Latifah Cruz|7644
Murphy Hurst|9111
Moses Mccullough|7610
Cora Fowler|9864
Eaton Mcleod|6362
Cailin Day|6087
Aiko Mcconnell|8973
Hadley Finley|6365
Germaine Frost|5493
Kasper Michael|9897
Karyn Powers|6116
Kaitlin Flores|5452
Noel Carter|8507
Uriel Malone|8858
Dorian Leblanc|6067
Stuart Velazquez|6331
Gray Short|7475
Robin Kidd|9952
Charde Gould|8891
Burton Pace|6303
Nolan Carroll|7281
Iliana May|5394
Jemima Mcleod|9849
Britanni Fox|6977
Quintessa Medina|7487
William Levine|7455
Raven Cline|8283
Laura Mcleod|8112
Maile Bender|9466
Cecilia Jacobs|8880
Rigel Glover|6103
Jemima Hicks|6340
Zenaida Hernandez|7805
Taylor Boone|7903
Karen Greer|9100
Sonya Gutierrez|9362
Hope Chavez|7528
Penelope Bruce|5913
Juliet Simpson|7941
Jordan Thomas|6787
Kaitlin Clemons|9153
Harlan Holmes|9713
Byron Bruce|7589
Tatyana Barlow|6634
Jack Vinson|5186
Lael Jacobs|6404
Cade Torres|5912
Prescott Pratt|8818
Clinton Preston|8566
Eric Benson|6643
Quentin Dickson|5094
Quinn Buckley|5393
Peter Osborne|9609
Yvonne Brady|6522
Britanni House|5209
Mollie Wilkins|8641
Abbot Levine|6946
Kermit Mason|9265
Alden Burton|8833
Leigh Mccarthy|5827
Camilla Knox|6294
Sebastian Meyer|9540
Yuri Orr|6439
Dana Hamilton|6283
Dale Byrd|7308
Clarke Davenport|6025
Tiger Ball|7977
Kirk Sutton|6377
Briar Joseph|9827
Cailin Forbes|9618
Jolene Lucas|8298
Chava Chapman|7734
Kendall Noel|6634
Joelle Dillon|5445
Kevin Stephens|5321
Adena Hicks|6999
Stephanie Robinson|5302
Damian Snyder|7827
Tiger Cummings|5317
Colorado Irwin|9379
Ainsley Lynn|6267
Madison Trevino|9624
Lara Mcclure|7267
Hyatt Bailey|5752
Allegra Spence|9736
Kiara Jarvis|5591
Ignatius Martinez|7784
Griffin Hernandez|5046
Reagan Hebert|8326
Brent Aguirre|7258
Mason Wallace|8317
Willow Slater|5811
Katell Blake|9912
Shea Bowers|6002
Germaine Preston|8446
Zenia Hood|5401
Lois Sullivan|5505
Stewart Stein|7980
Odessa Ochoa|5677
Vera Bridges|6021
Whoopi Trevino|6544
TaShya Kane|7068
Jessica Snyder|6005
Fuller Sawyer|6544
Rafael Mason|7123
Miranda Lawrence|9441
Belle Meadows|5640
Kameko Atkins|5541
Philip Maldonado|6669
Kelly Garcia|7895
Guinevere Vang|5186
Shelly Huber|5249
Camilla Parrish|5649
Orli Cruz|8340
Neil Little|9715
Clark Matthews|6308
Allegra Garrison|6794
Martha Nelson|6244
Allegra Sherman|6536
Bryar Blevins|9412
Bo Davis|6928
Cheyenne Harmon|7016
Hadley Shaffer|6666
Fletcher Cooper|5799
Jason Scott|6288
Cade Wade|6009
Indira Poole|9814
Darius Lott|9193
Griffith Cherry|8623
Ulysses Meyers|7187
Lavinia Pickett|6813
Fatima Olson|7514
Abel Mccoy|5044
Fritz Lindsay|5941
Kameko Bartlett|7659
Hedwig Potts|5598
Shellie Ford|8867
Conan Peterson|7243
Joelle Daniels|9162
Dahlia Whitley|8846
Fritz Morrow|9178
Alika Melendez|9180
Todd French|9919
Carol Marshall|7270
Gannon Goff|9672
Orla Travis|5880
Maggy Tran|5488
Nomlanga Trevino|8328
Xavier Valencia|5278
Deacon Browning|6567
Merrill Sexton|6224
Paula Phillips|6805
Barclay Vang|6928
Jeremy Hull|9969
Nero Mercer|6568
Bertha Wooten|6251
Dean Mcfarland|5765
Brock Contreras|9212
Ella Blanchard|6069
Portia Holden|9001
Sebastian Russell|5123
Leo Nieves|7009
Harrison Rocha|6395
Hanae Goodman|7924
Ishmael Guy|8235
Breanna Knox|5174
Kylee Miranda|6824
Hadassah Mcpherson|9566
Vielka Cole|7238
Ashton Hatfield|8251
Hedda Reyes|5310
Dieter Sexton|5109
Lois Neal|8250
Allen Sanchez|9658
Christopher Hayden|6162
Caryn Delaney|8435
Eric Savage|6916
Wang Cooper|7518
Lacey Harvey|7535
Edward Frederick|6628
Quin Rocha|5464
Dane Snyder|6875
Jana Noel|5303
Heather Emerson|6247
Audra Rodgers|9548
Althea Church|7357
Shelly Moses|8397
Ursa Pratt|6427
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment