How to input m values in n times(n lines) by Ruby? - ruby

I have some Ruby exercises and i have problem with inputs.
I want to know how to input M values in 1 lines with space between 2 values,
and do N lines like that.
Have anyone can help me? Please!

If you want to get an user input then you could consider using gets, this way:
# a stores what the user introduces, in this case "a b c"
a = gets.chomp
# => "a b c"
If for instance you want to allow the user to enter many values, separated by a whitespace or any other, then you can use split, like in:
# in this case split without arguments takes the input as string, and divides it within every whitespace ang gives you them in an array.
a = gets.chomp.split
=> ["a", "b", "c"]
Then you already have the way to get the user input for M values in 1 lines with space between 2 values. If you'd like to repeat this, then you could use times, specifying the amount of times you want this be done, i.e:
# This will store what the user introduces, splitted as before, and each array will be inside a "main" array.
# If for instance the input is 1 2 3 the first time, a b c the second time, then you get
a = 2.times.map do
gets.chomp.split
end
p a
# => [["1", "2", "3"], ["a", "b", "c"]]

Related

Ruby split a long string of characters into actual words

I've got an array of strings which contains 2 elements: first is a sequence of characters and the second will be a long string of comma-separated words, in alphabetical order that represents dictionary of some arbitrary length. Now I want to check if from the list of words of the second element I can create the word of the first element in the array.
Below example will better illustrate what I mean:
string_array = ["baseball", "a,all,b,ball,bas,base,cat,code,d,e,quit,z"]
Output: base,ball
so What I did is simple method:
def word_split(string_array)
splitted_arr = string_array[1].split(',')
strArr.include?(splitted_arr)
end
but it gives me only false result. How to compare those string in array?
I made a method that takes two arguments: a word and an array of words. You can easily make a wrapper function that operates on the data structure you proposed, if you want.
def find_sequence(target, words)
return [] if target.empty?
words.each do |word|
if target.start_with?(word)
# We found a good candidate for the first word, so let's recurse
# and see if we can find the rest of the words.
remainder = target.sub(word, '') # remove word from start of target
seq = find_sequence(remainder, words)
return [word] + seq if seq
end
end
nil
end
# Example 1: your example
s = ["baseball", "a,all,b,ball,bas,base,cat,code,d,e,quit,z"]
p find_sequence(s[0], s[1].split(",")) # ["bas", "e", "b", "all"]
# Example 2: no solution
p find_sequence("foobar", ["foo", "cat"]) # nil
# Example 3: backtracking
p find_sequence("abcde", ["abcd","abc","ab","a","d","bcde"]) # ["a", "bcde"]
By the way, this is an example of a depth first search.

Ruby array interpolation

I noticed the difference in printing array with and without interpolation:
Source code:
uuu="a b c d e f g";
o=uuu.split(' ');
puts "Interpolation:#{o}";
puts "Without interpolation";
puts o;
Output:
Interpolation:["a", "b", "c", "d", "e", "f", "g"]
Without interpolation
a
b
c
d
e
f
g
I don't understand why those differences happen.
When you call puts in the main context without an explicit receiver, you are calling Kernel#puts, and that calls $stdout.puts. Usually, $stdout.puts outputs the result of applying to_s to its argument. However, array is exceptional in that each element of it is printed in a separate line. From the doc:
puts(obj, ...) → nil
Writes the given objects to ios as with IO#print. Writes a record separator (typically a newline) after any that do not already end with a newline sequence. If called with an array argument, writes each element on a new line. If called without arguments, outputs a single record separator.
In your first example, you interpolated a string with an array, which applies to_s to it, and ends up with a string of the format ["a", "b", ...], which is passed to puts. In your second example, you passed an array directly to puts, to which the exceptional behaviour on arrays explained above applies.
This doesn't really have anything to do with how interpolation behaves. It's not interpolation that's giving you a difference in output, it's that your supply a string vs an array to puts.
The same results occur if you simply do this:
puts o.to_s
puts o
puts handles strings and arrays differently. In the first instance, you're giving it a string, into which an array has been interpolated. Interpolation invokes to_s on the value being interpolated, and when you invoke to_s on an array, it gives you the format you see in your output. For example [1, 2, 3].to_s is the string "[1, 2, 3]".
When you give puts an array as its argument, it prints the items in the array, one per line.

Ruby cutting fields and saving

I'm dealing with a file that has a bunch of entries like this
2012-07-15 10:16:27 C ?\path\to a filename\ called this file.doc
I want to take a line like this and cut the first 3 fields separated by spaces.
So...
var1 = 2012-07-15
var2 = 10:16:27
var3 = c
I've googled around and I just can not seem to find the right method to use. Thank you for your help!
Ruby's String#split accepts a limit as its second parameter. This will do exactly what you're looking for:
irb(main):005:0> str = "2012-07-15 10:16:27 C ?\path\to a filename\ called this file.doc"
=> "2012-07-15 10:16:27 C ?path\to a filename called this file.doc"
irb(main):006:0> str.split " ", 4
=> ["2012-07-15", "10:16:27", "C", "?path\to a filename called this file.doc"]
You can use destructuring to assign these into local variables, if you want:
one, two, three, rest = str.split " ", 4
The split method will do what you want:
string = '2012-07-15 10:16:27 C ?\path\to a filename\ called this file.doc'
date, time, drive = string.split

Printing an array of arrays on one line in console (one line per master array object) in Ruby

I have an array of arrays that is currently printing each object in the array on its own line. The master array holds many different people inside of it. Each person has 5 different objects stored to them (e.g. Last Name, First Name, DOB.. etc)
Kournikova
Anna
F
6/3/1975
Red
Hingis
Martina
F
4/2/1979
Green
Seles
Monica
F
12/2/1973
Black
What I'm trying to do is print out each person and their corresponding objects on one line, per person.
Does anyone have a solution for this? Additionally, the output should not contain array brackets ([]) or commas. I'm wondering if it will simply need to be a string, or if there is something I am missing.
Some of my code below:
space_array = [split_space[0],split_space[1],split_space[3],new_date,split_space[5]]
master << space_array
puts master
The ideal output would be something like this:
Kournikova Anna F 6/3/1975 Red
Hingis Martina F 4/2/1979 Green
Seles Monica F 12/2/1973 Black
your_array.each do |person|
puts person.join(" ")
end
The method puts will automatically put a new line. Use print instead to print the text out with no new line.
Or if you want, you can use the join function.
['a', 'b', 'c'].join(' ')
=> 'a b c'
You can just iterate over the outer array and join the inner arrays into a string. Since you provide no example data ready for copying and pasting, here's some example code I made up:
outer_array.each { |inner| puts inner.join(' ') }
more simple:
puts your_array.join(" ")

Split string into a list, but keeping the split pattern

Currently i am splitting a string by pattern, like this:
outcome_array=the_text.split(pattern_to_split_by)
The problem is that the pattern itself that i split by, always gets omitted.
How do i get it to include the split pattern itself?
Thanks to Mark Wilkins for inpsiration, but here's a shorter bit of code for doing it:
irb(main):015:0> s = "split on the word on okay?"
=> "split on the word on okay?"
irb(main):016:0> b=[]; s.split(/(on)/).each_slice(2) { |s| b << s.join }; b
=> ["split on", " the word on", " okay?"]
or:
s.split(/(on)/).each_slice(2).map(&:join)
See below the fold for an explanation.
Here's how this works. First, we split on "on", but wrap it in parentheses to make it into a match group. When there's a match group in the regular expression passed to split, Ruby will include that group in the output:
s.split(/(on)/)
# => ["split", "on", "the word", "on", "okay?"
Now we want to join each instance of "on" with the preceding string. each_slice(2) helps by passing two elements at a time to its block. Let's just invoke each_slice(2) to see what results. Since each_slice, when invoked without a block, will return an enumerator, we'll apply to_a to the Enumerator so we can see what the Enumerator will enumerator over:
s.split(/(on)/).each_slice(2).to_a
# => [["split", "on"], ["the word", "on"], ["okay?"]]
We're getting close. Now all we have to do is join the words together. And that gets us to the full solution above. I'll unwrap it into individual lines to make it easier to follow:
b = []
s.split(/(on)/).each_slice(2) do |s|
b << s.join
end
b
# => ["split on", "the word on" "okay?"]
But there's a nifty way to eliminate the temporary b and shorten the code considerably:
s.split(/(on)/).each_slice(2).map do |a|
a.join
end
map passes each element of its input array to the block; the result of the block becomes the new element at that position in the output array. In MRI >= 1.8.7, you can shorten it even more, to the equivalent:
s.split(/(on)/).each_slice(2).map(&:join)
You could use a regular expression assertion to locate the split point without consuming any of the input. Below uses a positive look-behind assertion to split just after 'on':
s = "split on the word on okay?"
s.split(/(?<=on)/)
=> ["split on", " the word on", " okay?"]
Or a positive look-ahead to split just before 'on':
s = "split on the word on okay?"
s.split(/(?=on)/)
=> ["split ", "on the word ", "on okay?"]
With something like this, you might want to make sure 'on' was not part of a larger word (like 'assertion'), and also remove whitespace at the split:
"don't split on assertion".split(/(?<=\bon\b)\s*/)
=> ["don't split on", "assertion"]
If you use a pattern with groups, it will return the pattern in the results as well:
irb(main):007:0> "split it here and here okay".split(/ (here) /)
=> ["split it", "here", "and", "here", "okay"]
Edit The additional information indicated that the goal is to include the item on which it was split with one of the halves of the split items. I would think there is a simple way to do that, but I don't know it and haven't had time today to play with it. So in the absence of the clever solution, the following is one way to brute force it. Use the split method as described above to include the split items in the array. Then iterate through the array and combine every second entry (which by definition is the split value) with the previous entry.
s = "split on the word on and include on with previous"
a = s.split(/(on)/)
# iterate through and combine adjacent items together and store
# results in a second array
b = []
a.each_index{ |i|
b << a[i] if i.even?
b[b.length - 1] += a[i] if i.odd?
}
print b
Results in this:
["split on", " the word on", " and include on", " with previous"]

Resources