Creating functions (Liberty Basic) - arrays

EDIT:
Ok I got how arrays work and that part seems to work. Im still having a problem with the functions. I do not understand how functions work correctly. I need to put something in the ( ) obviously but I dont understand what. You can see I have
search=findmonth()
Im not sure if that is even a good code to use I then have it where it calls up the function but of course because I dont know how to do functions it doesnt work. If someone can explain how functions work that would be great. All the information I have makes it really confusing and doesnt show real examples that explain anything.
This is the assingment, put it in code just so its smaller
Create two arrays
1. Monthname$(12) This array contains month names such as “January”, “February”, etc
2. MilesDriven(12) ‘ This array contains the miles driven for the month.
Notice that the MonthNames$(12) array is a string array while MilesDriven(12) is numeric array.
• Write a program to display the menu with the following options and ask for the user input.
Type P to populate miles and month name.
Type S to search for Month.
Type M to search for Month name with smallest Miles
Type L to search for MonthName with Largest Miles
Type E to exit.
• • If the user types P.
o Populate all the arrays.
• • If the user types S then:
o Ask the user for the Month Name.
o Search the array for that Month Name and find its position in the Monthname array.
o Display the MonthName$, and MilesDriven at the position found during the above search.
• • If the user types M then:
o Search the array for the smallest miles in MilesDriven array and find its position.
o Display the MonthName$, and MilesDriven at the position found during the above search.
• • If the user types L then:
o Search the array for the largest Miles in MilesDriven array and find its position.
o Display the MonthName$, and MilesDriven at the position found during the above search.
• If the user types E. then:
o Terminate the program.
• If the user types any other option:
o Display the message “Invalid Choice. Try again” and go back and display the menu.
PS: You program must keep displaying the menu until the user types the option E, to exit the program."
This is the code I have so far.
Dim MonthNames$(12)
MonthNames$(1) = "January"
MonthNames$(2) = "Febuary"
MonthNames$(3) = "March"
MonthNames$(4) = "April"
MonthNames$(5) = "May"
MonthNames$(6) = "June"
MonthNames$(7) = "July"
MonthNames$(8) = "August"
MonthNames$(9) = "September"
MonthNames$(10) = "October"
MonthNames$(11) = "November"
MonthNames$(12) = "December"
Dim MilesDriven(12)
Search=Findmonth()
E=0
While E = 0
Print "Press P to populate miles and month name"
Print "Press S to search for Month"
Print "Press M to search for Month name with smallest Miles"
Print "Press L to search for MonthName with Largest Miles"
Print "Press E to exit"
Input Answer$
Select Case Answer$
Case "P", "p"
For position = 1 to 12
Print "Enter the amount of miles driven in "; MonthNames$(position)
Input MilesDriven(position)
Next
Case "S", "s"
Function Findmonth()
Print “Please enter a month you want to search for”
Input Month$
For position = 1 to 12
If (Month$ = MonthName$(position)) then
Print "You have driven "; MilesDriven(position); " "; "in the month of " MonthNames$(position)
Exit for
End if
Next
If (position > 12) then
Print “Please enter a valid month”
End if
End function
Case "M", "m"
Case "L", "l"
Case "E", "e"
E=1
Case Else
Print "You made a wrong selection. Please enter again"
End Select
Wend
For position = 1 to 12
Print MonthNames$(position)
Print MilesDriven(position)
Next
Print "Goodbye"
End

There is no need to populate the miles into the month array, rather you have two arrays side by side, such that Monthnames$(i) is the month name and MilesDriven(i) is the miles for that month.
Note that, reading your assignment's instructions, this "populating" should only happen when the user types "P", so move the initialising of your arrays into your Select statement like this:
Dim Monthnames$(12)
Dim MilesDriven(12)
E = 0
While E = 0
Print "Press P to populate miles and month name"
Print "Press S to search for Month"
Print "Press M to search for Month name with smallest Miles"
Print "Press L to search for MonthName with Largest Miles"
Print "Press E to exit"
Input Answer$
Select Case Answer$
Case "P", "p"
Monthnames$(1) = "January"
Monthnames$(2) = "February"
Monthnames$(3) = "March"
Monthnames$(4) = "April"
Monthnames$(5) = "May"
Monthnames$(6) = "June"
Monthnames$(7) = "July"
Monthnames$(8) = "August"
Monthnames$(9) = "September"
Monthnames$(10) = "October"
Monthnames$(11) = "November"
Monthnames$(12) = "December"
MilesDriven(1) = 10
MilesDriven(2) = 20
MilesDriven(3) = 30
MilesDriven(4) = 40
MilesDriven(5) = 50
MilesDriven(6) = 60
MilesDriven(7) = 70
MilesDriven(8) = 80
MilesDriven(9) = 90
MilesDriven(10) = 100
MilesDriven(11) = 110
MilesDriven(12) = 120
Case "S", "s"
Rem - put search by name here
Case "M", "m"
Rem - put search by for smallest miles here
Case "L", "l"
Rem - put search by for largest miles here
Case "E", "e"
E=1
Case Else
Print "You made a wrong selection. Please enter again"
End Select
Wend
Print "Goodbye"
End

Related

Python 3 Input: Text file manipulation requiring loops, splitting, string indexing and 'r', 'w' , 'r+'

I am a beginner with python and I am unsure what I should be searching for with regards to my assignment. I am trying to find a way to manipulate a text file to the output format required.
The question is as follows:
"Write a program that reads the data from the text file called ‘DOB.txt’ and prints it out in two different sections."
DOB text file reads (Name, Surname and DOB per line):
Orville Wright 21 July 1988
Rogelio Holloway 13 September 1988
Marjorie Figueroa 9 October 1988
Debra Garner 7 February 1988
Tiffany Peters 25 July 1988
Hugh Foster 2 June 1988
Darren Christensen 21 January 1988
Shelia Harrison 28 July 1988
Ignacio James 12 September 1988
Jerry Keller 30 February 1988
Pseudo code as follows:
Read the file DOB.txt
create a loop that will go over the contents being read from the File
display every line being read ( this will have the name and the DOB of the
students)
Use string indexing to get the first name and the 2nd name
assign this to a variable and print the first name and surname
For example something like this first_name = name[0] + name[1]
Keep in mind the name is the iterator that will be looping over the file we
are reading too.
DO the same to the DOB ( use string indexing to get the DOB of the student )
Counter for numbering each name
counter for numbering each surname
open file for reading
store contents of file in the form of lines
loop through contents
split each line into words
access the word and charcaters using indexing
Expected results are as per below:
Name:
Orville Wright
Rogelio Holloway
Marjorie Figueroa
Debra Garner
Tiffany Peters
Birth Date:
21 July 1988
13 September 1988
9 October 1988
7 February 1988
25 July 1988
Not sure if I fully understood what your assignment wants from you but what I got is:
You need to parse over this file's lines
with open('dob.txt') as dob:
for row in dob:
#print(row) would show you you're actually printing the file's rows
You'll probably want to split the words in this row to a list. I named the list 'rowstrings'
with open('dob.txt') as dob:
for row in dob:
rowstrings = row.split()
If you try printing the 'rowstring' list's elements you'd see that on every line name and surname elements are at this list positions 0 and 1, and the DOB elements are at positions 2, 3 and 4.
with open('dob.txt') as dob:
for row in dob:
rowstrings = row.split()
name = rowstrings[0] + " " + rowstrings[1]
birthdate = rowstrings[3] + " " + rowstrings[2] + " " + rowstrings[4]
To have the counters I'd simply create the variables outside the loop and do this:
namecounter = 0
surnamecounter = 0
with open('dob.txt') as dob:
for row in dob:
rowstrings = row.split()
name = rowstrings[0] + " " + rowstrings[1]
birthdate = rowstrings[3] + " " + rowstrings[2] + " " + rowstrings[4]
namecounter += 1
surnamecounter += 1
To print the name and birthdate of all rows in your file the print statement needs to be inside the for loop.
namecounter = 0
surnamecounter = 0
with open('dob.txt') as dob:
for row in dob:
rowstrings = row.split()
name = rowstrings[0] + " " + rowstrings[1]
birthdate = rowstrings[3] + " " + rowstrings[2] + " " + rowstrings[4]
namecounter += 1
surnamecounter += 1
print("Name\n" + name + "\n\n" + "Birth date\n" + birthdate)
Since it looks like you want to first print the names and then print the birth dates you could create two empty lists and fill in one of these lists with the names and the other with the birth dates. You could then loop over the lists.
namelist = []
birthlist = []
namecounter = 0
surnamecounter = 0
with open('dob.txt') as dob:
for row in dob:
rowstrings = row.split()
name = rowstrings[0] + " " + rowstrings[1]
birthdate = rowstrings[3] + " " + rowstrings[2] + " " + rowstrings[4]
namecounter += 1
surnamecounter += 1
namelist.append(name) #adds the string to the list
birthlist.append(birthdate)
for row in namelist: #prints each name in the namelist
print(row)
for row in birthlist: #prints each birthdate in the birthlist
print(row)
This isn't a place to ask about your homework, especially without showing what you've done already and/or showing what errors you're having a hard time dealing with.
Some tips for the assignment:
Opening and closing files in Python.
I suggest scrolling down to the end of the section and reading about the with keyword. Example:
with open("file.txt", "r") as f:
do_something_to_file()
instead of :
f = open("file.txt", "r")
do_something_to_file()
f.close()
Splitting strings. Since you're reading the whole line as a string from a text file, you'll need to split it into first names, surname, DOB, etc. Definition of str.split() from the PyDocs. split() returns a list of the elements, separated by the character you passed, defaults to whitespace.
>>> string = "hello world"
>>> string.split()
['hello', 'world']
You can also specify a maximum number of elements to be split from the string. To set a maximum of 3 elements:
>>> string = "Today was a good day"
>>> string.split(" ", 2)
['Today', 'was', 'a good day']
You don't need to store a counter for something as simple as what you describe in the question. When iterating over the list of names to print, you can use enumerate. enumerate returns an object containing each of the elements of the iterable (in your case a list) you pass it, along with a count, starting from 0 by default. Example:
>>> word_list = string.split(" ", 2)
>>> for i, word in enumerate(word_list, 1):
... print(f"{i}. {word}")
...
1. Today
2. was
3. a good day
I would suggest adding code into your question by editing it. You can see examples of how to format your question here.
Good luck in your assignment.

Redacting one array with modified instances of another

Hello I have a problem that I am trying to solve.
Define a method called clean_slate that will take a String representing a record and another String representing a name as arguments. The method returns a string representing the original record, but with every instance of the name replaced with twice as many X's as the name contains characters. If a full name is passed, it will also replace instances where only the first or last name is used with as many X's as the full name contains characters. Your method should not be case sensitive. Assume that the inputs will always be a String. Return the original record if the name isn't found.
So far I have:
def clean_slate(record, name)
name = name.downcase
split_name = name.downcase.split(" ") #array
change_name = split_name.map do |letter|
letter = "X" * 2 * name.length
end
record_words = record.downcase.split(" ") #array
new_record = record_words.map do |word|
if word.include?(split_name[0] || split_name[1])
word = change_name
else
word
end
end
new_record.join(" ")
end
clean_slate("Megan Fox is a talented actress. megan knows sulfoxide is a chemical compound containing a sulfinyl (SO) functional group attached to two carbon atoms. It is a polar functional group. Ms. fox has many talents.", "Megan Fox")
I am returning the record but I am not getting the last name in the record redacted. Does anyone have any idea how I can fix that?
"XXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXX fox is a talented actress. XXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXX knows sulfoxide is a chemical compound containing a sulfinyl (so) functional group attached to two carbon atoms. it is a polar functional group. ms. fox has many talents."
Within your record.split.map you need to check if the record.downcase being passed include the first or last value for split, but at the same time to check if the word in the block is equal to any of those two, so it would be something like:
new_record = record.split.map do |word|
if record.downcase.include?(split_name[0] || split_name[1]) &&
word.downcase == split_name[0] || word.downcase == split_name[1]
...
Also if you use map over split_name to assign the amount of X, it'll return an array, and when you do word = change_name, it takes the value inside an array, as ['XXXXX'] (e.g), so you need to access the only one value inside:
word = change_name.first
As it's not needed to initialize a variable not being used inside the block, then just change_name.first.
This way, this works:
def clean_slate(record, name)
name = name.downcase
split_name = name.downcase.split(" ")
change_name = split_name.map do |letter|
letter = 'X' * 2 * name.length
end
new_record = record.split.map do |word|
if record.downcase.include?(split_name[0] || split_name[1]) &&
word.downcase == split_name[0] || word.downcase == split_name[1]
change_name.first
else
word
end
end
new_record.join(" ")
end
But it has some things you can improve:
split(" ") can be shortened as split
letter = 'X' * 2 * name.length can be 'XX' * name.length and
change_name = 'XX' * name.length no need to use map, so
change_name.first changes to change_name
join(" ") prefer single quotes instead double ones
You need a way to simplify the if statement inside the record.map and still you don't know if the name will be only two words to use [0] and [-1].
You could take a look to String#gsub.
def clean_slate(record, name)
record.gsub(/\b#{name.split.join('|')}\b/i, 'XX' * name.size)
end
Here's a cleaner way to implement this. Just compare each word in record to name and substitute the Xs.
def clean_slate record, name
names = name.downcase.split
new_record = []
record.split.each do |word|
new_record << word
if names.include?(word.downcase)
new_record[-1] = "X" * 2 * name.length
end
end
new_record.join(' ')
end
Result:
XXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXX is a talented actress. XXXXXXXXXXXXXXXXXX knows sulfoxide is a chemical compound containing a sulfinyl (SO) functional group attached to two carbon atoms. It is a polar functional group. Ms. XXXXXXXXXXXXXXXXXX has many talents.
If I understand your task right, I think you can do solution similar to it:
def clean_slate(record, name)
name = name.split.map(&:downcase)
record = record.split
record.map do |word|
if name.include? word.downcase
word = 'X' * 2 * name.join.length
else
word
end
end.join(' ')
end
#> clean_slate("Megan Fox is a talented actress. megan knows sulfoxide is a chemical compound containing a sulfinyl (SO) functional group attached to two carbon atoms. It is a polar functional group. Ms. fox has many talents.", "Megan Fox")
#=> "XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX is a talented actress. XXXXXXXXXXXXXXXX knows sulfoxide is a chemical compound containing a sulfinyl (SO) functional group attached to two carbon atoms. It is a polar functional group. Ms. XXXXXXXXXXXXXXXX has many talents."

Return 4 nearest postcodes from array with Geokit?

Continuing from where I've left off, I want to limit the number of postcodes (only select up to x, but for now, say 4).
point_a = Geokit::Geocoders::GoogleGeocoder.geocode "se18 7hp"
alpha = ["cr0 3rl", "W2 1AA", "abc 234", "aol 765", "wv1 111"]
miles = alpha.map do |m| point_a.distance_to(m) end
#=> an array of numbers in miles
The answer to return the nearest postcode was with: alpha[miles.index(miles.min)]
I am trying to return the nearest 4:
alpha[miles.index(miles[0..3].min)] # surely not possible
The question is, how to return an array of the nearest 4 postcodes?
You can use sort_by:
alpha.sort_by{|m| point_a.distance_to(m)}.take(4)
Or with Ruby 2.2.0+, min_by with argument :
alpha.min_by(4){|m| point_a.distance_to(m)}

Giving users a certain amount of tries until program exits

I'm creating a method where the user puts in a "PIN" number to access different methods.. Yes it's an ATM..
I'm trying to figure out how to make it so that the user gets a specific amount of tries until the program exit's..
After a bunch of research I haven't very well found anything useful.. The only thing I've found is to use .to_s.split(//) in order to add the number of the try into an empty array. Which doesn't make sense to me because why would you make an integer into a string..?
So my question is, how do you make it so that users only have a certain amount of tries, 3, until they get kicked out of the program?
Main source:
#!/usr/bin/env ruby
################
#ATM Rewrite
#
#Creator Lost Bam Not completed yet.
#
#11/19/15
##################
require_relative 'checking.rb'
require_relative 'savings.rb'
require_relative 'exit.rb'
require_relative 'loan.rb'
require_relative 'transfer.rb'
require_relative 'redirect.rb'
class ATM
attr_accessor :name, :checking_account, :savings_account, :pin_number, :transfer, :loan
def initialize( name, checking_account, savings_account )
#name = name
#checking_account = checking_account
#savings_account = savings_account
#pin_number = pin_number
end
end
##############
def pin
x = []
puts "Enter PIN Number:"
input = gets.chomp.to_i
if input == 1234
menu
else
x += 1.to_s.split(//) #<= This is what I found to convert integer to Array
puts "Invalid PIN, try again:"
input = gets.chomp
if x == 3
bad_pin
end
end
end
############
def menu #add #{name} on line 41
puts <<-END.gsub(/^\s*>/, ' ')
>
>Welcome thank you for choosing Bank of Bam.
>You may choose from the list below of what you would like to do
>For checking inquiries press '1'
>For savings account information press '2'
>To transfer funds press '3'
>To either apply for a loan, or get information on a loan press '4'
>To exit the system press '5'
>
END
input = gets.chomp
case input.to_i
when 1
checking_information
when 2
savings_information
when 3
transfer_funds
when 4
loan_info
when 5
exit_screen
else
puts "Invalid option please try again"
menu
end
end
def bad_pin
abort('Invalid PIN exiting sytem..')
exit
end
pin
Tried something new:
def pin
x = 3
puts "Enter PIN(#{x} attempts left):"
pin_num = gets.chomp
case pin_num.to_i
when 1234
menu
else
puts "Invalid PIN"
x -=1
return pin
if x == 0
bad_pin
end
end
end
It doesn't increment the number down it just keeps saying 3 tries left:
Enter PIN(3 attempts left):
4567
Invalid PIN
Enter PIN(3 attempts left):
45345
Invalid PIN
Enter PIN(3 attempts left):
6456
Invalid PIN
Enter PIN(3 attempts left):
4564
Invalid PIN
Your problem is that every time you recall the method the value of x resets again. You need to have a loop inside the pin method that'll keep track of attempts.
def pin
x = 3
while (x > 0) do
puts "Enter PIN(#{x} attempts left):"
pin_num = gets.chomp
case pin_num.to_i
when 1234
menu
else
puts "Invalid PIN"
x -=1
puts "no tries left" if x == 0
break if x == 0
end
end
end
Stay in the method. Recalling the method starts you back at three attempts.

Displaying full array in Liberty BASIC

Going through a tutorial but I cannot figure out how to do this. It wants me to have the program display all 10 names previously entered after the quit sub. I've experimented with some stuff but cannot figure out how to do this.
'ARRAYS.BAS
'List handling with arrays
dim names$(10) 'set up our array to contain 10 items
[askForName] 'ask for a name
input "Please give me your name ?"; yourName$
if yourName$ = "" then print "No name entered." : goto [quit]
index = 0
[insertLoop]
'check to see if index points to an unused item in the array
if names$(index) = "" then names$(index) = yourName$ : goto [nameAdded]
index = index + 1 'add 1 to index
if index < 10 then [insertLoop] 'loop back until we have counted to 10
'There weren't any available slots, inform user
print "All ten name slots already used!"
goto [quit]
[nameAdded] 'Notify the name add was successful
print yourName$; " has been added to the list."
goto [askForName]
[quit]
end
Insert this code between [quit] and end:
for I = 0 TO 10
print names$(I)
next I
That'll work ;)

Resources