How do I check for pangrams in a line in ruby? - file

Some of you may notice I'm already back with the same painful code already. I'm not sure if the other question is still open or not once I accept an answer.
Now the problem is a little simpler. I found some code that checked for pangrams. It use to be def pangram?('sentence') but I needed line to go in there so I tried changing it to def pangram?(line). It doesn't seem to mesh well with my coding style and doesn't work. I tried to use .contain('a' . . 'z') to check for a pangram but someone I know tried that and it didn't work. Also google isn't much help either.
Any ideas for how I could check for pangrams in an if stmt?
# To change this template, choose Tools | Templates
# and open the template in the editor
# This program reads a file line by line,
#separating lines by writing into certain text files.
#PPQ - Pangrams, Palindromes, and Quotes
class PPQ
def pangram?(line)
unused_letters = ('a'..'z').to_a - line.downcase.chars.to_a
unused_letters.empty?
end
def categorize
file_pangram = File.new('pangram.txt', 'w')
file_palindrome = File.new('palindrome.txt', 'w')
file_quotes = File.new('quotes.txt','w')
File.open('ruby1.txt','r') do |file|
while line = file.gets
if(line.reverse == line)
file_palindrome.write line
elsif(pangram?(line)== true)
file_pangram.write line
else
file_quotes.write line
end
end
end
file.close
file_pangram.close
file_palindrome.close
file_quotes.close
end
end
my_ruby_assignment = PPQ.new
my_ruby_assignment.categorize

I'm partial to simpler syntax, something like
def pangram?(line)
('a'..'z').all? { |word| line.downcase.include? (word) }
end
if pangram?(line) then file_pangram.write line end

def pangram?(string)
str = string.chars.map(&:downcase)
letters =('a'..'z').to_a
result = true
letters.each do |l|
if !(str.include? l.downcase)
result = false
break
end
end
result
end

Related

Less compact form

def read_file(filename):
trolls = dict()
try:
with open(filename) as file:
for line in file:
city, data = line.split(':')
for i in data.split():
trolls[city] = [int(_) for _ in data.split()]
except OSError as error:
print(f"Yeuch!: {error}")
return trolls
How can I rewrite this line:
trolls[city] = [int(_) for _ in data.split()]
in a less compact way?
In these two lines in your code
for i in data.split():
trolls[city] = [int(_) for _ in data.split()]
the for loop is uselessly repeating the work on the second line however many elements are in the list times, but the result is the same.
(in your code, the second line isn't indented but it should be, otherwise you'll just get a SyntaxError, so I assume it just didn't paste correctly and you have it indented)
I think you meant to do this
if city not in trolls:
trolls[city] = []
for i in data.split():
trolls[city].append(int(i))
or simply delete the for i in data.split(): line in your original code.

How do I get matches from a text file and output them in an array?

I'm using a text file with lines of movies. If a user inputs Oz, I want to output all the movies in the file that have the word Oz in it.
This is what I have so far.
puts "Enter the keyword you want to search for: "
keyword = gets
movies_file = File.new("movies.txt", "r")
movies = movies_file.read
movies_list = movies.split(" ")
match_list = []
movies_list.each do |w|
matchObj = w.match(keyword)
if matchObj then
matchlist.push(matchObj.captures[0])
end
end
match_list.each do |title|
puts title
end
Presuming you've got the file organized like this:
Wizard of Oz
Battlefield Earth
Twilight
Ozymandias
Then you can read it in this way:
lines = File.readlines('movies.txt').map(&:chomp)
Then to find matching lines:
matches = lines.grep(phrase)
There's no need for all the each stuff. Also the then on an if is almost never put in there, it's just useless decoration.

Array.include? myVariable not working as expected

I am coding a Ruby 1.9 script and I'm running into some issues using the .include? method with an array.
This is my whole code block:
planTypes = ['C','R','S'];
invalidPlan = true;
myPlan = '';
while invalidPlan do
print "Enter the plan type (C-Commercial, R-Residential, S-Student): ";
myPlan = gets().upcase;
if planTypes.include? myPlan
invalidPlan = false;
end
end
For troubleshooting purposes I added print statements:
while invalidPlan do
print "Enter the plan type (C-Commercial, R-Residential, S-Student): ";
myPlan = gets().upcase;
puts myPlan; # What is my input value? S
puts planTypes.include? myPlan # What is the boolean return? False
puts planTypes.include? "S" # What happens when hard coded? True
if planTypes.include? myPlan
puts "My plan is found!"; # Do I make it inside the if clause? Nope
invalidPlan = false;
end
end
Since I was getting the correct result with a hard-coded string, I tried "#{myPlan}" and myPlan.to_s. However I still get a false result.
I'm new to Ruby scripting, so I'm guessing I'm missing something obvious, but after reviewing similar question here and here, as well as checking the Ruby Doc, I'm at a loss as to way it's not acting correctly.
The result of gets includes a newline (\n), which you can see if you print myPlan.inspect:
Enter the plan type (C-Commercial, R-Residential, S-Student): C
"C\n"
Add strip to clean out the unwanted whitespace:
myPlan = gets().upcase.strip;
Enter the plan type (C-Commercial, R-Residential, S-Student): C
"C"

Class-Array Interaction Ruby

I'm trying to set up a program to help me take care of grading for students in a class. I've set it up to make a class of student then to read in from the file (something I'm not very familiar with in Ruby) via an array. My programming experience is in java so if there are errors that can be explained by that I apologize. Thank you in advance for your help.
class Student
def initialize(str_LastName, str_FirstName, arr_Score)
#str_LastName = str_LastName
#str_FirstName = str_FirstName
#arr_Score = arr_Score
str_Grade = ""
int_OutOf = 415
end
def get_LastName
str_LastName
end
def get_FirstName
str_FirstName
end
def get_Grade
str_Grade
end
def set_TotalScore()
sum = 0
arr_Score.each do |item|
sum += item
end
arr_Score[12] = sum
end
def set_Grade
if arr_Score[12]/int_OutOf >= 0.9
str_Grade = "A"
elsif arr_Score[12]/int_OutOf >= 0.8
str_Grade = "B"
elsif arr_Score[12]/int_OutOf >= 0.7
str_Grade = "C"
elsif arr_Score[12]/int_OutOf >= 0.6
str_Grade = "D"
else
str_Grade = "F"
end
end
end
def main
file_name = "Grades"
arr_students = Array.new(31)
arr_scores = Array.new(12)
int_i = 0
file_io = open(file_name).readlines.each do |line|
array = line.split(",").map(&:strip)
student = Student.new(array[0],array[1],array[2..-2]) #the final element in the array is for the final score
arr_students[int_i] = student
puts "read #{arr_students[int_i]}"
end
file_name = "Graded"
file_io = open(file_name,"a+")
arr_students.each do |student|
set_TotalScore
set_Grade
file.io_write(student)
puts "write #{student}"
end
end
main if __FILE__==$0
Here is my run at it. I tried to stay true in general to the original intent of your code while introducing more Rubyish ways of doing things.
class Student
def initialize(firstname, lastname, *scores)
#firstname, #lastname, #scores = firstname, lastname, scores
end
def total_score
#scores.map(&:to_i).inject(:+)
end
def grade
raise "TOO HIGH!" if total_score > MAX_SCORE
case total_score / MAX_SCORE
when 0.9..1.0; "A"
when 0.8...0.9; "B"
when 0.7...0.8; "C"
when 0.6...0.7; "D"
else "F"
end
end
def to_s
"#{#lastname}, #{#firstname}: #{total_score}, #{grade}"
end
end
MAX_SCORE = 415.0
DATA.each_line do |line|
arr = line.split(",").map(&:strip)
student = Student.new *arr
puts student
end
__END__
Herb,Goldberg,22,99,44,22,88,88
Mark,Sullivan,77,88,88,44,33
You can read and write to files like this(not tested):
outfile = File.open("Graded", "a+")
File.open("Grades").each_line do |line|
...
outfile.puts student
end
outfile.close
We can not easily reproduce your code because you open a file called "Grades" and we do not have or know of its content.
You should also add some code to first check whether your file exists, before continuing - right now your script exits with a Errno::ENOENT.
I would also suggest putting the logic in main into your class instead - let your class handle everything.
In the part:
if __FILE__ == $PROGRAM_NAME
end
You can then simply initialize your class with a simple call such as:
Foobar.new(ARGV)
You described the "Grades" file but I did not understand what you wrote - it would be easier if you could link in to a sample, like via a pastie or gist, then link it in; and to also say what the part is that is not working, which is also unclear.
The style issues are secondary, I consider your code ok - the other poster here does not.
You should go through codecademy to get your ruby syntax down.
To access your initialized instance variables (#str_LastName (which should be #last_name), etc) you need to use "attr_reader :str_LastName", preferably at the top of the class. That'll definite you getter (setter is attr_writer, both is attr_accessor).
You can also do a sum on an array like this: [1,4,6,7].inject(:+).
Does Java not allow case statements? You should use that in set_grade. You also don't need to initialize str_Grade. In set grade, you could do #grade_letter ||= "A", and then calling set_grade will return that value on each call.
I didn't look through your main method. It's ugly though. Ruby methods probably shouldn't be more than 5 lines long.

storing data into a file rather than returning to the terminal

i have this function: write_reversed_file(input_filename, output_filename) that writes to the given output file the contents of the given input file with the lines in reversed order. i just need the output to be written to the file (output_filename) rather than to the terminal (python shell).
the only part im missing is to store the output into the file.
i successfully managed to complete the reversing lines part.
def write_reversed_file(input_filename, output_filename):
for line in reversed(list(open(filename))):
print(line.rstrip())
def write_reversed_file(input_filename, output_filename):
s = ""
f = open(input_filename,"r")
lines = f.read().split("\n")
f.close()
for line in reversed(lines):
s+=line.rstrip()+"\n"
f = open(outPutFile.txt,"w")
f.write(s)
f.close()
It is good practice to use 'with open as' format when working with files since it is automatically closing the file for us. (as recommended in docs.python.org)
def write_reversed_file(input_filename, output_filename):
with open(output_filename, 'w') as f:
with open(input_filename, 'r') as r:
for line in reversed(list(r.read())):
f.write(line)
write_reversed_file("inputfile.txt", "outputfile.txt")

Resources