Count from list in ruby - ruby

Im thinking this is correct, but probably WAY off.
I have a string formatted as such
name, name1, name2, name3, name4, etc
admins_count = 0
if ["name2", "name3"].include?(player_list)
admins_count += 1
end
Is this the proper way to count matches in a list?
Essentially, its a list of players, I want to count how many of the names in the second list mtch against player_list.
this is what worked for me a combo of things
player_list = response[3].split(" ", 2)[1].chomp[1..-2]
admin_list = "Howard_Roark, Gerrit8500, fffizzz"
mod_list = "ZionRx, rodtang, fuzzamuzza, DJRedFlames, bingbong2715, ErebusAnima, Twentytenor2, zephyrnug, Tiberione, deadkill02, tTheoRyy, PyneApll, tercept, Hestehaven, Orjis87, Yaltar101"
mod_arr = mod_list.split(", ")
admin_arr = admin_list.split(", ")
player_arr = player_list.split(", ")
mods_count = 0
mod_arr.each do |s|
mods_count += 1 if player_arr.include? s
end
admins_count = 0
admin_arr.each do |s1|
admins_count += 1 if player_arr.include? s1
end
puts "players.value #{player_count}"
puts "mods.value #{mods_count}"
puts "admins.value #{admins_count}"

I think this is more of what you want:
formatted_string = "name,name1,name2,name3,name4";
string_arr = formatted_string.split(",")
string_arr.each do |s|
admin_count += 1 if player_list.include? s
end

If player_list is an Array, you could use the & operator. It takes two Arrays and returns a new Array of only the items the two Arrays have in common (with no duplicates).
# I'm assuming player_list becomes a string of 'name1, name2, name3...' after
# the 'chomp' method
player_list = response[3].split(" ", 2)[1].chomp[1..-2].split(",").map(&:strip)
admins_count = (["name2", "name3"] & player_list).size
So, if player_list contains "name2" then it will return ["name2"]. We then call .size on that and we would get 1 which would get assigned to admins_count.

Related

how to put a local variable(sub) in an array in ruby

if File.exist?("restaurant.txt") then
newfile=File.open("restaurant.txt","r")
lines=newfile.readlines
i=0
while i<lines.size
item=lines[i]
i+=1
quantity=lines[i].to_i
i+=1
price=lines[i].to_i
i+=1
sub=quantity*price
puts sub
end
end
I am trying to move the sub values into an array
Just create an array and push the values.
array = Array.new
if File.exist?("restaurant.txt") then
newfile = File.open("restaurant.txt","r")
lines = newfile.readlines
i=0
while i < lines.size
item = lines[i]
i += 1
quantity = lines[i].to_i
i += 1
price = lines[i].to_i
i += 1
sub = quantity*price
#puts sub
array.push(sub)
end
puts array.to_s
end
Using File#readlines, array slicing, array deconstruction, and asserting a precondition instead of using an if statement, this code can be simplified as follows:
#!/usr/bin/env ruby
FILENAME = 'restaurant.txt'
raise "#{FILENAME} does not exist" unless File.file?(FILENAME)
lines = File.readlines(FILENAME).map(&:chomp)
subs = lines.each_slice(3).map do |slice|
_item, quantity, price = slice
_item = _item.to_i # _item is unused, but this is here for completeness
quantity = quantity.to_i
price = price.to_f
quantity * price
end
p subs
Also, price, and maybe even quantity should be a floating point number and not an integer.

trouble appending hash value ruby

I'm writing a program which takes input, stores it as a hash and sorts the values.
I'm having trouble comparing a current hash value with a variable.
Sample Input:
3
A 1
B 3
C 5
A 2
B 7
C 2
Sample Output:
A 1 2
B 3 7
C 2 5
Everything works apart from this part, and I'm unsure why.
if values.key?(:keys)
if values[keys] >= val
values.store(keys,val.prepend(val + " "))
else
values.store(keys,val.concat(" " + val))
end
else
values.store(keys,val)
end
i = i + 1
end
Rest of code:
#get amount of records
size = gets.chomp
puts size
size = size.to_i
values = Hash.new(0)
i = 0
while i < (size * 2)
text = gets.chomp
#split string and remove space
keys = text.split[0]
val = text.split[1]
#check if key already exists,
# if current value is greater than new value append new value to end
# else put at beginning of current value
if values.key?(:keys)
if values[keys] >= val
values.store(keys,val.prepend(val + " "))
else
values.store(keys,val.concat(" " + val))
end
else
values.store(keys,val)
end
i = i + 1
end
#sort hash by key
values = values.sort_by { |key, value| key}
#output hash values
values.each{|key, value|
puts "#{key}:#{value}"
}
Could anyone help me out? It would be most appreciated.
The short answer is that there are two mistakes in your code. Here is the fixed version:
if values.key?(keys)
if values[keys] >= val
values.store(keys,values[keys].prepend(val + " "))
else
values.store(keys,values[keys].concat(" " + val))
end
else
values.store(keys,val)
end
The if statement was always evaluating as false, because you were looking for hash key named :keys (which is a Symbol), not the variable you've declared named keys.
Even with that fixed, there was a second hidden bug: You were storing a incorrect new hash value. val.concat(" " + val) would give you results like A 2 2, not A 1 2, since it's using the new value twice, not the original value.
With that said, you code is still very confusing to read... Your variables are size, i, text, val, values, key and keys. It would have been a lot easier to understand with clearer variable names, if nothing else :)
Here is a slightly improved version, without changing the overall structure of your code:
puts "How may variables to loop through?"
result_length = gets.chomp.to_i
result = {}
puts "Enter #{result_length * 2} key-value pairs:"
(result_length * 2).times do
input = gets.chomp
input_key = input.split[0]
input_value = input.split[1]
#check if key already exists,
# if current value is greater than new value append new value to end
# else put at beginning of current value
if result.key?(input_key)
if result[input_key] >= input_value
result[input_key] = "#{input_value} #{result[input_key]}"
else
result[input_key] = "#{result[input_key]} #{input_value}"
end
else
result[input_key] = input_value
end
end
#sort hash by key
result.sort.to_h
#output hash result
result.each{|key, value|
puts "#{key}:#{value}"
}
h = Hash.new { |h,k| h[k] = [] }
input = ['A 1', 'B 3', 'C 5', 'A 2', 'B 7', 'C 2'].join("\n")
input.each_line { |x| h[$1] << $2 if x =~ /^(.*?)\s+(.*?)$/ }
h.keys.sort.each do |k|
puts ([k] + h[k].sort).join(' ')
end
# A 1 2
# B 3 7
# C 2 5
This would be a more Ruby-ish way to write your code :
input = "A 1
B 3
C 5
A 2
B 7
C 2"
input.scan(/[A-Z]+ \d+/)
.map{ |str| str.split(' ') }
.group_by{ |letter, _| letter }
.each do |letter, pairs|
print letter
print ' '
puts pairs.map{ |_, number| number }.sort.join(' ')
end
#=>
# A 1 2
# B 3 7
# C 2 5

Ruby keeping a count from a list

I am grabbing some data from a list and I want to rank the items. There are 100 items from the list. When I run my code I get the data I am looking for but before every data I get "100" when it should be "1. ... 2. ..." Here is my code
lineList = mdoc.read.split("\n")
songList = []
count = 0
lineList.each do |line|
matchObj = line.match(/<td>(\S+.+)<\/td>/)
if matchObj then
songList.push(matchObj.captures[0])
count = count + 1
end
end
songList.each do |title|
puts count.to_s + ". " + title
end
The typical way to display a list is this:
song_list.each_with_index do |song, i|
puts '%d. %s' % [ i + 1, song ]
end
This uses the string formatting function % and each_with_index.

Count the number of vowels,pronouns in each line of string?

I need to count the number of vowels,words,pronouns("he,she,them") in each line of a string entered by user. if input is "they are playing. he is studying" the output expected is Sentence 1 has 3 words,has 4 vowels , 1 pronoun. \nSentence 2 has 3 words,4 vowels , 1 pronoun. I have written the following code but getting an error unexpected-end-of-input.
string = gets
string =string.chomp
sentencecount = 0
wordcount = 0
pronouns={"He"=>0,"She"=>0,"They"=>0,"Them"=>0}
procount=0;
string.split(".").each do |sentence|
wordcount = 0
sentencecount += 1 #tracking number of sentences
vowels=sentence.scan(/[aeoui]/).count
procount=0
sentence.split(/\w+/).each do |word|
pronouns.each do|key,value|
if (key.eq word)
procount++
wordcount += 1 # tracking number of words
end
puts "Sentence #{sentencecount} has #{wordcount} words, has #{vowels} vowels"
end
you don't need semicolon at the end of the lines
if requires an end (unless it's the inline form)
++ operator doesn't exist in Ruby
you compare two strings with the == operator (it's a method actually)
string = gets.chomp
sentencecount = 0
wordcount = 0
pronouns = {"He"=>0, "She"=>0, "They"=>0, "Them"=>0}
procount = 0
string.split(".").each do |sentence|
wordcount = 0
sentencecount += 1 #tracking number of sentences
vowels = sentence.scan(/[aeoui]/).count
procount = 0
sentence.split(/\w+/).each do |word|
pronouns.each do|key, value|
if key == word
procount += 1
end
wordcount += 1 # tracking number of words
end
end
puts "Sentence #{sentencecount} has #{wordcount} words, has #{vowels} vowels"
end
Based off of your initial attempt, I've optimized it slightly and make it more readable in terms of code.
string = gets.chomp
pronouns = ['he', 'she', 'they', 'them']
total_word_count = 0
total_procount = 0
total_vowel_count = 0
sentences = string.split(".")
total_sentence_count = sentences.size
sentences.each_with_index do |sentence, idx|
# VOWELS
vowel_count = sentence.scan(/[aeoui]/).count
total_vowel_count += vowel_count
# WORDS
words = sentence.split
sentence_word_count = words.size
total_word_count += sentence_word_count
# PRONOUNS
sentence_procount = 0
words.each do |word|
sentence_procount += 1 if pronouns.include?(word.downcase)
end
total_procount += sentence_procount
puts "Sentence #{idx + 1} has #{sentence_word_count} words, has #{vowel_count} vowels"
end
puts "Input has #{total_sentence_count} sentences, #{total_word_count} words, #{total_vowel_count} vowels, and #{total_procount} pronouns"
I suggest you return an array of hashes, one for each line, each hash containing statistics for the associated line. You can then do what you want with the information in that array.
VOWELS = 'aeiou'
PRONOUNS = %w| he she they them |
#=> ["he", "she", "they", "them"]
PRONOUN_REGEX = /\b#{Regexp.union(PRONOUNS)}\b/
#=> /\b(?-mix:he|she|they|them)\b/
def count_em(str)
str.downcase.split(/\n/).map { |line|
{ vowels: line.count(VOWELS),
words: line.scan(/[[:lower:]]+/).count,
pronouns: line.scan(PRONOUN_REGEX).size } }
end
a = count_em "He thought that she thought that he did not know the truth\n" +
"René knew she would torment them until they went bananas\n"
#=> [{:vowels=>14, :words=>12, :pronouns=>3},
# {:vowels=>15, :words=>10, :pronouns=>3}]
a.each.with_index(1) { |h,i|
puts "In line #{i} there are %d vowels, %d words and %d pronouns" %
h.values_at(:vowels, :words, :pronouns) }
# In line 1 there are 14 vowels, 12 words and 3 pronouns
# In line 2 there are 15 vowels, 10 words and 3 pronouns
puts "The total number of vowels in all lines is %d" %
a.map { |h| h[:vowels] }.reduce(:+)
# The total number of vowels in all lines is 29
This solution is incomplete in that it doesn't deal with contractions ("don't"), possessives ("Mary's"), abbreviations ("1st"), initials and numeric parts of names ("J. Philip ('Phil') Sousa III") and other twists of the English language.

How to input integer value to an array, based preceeding row + column values? [duplicate]

This question already has an answer here:
How to input integer value to an array, based preceeding row + column values? [duplicate]
(1 answer)
Closed 8 years ago.
For this following project, I am supposed to take input in the following format : R1C5+2 , which reads it as "in the table, Row 1 Column 5 ,add 2. Or in this format : R1C2C3-5 , which reads : "in the table, Row 1 Column 2-3, subtract 5. This is assuming that all numbers in the table are initially all 0.
Where I left Off:
I am having trouble finding a way to detect for a "+" or "-" to either add/subtract values in the table. Also, in providing a range to allow multiple additions when provided two C's or R's. For example: R1R5C2C3+2 (Row Range 1 - 5, Column Range 2 - 3, add 2).
Here is the following code:
puts 'Please input: '
x = gets.chomp
col = []
row = []
x.chars.each_slice(2) { |u| u[0] == "R" ? row << u[1] : col << u[1] }
p col
p row
puts "Largest # in Row array: #{row.max}"
puts "Largest # in Columns array: #{col.max}" #must be in "" to return value
big_row = row.max.to_i
big_col = col.max.to_i
table = Array.new (big_row) { Array.new(big_col) }
I thank you all for the help!
You've accidentally posted this twice. Here is the answer I gave on the other copy:
The method you are looking for is the =~ operator. If you use it on a string and give it a regexp pattern it will return the location of that pattern in the string. Thus:
x = 'R1C2C3-5'
x =~ /R/
returns: 0 since that is the position of 'R' in the string (counted just like an array 0,1,2...).
If you are unfamiliar with regexp and the =~ operator, I suggest you check out the Ruby doc on it, it is very valuable. Basically the pattern between the forward slashes get matched. You are looking to match + or -, but they have special meaning in regexp, so you have to escape them with a backslash.
x =~ /\+/
x =~ /\-/
but you can combine those into one pattern matcher with an OR symbol (pipe) |
x =~ /\+|\-/
So now you have a method to get the operator:
def operator(my_string)
r = my_string.slice(my_string =~ /\+|\-/)
end
I would also use the operator to split your string into the column/row part and the numeric part:
op = operator(x) # which returns op = '-'
arr = x.split(my_string(x)) # which returns an array of two strings ['R1C2C3', '5']
I leave further string manipulation up to you. I would read through this page on the String class: Ruby String Class and this on arrays: Ruby Array Class as Ruby contains so many methods to make things like this easier. One thing I've learned to do with Ruby is think "I want to do this, I wonder if there is already a built in method to do this?" and I go check the docs. Even more so with Rails!
Your homework, sir.
puts 'Please input: '
x = gets.chomp
col = []
row = []
sign = ''
val = ''
x.chars.each_slice(2) do |u|
case u[0]
when 'R' then
row << u[1]
when 'C' then
col << u[1]
when '+', '-'
sign, val = u[0], u[1]
else
puts 'Invalid input.'
exit
end
end
big_row = row.max.to_i
big_col = col.max.to_i
table = Array.new (big_row) { Array.new(big_col) }
# Initialize table to all zeros
table.map! do |row|
row.map! { |col| 0 }
end
rows_range = row.length == 1 ? row[0]..row[0] : row[0]..row[1]
cols_range = col.length == 1 ? col[0]..col[0] : col[0]..col[1]
table.each_with_index do |row, ri|
if rows_range.include? (ri + 1).to_s
row.each_with_index do |col, ci|
if cols_range.include? (ci + 1).to_s
table[ri][ci] = (sign + val).to_i
end
end
end
end
# Padding for fields in table.
padding = 4
# Table
table.each do |row|
row.each do |col|
print "#{col.to_s.rjust(padding)}"
end
print "\n"
end

Resources