Last active
October 27, 2020 20:54
-
-
Save mikerourke/bd63da404055fe2f28aa07f9fcdbb4d8 to your computer and use it in GitHub Desktop.
Fortran Blog Post
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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