How to delete double quotation mark from ruby array? - ruby

Based on the link
I tried to delete "" in the array on ruby
However still not get what I want, if anyone knows, please advice me
a = gets
lines = []
aaa = []
b = []
bb =[]
while line = gets do
lines << line.chomp.split(' ')
end
for k in 0..(lines.size - 1) do
b << lines[k][1].to_i + 1
end
for i in 0..(lines.size - 1)do
bb << lines[i][0] + ' ' + b[i].to_s
end
for l in 0..(lines.size - 1)do
p bb[l]
end
Input
3
Tanaka 18
Sato 50
Suzuki 120
Output
[["Tanaka", "18"], ["Sato", "50"], ["Suzuki", "120"]]
"Tanaka 19"
"Tanaka 19"
"Sato 51"
"Suzuki 121"

As pointed out in the comments, you can get rid of the quotation marks by replacing p (Ruby's inspect/print) with puts.
While we're at it, you can make this much more "Ruby-ish" by using .readlines to scoop up all the input into an array, and by replacing the multiple counting loops with .map or .each iterators. The following is more concise, and allows you to lose the first input line which you're just throwing away anyway.
lines = STDIN.readlines(chomp: true).map do |line|
l = line.split(' ')
[l[0], l[1].to_i + 1].join(' ')
# or
# "#{l[0]} #{l[1].to_i + 1}"
end
lines.each { |line| puts line }
With Ruby 3, you can use rightward-assignment for the first part if you find it more readable:
STDIN.readlines(chomp: true).map do |line|
l = line.split(' ')
"#{l[0]} #{l[1].to_i + 1}"
end => lines

Related

Simplify similar loops into one

I am writing a braille converter. I have this method to handle the top line of a braille character:
def top(input)
braille = ""
#output_first = ""
#top.each do |k, v|
input.chars.map do |val|
if k.include?(val)
braille = val
braille = braille.gsub(val, v)
#output_first = #output_first + braille
end
end
end
#output_first
end
I'm repeating the same each loop for the middle and bottom lines of a character. The only thing that is different from the method above is that the #top is replaced with #mid and #bottom to correspond to the respective lines.
Trying to figure a way to simplify the each loop so I can call it on top, mid and bottom lines.
You can put the loop in a separate method.
def top(input)
#output_first = handle_line(#top)
end
def handle_line(line)
result = ''
line.each do |k, v|
input.chars.map do |val|
if k.include?(val)
braille = val
braille = braille.gsub(val, v)
result = result + braille
end
end
end
result
end
You can then call handle_line in your #mid and #bottom processing
I'm not sure whats in the #top var but I believe braille has limited number of characters and therefore I would consider some map structure
BRAILLE_MAP = {
'a' => ['..',' .','. '], # just an example top,mid,bot line for character
'b' => ['..','..',' '],
# ... whole map
}
def lines(input)
top = '' # representation of each line
mid = ''
bot = ''
input.each_char do |c|
representation = BRAILLE_MAP[c]
next unless representation # handle invalid char
top << representation[0] # add representation to each line
mid << representation[1]
bot << representation[2]
end
[top,mid,bot] # return the lines
end
There may be better way to handle those 3 variables, but I cant think of one right now

Why does Ruby convert `string.chr` values to `?`?

I want to shift the chr value of the characters in a string by a certain amount. This code:
def encrypt2(word, num)
cipher = word.split('').map{|e|
e = e.ord + num
e = e.chr
}.join.reverse
puts cipher
end
encrypt2('hellozz', 10)
outputs: ??yvvor. It seems that after 126.chr, it only returns question marks.
e = e.ord + num will produce non-ASCII characters.
You can make use the String#next method to get the next ASCII character for a given character. However, 'z'.next will be 'aa' due to the carry created, hence, in such cases one has to pick the first character of that result.
So, you could write:
num.times { e = e.next[0]}
def encrypt2(word, num)
word.chars.map {|e| num.times {e = e.next[0]}; e}.join.reverse
end
puts encrypt2('hellozz', 10)
#=> "jjyvvor"
puts encrypt2("naïve", 1)
#=> fwðbo

Transposing a string

Given a (multiline) string, where each line is separated by "\n" and may not be necessarily of the same length, what is the best way to transpose it into another string as follows? Lines shorter than the longest one should be padded with space (right padding in terms of the original, or bottom padding in terms of the output). Applying the operation on a string twice should be idempotent modulo padding.
Input string
abc
def ghi
jk lm no
Output string
adj
bek
cf
l
gm
h
in
o
Here are five approaches. (Yes, I got a bit carried away, but I find that trying to think of different ways to accomplish the same task is good exercise for the grey cells.)
#1
An uninteresting, brute-force method:
a = str.split("\n")
l = a.max_by(&:size).size
puts a.map { |b| b.ljust(l).chars }
.transpose
.map { |c| c.join.rstrip }.join("\n")
adj
bek
cf
l
gm
h
in
o
#2
This method and all that follow avoid the use of ljust and transpose, and make use of the fact that if e is an empty array, e.shift returns nil and leaves e an empty array. (Aside: I am often reaching for the non-existent method String#shift. Here it would have avoided the need to convert each line to an array of characters.)
a = str.split("\n").map(&:chars)
a.max_by(&:size).size.times.map { a.map { |e| e.shift || ' ' }.join.rstrip }
#3
This and the remaining methods avoid the need to compute the length of the longest string:
a = str.split("\n").map(&:chars)
a_empty = Array(a.size, [])
[].tap { |b| b << a.map { |e| e.shift || ' ' }.join.rstrip while a != a_empty }
#4
This method makes use of Enumerator#lazy, which has been available since v2.0.
a = str.split("\n").map(&:chars)
(0..Float::INFINITY).lazy.map do |i|
a.each { |e| e.shift } if i > 0
a.map { |e| e.first || ' ' }.join.rstrip
end.take_while { c = a.any? { |e| !e.empty? } }.to_a
(I initially had a problem getting this to work, as I was not getting the element of the output (" o"). The fix was adding the third line and changing the line that follows from a.map { |e| e.shift || ' ' }.join.rstrip to what I have now. I mention this because it seems like it may be common problem when using lazy.)
#5
Lastly, use recursion:
def recurse(a, b=[])
return b[0..-2] if a.last.empty?
b << a.map { |e| e.shift || ' ' }.join.rstrip
recurse(a, b)
end
a = str.split("\n").map(&:chars)
recurse(a)
I would write it like this:
def transpose s
lines = s.split(?\n)
longest = lines.map { |l| l.length }.max
(0..longest).map do |index|
lines.map { |l| l[index] || ' ' }.join
end * ?\n
end
This one works
s = "abc\ndef ghi\njk lm no\n"
s = s.split("\n")
s2 = ''
i = 0
while true
line = ''
s.each do |row|
line += (row[i] or ' ')
end
if line.strip == ''
break
end
s2 += line + "\n"
i += 1
end
puts s2
This one also works
s = "abc\ndef ghi\njk lm no\n"
s = s.split("\n")
maxlen = s.inject(0) {|m,r| m=[m, r.length].max}
s.map! {|r| r.ljust(maxlen).split(//)}
s = s.transpose.map {|r| r.join('')}.join("\n")
puts s
A play on what Chron did for an earlier version of ruby (e.g., 1.8.x). Example based on your original input that showed newline characters
str="abc\\n
def ghi\\n
jk lm no\\n"
def transpose s
lines = s.gsub("\\n","").split("\n")
longest = lines.map { |line| line.length }.max
(0..longest).map do |char_index|
lines.map { |line| line.split('')[char_index] || ' ' }.join
end * "\\n\n"
end
puts transpose(str)
I would write it like this:
def transpose_text(text)
# split the text into lines
text = text.split("\n")
# find the length of the longest line
max_line_length = text.map(&:size).max
# pad each line with white space and convert them to character arrays
text.map! { |line| line.ljust(max_line_length).chars }
#transpose the character arrays and then join them all into one string
text.transpose.map(&:join).join("\n")
end

Ruby Array Loop

I am currently trying to create a ruby algorithm to execute the following:
l = Array.new
Given array is text in the form of an array and has three manifests each titled Section No. 1, Section No. 2, Section No. 3 respectively.
Put the entire text in one string by looping through the array(l) and adding each line to the one big string each time.
Split the string using the split method and the key word "Section No." This will create an array with each element being one section of the text.
Loop through this new array to create files for each element.
So far I have the following:
a = l.join ''
b = Array.new
b = a.split ("Section No.")`
How would I go writing the easiest method to the third part?
Should only be about 2-3 lines.
Output would be the creation of three files each named after the manifest titles.
"Complex Version"
file_name = "Section"
section_number = "1"
new_text = File.open(file_name + section_number, 'w')
i = 0
n= 1
while i < l.length
if (l[i]!= "SECTION") and (l[i+1]!= "No")
new_text.puts l[i]
i = i + 1
else
new_text.close
section_number = (section_number.to_i +1).to_s
new_text = File.open(file_name + section_number, "w")
new_text.puts(l[i])
new_text.puts(l[i+1])
i=i+2
end
end
b.each_with_index(1) do |text, index|
File.write "section_#{index}.txt", text
end
To answer your most basic question, you could probably get away with:
sections.each_with_index do |section, index|
File.open("section_#{index}.txt", 'w') { |file| file.print section }
end
Here's an alternate solution:
input_string = "This should be your manifest string"
starting_string = "Section No."
copy_input_string = input_string.clone
sections = []
while(copy_input_string.length > 0)
index_of_next_start = copy_input_string.index(starting_string, starting_string.length) || copy_input_string.length
sections.push(copy_input_string.slice!(0...index_of_next_start))
end
sections.each_with_index do |section, index|
File.open("section_#{index}.txt", 'w') { |file| file.print section }
end
create string s by putting a space between each string in l
s = l.join ' '
split on 'Section No.' - note that 'Section No.' no longer appears in a
a = s.split('Section No.')
throw away the part before the first section
a = a[1..-1]
create the files
a.each do |section|
File.open('Section' + section.strip[0], 'w') do |file_handle|
file_handle.puts section
end
end

More concise way of inserting a character between all characters in a string

I want to insert a character at every possible index of a string, including before the first element and after the last. Right now I'm doing:
result = []
result << c + str
result << str + c
for i in 0..str.length-2 do
result << (str[0..i] + c + str[i+1..-1])
end
Is there a way of doing this without having 2 special cases and having a loop from 0 to str.length - 2
EDIT
Sample output with '-' and 'hello':
["-hello", "h-ello", "he-llo", "hel-lo", "hell-o", "hello-"]
I'll assume you want ["-hello", "h-ello", "he-llo", "hel-lo", "hell-o", "hello-"], your question is not clear.
s = "hello"
(0..s.size).map { |i| s.clone.insert(i, "-") }
#=> ["-hello", "h-ello", "he-llo", "hel-lo", "hell-o", "hello-"]
For those that prefer a functional approach (I do):
(0..s.size).map { |i| (s[0...i] + "-" + s[i..-1]) }
#=> ["-hello", "h-ello", "he-llo", "hel-lo", "hell-o", "hello-"]

Resources