How to stop JBehave from trimming multiline parameters? - bdd

I have a step where I need to check certain message. I used a multi-line parameter:
Then I see welcome message: 'Welcome to our site!
Some more text
Even more text'
Problem is that message should have spaces at the end of first and second lines (IDK why, but it should). And JBehave trims spaces from each line. So test fails.
How can I set it not to trim this parameter?
I've tried writing \n instead of actual line-breaks, but it wasn't replaced with line-breaks
Also tried adding {trim=false} in the beginning of parameter, but it reads it as part of the parameter.
Made some experiments with quotation marks (used ", ', none), it didn't help either...

I have tested that and it seems that JBehave actually truncates spaces at the end of the test:
When some step with multitline parameter:first line has 10 spaces at the end
Second line has 6 spaces at the end
Third line has no spaces at the end, but fourth line has 8 spaces
Fifth line has 3 spaces, and Sixth line has only 7 spaces
#When("some step with multitline parameter:$lines")
public void stepWithMultilneString(String s) {
String lines [] = s.split("\\r?\\n");
for(int i = 0; i < lines.length; i++) {
System.out.format("Line %d is: >>%s<<\n", i+1, lines[i]);
}
}
Line 1 is: >>first line has 10 spaces at the end <<
Line 2 is: >>Second line has 6 spaces at the end <<
Line 3 is: >>Third line has no spaces at the end, but fourth line has 8 spaces<<
Line 4 is: >> <<
Line 5 is: >>Fifth line has 3 spaces, and Sixth line has only 7 spaces<<
When some step with multitline parameter:first line has 10 spaces at the end
Second line has 6 spaces at the end
Third line has no spaces at the end, but fourth line has 8 spaces
Fifth line has 3 spaces, and Sixth line has only 7 spaces
I suggest a bypass - a step with delimiters ! at the beginning and end of the text:
When step with multitline parameter surrounded by !:!first line has 10 spaces at the end
Second line has 6 spaces at the end
Third line has no spaces at the end, but fourth line has 8 spaces
Fifth line has 3 spaces, and Sixth line has only 7 spaces
!
#When("step with multitline parameter surrounded by !:$string")
public void stepWithMultilneStringVersion2(String s) {
if( s.startsWith("!")) {
s = s.substring(1);
}
if( s.endsWith("!")) {
s = s.substring(0, s.length()-1);
}
String lines [] = s.split("\\r?\\n");
for(int i = 0; i < lines.length; i++) {
System.out.format("Line %d is: >>%s<<\n", i+1, lines[i]);
}
}
Line 1 is: >>first line has 10 spaces at the end <<
Line 2 is: >>Second line has 6 spaces at the end <<
Line 3 is: >>Third line has no spaces at the end, but fourth line has 8 spaces<<
Line 4 is: >> <<
Line 5 is: >>Fifth line has 3 spaces, and Sixth line has only 7 spaces <<
Line 6 is: >> <<
When step with multitline parameter surrounded by !:!first line has 10 spaces at the end
Second line has 6 spaces at the end
Third line has no spaces at the end, but fourth line has 8 spaces
Fifth line has 3 spaces, and Sixth line has only 7 spaces
!

Related

Generating star pattern in LUA

I am new to programming in LUA. And I am not able to solve this question below.
Given a number N, generate a star pattern such that on the first line there are N stars and on the subsequent lines the number of stars decreases by 1.
The pattern generated should have N rows. In every row, every fifth star (*) is replaced with a hash (#). Every row should have the required number of stars (*) and hash (#) symbols.
Sample input and output, where the first line is the number of test cases
This is what I tried.. And I am not able to move further
function generatePattern()
n = tonumber(io.read())
i = n
while(i >= 1)
do
j = 1
while(j<=i)
do
if(j<=i)
then
if(j%5 == 0)
then
print("#");
else
print("*");
end
print(" ");
end
j = j+1;
end
print("\n");
i = i-1;
end
end
tc = tonumber(io.read())
for i=1,tc
do
generatePattern()
end
First, just the stars without hashes. This part is easy:
local function pattern(n)
for i=n,1,-1 do
print(string.rep("*", i))
end
end
To replace each 5th asterisk with a hash, you can extend the expression with the following substitution:
local function pattern(n)
for i=n,1,-1 do
print((string.rep("*", i):gsub("(%*%*%*%*)%*", "%1#")))
end
end
The asterisks in the pattern need to be escaped with a %, since * holds special meaning within Lua patterns.
Note that string.gsub returns 2 values, but they can be truncated to one value by adding an extra set of parentheses, leading to the somewhat awkward-looking form print((..)).
Depending on Lua version the metamethod __index holding rep for repeats...
--- Lua 5.3
n=10
asterisk='*'
print(asterisk:rep(n))
-- puts out: **********
#! /usr/bin/env lua
for n = arg[1], 1, -1 do
local char = ''
while #char < n do
if #char %5 == 4 then char = char ..'#'
else char = char ..'*'
end -- mod 5
end -- #char
print( char )
end -- arg[1]
chmod +x asterisk.lua
./asterisk.lua 15
Please do not follow this answer since it is bad coding style! I would delete it but SO won't let me. See comment and other answers for better solutions.
My Lua print adds newlines to each printout, therefore I concatenate each character in a string and print the concatenated string out afterwards.
function generatePattern()
n = tonumber(io.read())
i = n
while(i >= 1)
do
ouput = ""
j = 1
while(j<=i)
do
if(j%5 == 0)
then
ouput=ouput .. "#";
else
ouput=ouput .. "*";
end
j = j+1;
end
print(ouput);
i = i-1;
end
end
Also this code is just yours minimal transformed to give the correct output. There are plenty of different ways to solve the task, some are faster or more intuitive than others.

Read file text and store in array 2d

I have a file text "a.txt" :
1 2 3
4 5 6
7 8 9
Now i want store it in array 2d :
array ={ {1,2,3}{4,5,6}{7,8,9} }
I have try to :
array ={}
file = io.open("a.txt","r")
io.input(file)
i=0
for line in io.lines() do
array[i]=line
i=i+1
end
But it doesn't success.
Does anyone suggest me a way to do it?
You have some errors in your code. You first open the file a.txt and then set it for standard input. You don't need the open(). But i recommend to open the file and operate on it, using the lines() iterator on the file:
array = {}
file = io.open("a.txt","r")
i = 0
for line in file:lines() do
array[i]=line
i=i+1
end
Furthermore, with your method, you don't get the array you wished for ({ {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }) but instead an array containing strings as elements:
{ "1 2 3", "4 5 6", "7 8 9" }.
To get the latter, you have to parse the string you have read. An easy way to do this is to use string.match with captures:
array ={}
file = io.open("a.txt","r")
for line in file:lines() do
-- extract exactly three integers:
local t = { string.match(line, "(%d+) (%d+) (%d+)")) }
table.insert(array, t) -- append row
end
See https://www.lua.org/manual/5.3/manual.html#pdf-string.match. For a arbitrary number of integers (or other numbers) on every line, you can use a loop together with string.gmatch():
array ={}
file = io.open("a.txt","r")
for line in file:lines() do
local t = {}
for num in string.gmatch(line, "(%d+)") do
table.insert(t, num)
end
table.insert(array, t)
end

Using Regex and ruby regular expressions to find values

So I'm currently trying to sort values from a file. I'm stuck on the finding the first attribute, and am not sure why. I'm new to regex and ruby so I'm not sure how to go about the problem. I'm trying to find values of a,b,c,d,e where they are all positive numbers.
Here's what the line will look like
length=<a> begin=(<b>,<c>) end=(<d>,<e>)
Here's what I'm using to find the values
current_line = file.gets
if current_line == nil then return end
while current_line = file.gets do
if line =~ /length=<(\d+)> begin=((\d+),(\d+)) end=((\d+),(\d+))/
length, begin_x, begin_y, end_x, end_y = $1, $2, $3, $4, $5
puts("length:" + length.to_s + " begin:" + begin_x.to_s + "," + begin_y.to_s + " end:" + end_x.to_s + "," + end_y.to_s)
end
end
for some reason it never prints anything out, so I'm assuming it never finds a match
Sample input
length=4 begin=(0,0) end=(3,0)
A line with 0-4 decimals after 2 integers seperated by commas.
So it could be any of these:
2 4 1.3434324,3.543243,4.525324
1 2
18 3.3213,9.3233,1.12231,2.5435
7 9 2.2,1.899990
0 3 2.323
Here is your regex:
r = /length=<(\d+)> begin=((\d+),(\d+)) end=((\d+),(\d+))/
str.scan(r)
#=> nil
First, we need to escape the parenthesis:
r = /length=<(\d+)> begin=\((\d+),(\d+)\) end=\((\d+),(\d+)\)/
Next, add the missing < and > after "begin" and "end".
r = /length=<(\d+)> begin=\(<(\d+)>,<(\d+)>\) end=\(<(\d+)>,<(\d+)>\)/
Now let's try it:
str = "length=<4779> begin=(<21>,<47>) end=(<356>,<17>)"
but first, let's set the mood
str.scan(r)
#=> [["4779", "21", "47", "356", "17"]]
Success!
Lastly (though probably not necessary), we might replace the single spaces with \s+, which permits one or more spaces:
r = /length=<(\d+)>\s+begin=\(<(\d+)>,<(\d+)>\)\send=\(<(\d+)>,<(\d+)>\)/
Addendum
The OP has asked how this would be modified if some of the numeric values were floats. I do not understand precisely what has been requested, but the following could be modified as required. I've assumed all the numbers are non-negative. I've also illustrated one way to "build" a regex, using Regexp#new.
s1 = '<(\d+(?:\.\d+)?)>' # note single parens
#=> "<(\\d+(?:\\.\\d+)?)>"
s2 = "=\\(#{s1},#{s1}\\)"
#=> "=\\(<(\\d+(?:\\.\\d+)?)>,<(\\d+(?:\\.\\d+)?)>\\)"
r = Regexp.new("length=#{s1} begin#{s2} end#{s2}")
#=> /length=<(\d+(?:\.\d+)?)> begin=\(<(\d+(?:\.\d+)?)>,<(\d+(?:\.\d+)?)>\) end=\(<(\d+(?:\.\d+)?)>,<(\d+(?:\.\d+)?)>\)/
str = "length=<47.79> begin=(<21>,<4.7>) end=(<0.356>,<17.999>)"
str.scan(r)
#=> [["47.79", "21", "4.7", "0.356", "17.999"]]
Sample input:
length=4 begin=(0,0) end=(3,0)
data.txt:
length=3 begin=(0,0) end=(3,0)
length=4 begin=(0,1) end=(0,5)
length=2 begin=(1,3) end=(1,5)
Try this:
require 'pp'
Line = Struct.new(
:length,
:begin_x,
:begin_y,
:end_x,
:end_y,
)
lines = []
IO.foreach('data.txt') do |line|
numbers = []
line.scan(/\d+/) do |match|
numbers << match.to_i
end
lines << Line.new(*numbers)
end
pp lines
puts lines[-1].begin_x
--output:--
[#<struct Line length=3, begin_x=0, begin_y=0, end_x=3, end_y=0>,
#<struct Line length=4, begin_x=0, begin_y=1, end_x=0, end_y=5>,
#<struct Line length=2, begin_x=1, begin_y=3, end_x=1, end_y=5>]
1
With this data.txt:
2 4 1.3434324,3.543243,4.525324
1 2
18 3.3213,9.3233,1.12231,2.5435
7 9 2.2,1.899990
0 3 2.323
Try this:
require 'pp'
data = []
IO.foreach('data.txt') do |line|
pieces = line.split
csv_numbers = pieces[-1]
next if not csv_numbers.index('.') #skip the case where there are no floats on a line
floats = csv_numbers.split(',')
data << floats.map(&:to_f)
end
pp data
--output:--
[[1.3434324, 3.543243, 4.525324],
[3.3213, 9.3233, 1.12231, 2.5435],
[2.2, 1.89999],
[2.323]]

Print lines from readline() without double spacing

I'm trying to print the top 10 lines of a file. single spaced. without spaces at the end
What can i change so that the output is single spaced instead of double spaced?
thanks
so far I've got:
with open('1.txt') as f:
i = 1
while i <= 10:
line = f.readline()
print line
i = i+1
f.close()
and i get an out put of:
1
2
3
4
5
6
7
8
9
10
easiest fix is to put a comma on the end of the print statement:
change
print line
to
print line,
You can simply use str.rstrip('\n') to do this. rstrip trims a trailing character, which in this case would be \n (newline character).
with open('1.txt') as f:
i = 1
while i <= 10:
line = f.readline().rstrip('\n')
print line
i = i+1
f.close()

How to generate random lines of text of a given length from a dictionary of words (bin-packing problem)?

I need to generate three lines of text (essentially jibberish) that are each 60 characters long, including a hard return at the end of each line. The lines are generated from a dictionary of words of various lengths (typically 1-8 characters). No word may be used more than once, and words must be separated by spaces. I think this is essentially a bin-packing problem.
The approach I've taken so far is to create a hashMap of the words, grouped by their lengths. I then choose a random length, pull a word of that length from the map, and append it to the end of the line I'm currently generating, accounting for spaces or a hard return. It works about half the time, but the other half of the time I'm getting stuck in an infinite loop and my program crashes.
One problem I'm running into is this: as I add random words to the lines, groups of words of a given length may become depleted. This is because there are not necessarily the same number of words of each length in the dictionary, e.g., there may only be one word with a length of 1. So, I might need a word of a given length, but there are no longer any words of that length available.
Below is a summary of what I have so far. I'm working in ActionScript, but would appreciate insight into this problem in any language. Many thanks in advance.
dictionary // map of words with word lengths as keys and arrays of corresponding words as values
lengths // array of word lengths, sorted numerically
min = lengths[0] // minimum word length
max = lengths[lengths.length - 1] // maximum word length
line = ""
while ( line.length < 60 ) {
len = lengths[round( rand() * ( lengths.length - 1 ) )]
if ( dictionary[len] != null && dictionary[len].length > 0 ) {
diff = 60 - line.length // number of characters needed to complete the line
if ( line.length + len + 1 == 60 ) {
// this word will complete the line exactly
line += dictionary[len].splice(0, 1) + "\n"
}
else if ( min + max + 2 >= diff ) {
// find the two word lengths that will complete the line
// ==> this is where I'm having trouble
}
else if ( line.length + len + 1 < 60 - max ) {
// this word will fit safely, so just add it
line += dictionary[len].splice(0, 1) + " "
}
if ( dictionary[len].length == 0 ) {
// delete any empty arrays and update min and max lengths accordingly
dictionary[len] = null
delete dictionary[len]
i = lengths.indexOf( len )
if ( i >= 0 ) {
// words of this length have been depleted, so
// update lengths array to ensure that next random
// length is valid
lengths.splice( i, 1 )
}
if ( lengths.indexOf( min ) == -1 ) {
// update the min
min = lengths[0]
}
if ( lengths.indexOf( max ) == -1 ) {
// update the max
max = lengths[lengths.length - 1]
}
}
}
}
You should think of an n-letter word as being n+1 letters, because each word has either a space or return after it.
Since all your words are at least 2 characters long, you don't ever want to get to a point where you have 59 characters filled in. If you get to 57, you need to pick something that is 2 letters plus the return. If you get to 58, you need a 1-letter word plus the return.
Are you trying to optimize for time? Can you have the same word multiple times? Multiple times in one line? Does it matter if your words are not uniformly distributed, e.g. a lot of lines contain "a" or "I" because those are the only one-letter words in English?
Here's the basic idea. For each line, start choosing word lengths, and keep track of the word lengths and total character count so far. As you get toward the end of the line, choose word lengths less than the number of characters you have left. (e.g. if you have 5 characters left, choose words in the range of 2-5 characters, counting the space.) If you get to 57 characters, pick a 3-letter word (counting return). If you get to 58 characters, pick a 2-letter word (counting return.)
If you want, you can shuffle the word lengths at this point, so all your lines don't end with short words. Then for each word length, pick a word of that length and plug it in.
dictionnary = Group your words by lengths (like you already do)
total_length = 0
phrase = ""
while (total_length < 60){
random_length = generate_random_number(1,8)
if (total_length + random_length > 60)
{
random_length = 60 - total_length // possibly - 1 if you cound \n and -2 if you
// append a blank anyway at the end
}
phrase += dictionnary.get_random_word_of_length(random_length) + " "
total_length += random_length + 1
}

Resources