Why do these 2 for looping over sequences differ? - raku

First:
$ raku -e "for 1...6, 7...15 { .say }"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Now:
$ raku -e "for 1...3, 7...15 { .say }"
1
2
3
7
11
15
I would expect this case to print 1,2,3,7,8,... 15.
What's happening here?

I think you might want the raku Range operator .. (two dots) and not the raku Sequence operator ... (three dots).
Here's how you examples look with the Range operator instead:
> raku -e 'for 1..6, 7..15 { .say }'
1..6
7..15
Oh, that's not good ... looks like for is just iterating over the two things 1..6 and 7..15 and stringifying them.
We can use a Slip | to fix that:
> raku -e 'for |(1..6), |(7..15) { .say }'
1
2
... (all the numbers)
14
15
And then:
raku -e 'for |(1..3), |(7..15) { .say }'
1
2
3
7
8
9
10
11
12
13
14
15
With the Sequence operator, you have made something like:
>raku -e 'for 3,7...15 { .say }'
3
7
11
15
That is raku for "make a sequence that starts with 3, then 7, then all the values until you get to the last at 15" ... and since the gap from 3 to 7 is 4, raku will count up in steps of 4. Then you began it with 1..3. ;-)
~p6steve

It's because it is two deductive sequences.
1...3
Is obviously a sequence where you add 1 to each successive value.
1, 2, 3
And since 7 is 4 more than 3, this is a sequence where you add 4 to each successive value.
3, 7 ... 15
3, 7, 11, 15
To get what you want, you could use a flattened Range.
1...3, |(7..15)
Or even a flattened Sequence.
1...3, |(7...15)

TL;DR This answer focuses on addressing what you originally asked (which was about "sequences") and precisely what the code you wrote is doing, rather than providing a solution (using ranges instead).
This is a work in progress dealing with something that seems both poorly documented and hard to fathom (which may explain part though not all of the doc situation). Please bear with me! (And I may just end up deleting this answer.)
1 ... 3, 7 ... 15 ≡ 1 ... (3, 7) ... 15
In the absence of parentheses, operators within an expression are applied according to rules of "precedence" and "associativity".
Infix , has a higher precedence than infix ....¹ The above two lines of code thus produce the same result (1␤2␤3␤7␤11␤15␤):
for 1 ... 3, 7 ... 15 { .say } # Operator evaluation by precedence
for 1 ... (3, 7) ... 15 { .say } # Operator evaluation by parentheses
That said, while the result is what, given a glance at the code, I would expect based on my own "magical" DWIM ("Do What I Mean") thinking, I must say I don't yet know what the precise Raku(do)'s rule(s) are that lead to it DWIMing.
The doc for infix ... says:
If the endpoint is not *, it's smartmatched against each generated element and the sequence is terminated when the smartmatch succeeded.
But that seems overly simple. What if the endpoint of one sequence is another sequence? (As, at least taking a naive view, appears to be the case in your code.)
Also, as #MustafaAydin has noted:
how does your post explain the irregular last step size (of 2) instead of 3? I mean 4, 7 ... 15 alone produces (4, 7, 10, 13). But 1... 4, 7...15 now produces 7, 10, 13, 15 in the tail. Why is 15 included? Maybe i'm missing something idk
I'm at least as confused as Mustafa.
Indeed, I'm confused about several things. How come Raku(do) flattens the two sequences? [D'oh. Because the infix comma is higher precedence than the infix ....] Why doesn't it repeat the 3 in the final combined list? [Perhaps because multiple infix ...s are smart about what to do when there's an expression that's the endpoint of one sequence and the start of another?]
I'm going to go read the old design docs and/or spelunk roast and/or the Rakudo compiler code to see if I can see what's supposedly/actually going on. But not tonight.
Footnotes
¹ There's a table of operators in the current official operator doc. Supposedly this table:
summarizes the precedence levels offered by Raku, listing them in order from high to low precedence.
Unfortunately, at the time of writing this, the central operator table in the Operators page is profoundly wrong #4071.
Until that's fixed, here are "official" and "unofficial" options for determining the precedence of operators:
"official" Use in page search to search the official doc operator page for the operator of interest. Skip to the match in the entries on the left hand side of that same page. As you'll see, infix ,' is one level higher precedence than infix ...`:
Comma operator precedence
infix ,
infix :
List infix precedence
infix Z
infix X
infix ...
"unofficial" Look at the corresponding page of a staging site for an improved doc site. (I don't know how up to date it is, but the central table appears to list operators by precedence order as it claims.)

Related

Boundary Value Analysis - When to use two value or three value?

I had a few questions regarding boundary value analysis that I was hoping someone could help me with. I am learning this for a university exam based off of the ISTQB spec, not for real world application at the moment.
The first is - when should you assume to use two and three value methods of BVA? Is there any actual distinction as to when you should use one or the other, or does it depend on the specific question asked (in terms of an examination) and I would simply need to just know how to use both? Is there a default method to use?
Secondly, consider this possible question:
A smart home app measures the average temperature in the
house and provides feedback to the occupants for different
average temperature ranges:
• Up to 10 C – Icy cool!
• 11 C to 15 C - Chilled out!
• 16 C to 19 C - Cool man!
• 20 C to 22 C –Too warm!
• Above 22 C - Hot and Sweaty!
Apply 3 point BVA to the above temperature ranges. How many test cases would you consider?
The answer that was provided was that:
For 10 - we would test 9, 10, 11.
For 11 - we would test 10 (already tested), 11 (already tested), 12
For 16 - we would test 15, 16, 17
For 20 - we would test 19, 20, 21
For 22 - we would test 21 (already tested), 22, 23
This would result in a a total of 12 test cases.
Can somebody please explain to me as to why we would test the upper boundary in the first partition (10 degrees), but not the upper boundaries in other valid partitions (such as 15, which would lead to us testing 14,15,16 or 19 leading to testing 18,19,20). Is this because the boundary of 10 is the only boundary within that partition, as the lower boundary is open?
As a follow on, assume that the boundaries were instead:
• 0 C to 10 C – Icy cool!
• 11 C to 15 C - Chilled out!
• 16 C to 19 C - Cool man!
• 20 C to 22 C –Too warm!
• 23 - 40 C - Hot and Sweaty!
Would the values that are tested then change to the below? Would we still need to test the upper boundary in the first partition, or would we now ignore this as we have a lower boundary value?
For the lower invalid partition -2, -1, 0
For the first valid partition: -1, 0, 1
For the second valid partition: 10, 11, 12
For the third valid partition: 15, 16, 17
For the fourth valid partition: 19, 20, 21
For the fifth valid partition: 22, 23, 24
For the upper invalid partition: 40, 41, 42
Thank you in advance - I think I have been over complicating things in my head and wracking my brain over this!
3-value boundaries are not strictly required. E.g. in your example 9 and 10 are from the same equivalence class. Personally I'd either skip 9 completely or randomize values across the whole partition.
In your "provided answers" the division "which cases relate to which partition" is arbitrary. Is 11 a "negative" boundary for ∞-10 range or a "positive" boundary for 11-15 range? There's no right answer. In practice you'll simply write these 8 checks w/o labelling which one is for which boundary:
* 10 - Icy
* 11, 15 - Chilled out
* 16, 19 - Cool man
* 20, 22 - Too warm
* 23 - Hot and Sweaty
If you decide to go with "3-value method" and check non-boundary values for each range you'll get additional 5 cases because there are 5 ranges.
Interestingly your "provided answer" is inconsistent. Every equivalence class has non-boundary value checked except for the "Hot and Sweaty" - it should've had 24 on the list resulting in 13 cases.
Disclaimer: this is an answer of a practitioner. I haven't read ISTQB, so if you need this info to pass a test (as opposed to using it in practice) - use it with caution.
Jordan -
You have a point and I think the authors of the question you quote made a mistake. Following the ISTQB definition (CTFL 2018, Section 4.2.2): "three boundary values per boundary: the values before, at, and just over the boundary."
The problem is that almost everywhere you look, the examples given are of a single valid range, with invalid ranges on both sides ("almost everywhere" includes Jorgensen's book, "SW testing, a Craftsman's Approach", which the ISTQB syllabus quotes as reference in this case).
Following the ISTQB definition above, for EACH boundary value, you need to repeat the "before, at, and just over" analysis. For the first example, this would give you:
For 10 - we would test 9, 10, 11.
For 11 - we would test 10 (already tested), 11 (already tested), 12
For 15 - we would test 14, 15, 16
For 16 - we would test 15 (already tested), 16 (already tested), 17
For 19 - we would test 18, 19, 20
For 20 - we would test 19 (already tested), 20 (already tested), 21
For 22 - we would test 21 (already tested), 22, 23
This would result in a a total of **14** test cases.
There is one way to explain the 12 tests in the answer, and for that you need to read "The Boundary Value Fallacy" by René Tuinhout, in the Sep 2018 issue of "Testing Experience" Magazine (good luck finding it... I tried a bit but the places I found all asked me to create an account).
Following that article, the values 12, 14 and the values 17,18 can be "merged" (that is, testing with one of them is sufficient to find the type of errors that are possible in code that defines boundaries). But I will be very surprised if the writers of the question (which I understand aims at the Foundation level) were thinking of this. It is definitely an advanced topic.

Regular expression (0+1)*1(0+1)*0 DFA

I'm trying to understand the regular expression: (0+1)*1(0+1)*0 Could you provide examples that matches this pattern?
Let me explain :
1 - (0+1) mean any number of 0, then a 1
2 - (0+1)* means the previous line any number of times (can be 0)
3 - (0+1)*1 mean the previous line and a 1
4 - (0+1)*0 means line 2 and a 0
10 works : 0 times (0+1), then a 1, then 0 times (0+1), then a 0.
00000000000100000000000110 works : eleven 0 and a 1, twice (this is (0+1)*). Then, a 1. Then, no (0+1), and the last 0. A few other examples :
10
00001000010000110000100001000010
01010110
0110
I hope you understood (I'm not english, my english is bad, sorry)
EDIT : There are a lot of websites that can help you with regular expressions, whether it is learning or testing regex.

Discrete Binary Search Main Theory

I have read this: https://www.topcoder.com/community/competitive-programming/tutorials/binary-search.
I can't understand some parts==>
What we can call the main theorem states that binary search can be
used if and only if for all x in S, p(x) implies p(y) for all y > x.
This property is what we use when we discard the second half of the
search space. It is equivalent to saying that ¬p(x) implies ¬p(y) for
all y < x (the symbol ¬ denotes the logical not operator), which is
what we use when we discard the first half of the search space.
But I think this condition does not hold when we want to find an element(checking for equality only) in an array and this condition only holds when we're trying to find Inequality for example when we're searching for an element greater or equal to our target value.
Example: We are finding 5 in this array.
indexes=0 1 2 3 4 5 6 7 8
1 3 4 4 5 6 7 8 9
we define p(x)=>
if(a[x]==5) return true else return false
step one=>middle index = 8+1/2 = 9/2 = 4 ==> a[4]=5
and p(x) is correct for this and from the main theory, the result is that
p(x+1) ........ p(n) is true but its not.
So what is the problem?
We CAN use that theorem when looking for an exact value, because we
only use it when discarding one half. If we are looking for say 5,
and we find say 6 in the middle, the we can discard the upper half,
because we now know (due to the theorem) that all items in there are > 5
Also notice, that if we have a sorted sequence, and want to find any element
that satisfies an inequality, looking at the end elements is enough.

What's the equivalent in Perl 6 to star expressions in Python?

In Python 3, suppose you run a course and decide at the end of the semester that you’re going to drop the first and last homework grades, and only average the rest of them:
def drop_first_last(grades):
first, *middle, last = grades
return avg(middle)
print drop_first_last([100,68,67,66,23]);
In Perl 6:
sub drop_first_last(#grades) {
my ($first, *#middle, $last) = #grades;
return avg(#middle);
}
say drop_first_last(100,68,67,66,23);
Leads to the error "Cannot put required parameter $last after variadic parameters".
So, what's the equivalent express in Perl 6 as star expressions in Python?
sub drop_first_last(Seq() \seq, $n = 1) { seq.skip($n).head(*-$n) };
say drop_first_last( 1..10 ); # (2 3 4 5 6 7 8 9)
say drop_first_last( 1..10, 2 ); # (3 4 5 6 7 8)
The way it works: convert whatever the first argument is to a Seq, then skip $n elements, and then keep all except the last $n elements.
Perl5:
sub drop_first_last { avg( #_[ 1 .. $#_-1 ] ) } #this
sub drop_first_last { shift;pop;avg#_ } #or this
Perl6:
sub drop_first_last { avg( #_[ 1 .. #_.end-1 ] ) }
Use a slice.
sub drop_first_last (#grades) {
return avg(#grades[1..*-2])
}
Workarounds such as have been shown in the rest of the answer are correct, but the short answer to your question is that there is no equivalent expression in Perl 6 to the * in Python.
This kind of arguments are called, in general, variadic, and *slurpy+ in Perl 6, because they slurp the rest of the arguments. And that's the key, the rest. There can be no argument declared after an slurpy argument in a subroutine's signature. This example below also uses a workaround:
sub avg( #grades ) {
return ([+] #grades) / +#grades;
}
sub drop_first_last($first, *#other-grades) {
return avg(#other-grades[0..*-1]);
}
my #grades = <10 4 8 9 10 8>;
say drop_first_last( |#grades );
but is first using the slurpy * in the signature to show how it works, and then, by calling it with |#grades, is flattening the array instead of binding it into an array argument. So the long answer is that there is actually an * or variadic symbol in signatures in Perl 6, and it works similarly to how it would do it in Python, but it can only be placed last in those signatures since it captures the rest of the elements of the expression.
In case the first and last values are needed for some other reason,
unflattened list structure inside slices maps across to the results
in most cases, so you can do this (you have to use a $ sigil on
$middle to prevent autoflattening):
my #grades = (1,2,3,4,5,6);
my ($first, $middle, $last) = #grades[0,(0^..^*-1),*-1];
$first.say; $middle.say; $last.say;
#1
#(2 3 4 5)
#6

Converting binary to decimal with out using a function

I'm trying to create a binary to decimal converter, and have got stuck on the code. I have researched forums for any help, but they all seam to use functions, which can not be used within a private sub. Please can anyone give me help on a solution to this problem?
I would use the positional notation method:
http://en.wikipedia.org/wiki/Positional_notation
http://www.wikihow.com/Convert-from-Binary-to-Decimal
So basically, without giving you the answer, you want to loop through binary place holders, filling up a variable as you go along. You would use an index to move from the least significant placeholder to the most.
For example : 10011011 in binary is 155 decimal.
So every place holder is a power with a base of two. Then you add the value for each one until your finished, like so:
placeholder 1 is: 2 pow 0 equals 1.
placeholder 2 is: 2 pow 1 equals 2.
placeholder 3 is: 2 pow 2 equals 4.
placeholder 4 is: 2 pow 3 equals 8.
placeholder 5 is: 2 pow 4 equals 16.
placeholder 6 is: 2 pow 5 equals 32.
placeholder 7 is: 2 pow 6 equals 64.
placeholder 8 is: 2 pow 7 equals 128.
Now we only add for the placeholders that have 1s.
128+16+8+2+1 = 155
What you will need:
A loop looping through indexes, and incrementing the exponent value as you go along, only adding the value if the index equals 1 in the binary number.
Hope my explanation makes sense. Good luck.